auto-fu.zshを使う+キャンセルできるようにする

はてなブログを使ってみた. これはすごい!

まず, デモで補完候補がグループ別にメニュー表示されているのがカッコよかったので真似してみた.

setopt   auto_list auto_param_slash list_packed rec_exact
unsetopt list_beep
zstyle ':completion:*' menu select
zstyle ':completion:*' format '%F{white}%d%f'
zstyle ':completion:*' group-name ''
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
zstyle ':completion:*' keep-prefix
zstyle ':completion:*' completer _oldlist _complete _match _ignored \
    _approximate _list _history
autoload -U compinit
compinit

auto-fu.zsh自体は, うちの環境では基本的には解説されている通りに設定したら動いた.

source ~/.zsh/auto-fu.zsh
function zle-line-init () {
    auto-fu-init
}
zle -N zle-line-init

ただ「-azfu-」と表示されるのは要らないなぁと思ったので表示されないようにしたのと, アクティブな補完候補がグレーで表示されているときに, カーソル直下の文字がなぜか真っ黒になって読めなかったので, 色設定を調整した. fg=whiteにしてなぜグレーになるのかは謎. fg=white,boldだときちんと白くなる. うちの環境が変なのか.

function () {
    local code
    code=${functions[auto-fu-init]/'\n-azfu-'/''}
    eval "function auto-fu-init () { $code }"
    code=${functions[auto-fu]/fg=black,bold/fg=white}
    eval "function auto-fu () { $code }"
}

かなり無理矢理. auto-fu.zshのTODOにzstyleableと書いてあるので, そのうちもっと正しく変更できるようになると期待.

ただでさえすごいzshが最強になった. TAB押さなくてもアクティブな補完候補が選択されるのは慣れればかなり快適. でもたまに補完をキャンセルしたくてC-g押してみたりESC押してみたりしてしまってスペース押せばいいことに気づかなくて困るので, C-gやESCでアクティブな補完候補をキャンセルするようにしてみた.

function afu+cancel () {
    afu-clearing-maybe
    ((afu_in_p == 1)) && { afu_in_p=0; BUFFER="$buffer_cur" }
}
function bindkey-advice-before () {
    local key="$1"
    local advice="$2"
    local widget="$3"
    [[ -z "$widget" ]] && {
        local -a bind
        bind=(`bindkey -M main "$key"`)
        widget=$bind[2]
    }
    local fun="$advice"
    if [[ "$widget" != "undefined-key" ]]; then
        local code=${"$(<=(cat <<"EOT"
            function $advice-$widget () {
                zle $advice
                zle $widget
            }
            fun="$advice-$widget"
EOT
        ))"}
        eval "${${${code//\$widget/$widget}//\$key/$key}//\$advice/$advice}"
    fi
    zle -N "$fun"
    bindkey -M afu "$key" "$fun"
}
bindkey-advice-before "^G" afu+cancel
bindkey-advice-before "^[" afu+cancel
bindkey-advice-before "^J" afu+cancel afu+accept-line

これらの設定を含むzshの設定は下記参照.

追記

C-jを「キャンセルしつつ実行」に割り当て

追記

はてなブログで更新されたバージョンではzstyleでオプションを指定できるようになったので, それに合わせて設定も変更. さらにはてなブログのzcompileして使うやり方も適用.

# precompiled source
function () { # precompile
    local A
    A=~/.zsh/modules/auto-fu/auto-fu.zsh
    [[ -e "${A:r}.zwc" ]] && [[ "$A" -ot "${A:r}.zwc" ]] ||
    zsh -c "source $A; auto-fu-zcompile $A ${A:h}" >/dev/null 2>&1
}
source ~/.zsh/modules/auto-fu/auto-fu; auto-fu-install

# initialization and options
function zle-line-init () { auto-fu-init }
zle -N zle-line-init
zstyle ':auto-fu:highlight' input bold
zstyle ':auto-fu:highlight' completion fg=white
zstyle ':auto-fu:var' postdisplay ''

# afu+cancel
function afu+cancel () {
    afu-clearing-maybe
    ((afu_in_p == 1)) && { afu_in_p=0; BUFFER="$buffer_cur"; }
}
function bindkey-advice-before () {
    local key="$1"
    local advice="$2"
    local widget="$3"
    [[ -z "$widget" ]] && {
        local -a bind
        bind=(`bindkey -M main "$key"`)
        widget=$bind[2]
    }
    local fun="$advice"
    if [[ "$widget" != "undefined-key" ]]; then
        local code=${"$(<=(cat <<"EOT"
            function $advice-$widget () {
                zle $advice
                zle $widget
            }
            fun="$advice-$widget"
EOT
        ))"}
        eval "${${${code//\$widget/$widget}//\$key/$key}//\$advice/$advice}"
    fi
    zle -N "$fun"
    bindkey -M afu "$key" "$fun"
}
bindkey-advice-before "^G" afu+cancel
bindkey-advice-before "^[" afu+cancel
bindkey-advice-before "^J" afu+cancel afu+accept-line