Just learn to write an interactive function in elisp:
If called with prefix, open calendar and get the date which is picked by user.
I try to do something like this:
(calendar)
(org-get-date-from-calendar)
It return today straight away instead of let user to pick a date.
As you've seen, the problem is that after invoking (calendar)
your code simply continues and doesn't wait around for any interactions in the calendar window. You need to prevent the emacs command loop from continuing until the user has selected a date.
Setting up your own keys is one way to do this. For example, if you look at the org-read-date-minibuffer-local-map
variable in the org-mode source code, you can see that org-mode essentially takes over keys in calendar mode to allow the user to navigate the calendar while org-mode waits for the result. Studying this keymap and the org-eval-in-calendar
function might give you some ideas on how to achieve what you want.
Another way to wait for the result is via recursive-edit. The code below enters the calendar and, by calling (recursive-edit)
, waits for the user to exit the calendar via the q
key, which normally invokes calendar-exit
. The code temporarily applies advice to that function to have it set a local variable to the date selected in the calendar before calling calendar-exit
(via the funcall
) and then exiting the recursive edit:
(let* (date
(adv '(lambda (fn &rest args)
(setq date (calendar-cursor-to-date))
(funcall fn args)
(exit-recursive-edit))))
(advice-add 'calendar-exit :around adv)
(calendar)
(message "Select the desired date, then type `q' to exit.")
(recursive-edit)
(advice-remove 'calendar-exit adv)
date)
Using advice can be a brittle approach, though. It potentially changes function semantics in unexpected ways — and see this page for other potential problems — plus there are probably other issues lurking with this approach with respect to abnormal exits. You're better off using keymap approaches like those used in org-mode.