kbigwheelのプログラミング・ソフトウェア技術系ブログ

プログラミング・ソフトウェア技術系のことを書きます

なぜ今10年使ったzshをやめてfish shell / nushell / xonsh / elvishへ移行しようとしているか

zshをかれこれ10年ぐらい使っている。

最初のきっかけは忘れたけども、本格的に使うようになったのは2007年ぐらいに書かれた「漢のzsh」という伝説的な紹介記事によるもので僕の .zshrc には未だに 漢のzsh 4thから引用 みたいな設定がたくさんある。

【連載】漢のzsh | TECH+

そんなzsh、僕は会社でmac自宅でlinuxを使うようになってもhomeshickというツールを使って設定を同期していたのだけど近頃調子が悪い。自宅のlinuxの方は問題ないのだけど会社のmacでshellの立ち上げに5秒ぐらいかかるようになってしまった。 tmuxを使っているのでshellを立ち上げ中に元のペインへ戻って作業をしているのだけど考えてみると結構作業効率を落としている。なにか目的があって別のシェルを立ち上げているので、一時的にでも別のことをせざるを得ないということは思考が中断されている。人間の脳のコンテキストスイッチはかなり効率が悪いのでこれは良くない。

調べてみたらzsh+anyenvが不味そうなことがわかったのでそこを直そうかとも思ったんだけど、そもそもその問題を解決しても起動に1.5秒ぐらいかかる。 なんでこんな時間がかかるんだとzshプラグインマネージャーを比較し始めたあたりでもう嫌になってきた。

そうだ、fishをためそう。

fish shell

fish shellは新時代のshellとして数年前から話題になっていた。 ただ、移行に踏み切らなかった理由はいくつかあって、一つにposix標準じゃないこと、もう一つはportabilityの観点だった。

fish shellの懸念

posix標準のshellというのはだいたいsh互換のシェルという意味で、ifやwhileなどの構文がshと同じようにかけるshellだ。 fish shellはこのif for whileのような構文がshと違うことがネックだった。というのは僕のようなインフラ寄りのエンジニアにとってシェルスクリプトは日常書くので2種類の構文を使うと混同して混乱してしまう恐れがある。

もう一つのportabilityというのはログイン先のサーバなどでfishが使えないことで、数年前はまだfish shellは新しめのshellという印象だったのでログインした先のredhatcentosで使えるかが不安だった。当時は日常的に数十台のサーバへログインして作業しており、サーバによってはその中でツールをインストールして実行していたので手元のPCと出先のサーバでshellが違うことはこれまた認知負荷を余計に高める要因だった。

しかし、状況が変化した。

サーバレスの時代

オンプレからAWS初期の時代はインスタンスに直接sshしての作業は日常茶飯事だったが、Lambda, ECS, EKSへ移行していくに連れcompute nodeへログインすることはおろか踏み台サーバを使用することすらまれになってきた。 そして今の会社ではついに全面EKS / lambda移行を行い、踏み台サーバすらない状態になっている。 こうなると懸念だったポータビリティの観点はほとんどどうでもよくなる。 また、posix標準についても5年前は不慣れだったposix標準構文に十分慣れたことで混同する恐れがほとんどなくなったために問題はクリアされた。

zshからの移行先

こうして、fish shellを避ける理由がなくなったのでzshrcからfishへの設定移行をしているのだが、bigwheel/fish-castleかなり移行を進めた段階でこれはこれで気になる点がいくつか出てきた。一つは設定のポータビリティで、サーバーへはログインしなくなったものの会社と自宅PCで同じ設定は使いたいのだがfish shellはuniversal variablesという変数周りのポータビリティがそもそも設計思想になく各PCでuniversal variablesは固有の思想になっているため同期に難がある。

またC++で書いているのも気になって、令和ならgolangかrust使っているほうが将来性があるのではという気になってきた。 そこで上がった選択肢が以下

  • xonsh
  • nushell
  • elvish

特にnushellはすでに一定の信頼を得ている気がするので、これが良さそうであればfish shellを飛び越してこれにするのもありだと思っている。

追記

fish, nushell, elvishと試した結果、結局fishを使うことにした。 nushellはHistory (ctrl + r) with fzf · Issue #1616 · nushell/nushellにある通りhistoryに対して高度な検索を行えないのが痛い。 elvishは最初ctrl-aのようなショートカットキーが使えなくて、しばらく調べてreadline-binding: Readline-like Key Bindings - Elvish Shellで有効化できることはわかったのだけど、fishの哲学のout of the boxで使用できるというものが以下に価値があるかわかった & elvishは全編こんな感じで対処しないといけない匂いを感じたので結局fishに戻ってきた。