這幾天在寫 hexo.el 遇到一些 Emacs Lisp 中 process 相關的處理方式,做個簡單的整理筆記(也順便試用 hexo.el
)。不過有些因為目前我沒用過/用不到,所以也懶得去研究其中差異,不要打我。
Process
start-process
(Async)
(start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)
這是 Emacs Lisp 中最低階的 process 呼叫方法之一,他 stdout 輸出的 BUFFER
(fundamental-mode
) 連 ANSI color 都沒有(所以會看到一堆亂七八糟的 ANSI color 控制字元),要自己使用 set-process-filter
來自訂 Buffer 的 IO。
設定不出來的 filter…
看一下 set-process-filter 的文件:
1
2
3
4
5
6
7
8
9
10 (set-process-filter PROCESS FILTER)
Give PROCESS the filter function FILTER; nil means default.
A value of t means stop accepting output from the process.
When a process has a non-default filter, its buffer is not used for output.
Instead, each time it does output, the entire string of output is
passed to the filter.
The filter gets two arguments: the process and the string of output.
看起來自訂 filter 應該很容易,所以我這樣寫:
1 | (set-process-filter my-process (lambda (process string) |
但很奇怪,雖然 ANSI color 控制字元經過實驗確實被
ansi-color-apply
給消掉了,但不管怎麼試顏色(text-properties)仍舊就是出不來。這裡有待高人指點。
call-process
(Sync)
(call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS)
總之我是把這玩意看作是 start-process
的 sync 版本。
start-process-shell-command
(Async)
(start-process-shell-command NAME BUFFER COMMAND)
這玩意基本上跟 start-process
一樣,只是吃的 input 變成 shell command string 而已。如果你只是要開個 process 做些事情、不用去讀他的 output 的話,用這個沒問題。但如果你還需要漂亮的輸出…還是用 shell-command
吧。
call-process-shell-command
(Sync)
(call-process-shell-command COMMAND &optional INFILE BUFFER DISPLAY)
應該只是 start-process-shell-command
的 sync 版本(好隨便)。
Shell command
shell-command
(Sync)
(shell-command COMMAND &optional OUTPUT-BUFFER ERROR-BUFFER)
這玩意很容易使用,看一下上面這兩行你大概就知道這是啥了。而且這玩意會自動幫你 render ANSI color 成 propertized text(用人類的話來說,就是你可以在 OUTPUT-BUFFER
中看到字體有顏色),真是太棒了。
async-shell-command
(Async)
(async-shell-command COMMAND &optional OUTPUT-BUFFER ERROR-BUFFER)
跟 shell-command
幾乎一樣,只是會自動幫你在 COMMAND
的結尾加上 &
萬一執行的指令需要輸入東西(例如
git push
可能會叫你輸入密碼)怎麼辦?利用前面提過的
set-process-filter
:
1
2
3
4
5 (let ((process-buffer-name "*test-process*")
(process-object nil))
(async-shell-command "echo hello" process-buffer-name)
(setq process-object (get-buffer-process process-buffer-name))
(set-process-filter process-object 'comint-output-filter))
comint-output-filter
很方便,你不用自己浪費生命寫 filter,這個 filter 會自動幫你抓是否有 prompt 之類的東西。
shell-command-to-string
(Sync)
(shell-command-to-string COMMAND)
這玩意本質跟 shell-command
一樣,只是用途就如名稱那樣是「執行完 shell command 後,return stdout 為字串」而不是另外開一個 buffer 來慢慢顯示 stdout。所以他只有 Synchronous。