zshの標準エラー出力の色を赤くする

[追記]以下の方法は良くないようです。必ず、このエントリー最後の「stderredを使う」を参照してください[/追記]

最近stderrを赤くするように設定したら、コマンドの出力がかなり見やすくなりました。 f:id:itchyny:20171116233845p:plain

設定はこんな感じに書いてます。

zmodload zsh/terminfo zsh/system
color_stderr() {
  while sysread std_err_color; do
    syswrite -o 2 "${fg_bold[red]}${std_err_color}${terminfo[sgr0]}"
  done
}
exec 2> >(color_stderr)

fg_bold[red] のところを fg[red] とかbg_bold[red] とかするとスタイルを変更できます。 古いzshでは動かないらしいので、古い環境も気にしたい場合は is-at-least 4.3.4 でチェックするとよさそうです。

この設定の元ネタはcoloring stderr - was Re: piping stderrです。 大体はうまくいくし、普段使う分には大きな問題は起きていないのですが、わりと乱暴なことをやっているという自覚はあります。 元ネタのスレッドでも触れられていますが、 echo L1; echo L2 >&2; echo L3; echo L4 >&2 とやると L2L3 が逆に出力されたりします。 あと bash -i したあとに top を起動できないといったりします。

いくつか問題が起きるケースはありそうだけど、二週間ほど試してみて普段端末を触る範囲では困っていないのと、stderrに色が付くのがありがたいので使っています。もっといい方法があれば教えてください。

ついでに使っているPROMPTの設定はこんな感じです。終了コードを元に色を変更しています。

PROMPT="%(?.%{$fg[green]%}.%{$fg[blue]%})%B%~%b%{${reset_color}%} "
PROMPT2="%{$bg[blue]%}%_>%{$reset_color%}%b "
SPROMPT="%{$bg[red]%}%B%r is correct? [n,y,a,e]:%{${reset_color}%}%b "

stderredを使う

上の設定を使うと、 echo foobar | vim - が動かなくなります。これは結構困ります。端末で出力先を無理やり変える方法はやはり色々トラブルの元となるようです。 代わりにstderredを使うのをおすすめします。ビルドする必要はありますが、上の方法よりも直接的な方法なのでトラブルは起きないと思います。 github.com

if [ -f /usr/local/lib/libstderred.dylib ]; then
  export DYLD_INSERT_LIBRARIES="/usr/local/lib/libstderred.dylib${DYLD_INSERT_LIBRARIES:+:$DYLD_INSERT_LIBRARIES}"
  export STDERRED_ESC_CODE=$'\x1b[1;31m'
fi