I have a custom function that updates the etags
file before prompting the user to input a desired tag to be located. Although I am pretty good about setting the current buffer to read-only before going about other activities, sometimes I forget and I start typing the name of the tag before the new tags file is fully populated. As a result, I start typing the tag name to be searched and it gets inserted into the current buffer instead of the minibuffer -- because the tags creation process hasn't finished. One option that came to mind is figuring out (with help from emacs.stachexchange.com) how to block user input until the tags file is updated and the minibuffer is opened, but I am open to other solutions that I may be unaware of. How can I prevent myself from jumping the gun and typing the tag name into the current buffer instead of the minibuffer (before it openes when the tag file is complete)?
Asked
Active
Viewed 124 times
4

lawlist
- 18,826
- 5
- 37
- 118
-
1Is this an asynchronous process updating the tags file? Why not make it synchronous? e.g. `(defun foo () (interactive) (shell-command "sleep 3") (call-interactively 'find-tag))` does not cause the problem you've described, and seems to be more or less what you actually want? – phils Feb 15 '19 at 03:53
-
@phils -- yes, I am running a `start-process` / `set-process-sentinel` and monitoring it for completion before popping open the minibuffer. `(set-process-sentinel (start-process "build-tags" nil "/bin/bash" "-c" COMMAND-LINE) (lambda (p e) (when (= 0 (process-exit-status p)) (throw 'exit nil))))`; and, breaking a `resursive-edit`. I had not considered a synchronous process ... that is indeed a good solution. At your convenience, please write up an answer similar to your comment ... Thank you very much. – lawlist Feb 15 '19 at 04:11
-
1@phils `call-process` was also my first thought. But, I assumed that this was too simple. I also discarded that solution because of the "partially" in the title. I think the `call-process` can introduce annoying latencies. Maybe a better solution would be to buffer the user input until `etag` finishes and to decide afterwards what to do with the buffer contents. I would also suggest to take a look at existing solutions, e.g., `semantic` which scans for tags when emacs is idle. See also `timer-set-idle-time`. – Tobias Feb 15 '19 at 14:20
-
1If rebuilding TAGS is very fast, then this is likely fine in practice. Personally I use a cron job to periodically build a new TAGS file. It firstly checks to see whether there's any file in the project more recent than `TAGS` itself. If so, it creates a new tags file with a temporary filename. Finally, if the new tags file is *different* to TAGS then it makes the replacement. This way Emacs only revisits the TAGS file if something actually changed, and *most* of the time it will have indexed what I'm after before I use it. – phils Feb 15 '19 at 21:22
1 Answers
3
I suspect that the simplest approach is entirely adequate here. Using a synchronous process will prevent you from inadvertently typing into the wrong buffer -- anything you do type while the command is running will be buffered and will end up where you want it: as input to the find-tag
prompt.
e.g.:
(defun my-find-tag ()
"Update TAGS file and then call `find-tag'."
(interactive)
(call-process "ctags" nil nil nil "-e" "-R" ...)
(call-interactively 'find-tag))

phils
- 48,657
- 3
- 76
- 115