履歴を絞りこみながら正規表現で検索する。

※10/29追記
deruiの日記が最新です。この内容は古いです。

どうも、最近やたらと忙しいせいでやる気が妙に無いderuiです。

さて、今回はこれも結構以前の記事ですが、こちら↓の記事を見て、isearch風に絞りこみながら検索したいなぁ、と思い、さっぱりやったこともないzshスクリプトをやってみることにしました。
http://d.hatena.ne.jp/rubikitch/20070927/119086674

で、なんとか苦心してできたのが以下。↑の記事をかなり参考にさせてもらっています。ありがとうございます。

typeset -A HISTORY_INCREMENTAL_KEYS
set -A HISTORY_INCREMENTAL_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

incremental-search-history-regexp() {
    local query=$1
    local key=$2
    if [ -n "${HISTORY_INCREMENTAL_KEYS[$key]}" ]; then
        zle -A .self-insert self-insert        
        BUFFER="`head -${HISTORY_INCREMENTAL_KEYS[$key]} $HISTORY_GREP_TEMPFILE | tail -1 | perl -pe 's/\\\\n/\\021\\n/g'`"
        zle -R
        zle accept-line
    else
        history -n 1 | egrep "$query" | tail -100 | uniq | tail -$HISTORY_MENU_LENGTH | tac > $HISTORY_GREP_TEMPFILE
        zle -M  "`ruby -e '%w[A S D F G H J K L Q W E R T Y U I O P ].zip(open(ARGV[0]).readlines){|k,l| print %[#{k}: #{l}]}' $HISTORY_GREP_TEMPFILE`"
        zle -R
    fi
}

ishr-self-insert() {
    LBUFFER+=${KEYS[-1]}
    incremental-search-history-regexp $BUFFER ${KEYS[-1]}
}

ishr-backward-delete-char() {
    zle -A .backward-delete-char backward-delete-char
    zle backward-delete-char
    zle -N backward-delete-char ishr-backward-delete-char
    incremental-search-history-regexp $BUFFER
}

incremental-search-history-menu() {

    local loop=1
    local query=""

    integer stat

    zle -N self-insert ishr-self-insert
    zle -N backward-delete-char ishr-backward-delete-char
    zle recursive-edit
    stat=$?
    zle -A .self-insert self-insert
    zle -A .backward-delete-char backward-delete-char

    zle -R -c
    (( stat )) && zle send-break

    return $?
}

zle -N incremental-search-history-menu
bindkey "^[@" incremental-search-history-menu


M-@に割り当てているのは、なんとなく空いているキーだったからです。特に深い意味はありません。

で、入力していくと、↑の記事でも出力されるような形式で出力されていきます。そして、任意の位置でA〜Pを押すと(わざと大文字のみにしています)、その位置の履歴が入力される、という寸法です。

自分の環境ではなんとか上手くいっていますが、もし試してみて上手くいかなかったりしたらごめんなさい。
それと、C-hとかBackspaceとかで文字を削除する場合には上手くいきますが、killとかしたりすると途端に上手くいかなくなります。この辺は直したいなぁとは思っています。

基本的なアイデアを与えてくださったid:rubikitch さん、有用な記事をありがとうございます!