これからfishというシェルについてお話します。

あなたがfishを使うべき理由は以下になります。

  1. ユーザーインターフェース、マニュアル、スクリプトに至るまで使い易さを第一に開発されている開発陣の真心!
  2. 補完が超強力
  3. 独自機能であるsuggestion(予測入力)がゲロ強!
  4. 無設定で強力機能の恩恵に与れる
  5. 覚えることが少ない
  6. マニュアルが具体的で超絶わかりやすい
  7. fishシェルスクリプトは読み書きしやすい
  8. 仕様が必要十分
  9. Emacsからデータを渡して起動できる
  10. 終了時にEmacsでログを参照できる(tmux使用)
  11. 設定ファイルをいじらなくても関数や変数の設定を永続化できる
  12. カラフル
  13. Webインターフェースで設定できる…なんという大胆さ
  14. 新しいシェルだが10年の歴史があり実績もある
  15. fish-mode(レビュー) でEmacsでも快適にfishスクリプトが書ける
  16. 補完時に説明が出てくる
  17. fish自体でPCRE含む強力な文字列操作ができる

それでは僕がfishとの出会って一目惚れしたストーリーをお楽しみください。

21世紀のシェル

あなたは、シェルといったら何を思い浮かべますか?
^bash? sh? csh? tcsh? zsh? eshell? pry? irbsh?(笑)
いろいろありますね。
僕はひょうんなことから1週間前にfishというシェルに出会いました。
User-Friendly Interactive Shellの略で、使い易さを全面に押し出している最後発シェルです。
最強のシェルとして名高いzshも1990年生まれと、もうかなり古いです。
それに対しfishは2005年生まれと、まさに21世紀型のシェルです。
新しいもの好きで好奇心がある僕は、あっさりとfishにのめりこみました。

zshは古いし難しい

僕は15年もの間zshを使ってきました。
コマンドラインスタックとか、補完が強力で使いやすいと当時思いました。
当時は機能が多ければ多いほどいいと信仰していたので、
とても高機能なところにも惚れていました。
しかし、高機能とは裏をかえせば学習コストが高く、
覚えるのに時間がかかることが問題です。
しかも使用頻度の低い機能というのはすぐに忘れてしまいます。
これではらちがあかんと思いました。

僕はシェルスクリプトが苦手で、ちょっと複雑な処理をしたければbetter shell scriptとしてRubyを使っています。
とくにクオートがからんでくると頭が混乱してしまいます。
構文もとっつきにくく、なかなか覚えられませんでした。

eshellとの出会い

そのまま何年もたち、Emacsひきこもり生活が当たり前になりました。
そんな中で見付けたシェルとしてeshellがあります。
すべてEmacs Lispで書かれたシェルです。
Emacs Lispで書かれているということは、eshellのすべてを自分好みにいじれるということです。
しかもWindows含めすべてのOSで動きます。
Emacs Lispにはそれなりに自信のある僕は、すっかり使い熟すようになりました。
Emacs Lisp力に比例して強くなるeshellは、僕向けのシェルです。

使い始めてすぐにeshellを強化し始めました。
まずはzshのように無限のヒストリを持つようにしました

これで大昔に実行したコマンドラインをanythingやhelmでいつでも呼び出せるようになりました。
履歴の絞り込み検索は他のシェルにはないので俺仕様eshellの主力武器です。
zshの履歴もeshellの履歴に突っ込んだのでコマンドラインヒストリは資産そのものです。
これはとても使いやすいです。
また、Emacsのシェルらしく、Emacs Lisp式を評価できる点も好感をもてます。
M-:やielmの代わりとしても重宝しています。

また、パーサを乗っ取れるのでプレフィクスによってRubyやzshを呼び出すこともできるようにしました。
たとえば、「rb」を前置して「rb 3+4」と実行すると「ruby -e 'p 3+4'」に展開されます。
eshellそのものは入力リダイレクトやバイナリデータに対応できないなど機能が貧弱です。
それを外部プログラム呼び出しによってカバーできる俺仕様eshellはかなりいいものです。

eshellの限界

