fishのインクリメンタル補完(下のような補完)が神すぎてzshをやめてfishを使っていました。
しかし、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
で部分的アクセプトが可能です。
つまり次のような対応関係ですね。
fish | zsh |
→(Ctrl + f) | →(Ctrl + f) |
Alt + → | Alt + f |
終わりに
インクリメンタル補完のおかげで「fish >>>>>>> zsh」と思っていましたが、zshがインクリメンタル補完を実現してしまった今、「zsh > fish」が証明されてしまいいましたね。みんなもzshに戻ろう!