I want to run some Elisp when my command executed by async-shell-command terminates.

How can I do this? Does it have completion hooks?

  • async-shell-command calls shell-command, the latter of which contains a doc-string that states in part: "...In Elisp, you will often be better served by calling call-process or start-process directly, since it offers more control and does not impose the use of a shell (with its need to quote arguments)." When you execute something synchronously, you wait for it to finish before moving on to another task. When you execute something asynchronously, you can move on to another task before it finishes. Perhaps use the synchronous method here: start-process/set-process-sentinel. – lawlist Jun 21 '18 at 19:02
  • Here is a link to an example of how to wait until a process ends before doing something else -- In this example, a Lisp message is generated after running five (5) separate processes: stackoverflow.com/a/42879986/2112489 – lawlist Jun 21 '18 at 19:11

You can specify the output buffer for async-shell-command. The shell runs as a process of the output buffer. You can get that process with get-buffer-process. Define your own process sentinel for the shell and set it with set-process-sentinel. It is wise to run shell-command-sentinel from your sentinel since that is the sentinel actually set by async-shell-command.

Note that the output buffer may not be associated with any other process when you call async-shell-command. Otherwise an other buffer could be used as process buffer for the shell command (see the documentation of the variable async-shell-command-buffer).

There follows an example:

(defun do-something (process signal)
  (when (memq (process-status process) '(exit signal))
    (message "Do something!")
    (shell-command-sentinel process signal)))

(let* ((output-buffer (generate-new-buffer "*Async shell command*"))
       (proc (progn
               (async-shell-command "sleep 10; echo Finished" output-buffer)
               (get-buffer-process output-buffer))))
  (if (process-live-p proc)
      (set-process-sentinel proc #'do-something)
    (message "No process running.")))

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.