zshで特定のコマンドをヒストリに追加しない条件を柔軟に設定する

zshを使ってると、 ^R なんかでコマンドヒストリから探すことが多くなる。なので、ヒストリは大事にメンテナンスしたい。余計なのを入れたくない。

zsh であるコマンドを履歴に登録しない方法 | Carpe Diemってページで先頭にスペースを入れるテクニックが解説されてたけど、もうちょっと柔軟に条件指定できる方法があるので紹介。

zshaddhistory を使って HISTIGNORE みたいなことをする

bashには HISTIGNORE という環境変数があって、ヒストリに保存しないコマンドの条件を * とかワイルドカードでパターン指定できる。でも、なぜかzshにはない。

でもそこはzsh、何とかする方法があった。zshaddhistory という特殊関数を使うと解決できる。

zshaddhistory 関数はコマンドラインがヒストリに追加される前に呼び出されて、こいつが偽(0以外)を返したらその行はヒストリに追加されない。うん、こいつでいけそうだ。

zshrcの例

こんな感じでzshrcに書いておけばOK。

zshaddhistory() {
    local line=${1%%$'\n'}
    local cmd=${line%% *}

    # 以下の条件をすべて満たすものだけをヒストリに追加する
    [[ ${#line} -ge 5
        && ${cmd} != (l|l[sal])
        && ${cmd} != (c|cd)
        && ${cmd} != (m|man)
    ]]
}

この場合、以下のいずれかを満たすコマンドラインがヒストリに追加されなくなる。

  • 4文字以下である
  • コマンド名の部分が l, ls, la, ll のいずれかである
  • コマンド名の部分が c, cd のいずれかである
  • コマンド名の部分が m, man のいずれかである

いくつかポイントを解説しておく。

line 変数

この関数はコマンドライン全体が引数になって、それには末尾の改行も含まれている。それでは扱いにくいので、最初の line ってとこで改行を捨てて line 変数に格納している。

cmd 変数

cmd 変数にはコマンドラインのうち最初のスペース以降を捨てた文字列が入っている。つまり、引数とかを捨てた、先頭のコマンド名の部分になる。

${#line} ってとこ

${#line} ってのは line 文字列の文字数になる。ここでは4文字以下の短いコマンドラインはヒストリに追加しないようにしてる。

こいつを参考に、cd とかの部分を適当に変更して使ってみるといいよ。

参考

man zshmisc の zshaddhistory
zshの本のP334

zshの本 (エッセンシャルソフトウェアガイドブック)

zshの本 (エッセンシャルソフトウェアガイドブック)