zshで ヒストリに登録したくない(無視したい)コマンドラインを指定する


はじめに

zshに限ったことじゃないですが、 コマンドライン操作においてよく使うのがヒストリ機能です

入力したことのあるコマンドラインの参照、展開、抽出なんかができるわけですが
たまにヒストリを検索したり、掘っていく時に、このコマンド邪魔だなーってなりませんか
pwd,cd,vim なんかがそうです

また、 HIST_VERIFY オプションを設定していない場合に、誤って危なげなコマンド(mv,rm)を展開して実行しちゃう
なんてこともあるかと

実はzshでは、ヒストリに積みたくないコマンドを指定できます!
というマニアックな記事

こう書くのじゃ

肝心の設定ですが、 変数 HISTORY_IGNOREに無視したいコマンドを指定してあげるだけです

.zshrc
HISTORY_IGNORE="pwd"

上記の例では pwd がヒストリファイルに書き込まれなくなります
HISTORY_IGNORE には パターンを指定できます

なので複数のコマンドを指定する場合は、次のように指定します

.zshrc
HISTORY_IGNORE="(cd|pwd|l[sal])"

上記の例では cd,pwd,ls,la,ll が無視されます。便利!
書き方は Glob Operators を参考にするといいです

HISTORY_IGNOREでは、ヒストリファイル書き込み時には除外してくれますが、内部ヒストリ(メモリ)には普通に履歴が積まれます※fc -l すると残ってるのがわかる

内部ヒストリ登録時も無視する場合は次の方法で指定します

ヒストリ(メモリ)にも積みたくない

zshaddhistoryを使う

.zshrc
zshaddhistory() {
  emulate -L zsh
  [[ ${1%%$'\n'} != ${~HISTORY_IGNORE} ]]
}

このHook関数は コマンドライン実行前(=ヒストリ登録前)に呼び出されます
zshaddhistoryがステータス 1を返す場合は、内部履歴に登録されなくなります

少し解説

  • 左辺 ${1%%$'\n'}
    コマンドラインから改行文字を取り除いてます
    変数展開の ${name%%pattern} 構文を使用しています

  • 右辺 ${~HISTORY_IGNORE}
    HISTORY_IGNORE をパターンとして展開してます
    複数文字との比較でよくある && || とかで記述しなくてよくなるから便利ですね

ポイント

個人的にこの設定のいいところは、 ignoreしたコマンドでも、次のコマンドを実行するまでは履歴に残っている点です
つまり「引数の一部だけほしい」「引数を変えて実行したい」ときなんかに直前のコマンドとして参照、展開が可能です

最後に

本当は、実行に失敗したコマンドを除外したかったのですが、できませんでした
zshaddhistory の仕様(コマンド実行後ではなくコマンド実行前に呼ばれる)じゃ無理ぽ
ご存知の方いましたら、教えて下さい。

以上、参考になればうれしいです