TL;DR
.zshrc に以下を書けば良い:
# Enable dirtrack on(multi-)term-mode.
if [[ "$TERM" = eterm* ]]; then
chpwd() { printf '\032/%s\n' "$PWD" }
fi
追記 (May 14, 2025): oh-my-zsh を使っていれば emacs プラグインが勝手にやってくれる:
plugins=(emacs)
仔細
term-mode
は Emacs
本体に付属する端末エミュレータである。基本的には Emacs
内でシェルを起動するために使うもので、古い shell-mode
よりも端末に近い動きをするので便利なのだが、一つ問題がある。シェル内でディレクトリを移動しても
Emacs バッファの PWD がそのままでは追従しない点だ。 こういう追従を Emacs
では Directory Tracking (dirtrack)
と呼んだりするが、shell-mode
や eshell
ではデフォルトで提供しているのに term-mode
だけそうではない。
要するにシェル内で cd
してもバッファの PWD
は開いた時点のもの (基本的には直前にアクティヴだったバッファの PWD
を継承する) のままなので、移動したつもりで C-x C-f
などをするとパスが違ってアレっとなることになる。
実は term-mode
にも dirtrack
機能自体は存在しているのだが、これはシェルがディレクトリ移動を伴うコマンドを実行したときに特定のエスケープシーケンスを含んだ行を印字することで
Emacs 側に通知するという仕組みになっている。 Emacs と同じく GNU
プロジェクトの成果物である bash は Emacs
内での動作を検出すると自動的にこのような挙動を取るが、zsh は Emacs
の事情なんか知ったことではないので手動で設定する必要がある。
まずもって「ディレクトリ移動のコマンドをフックする」必要がある訳だが、zsh
の場合これは簡単で cd
/ pushd
/
popd
のようなディレクトリ移動を行うビルトインコマンドは移動後に
chpwd
というフック関数があればそれを実行するようになっている:
chpwd() { printf '\032/%s\n' "$PWD" }
基本的にはこれを .zshrc に書けば良いのだが、Emacs
以外の端末エミュレータ (Terminal.app など)
を使う場合にもこれが印字されるとかなり鬱陶しい。 term-mode
が起動するシェルの環境変数 TERM
はデフォルトでは
"eterm-color"
という値になっているため、これを Emacs
上での動作の判断に使うことができる:
if [[ "$TERM" = eterm* ]]; then
chpwd() { printf '\032/%s\n' "$PWD" }
fi
コメント
コメントを投稿