Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

たった2つのポイントで!zshでもfish並のインクリメンタル補完を実現する

fishのインクリメンタル補完(下のような補完)が神すぎてzshをやめてfishを使っていました。

f:id:panda_noir:20180223192120g:plain

しかし、fishを使っているうちに色々と不具合が出てきました。

  • シェルスクリプトがbashやzshと異なる
  • (2018/6/19追記) 設定ファイルの書き方がbashやzshと異なる
  • bashのようなエイリアス機能がない
  • PATHなどの設定がおかしくなるのでログインシェルはbashにしなければならない
  • ログインシェルがbashなので、source config.fishによる変更の反映ができない(かといってsource .bashrcもできない)
  • TAB補完が使いづらすぎる

まあまあ大きい不具合だらけです。それでもインクリメンタル補完が神がかっていたので仕方なくfishを使っていました。

が、zshの設定を見直したところ、fish並のインクリメンタル補完を実現できましたのでこの度zshへ戻ってきました。

見直した2点

ポイントは

  • zsh-autosuggestionsを入れること
  • predict-onを切ること

この二点でした。これを踏まえて最小構成を作ると以下のようになります。

bindkey -e

source ~/.zplug/init.zsh
zplug "zsh-users/zsh-autosuggestions"

if ! zplug check --verbose; then
    printf 'Install? [y/N]: '
    if read -q; then
        echo; zplug install
    fi
fi
zplug load

なぜpredict-onを切るのか

predict-onは「サジェストを入力されたものとして扱う」機能です。そのため、サジェストが表示されたらエンターを押すだけでそのコマンドを実行できます。

一見便利な機能のようですが、前方を修正すると、後方が消えるという致命的な動作をします。

例えばless article.mdと入力したあと、vim article.mdにしたくなったとします。ここで、lessを消してvimと入力していると、article.mdの部分が消されてしまいます。引数は同じままコマンドを変えたい場面は頻繁に起こるのでこれはストレスですよね。

そして、このpredict-onが無効になればzshの補完はとんでもなく快適になるのです。ぶっちゃけ邪魔以外の何者でもありません。

zsh-autosuggestions

zsh-autosuggestionsはサジェストをうっすらと表示してくれます。サジェストを確定させるには→キーを押すか、Ctrl + fをすればOKです。

ここまではほぼfishですが、fishには更に便利な機能として「1単語のみサジェストを受け入れる」という機能が有ります。

→キーはサジェストが全て確定してしまうのに対し、1単語のみサジェストなら引数ごとに受け入れる受け入れないが決められます。

zsh-autosuggestionsでも実は1単語のみ確定することが可能です。よく公式READMEを読んでいたら「forward-word を入力すると部分的にアクセプトできるよ」と書いてありました。

forward-wordというのがMeta + fというキーバインドを表すので、UbuuntuならAlt + fあるいはEsc後にfで部分的アクセプトが可能です。

つまり次のような対応関係ですね。

fishzsh
→(Ctrl + f)→(Ctrl + f)
Alt + →Alt + f

終わりに

インクリメンタル補完のおかげで「fish >>>>>>> zsh」と思っていましたが、zshがインクリメンタル補完を実現してしまった今、「zsh > fish」が証明されてしまいいましたね。みんなもzshに戻ろう!