ずっと他のシェルを使っていたのですが fish に切り替えました。せっかく設定を dotfiles として Git で管理していたのに、設定の依存関係を何も覚えておらず持ち運べない状態になっていたので、いっそのこと全部やめて新しくしようと思ったのが移行のきっかけです。
fishは Friendly interactive shell というシェルで、friendly さ(+親切さ)があるシェルです。何も設定を足していない標準の状態でも強力な設定がされているのが魅力の一つです。
他のシェルだとプラグインの設定や関数をたくさん書いて設定していたような補完機能が標準で手に入りました。たとえばコマンド入力中にこれまでの実行履歴やその階層のファイル一覧を見て、予測変換を出してくれます。
このとき ctrl + f を押すことでその補完で入力でき、入力時間を大幅に短縮できます。
もちろん既存のシェルにある tab で補完候補を出したり、切り替える機能もついています。これも fish では標準で tab 連打した時に候補にフォーカスを当てることができ、インタラクティブにファイルを選択することができます。
設定ファイルの分割は標準機能として実現できます。また、そして補完用の設定やコマンド用の設定の分割も標準で行え、関数をコマンドとして定義していけます。このように設定ファイルの置き場によっていろんな設定が自動でされるので、FW 的な印象も持ちました。少し使い方を覚えるだけでたくさんの設定ができ、またピンポイントで挙動を制御したいときは script を書いて制御でき、FW が持つ生産性とプリミティブな仕組みが持つコントール性のバランスがよかったです。
とくに functions は感動的で、fish は export や nvm が使えないみたいな問題も、function に export や nvm 関数を定義してコマンドとしてそれを使うみたいなことができたり(標準で設定済みだったり)して、よかったです。
Homebrew から手に入れることができます。
brewinstall fish
インストール後fish
と打てば fish が立ち上がります。
> fishWelcome to fish, the friendly interactive shellTypehelpfor instructions on how to use fishyou@hostname ~>
毎回打ち直すのはめんどくさいと思うので、ログインシェルを変更するとよいでしょう。fish はデフォルトシェルではないのでそもそもの設定対象のリストに追加する作業から発生するのでちょっとめんどうです。ここでは fish 自体の設定について解説したいのでシェルの変更方法については解説しませんが、こちらの記事を参照してください。
FYI:https://www.task-notes.com/entry/20150117/1421482066
fish の設定は ~/.config/fish/ 配下で行います。zsh や bash のように HOME 配下に rc ファイルがあるわけではないので注意しましょう。ファイルの拡張子は .fish で ~/.config/fish/config.fish に設定ファイルをかけば設定ができます。
FYI:https://fishshell.com/docs/current/tutorial.html#startup-where-s-bashrc
ただしこのファイル以外の場所に設定を書いても設定を読み込め、その方が設定ファイルの分割をする上で有利なので後に紹介します。
fish それ自体には plugin 機構はありませんが、functions やcompletions を使って plugin manager として使える外部ツールがあります。ここでは plugin manager として使えるfisher を使います。
plugin manager を名乗るツールは複数ありますが結局は fish の機能を呼び出しているだけのようでした。公式 Docや実行後の ~/.config/fish/ を読む限りは、functions や conf.d 配下に *.fish を置くことで設定を足しているようです。なので、仮に plugin manager を移行するとなってもそこまで影響なさそうだったので、特に理由やこだわりがあるわけでは無く比較的後発で人気がありそうな fisher を選択しました。
fish ではいわゆる profile や rc がついたファイル名で設定のエントリポイントは読み取りません。エントリポイントとしては~/.config/fish/config.fishになるとは思いますが、これを使わなくても後述するファイル分割に使うフォルダを使えばエントリポイントを作らなくても動かせます。
functions, fisherfile, conf.d といった設定用のファイル・フォルダはこの直下に置かれます。
設定には alias に関するもの、環境変数に関するもの、util 関数に関するものといろいろ増えたり管理したくなるものです。そこで設定ファイルを分割したくなるわけですが、fish ではこれが簡単にできます。fish では~/.config/fish/conf.d/*.fish は全部設定ファイルとして読み込まれます(ただし ver2.3.0 以降)。そのため conf.d 配下に設定を分割していれておけば設定は簡単に分割できます。
FYI:https://fishshell.com/docs/current/index.html#initialization-files
FYI:https://stackoverflow.com/questions/48749443/fish-shell-import-config-into-main-config
zsh/bash などでは
#!/bin/bash -eubash_conf=~/.config/bash. $bash_conf/base.bash. $bash_conf/alias.bash. $bash_conf/jump.bash. $bash_conf/env.bash
や
function loadlib(){ lib=${1:?"You have to specify a library file"} if [ -f "$lib" ];then #ファイルの存在を確認 . "$lib" fi}loadlib ~/.zsh/load_preztoloadlib ~/.zsh/zsh_alias
などの工夫で設定を分割したりしていたものですが、それをやらなくていいのは嬉しかったです。
調べているとfisher add
で設定を追加する記事をよく見ましたが、私はそれを使わずにfishfile
に書いて管理しています。PC の移行を考え、どんなプラグインを使っているかを dotfiles と Git で管理したいからです。
ただ dotfiles として管理しないのであれば、fisher add
で直接プラグインを入れてもいいとは思います。仮に fishfile を使ってなくても、パッケージ管理用のコマンドで自分がどんなファイルを持っているか調べられるので、忘れてもリカバリは容易です。
# package一覧を取得fisherls# packageを削除fisherrm XXX
こういった今風(っていいのか知らないけど)なパッケージマネージメントができるのは本当に嬉しいです。
とまあ fish はとても良いのですが、もちろんデメリットもあります。実際のところ以前 fish に移行しようとしたときはこれらのデメリットを考えて採用しなかったことがありました。
bash/zsh などで nvm を使っていると、
exportNVM_DIR="$HOME/.nvm"[-s"$NVM_DIR/nvm.sh"]&&\."$NVM_DIR/nvm.sh"[-s"$NVM_DIR/bash_completion"]&&\."$NVM_DIR/bash_completion"
のような設定を読み込む必要がありますが、この $HOME/.nvm/nvm.sh は fish では動きません。そのため fish では nvm を使うことができず、fish-nvm のような別のツールを使うか、bass のようなツールで bash の設定を fish に読み込んで nvm コマンドを実行する必要があります。
FYI:https://medium.com/@joshuacrass/nvm-on-mac-for-fish-users-e00af124c540
不用意に依存や設定を複雑にしたくなかったので私はそもそも nvm をやめて、voltaというツールに移行しました。
alias, env, keybind として設定を分けています。
# vim -> nvimalias vim='nvim'# GitHubを表示alias hb="hub browse"###### Git系###alias g='git'alias gb='git branch'alias gbc='git checkout -b'alias gc='git commit --verbose'alias gco='git checkout'alias gia='git add'alias gm='git merge'alias gp='git push'alias gfm='git pull'
Git のエイリアスは昔から使っていた prezto の Git モジュールのもののうち、よく使っていたものです。
fishfile には
rafaelrinaldi/pureoh-my-fish/plugin-peco
をセットしています。
普段は VSCode での作業なのでシェルにそこまでの機能は求めておらず、これだけで間に合っています。
plugin-peco は peco を使ってコマンド履歴を interactive に filter をかけて辿れるツールです。
peco は シングルバイナリな interactive filtering tool です。plugin-peco はこの peco を使ってコマンド履歴をフィルタリングする関数を提供します。そのためpeco は別途自分でインストールしておく必要があります。
brewinstall peco
fish では key bind は fish_user_key_bindings 関数に書いていきます。plugin-peco によって peco_select_history が使えるようになっているので、この関数を呼び出すキーバインドを設定します。私は ctrl + r で履歴を絞り込めるようにここに peco_select_history を書いておきます。(bash/zsh だと このバインドで履歴を検索できたはずなので。)
function fish_user_key_bindingsbind\cr'peco_select_history (commandline -b)'end
Available themesから好きなテーマを選んで fisher で入れることができます。
というのが好みなので、それで探していました。
その結果いつも通りpure を使うことにしました。自分が尊敬している人が使っているものなので個人的な思い入れがあったりもします。
dotfiles そのものは訳があって公開できないのですが、fish 周りだけ切り出してレポジトリを作ったので興味ある方はご覧ください。