7

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?

Drew
  • 75,699
  • 9
  • 109
  • 225
Matthew Piziak
  • 5,958
  • 3
  • 29
  • 77
  • `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: https://stackoverflow.com/a/42879986/2112489 – lawlist Jun 21 '18 at 19:11

1 Answers1

10

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.")))
Tobias
  • 32,569
  • 1
  • 34
  • 75