素人が zsh の仕組みを学びながら良く行くディレクトリに行けるようにしてみる


はじめに

まず、zsh には cdr や z などの有名な拡張があります。ちゃんと設計されたものを使いたければそっちを使って下さい。でも、素人が何がやってみたいと思ったら、既存のものがあるかどうか気にせずにやってみたらよいと思います。別にこれで仕事をしてるわけでもない素人は車輪の再発明なんて気にする必要はありません。同じ物でも劣化品でも何でも作って学びましょう。hello.c なんて、いったいこれまでに何度書かれてきたことか。だいたい私、hello.c をそらで書けませんし。

zsh が cd したときに自動実行するのは何?

function chpwd() が実行されます。

function chpwd() {
  echo "ふざけてんの?"
}

としておけば、
zsh
% cd
ふざけてんの?
% cd
ふざけてんの?
% cd
ふざけてんの?
% cd
ふざけてんの?

となります。

どうやってディレクトリの頻度を保存しよう

テキストに書きこんでも良いのですが、ここは素直に sqlite を使いましょう。いえ、私が使ってみたかったんです。sqlite の DB にパスと回数を記録することにします。では早速 DB を作りましょう。普通のプロダクトなら初回起動時に自動生成するもんですが、自分プロダクトです。気にせずにいきましょう。

sqlite3 $HOME/.cache/.dirstack.db "create table dirstack(path text, freq integer)"

で DB へ書き込むスクリプトは

~/.local/bin/OreDirStack
#!/bin/zsh
DIRSTACK_DB=$HOME/.cache/.dirstack.db

# カレントディレクトリの回数を調べます。なければ失敗して count は空です。
count=$(sqlite3 $DIRSTACK_DB "select freq from dirstack where path=\"$PWD\" ")

# count が空なら現ディレクトリ、1 回を登録
if [ -z $count ]; then
  sqlite3 $DIRSTACK_DB "insert into dirstack values(\"$PWD\",1)"
else
# そうじゃなかったら、1 足して登録
  count=$(( $count + 1 ))
  sqlite3 $DIRSTACK_DB "update dirstack set freq=$count where path=\"$PWD\" "
fi

# Validation
# sqlite3 $DIRSTACK_DB "select * from dirstack order by freq DESC"

return

その DB を使って移動しよう

ここは当然 peco でしょう。頻度の高い順に並べたクエリ結果を peco に流しこんで使います。難しい zle 関数とか書けなくても zsh の global alias で次のようにすれば cd :df で頻度の高いディレクトリにあっという間に移動できます。

alias -g :df='$(sqlite3 ~/.cache/.dirstack.db "select path from dirstack order by freq desc"| peco)'