# 制御記号付きのmake-processの出力をいい感じに処理する方法

Date: 2020-05-23
URL: https://s.conao3.com/blog/2020/5fb67c
Author: conao3 (Naoya Yamashita)

# Intro

Emacsからプロセスを実行できます。

実行する方法は[いろいろあります](https://qiita.com/tadsan/items/17d32514b81f1e8f208a)が、最も低レベルな関数は `make-process` です。

最もユーザーに近い関数は `shell-command` で、 `M-!` に割り当てられています。
この関数はコマンド文字列を渡すだけで、お手軽に実行できます。

# make-process

[make-process](https://www.gnu.org/software/emacs/manual/html_node/elisp/Asynchronous-Processes.html#Asynchronous-Processes)は非同期プロセスを作成します。

必須のオプションは `:name` で、プロセスオブジェクトを返却します。
さらに `:buffer`, `:command`, `:coding`, `:connection-type`, `:noquery`, `:stop`, `:filter`, `:sentinel`, `:stderr` オプションが存在し、細かくプロセスの管理方法を制御できます。

基本的に `:name`, `:buffer`, `:command` を指定することになります。

```emacs-lisp
(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` にしなければフィルター関数を使えないかと思いましたが、よく見ればいくつかのマーカーを設定するだけで使えました。

```emacs-lisp
(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"))
```

![img](https://s.conao3.com/img/5fb67c-1cadeff9-aaf3-4595-abad-0f7e79512326.gif)

# まとめ

Emacsは良いエディタで、Elispは強力ですが、GitをElispで実装するのは現実的ではありません。

このように外部コマンドとElispを有効に協調させながら作業しやすい環境を整えていきましょう。
