When I'm currently in a large project and I call the command projectile-regenate-tags, the project will be scanned by ctags and the tags will be stored in the TAGS file.

While all this action is progressing, Emacs will be unreachable until the tags generation is completed.

I know there are some attempts to make Emacs process asynchronously, or even doing it in the background. My knowledge of concurrency is somewhat limited, so

I'm wondering if there is any way that I could call projectile-regenerate-tags and while the tags file being processed, I can do further other things with Emacs and the text? If so, what would be a good way to make it so?

  • Open a bug report. This is not something you can fix by customizing an option. – wasamasa Dec 25 '15 at 23:40
  • Is it really a bug? I guess Emacs is waiting on input when it's done. Why do you consider it as a bug? – ReneFroger Dec 25 '15 at 23:52
  • 1
    Could you maybe invoke the code that provides the behavior you need asynchronously, using emacslient or emacs in batch mode? Remember that you can invoke any program or shell script using, say, & in Dired. – Drew Dec 26 '15 at 0:01
  • 2
    It's a bug for projectile to do this synchronously, not for Emacs to do what it's told to. There is no magical switch that makes every single operation in Emacs non-blocking, it's up to package authors to leverage its possibilities properly. You may believe it's normal for a text editor to not ever hang up, but that's their authors respecting this very basic design assumption. – wasamasa Dec 26 '15 at 6:44
  • 2
    @ReneFroger This is not an Emacs bug, but a projectile bug. The Emacs team cannot do anything about Emacs to fix this issue with projectile (unless they invent the magic pill transforming synchronous code to equivalent asynchronous code), report it for projectile instead. – wasamasa Jan 13 '16 at 21:14

You can use https://github.com/redguardtoo/counsel-etags/blob/master/counsel-etags.el which originally called aysnc-shell-command to run shell command ctags -e -R.

Or else write your own implementation. Just three lines:

  (let* ((async-shell-command-buffer 'new-buffer)
         (display-buffer-alist '(("Async Shell Command" display-buffer-no-window))))
    (async-shell-command "ctags -e -R"))

The problem of async-shell-command is it will create a buffer and it can't notify the user when the tags file is generated. So here is a better version,

(defun counsel-etags-async-shell-command (command)
  "Execute string COMMAND and create tags file asynchronously."
  (let* ((proc (start-process "Shell" nil shell-file-name shell-command-switch command)))
     `(lambda (process signal)
        (let* ((status (process-status process)))
          (when (memq status '(exit signal))
             ((string= (substring signal 0 -1) "finished")
              (let* ((cmd (car (cdr (cdr (process-command process))))))
                (message "Tags file was created.")))
              (message "Failed to create tags file.\nerror=%s\ncommand=%s"

(counsel-etags-async-shell-command "ctags -e -R")
| improve this answer | |

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.