しかし、それでも弱点は残っています。
大量の出力があるとフリーズしたかのように遅くなったり、補完がとても弱いことです。
eshellの補完はpcompleteが担っていますが、対応コマンドは少なく、今更補充したところで焼け石に水です。
そこでeshellにも限界が見えてきました。

理想のシェルを探して

そこで、理想のシェルを探そうと旅に出ました。
出会ったのがfishでした。
何も設定しなくても便利な機能が最初から有効になっていることにものすごい好感を持てました。
zshは確かに超高機能ですが、多くの機能が無効になっているため、高機能を活かすにはわざわざ設定で有効にする必要があります。
これでは設定を知らないとzshを活かせないということです。
fishは最初からフルパワーであるように設定されています。
例えてれみれば最初からRPGで最強の武器を持ちながら旅に出るようなものです。
普通の装備だと苦戦するような敵をあっさり仕留めまくるのは想像に難くありません。
「強くてニューゲーム」ともいえます。

使いやすいfish

fishはとにかく使い易さを最重視して設計しています。
その姿勢は一貫しています。
補完は超強力で、しかもsuggestionといって入力を予測してくれる機能がめちゃくちゃ便利です。
それなしでは生きていけないほどです。

マニュアルも平易な英語で書かれていて、しかも具体例がたくさん載っています。
多くのツールのマニュアルはただ抽象的事実しか書いてなくて、それを使うったらどうなるうのかが書いていません。
そのため使い方がわからず、イメージつかめません。
人は具体例があるおかげですんなり理解できるようになります。

シェルスクリプトも他のシェルとは一線を画していて、まったく違う構文です。
スクリプトはLua似のクリーンでコンパクトな仕様です。
シェルスクリプトでありながらシェルスクリプトではない、それがfishシェルスクリプトです。

fishにおいてはめったに使われない複雑な機能は存在せず、それを実現するためには外部プログラムにお任せするという潔いスタンスです。
必要十分な仕様なので覚えるのは難しくありません。
僕はたった2日で英語マニュアルを読破し、全容を把握できました。
他のシェルだと何ヶ月かかるかわかったものではありません。
この学習コストの低さはありがたい限りです。

シェル革命!

僕はあっさりzshを捨て、ログインシェルをfishに乗り換えました。

僕はfishと出会ったことでシェルそのものの見方が変わりました。
僕はEmacs引きこもり族なので、シェルもEmacsと連携できないと気がすみません。
Emacsの機能を使ってシェルコマンドを入力し、出力をすぐにEmacsの編集機能で取り込めないといけません。
それができないととても苦痛です。
それができるからこそ、補完が貧弱で重くなるeshellを我慢してまで使っていました。

ところが、eshellを長く使ってくるにつれて、出力がいつまでも残っていること自体に大したメリットを感じなくなってしまいました。
eshellバッファが増えまくると、逆に煩わしさすら感じました。

そこで新しいfishをどう僕に適応させるか…すこし考えました…結論はあっさりと出ました。
fishを立ち上げるときは常に新しい端末で立ち上げます。
そして、Emacsからbuffer-file-nameや最近扱ったバッファのファイル名などの情報をfishに渡し、default-directoryにcdした状態で起動すれば十分だと気付きました。
ログがEmacsで参照できないという問題については、tmuxのcaputure機能を使ってログをファイルに保存して、後でEmacsで見られるようにすればいいことがわかりました。
fishに入るときと出るときにEmacsとのやりとりができれば十分だったのです。

これがわかればeshellに固執する必要がなくなりました。
メインシェルの座をあっさりfishに明け渡し、長年メインシェルに降臨していたeshellはあっさりサブシェルに成り下がりました。
eshellはeshellでEmacs Lispを実行できたり、過去に実行したコマンドを再実行するくらいはできます。
複数のキルリングの内容を使ってコマンドを実行するのもeshellが有利です。
今や専らそれらの目的でしかeshellは使っていません。
今の僕のEmacsにおいて、M-!はfishの端末を立ち上げるコマンドに置き換わっています(笑)

というわけで今はfishとeshellの二刀流です。

fishの良さは多くの人に分かち合いたいので、そのうちfishのサイトを立ち上げることも考えています。

長文をお読みいただき、ありがとうございます。

本日もお読みいただき、ありがとうございました。参考になれば嬉しいです。