Emacs里异步执行shell命令的正确方法

需求:异步执行一系列shell命令,比如git add . && git commit -am "Update." && git push,不需要显示结果,也不要改布局,程序执行后做好清理。

分析:因为是shell命令,所以类似start-process的函数用起来不方便。比较容易想到的是async-shell-command,也就是M-&

尝试1:因为要「无痕」,所以直接用async-shell-command也不好,我想到的方法是设置display-buffer-alist让window不显示,同时设计一个在程序执行结束后关掉buffer的sentinel函数,代码类似下面的样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
(defun kill-buffer-when-done (process signal)
(when (and (process-buffer process)
(memq (process-status process) '(exit signal)))
(message "%s: %s."
(car (cdr (cdr (process-command process))))
(substring signal 0 -1))
(kill-buffer (process-buffer process))))
(let ((display-buffer-alist
'(("\\*asyn\\*" display-buffer-no-window (nil))))
(async-shell-command-buffer 'new-buffer))
(async-shell-command "git add . && git commit -am \"Update.\" && git push" "*asyn*")
(set-process-sentinel (get-buffer-process "*asyn*") #'kill-buffer-when-done))

解决

其实一句话就可以了😂:

1
2
(call-process-shell-command
"cd ~/.emacs.d/; git add . && git commit -am \"Update.\" && git push" nil 0)

但还是有点不方便:没法看程序执行成功还是失败了。不管了,我只是想安静的执行shell命令,别的不管。