Emacsを使っていると、ふとした瞬間に迷います。
シェルコマンドはEmacsの中で実行するべきか。それとも C-z で一度Emacsを止め、元のターミナルに戻って作業し、fg で帰ってくるべきか。
どちらもできる。だからこそ、判断が揺れます。
1. Emacs内でシェルを使う(shell / eshell / vterm)
Emacsには、外部コマンドを実行するための仕組みがいくつもあります1。
M-!のような単発実行shellやeshellのような簡易シェル- 実際の端末にかなり近い挙動をする
vterm
特に vterm は、bash や zsh をそのまま動かせるため、
「ほぼ端末なのに、Emacsの中にある」という感覚がありました2。
コードを少し直す。
すぐ下のバッファで make や pytest を実行する。
出力を見て、またその場で修正する。
この往復がとても速いです3。
作業の文脈が一つの画面にまとまっている感じがあります。
ログをコピーしてメモに貼ったり、
コマンド結果をそのまま編集対象にしたりするのも自然でした。
1.1. C-z でターミナルに戻るという選択
ここで一度、話を整理します。C-z は、実行中のプログラムを「一時停止」する操作です4。
Emacsで C-z を押すと、Emacsは止まり、
起動元のターミナルに制御が戻ります。
そこで別の作業をして、fg(foreground)と入力すると、
再びEmacsが前面に戻ってきます5。
かなり昔からある、UNIXらしい操作です。
- 出力が非常に多いコマンド
- フルスクリーンのTUIツール(htop など)
- tmuxで複数ペインを切り替えながらの作業
こうした場面では、Emacs内のvtermより、
素の端末のほうが安定していて速いと感じます6。
2. どちらも正しく、どちらも不完全
ここまで使ってきて感じたのは、
どちらの選択も「間違いではない」ということです。
- Emacs内シェルは統合性が高い。
- 外部端末は純粋に操作しやすい。
問題は、作業内容が日によって変わる点です。
短い編集と確認を繰り返す日もあれば、
ほぼ一日中、端末で調査や実行をする日もあります。
そのため、
- Emacs内で完結させる日は vterm
- 端末作業が中心の日は、最初からEmacsを別ウィンドウで起動
という切り分けに落ち着きました。
- Emacsでは
shell,eshell,term,vtermなど複数のシェル・インターフェースがあり、それぞれ特徴と互換性が異なります。たとえばvtermはCで書かれたlibvtermを使うため高い互換性と性能があります。 – emacsmirror/vterm: Fully-featured terminal emulator - vtermは、C言語で実装されたlibvtermライブラリを動的モジュールとして読み込むことで、Emacs内で完全に機能する端末エミュレータを実現しています。Emacs Lispのみで実装された他のシェルモードと比較して、エスケープコードの完全なサポートと高速な描画性能を持ちます。 – GitHub – akermu/emacs-libvterm: Emacs libvterm integration
- 実際に
vtermは Emacs Lisp 単体のシェルモードとは異なり、外部シェルを端末エミュレーションとして完全に近い形で動かせます。 – emacsmirror/vterm: Fully-featured terminal emulator - UNIXのジョブ制御では
C-zがSIGTSTPシグナルを送りプロセスを一時停止し、fgで再度フォアグラウンドに復帰させます。これはbashなどPOSIXシェルで広くサポートされている制御方法です。 – Ask HN: If you were rewriting Emacs from scratch - fgコマンドは、停止中またはバックグラウンドで実行中のジョブをフォアグラウンドに移動させます。ジョブが停止している場合はSIGCONTシグナルを送信して再開し、直接的な端末インタラクションモードに移行させます。ジョブを指定しない場合、最も最近のジョブがデフォルトで選択されます。 – How To Use Bash’s Job Control to Manage Foreground and Background Processes | DigitalOcean
- 一部の端末ツール(例:
htopのようなTUIアプリ)はEmacs標準の shell モードでは正しく表示されないことがあり、専用端末やvtermのような高互換ターミナルが推奨されます。 – emacsmirror/vterm: Fully-featured terminal emulator