4

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)?

  • 1
    Is 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 at 3: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 at 4: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 at 14:20
  • 1
    If 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 at 21:22
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))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.