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.
I tried
(org-read-date)
And that worked for me
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.
Related
In emacs lisp, I expect the following to display a list of options in the completion buffer as I type. It prompts for information but doesn't display choices, either before or after I start typing. For example, I'd expect it to display 'First' after I'd typed 'F'.
(defun reader ()
(interactive)
(let ((choices '("First" "Second" "Third")))
(completing-read "Choose: " choices)))
Essentially I'm looking for something similar to the output described here. But what I get is this (there's nothing below the line, which is the edge of my window):
Can anyone explain where I'm going wrong with completing-read?
That's the way completing-read behaves. You're not doing anything wrong. It just doesn't support any kind of automatic, incremental completion.
If you want such automatic completion then you either need to write your own code to provide that or use a completion framework that provides it.
Icicles was the first to provide this incremental-completion behavior. Many other packages now provide the same or similar.
I can insert an inactive timestamp interactively with org-time-stamp-inactive (C-c C-!), then pressing Enter when presented with the calendar. This inserts a value like [2021-12-10 Fri].
I would like to know if this can be achieved programmatically with org-time-stamp-inactive. I tried org-time-stamp-inactive '(16) but this also inserts a time which I do not want. I can do insert (format-time-string "[%Y-%m-%d %a]") but this uses a different approach, and I would like to know if what I want can be achieved with org-time-stamp-inactive.
EDIT (in response to comment): No, it is not possible, but you got to look at the code to make sure. org-time-stamp-inactive is a thin wrapper around org-time-stamp. That in turn calls org-insert-time-stamp, which takes a time and a with-hm argument (among others - see the doc string of the function with C-h f org-insert-time-stamp for the details). If with-hm is nil, then no time is printed. But org-time-stamp (and therefore org-time-stamp-inactive) always calls org-insert-time-stamp with a non-nil with-hm, so the time is always inserted in that case. The best you can do is call the underlying function org-insert-time-stamp like so: (org-insert-time-stamp (current-time) nil 'inactive).
I still think your simple suggested solution (elaborated a bit in the original answer below) is the best way to go about the problem.
[ORIGINAL ANSWER]
Org mode is plain text: things may appear differently, but all that is smoke and mirrors: you can cat an Org mode file in the terminal and see precisely what it contains. In particular, inactive time data are just strings of the form [2021-12-11]. So there is no penalty if you do it manually, instead of going through some Org mode interfaces: the end result is the same, so your manually inserted date is just as good as the one inserted by org-time-stamp-inactive.
So assuming that the simple solution you suggested is acceptable, here's filling in the details:
(defun my/org-insert-current-time-as-inactive-time-stamp ()
(interactive)
(insert (format-time-string "[%Y-%m-%d]")))
(define-key org-mode-map (kbd "C-c _") #'my/org-insert-current-time-as-inactive-time-stamp)
C-c _ was undefined in the Org mode keymap in my case, but YMMV: choose something that is not used.
I'm trying to call the following org-mode function to insert the current timestamp in the buffer. The function is called by a script.
(org-time-stamp-inactive)
This, as expected, brings up a prompt asking for the date to use for the timestamp. But I want to skip the prompt and insert the timestamp directly. Is that possible at all? Haven't found anything that could help me.
This should insert the current inactive time stamp:
(org-insert-time-stamp nil nil t)
org-time-stamp unconditionally¹ calls org-read-date to prompt the user for a date. You can't pass a date. But you can locally bind org-read-date to a function that returns the date that you want to use.
(require 'cl)
(flet ((org-read-date (org-with-time &rest args)
(format-time-string (if org-with-time "%Y-%m-%d %H:%M" "%Y-%m-%d")
(current-time))))
(org-time-stamp-inactive with-time))
¹ Except sometimes when there is already a time stamp, but that's no help.
I ended up creating the timestamp from scratch with the following call:
(insert (format-time-string "[%Y-%m-%d %a]"))
You can find the answer in documentation for similar function (org-time-stamp)
[...] With two universal prefix arguments, insert an active timestamp
with the current time without prompting the user. [...]
So.. all you need to do is press C-u C-u before you invoke the function (for example C-u C-u M-x org-time-stamp-inactive RET)
I have not been able to get the minibuffer-exit-hook to play nice with read-string. As far as I can tell, I should no longer be in the minibuffer after finishing up with read-string. However, the condition (minibufferp) says I'm still in the minibuffer even though read-string finished. read-string is written in C, so I can't add the hook there (i.e., at the tail end of the read-string function).
"Documentation [minibuffer-exit-hook]: Normal hook run just after exit from minibuffer.
[After thinking a little more about this, I'm pretty sure it's a bug -- so I filed a bug report: bug#16524. As I learn more, I'll update this thread.
(defun test ()
(interactive)
(read-string "Prompt: " "testing"))
(add-hook 'minibuffer-exit-hook (lambda ()
(cond
((minibufferp)
(message "Focus is still in the minibuffer: %s" (buffer-name)))
(t (message "Contragulations -- focus is now in: %s." (buffer-name))))))
The doc string is not exact; that's all. The hook is run when inputting text in the minibuffer is done (no longer possible). The buffer that is current when it is run is still the minibuffer. (And that's the way it should be, FWIW.)
Note that the Elisp manual puts it slightly differently (but again, not very precisely):
This is a normal hook that is run whenever the minibuffer is
entered.
("Whenever", meaning about the same time as, not necessarily after.)
If you want to do something after every use of read-string in your code, then define a function that does the following: first (read-string...), then whatever you want done next. And use that function.
If you need to affect also other invocations of read-string, besides those you write in your code, then advise function read-string to perform whatever action after the vanilla code finishes.
For example:
(defadvice read-string (after fooness activate)
(message "buffer: %S" (current-buffer)))
[Note: Yes, you can advise primitives (functions written in C). You used to even be able to advise special forms, but they regressively took away that feature.]
Running a hook after you truly exited the minibuffer is rather pointless: you could be in any kind of buffer (since minibuffer use can be triggered from anywhere) and you hence know very little about the current context (unless you use a buffer-local exit-hook, I guess).
If you want to run a hook when the selected window changes, then your best option is probably to use a post-command-hook that stores the current selected-window in an auxiliary variable and uses it to compare to the previous selected-window.
In CEDET, the minor mode semantic-idle-summary-mode displays information about the symbol under point in the echo area. I really like this mode, as it helps me remember, for instance, which arguments the function I'm calling needs.
The problem is, it's a little buggy about displaying in the echo area. Since it automatically activates whenever there's a symbol under point, it sometimes hides useful information that is being displayed in the echo area (after all, that's the area that emacs uses to tell you stuff).
Is there a way to display the summary information somewhere else? A tooltip would be ideal, but one of the ecb frames is acceptable as well.
The first thing that comes to mind is the variable tooltip-use-echo-area which controls where / how tooltips are displayed. When set to t, all tooltips are displayed in the echo area. What is its value on your system? Maybe it would be possible to force cedet to use actual (pop-up) tooltips by setting that variable to nil.
semantic-idle-summary-mode uses the function eldoc-message and a few other eldoc queries to determine when to display messages. This means it should be pretty good at not covering up useful information.
Since eldoc is the preferred mode for providing similar summary information in Emacs Lisp buffers, the best thing would be to configure eldoc, but I didn't see a way to do it since eldoc-message appears configured to always call message.
Anyway, what that means is you can use defadvice to override eldoc-message to use a tooltip, and you will have your solution.
The below snippit is a guess at how to use defadvice, but I didn't give it a try.
(defadvice eldoc-message (around bruce-mode activate)
"Make eldoc display messages as a tooltip."
(if (some condition that means I want to use a tooltip)
(bruce-eldoc-message (ad-get-arg 0))
ad-do-it))
(require 'tooltip)
(defun bruce-eldoc-message (&rest args)
"My version of displaying a message for eldoc."
(if (null (cdr args))
;; One argument
(tooltip-show (car args))
;; Else, use format
(tooltip-show (apply 'format args)))
)
I had a similar need as you,
and I addressed it with this extension.
As you can see on this screenshot,
it shows the function arguments at the point of its invocation, without altering the echo area.
Some neat features are:
Shows you all overloaded functions, including constructors where appropriate.
Highlights in bold the current argument.
Jump to definition functionality for the current function variant.