Fri Dec 14 2018

今年書いて良かった .zshrc

これは "今年書いて良かった dot files アドベントカレンダー" 14日目の記事です.

準備 (bindkey)

Zsh には bindkey という機能があって、ターミナルから普通にコマンドを入力する以外に Ctrl で装飾したようなキー入力から関数を呼び出すことが出来る.

例えば以下を .zshrc に書いておくと、Ctrl-h で挨拶が出来る.

# test.zsh
greeting() {
    echo Hello
}
zle -N greeting
bindkey "^H" greeting

これはあくまで例だから有用性はない. Ctrl-h するとその時点で echo が実行されるので邪魔.

cympfh% _

この時点で Ctrl-h すると、

cympfh% Hello
_

こうなる. ここで _ がカーソル. ちなみに zle reset-prompt を呼ぶとプロンプトを作り直してくれるのだが、割と使う.

書いてよかった設定 (本題)

移動系

cd-up() {
    cd ..
    zle reset-prompt
}
zle -N cd-up
bindkey "^G^U" cd-up

cd-old() {
    cd -
    zle reset-prompt
}
zle -N cd-old
bindkey "^G^O" cd-old

cd-home() {
    cd
    zle reset-prompt
}
zle -N cd-home
bindkey "^G^H" cd-home

cd-recent() {
    cd $(cat ~/.zsh_pwd_history | tac | peco)
    zle reset-prompt
}
zle -N cd-recent
bindkey "^G^R" cd-recent

大体最初に示した bindkey の使い方の通り. 実際に呼びたい関数を定義して bindkey でキーマッピングを設定するだけ. 最後の cd-recent は最近行ったことのあるディレクトリを ~/.zsh_pwd_history別な設定 で書き出してるので、 ここから行き先を peco で選んで移動させるコマンド.

どれもそれなりに使ってるけど、一番使ってるのは明らかに cd-recent. 最近の履歴を使う系は基本的に便利.

コマンド履歴

call-history() {
    BUFFER=$(history -n 1 | tac | peco --query "$BUFFER")
    CURSOR=$#BUFFER
    zle reset-prompt
}
zle -N call-history
bindkey "^R" call-history

history コマンドはコマンド入力履歴を出力してくれるのは便利だけど、 どうせならそこからインタラクティブに選んで、それがターミナルに入力された状態にしたい.

ターミナルの入力をいじるのが目的なのに、そのためにコマンド入力をするのは不自然なので bindkey に仕込んだ. すでにコマンド入力されてる文字列があれば、予めその文字列で history をフィルタする. これは peco--query に指定すれば実現できる.

例えば、コマンドの頭だけ書いててオプション以降が思い出せない、みたいなときにその場で Ctrl-r を押すとそれっぽいのがズラっと出てくるので、気をつけて選べば良い. 選択した時点で実行させないのは、最後に念のために確認したり、ちょっとだけ変えたいときがあるので.

$BUFFER$CURSOR という2つの変数を使っていて、 察しの通り、$BUFFER にはその時点でコマンド入力されている文字列が入っているし、代入すればセットできる. 長さの異なる文字列をセットしてもカーソルは変わらずそこにあるので、$CURSOR$BUFFER の長さをセットすることでカーソルを末尾に持っていっておく.

これもめちゃくちゃ使ってる. 履歴使う系は基本全部便利.