Macでfishを使って良い感じなシェル環境をお手軽に作る

はじめに
------

この間カンファレンスに行った時に発表者が使ってたシェルがカッコ良かったのでfishに変えてみ他のでその備忘録。
元々、zshを使ってたけどそこまでカスタマイズしてたわけではないので移行はすんなりでした。

fishに関して詳しくは[こちら](https://www.google.com/search?ei=jryyXJroKo_5-wTbpI2YBA&q=Fish+%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88+shell&oq=Fish+%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88+shell)に詳しく載ってるので割愛。
簡単に書くとカスタマイズしなくてもデフォルトで結構行けてるzshみたいなものです。

本体の導入
-------

まずは本体の導入。と言ってもbrewするだけです。

```bash
$ brew update && brew install fish
```

続いてデフォルトシェルを変更

```bash
$ echo /usr/local/bin/fish | sudo tee -a /etc/shells
$ chsh -s /usr/local/bin/fish
```

これでTerminalを再起動するればシェルがfishに変わります。

続いてパッケージマネージャをインストールします。なお、ここからはfish上での作業なのでbashやzshでは動かないので先に上記の作業で本体を入れてシェルを切り替えてください。

```bash
$ curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
```

これで最低限必要なもの導入は完了です。

プロンプトを変更する
--------

続いてプロプントを変更します。デフォルトでも良い感じの見た目のものはあったのですが、gitのstatusとかに対応したものがなかったのでfisherで新しいテーマを入れます。

```bash
$ fisher add oh-my-fish/theme-bobthefish
```

ただ、これ単体だと文字化けするのでPowerline系のフォントを追加してTearminalのフォントを変えます。

```bash
$ git clone https://github.com/powerline/fonts.git                                                
$ cd fonts/                                                                                       
$ ./install.sh 
```

これでPowerline系のフォントがインストールされました。私は`Robot Mono`にしています。

履歴検索を追加
-------------

fishは履歴からのコマンドが補完でき非常に重宝しますが一方でbashやzshで良く使う履歴検索自体はデフォルトで無いようです。
なので、pecoを入れてそちらでコマンド検索できるようにします。

```bash
$ brew install peco                                                                               
$ fisher add oh-my-fish/plugin-peco                                                               
$ vim ~/.config/fish/config.fish                                                                  
```

中身はこちら。

```~/.config/fish/config.fish
function fish_user_key_bindings
  bind \cr 'peco_select_history (commandline -b)'
end
```

これでシェルを再起動すれば`C-r`で履歴が検索できます。

ディレクトリの履歴移動
-------------

zshだとcdにpushがデフォルトで付くのでpopdを使ってディレクトリを移動してたかと思います。
fishにその補完は無いのですがより便利な拡張が入っています。popdに相当する機能はprevdとnextdです。

```bash
$ mkdir -p dir1/dir2　
$ cd dir1
$ cd dir2
$ pwd
/tmp/dir1/dir2
$ prevd　# 戻る
$ pwd
/tmp/dir1/
$ prevd　# 戻る
/tmp/
$ nextd　# 進む
/tmp/dir1
```

popdと同じことができますね。dirhで一気に移動するとこともできます。

```bash
$ dirh
 3) /tmp
 2) /tmp/dir1
 1) /tmp/dir1/dir2
    /tmp/dir1/dir2/dir3
$ prevd 3
$ pwd
/tmp
```

Bashとの互換
----

### 非互換一覧

fishはBashやzshのようにPOSIX互換ではありません。なので色々仕様が違うようなのですが例えば以下のような差分があるようです。

- 標準エラー出力のリダイレクトは`^`を使う
- 変数は`NAME=hoge`ではなく`set NAME hoge`を使う
- 終了ステータスは`$?`ではなく`$status`を使う
- コマンド置換は``command``や`$(command)`ではなく`(command)`を使う

### Bashラッパー

自分で書くときは覚えようの世界かもですが、チュートリアルとかで他人の手順を参考にする時に不便です。
なので、`bass`というプラグインを入れます。

```bash
$ fisher add edc/bass
```

これでbashでの操作ができるようになります。

```bash
$ echo $(date)
fish: $(...) is not supported. In fish, please use '(date)'.
echo $(date)
     ^
$ bass 'echo $(date)'
Sat Apr 13 22:45:05 PDT 2019
```

まとめ
------

とりあえずzshに疲れたら非互換がちょっと面倒ですがfishでやるのも良いかと思います。あまりカスタマイズせずにカッコいいのは良いこと。
それではHappy Hacking!

参考
------

- [Fish Official Site](https://fishshell.com/)
- [fish shell を使いたい人生だった](https://dev.classmethod.jp/etc/fish-shell-life/)
- [fish shellが結構良かった話](https://qiita.com/hennin/items/33758226a0de8c963ddf)