Zsh で実行に失敗したコマンドを履歴に残さない テイク2
あらすじ:zsh で(例えば、間違ってタイプして)実行に失敗したコマンドを履歴に残さないように 以前の記事 で設定しました。ところが使っているうちに一つ気に入らない振る舞いをしている点が見つかります。この度、久しぶりに設定ファイルに手を入れて改良してみることにしました。
さて何が問題だったかというと、例えば
echo $fpath | tr ' ' '\n'
というコマンドが、履歴ファイルには
echo $fpath | tr ' ' ' '
という風に保存されてしまう点です……(\n
が評価されてしまっている)。これはひどい。
以前の実装では、実行するコマンド(${1%%$'\n'}
)を一時変数(_LASTCMD
)に保存し、実行直後に _LASTCMD
にいくつかの処理を施し、終了ステータスが 0
ならば履歴に書き込んでいました。この『いくつかの処理』で echo ${_LASTCMD}
としている箇所があったのが問題です。これは具体的には zsh のオプションで設定できる hist_reduce_blanks
という機能*1を自前で実装しているところに登場します。Shell expansion に精通していたら回避できるような気もするのですが、諦めて別の手段で解決します。そもそも zsh に元来備わっている機能を自前で実装する必要があるアプローチは筋が悪い。
ということで今までは
『実行前にコマンドを一時保存 → コマンドの文字列にいくつかの処理 → コマンドを履歴ファイルに保存』
としていたところを
『実行コマンドを履歴ファイルに保存(いくつかの処理は zsh におまかせ)→ 終了ステータスを見て不要なら履歴ファイルから消去』
とします。
こちら を参考にしました。下記のような設定を .zshrc
などに記入すれば良いはずです。*2
__update_history() { local last_status="$?" local HISTFILE=~/.zsh_history fc -W if [[ ${last_status} -ne 0 ]]; then ed -s ${HISTFILE} <<EOF >/dev/null d w q EOF fi } precmd_functions+=(__update_history)
実に 2 年越しの改良ですが(今のところ)概ね満足しています。*3