14695


`M-&` などで `shell-command` を実行すると、`*Async Shell Command*`
バッファが作成されますが、対応するプロセスが終了した時点で、このバッファに exit code をひも付け、それを取得ないし表示ことはできますでしょうか。

特に、複数個のプロセスを同時に、非同期で実行する場合などにおいて、 `*Async Shell Command*` を`rename-uniquely`
などで rename して、複数個作成することがよくあります。  
その際に、どのバッファ(を出力しているプロセス)がどの exit code であったかを、そのバッファから取得する方法が欲しくなるので、質問しました。


CC BY-SA 3.0
2015-08-20T17:16:52.010
14681
2015-10-20T09:02:13.560
754
question
emacs elisp
async shell command バッファに exit code をひも付けて取得ないし表示したい


「M-& など」という事ですが、ここでは `async-shell-command` に限って話を進めたいと思います。

`async-shell-command` の実行の流れとしては以下の通りです。

  * async-shell-command
  * shell-command
  * start-process
  * (set-process-sentinel proc 'shell-command-sentinel)

最終的に `set-process-sentinel` で実行プロセスの管理が開始されます(process status が変化する度に `shell-
command-sentinel` が実行されます)。

そこで、この `shell-command-sentinel` にフックを付けます。具体的には `nadvice` を使います。

[code]

    (defun set-async-process-exit-status (process signal)
      (when (eq (process-status process) 'exit)
        (let ((buf (process-buffer process))
              (st (process-exit-status process)))
          (when (string-match "Async Shell Command" (buffer-name buf))
            (set-buffer buf)
            (setq-local exit-status st)
            (goto-char (point-max))
            (insert (format "\nExit status: %d\n" st))))))
    
    (advice-add 'shell-command-sentinel :before #'set-async-process-exit-status)
    
[/code]

詳しい説明は省きますが、プロセスが終了した段階で `*Async Shell Command*` バッファに buffer local な変数である
`exit-status` にプロセスの exit status をセットして、その値をバッファの最後に表示します。

[code]

    M-& 
    Async shell command: ls
         :
    
    (assoc 'exit-status (buffer-local-variables (get-buffer "*Async Shell Command*")))
    => (exit-status . 0)
    
    M-& 
    Async shell command: hogehoge
         :
    
    (assoc 'exit-status (buffer-local-variables (get-buffer "*Async Shell Command*")))
    => (exit-status . 127)
    
[/code]

`(string-match "Async Shell Command" (buffer-name buf))` としている部分が `async-
shell-command` に依存していますので、`async-shell-command` 以外の elisp
関数で同じことを行う場合には適宜変更する必要があります。


CC BY-SA 3.0
2015-08-21T06:19:30.073
14695
2015-08-21T08:04:27.127
2015-08-21T08:04:27.127
14681
answer