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, 2015 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, 2015 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, 2015 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, 2015 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, 2016 at 21:14

1 Answer 1


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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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