Intro
Emacsからプロセスを実行できます。
実行する方法はいろいろありますが、最も低レベルな関数は make-process
です。
最もユーザーに近い関数は shell-command
で、 M-!
に割り当てられています。
この関数はコマンド文字列を渡すだけで、お手軽に実行できます。
make-process
make-processは非同期プロセスを作成します。
必須のオプションは :name
で、プロセスオブジェクトを返却します。
さらに :buffer
, :command
, :coding
, :connection-type
, :noquery
, :stop
, :filter
, :sentinel
, :stderr
オプションが存在し、細かくプロセスの管理方法を制御できます。
基本的に :name
, :buffer
, :command
を指定することになります。
(setq proc
(make-process
:name "sh"
:buffer (get-buffer-create "*proc*")
:command '("hub" "clone" "conao3/celpa")))
(progn
(delete-process proc)
(shell-command "rm -rf celpa"))
ただ、コマンドから送られてきた文字列を素朴に出力するため、gitのように CR
を利用してリッチに出力するコマンドの出力は盛大に壊れます。
CR
を解釈しながら賢く処理をすれば良いのですが、とても面倒です。
Emacs-jpで助けを求めると、eshellの関数を利用すれば良いのではという助言があり、調べてみると、きちんと出力できました。
eshellの仕組みに乗っかるので、 eshell-mode
にしなければフィルター関数を使えないかと思いましたが、よく見ればいくつかのマーカーを設定するだけで使えました。
(with-current-buffer (get-buffer-create "*proc*")
(set (make-local-variable 'eshell-last-input-start) (point-marker))
(set (make-local-variable 'eshell-last-input-end) (point-marker))
(set (make-local-variable 'eshell-last-output-start) (point-marker))
(set (make-local-variable 'eshell-last-output-end) (point-marker))
(set (make-local-variable 'eshell-last-output-block-begin) (point)))
(setq proc
(make-process
:name "sh"
:buffer (get-buffer-create "*proc*")
:command '("hub" "clone" "conao3/celpa")
:filter (lambda (proc string)
(eshell-output-filter proc string))))
(progn
(delete-process proc)
(shell-command "rm -rf celpa"))
まとめ
Emacsは良いエディタで、Elispは強力ですが、GitをElispで実装するのは現実的ではありません。
このように外部コマンドとElispを有効に協調させながら作業しやすい環境を整えていきましょう。