history-menu - 最近入力したコマンドを現在位置に挿入
最近実行したコマンドをつなげて再実行したい場合みんなならどうする?直前のコマンドならば!!で実行できるね。zshならば!!のあとにTabを押すと実際のコマンドに展開されるし、!!などを使ってコマンドを実行しても展開された形で履歴に登録される。さすがzshだ。
2つ前のコマンドも!-2で展開される。けれど、打ちにくい上Tabも入れると4ストロークと多いので俺は好きではない。
そこで俺はirbsh風のヒストリメニューwidgetを作ってみた。C-vで過去20個の履歴が表示され、asdf〜とホームポジションのキーで選択するとカーソル位置に挿入される。これなら2ストロークでなおかつ履歴が一覧できるので効率的かつ直観的だ。
C-vはquoted-insertでEmacsならC-qなのでC-qに移しておいた。
[*]の位置でC-v s C-v a Enterを押したところの様子はこんな感じだ。zshは複数行にわたるコマンドを編集できるので、履歴の後に改行を入れておいた。これで長ったらしくならずに見やすくなる。
スクリプトに含まれる\021はC-qなのでquoted-insertをデフォルトのC-vで使っている人は\026に書き換えればいいです。
% echo bake bake % echo boke boke % [*]echo bake echo boke bake boke
ソースは以下だ。もってけ!
HISTORY_MENU_LENGTH=20 typeset -A HISTORY_MENU_KEYS set -A HISTORY_MENU_KEYS a 1 s 2 d 3 f 4 g 5 h 6 j 7 k 8 l 9 q 10 \ w 11 e 12 r 13 t 14 y 15 u 16 i 17 o 18 p 19 @ 20 history-menu () { zle -M "`history -n -$HISTORY_MENU_LENGTH | tac | \ ruby -e '%w[a s d f g h j k l q w e r t y u i o p @].zip(ARGF.readlines){|k,l| print %[#{k}: #{l}]}' `" zle -R read -k key if [ -n "${HISTORY_MENU_KEYS[$key]}" ]; then zle -U "`history -n -${HISTORY_MENU_KEYS[$key]} | head -1 | perl -pe 's/\\\\n/\\021\\n/g'``echo \"\021\"` " else zle -R -c fi } zle -N history-menu bindkey "^V" history-menu bindkey "^Q" quoted-insert