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?
Emacs Stack Exchange is a question and answer site for those using, extending or developing Emacs. It only takes a minute to sign up.
Sign up to join this communityYou 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.")))
async-shell-command
callsshell-command
, the latter of which contains a doc-string that states in part: "...In Elisp, you will often be better served by callingcall-process
orstart-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
.