auto-fu.zshでコマンドを確定するときに不完全な補完サフィックスを無視する

auto-fu.zshのちょっとした改善.

動機

auto-fu.zshを使っていると, TABを押さなくても自明な補完候補はカーソルの後ろに表示される. たとえば, directory-with-very-long-nameというディレクトリの中身を見たいときに

$ ls -l dir 

まで打てば(他にdirではじまるディレクトリが無ければ),

$ ls -l directory-with-very-long-name/

という感じに補完されて, このままEnterを押せば目的のディレクトリがlsされる. これはとてもべんり.

ただ, 個人的にはEnterを押さずにTABを押してしまうことがよくある. たとえば, directory-with-very-long-nameの中に01, 02というファイルがあり, 他には何もなかったとすると, TABを押したときには次のようになる.

$ ls -l directory-with-very-long-name/0
files
01  02

directory-with-very-long-nameの中には2つのファイルしかなく, どちらも0ではじまるので, directory-with-very-long-name/0まで補完してくれる. これもこれでべんりではあるけれど, いまはdirectory-with-very-long-nameに対してlsしたかっただけなので, 0は余計. 以前書いたauto-fu.zshを使う+キャンセルできるようにするを使えば, この状態から補完をキャンセルしたり, 補完された部分を除いて確定することはできる. しかし困ったことに, うっかりこのままEnterを押してしまうことがよくある. すると

ls: cannot access directory-with-very-long-name/0: No such file or directory

と言って怒られる. directory-with-very-long-name/0までではまだ完全には補完されていない(補完候補の選択が確定していない)のだから, 不完全な0の部分は無視してほしい. そしてもちろん, 最初の例のように, 補完候補が1つしかない場合は候補の選択は既に終わっていると見なして, 従来通り動作してほしい.

そもそも最初にTABを押してしまうのが悪いけれど, しばらく使っていれば慣れるかと思ったものの何度もやってしまうので, いい加減なんとかすることにした.

ソースコード

auto-fu.zshを読み込んだ後で以下を実行するようにすれば動的にパッチが当たる.

# delete unambiguous prefix when accepting line
function afu+delete-unambiguous-prefix () {
    afu-clearing-maybe
    local buf; buf="$BUFFER"
    local bufc; bufc="$buffer_cur"
    [[ -z "$cursor_new" ]] && cursor_new=-1
    [[ "$buf[$cursor_new]" == ' ' ]] && return
    [[ "$buf[$cursor_new]" == '/' ]] && return
    ((afu_in_p == 1)) && [[ "$buf" != "$bufc" ]] && {
        # there are more than one completion candidates
        zle afu+complete-word
        [[ "$buf" == "$BUFFER" ]] && {
            # the completion suffix was an unambiguous prefix
            afu_in_p=0; buf="$bufc"
        }
        BUFFER="$buf"
        buffer_cur="$bufc"
    }
}
zle -N afu+delete-unambiguous-prefix
function afu-ad-delete-unambiguous-prefix () {
    local afufun="$1"
    local code; code=$functions[$afufun]
    eval "function $afufun () { zle afu+delete-unambiguous-prefix; $code }"
}
afu-ad-delete-unambiguous-prefix afu+accept-line
afu-ad-delete-unambiguous-prefix afu+accept-line-and-down-history
afu-ad-delete-unambiguous-prefix afu+accept-and-hold

補完の設定とauto-fu.zshまわりの設定も含む使用例:


追記

2010-08-24T05:35:56+0000
なんか余計なことしてたので修正