🐠

zshのコマンドが失敗したら履歴を残さない(precmdフックを使う)

に公開

やりたいこと

  • zshで、コマンド実行が失敗したら履歴に残らないようにしたい
    • とりあえず動けばよい

環境

zsh --version

zsh 5.8.1 (x86_64-ubuntu-linux-gnu)
or
zsh 5.9 (arm64-apple-darwin24.0)

他の記事でも取り上げられているが・・・

失敗したコマンドを残さない方法は紹介されているのですが、私の環境のせいなのか、書かれているzshaddhistoryフックが使えませんでした。
やりたいことは、直前のコマンドの実行結果を使って判定して、書き込みするかを決めるということです。

ワークアラウンド

git hooksの実行順は、このようになっています。

  • zshaddhistory
  • preexec
  • precmd

自分のzsh環境でコマンド結果が出るタイミングを調べていると、precmdの段階では実行結果が反映されていました。
ということで、このprecmdフックを使うことにして.zshrcに判定処理を書きます。

.zshrc
# zsh history write on condition
function save_command() {

  EXIT_STATUS=$?

  if is_ignore_history "$cmd"; then
    return 1
  fi

  if (( $EXIT_STATUS == 0 )); then
    print -sr -- "$cmd"
    fc -W
  fi
}

# Workaround for when the exit status of the last command is available
# in precmd instead of in zshaddhistory.
autoload -Uz add-zsh-hook
# zshaddhistory() is called before precmd.
add-zsh-hook precmd save_command

テストするには

履歴ファイル~/.zsh_historyを開いて、false とかech test とか打つと記録されないことがわかります。

setoptの調整

setoptはこのようになっています。

% setopt | grep hist
extendedhistory
histexpiredupsfirst
histfindnodups
histignorealldups
histignorespace
histnostore
histreduceblanks
histverify
sharehistory

まとめ

  • zshの履歴に、コマンドが失敗したら記録しない(成功したときだけ記録する)ようにしました
  • 課題:コマンドが失敗したときと、コマンドがtypoしてたときと、どちらも記録されないのが困ることがある

Discussion