コマンドが失敗したらプロンプトを赤くする (2)

2009-01-02 22:14
Prompt (VGA)

しばらく前から、コマンドの終了ステータスをプロンプトの色に反映させるようにしている。

終了ステータスとは

C言語なら

int main(int argc, char* argv[])
{
    ...
    return 0;
}

この return している 0 が終了ステータス。この整数値の下位 8bit がプロセスの終了時に親 (そのプロセスを起動したプロセス) にわたる。

終了ステータスの指定方法はいろいろある。C言語の場合 main 関数の戻り値以外にも exit 関数の引数でも指定できる。Ruby, Perl の場合、そもそも main 関数は無くて exit 関数に引数を与える方法だけがつかえる。

この値はシェル上で $? で参照できる。

% perl -e 'exit(0xdead)'; echo $?
173
%

慣例として、正常終了のときは 0 を返すことになっている。

% ls /etc/passwd
/etc/passwd
% echo $?
0
% ls /etc/passwdddd
ls: /etc/passwdddd: No such file or directory
% echo $?
1
%

ファイルが存在して無事表示できたので 0, ファイルが存在しなかったときは 1 を返しているのがわかる。ここではこの二種類しか観測できなかったけど、例えば grep だと 2 もあります。

% echo hello | grep hello
hello
% echo $?
0
% echo hello | grep helo
% echo $?
1
% echo hello | grep
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
% echo $?
2
%

パターンにマッチする行が見つかったら 0, 見つからなければ 1, そもそもそれ以前の問題 (引数が足りない) の場合 2 を返している。

プロンプトの色を変える

やっと本題。zsh だと ~/.zshrc にこんな感じで書くと良い。

autoload -U colors
colors
PROMPT="%{$fg[green]%}%#%{$reset_color%} "

precmd () {
  PROMPT="%{%(?.$fg[green].$fg[red])%}%#%{$reset_color%} "
}

%(?.foo.bar) ってところで条件分岐しているだけです。くわしくは zshmisc (1) の “Conditional substrings” を参照。なので、色以外も切り替えられます。

PROMPT="('-')/ "
precmd () {
  PROMPT="(%(?.'-'.;_;))/ "
}

うん。

('-')/ echo hello
hello
('-')/ echoo hello
zsh: command not found: echoo
(;_;)/ echo hello
hello
('-')/

かわいすぎた。

追記

はてなブックマーク - @lukesilvia.bookmarks

RPROMPT 使っている場合は、%{$reset_color%} のしないと、RPROMPT が手前にずれる

というコメントを読んで、PROMPT 中のエスケープシーケンスを %{ … %} でかこっていない部分に気づいたので「プロンプトの色を変える」の最初の例を修正しました。

% echo -n $fg[green] | hexdump -c
0000000 033   [   3   2   m
0000005
% echo -n $fg[red] | hexdump -c
0000000 033   [   3   1   m
0000005
% echo -n $reset_color | hexdump -c
0000000 033   [   0   0   m
0000005
%

ここらへんは全部エスケープ (033) が含まれてます。

Dubhead

面白いアイディアと思います。
UbuntuのZsh 4.3.6で試したところ、Ctrl-C入力で赤プロンプトになっちゃいますが、
これ何とかなりませんかね…

kzys

私がつかっている Mac と Linux でもなります。
そういうものだと受け入れてましたが、なぜそうなるかは気になるので、時間ができたときに調べてみます。

Leave a Reply