Unengineered Weblog

PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND

ダム端末でzshをまともに使う方法(9term, Acme, Emacsなど)

zshmacOSのデフォルトログインシェルである。多機能で便利なシェルであるが、ダム端末で使われることを想定していないようだ。この記事ではダム端末とはshellやコマンドの出力をそのまま表示する端末のこととしよう。Acme, 9term, Emacs shellなどはダム端末である。それに対してxtermやGNOME Terminal, Terminal.appはVT100をエミュレートしている端末で、出力に含まれるESC [から始まるエスケープシーケンスによって文字色を変えたりする機能をもつ(この辺はよくわかってない。Wikipediaなどの情報を参照している)。xtermを想定した出力をダム端末に送ると、ダム端末はエスケープシーケンスを解釈できず、エスケープシーケンスがそのまま奇妙な文字列として表示されてしまうのである。zshをデフォルト設定で用いると出力されるエスケープシーケンスによってAcmeEmacsの表示が崩れる。

acmeユーザーならシェルにrc(1)を使うだろう(私も同様)から、誰がこの記事を参照するんだろう?

解決策

次のソースを$HOME/.zshrcに書けばOK

if [ "$TERM" = dumb ]
then
    unsetopt ZLE
    unsetopt PROMPT_CR

    export PS1='%0~ %# '
    export PAGER='col -xb'
    export EDITOR='ed'
fi

解説

現在の端末がダム端末かどうか調べるには環境変数TERMを確認すれば良い。

Zsh Line Editor (ZLE)

ZLEはreadlineみたいな機能を提供してると思われる。こいつがむちゃくちゃな出力をする元凶。オフ。

PROMPT_CR

xterm上の端末ではzshは出力の最後に改行がついていない場合、%を出力して自動的に改行する。ダム端末では最後に改行がついてるかどうか判別できず、常に末尾に%をつけてくる。

環境変数

PS1

文字の色がないプロンプトにする必要がある。端末の文字色はエスケープシーケンスによって制御しているからだ。色がつかなければ何でもよい。

PAGER

通常はman(1)やgit(1)はless(1)を起動して出力を表示する。しかしながらダム端末ではlessなど動かない。これらのコマンドは環境変数PAGERが設定されているとlessの代わりに$PAGERを起動して表示する。col(1)はエスケープシーケンスを削除してくれるコマンドである。manの出力にはタイトルや強調に使うエスケープシーケンスが含まれているのでそれらを削除する。colの代わりにcatを用いるとエスケープシーケンスが削除されずにダム端末によっては表示されてしまう。

lessみたいに行を少しずつ表示をしたければBrian W.Kernighan, Rob Pikeの「Unixプログラミング環境」に紹介されているpを使えば良い。plan9portにも提供されている。このソフトウェアはエスケープシーケンスを使っていないので正常に動作する。

EDITOR

ダム端末ではviなどのスクリーンエディタは利用できない。コマンドによってはエディタが不意に起動する場合もあるので、スクリーンエディタが起動できないようにすること。ここではedとした。

参考になる文献

xtermのエスケープシーケンスについて www.xfree86.org

過去のPOSIXにあったcolコマンド(今は削除されたみたい) pubs.opengroup.org