一 月
9
月曜日

fish shellを使う

なんとなく新しいshellに手を出してみたくなった。fishを触ってみたところ良さそうだったので移住のためのメモを作成。


fishの特徴

fish (Friendly Interactive SHell)は分かり易さ・ユーザフレンドリーに重きを置いた敷居の低さと実用性の両方を兼ね備えたシェル。 以下のような特徴がある。

オートサジェスチョン
履歴と補完機能によるオートサジェスチョン。 入力中の文字列に対してパス、コマンドオプション、履歴を元にサジェストされる。
24bitカラーのサポート
True color(1677万色)をサポート。
シンプルでクリーンなスクリプト構文
モダンなスクリプト構文。
manページを元にしたコマンド補完
manページから補完設定を自動生成するため個別の補完設定なしで補完が有効になる。
充実したドキュメント
分かり易いドキュメントが充実している。シェル上から help と打てばブラウザが開きHTMLベースのドキュメントが閲覧できる。

インストール

Homebrewでインストール

$ brew install fish
$ fish -v
fish, version 2.4.0

コンフィグレーション

fishは起動時に以下の優先順位でコンフィグレーションを読み込む。

  1. 基底コンフィグレーション
  2. システム共通コンフィグレーション
  3. 各種コンフィグレーションスニペット
  4. ユーザ固有コンフィグレーション

基底コンフィグレーション

基底コンフィグレーションはfishに同梱されている編集不要の基礎となるコンフィグレーション。
パスは$__fish_datadir/config.fishとなっており変数$__fish_datadirの値は、

echo $__fish_datadir

で確認できる。

一般的には/usr/share/fish/config.fish
homebrewの場合は/usr/local/Cellar/fish/2.4.0/share/fish/config.fishとなる。

システム共通コンフィグレーション

システム共通コンフィグレーションはOS内で共通的に利用されるfishコンフィグレーション。 パスは$__fish_sysconfdir/config.fishとなっており変数$__fish_sysconfdirの値は

echo $__fish_sysconfdir

で確認できる。

一般的には/etc/fish/config.fish
homebrewの場合は/usr/local/Cellar/fish/2.4.0/etc/fish/config.fishとなる。

各種コンフィグレーションスニペット

コンフィグレーションスニペットはファイル拡張子.fishを持つファイルで以下のディレクトリに配置することができる。

  • ユーザ固有コンフィグレーションスニペット ($XDG_CONFIG_HOME/fish/conf.d)
  • システム共通コンフィグレーションスニペット ($__fish_sysconfdir/conf.d)
  • 基底コンフィグレーションスニペット ($__fish_datadir/conf.d)

ユーザ固有コンフィグレーション

ユーザ固有コンフィグレーションはユーザ毎のコンフィグレーションでXDG Base Directory Specificationに則りパスは$XDG_CONFIG_HOME/fish/config.fishとなる。

環境変数XDG_CONFIG_HOMEを定義していない場合デフォルトとして~/.configが適用されるためコンフィグレーションパスは~/.config/fish/config.fishとなる。

基本的な使い方

viモードを有効にする

コマンドラインエディタをviモードにすることができる。 シェル上からfish_vi_key_bindings関数を実行するとviモードになる。元に戻したい場合はfish_default_key_bindings関数を実行すれば良い。

ただしfishの標準はemacsモードであるためviモードにすると公式チュートリアルにあるいくつかのキーバインドが効かない状態になる。 本来はデフォルトのemacsキーバインディングを一旦忘れvi的にはどのキーに割り当てるのが自然か考えてみるのが良い気がするが ここでは一旦viモードにデフォルトのキーバインディング取り込んで動作させる。

$XDG_CONFIG_HOME/fish/functions/fish_user_key_bindings.fish を編集しデフォルトのキーバインディングをviの全モードで利用できるようにする。

function fish_user_key_bindings
  for mode in insert default visual
    fish_default_key_bindings -M $mode
  end
  fish_vi_key_bindings --no-erase
end

またこれはviモードとは直接関係無いが公式チュートリアルではMETAキーに ALT を利用している。 iTerm2を利用している場合は ALT をMETAキーとして利用できるようにしておく必要がある。

iTerm2のメニューから Profiels Open Profiles.. Edit Profiles.. Keys Left option key acts as:+Escに設定する。

オートサジェスチョン

オートサジェスチョンは入力中のコマンド、パスに対するサジェスチョンをグレーで表示する。

例えばlsと入力すると以下ように履歴から対象とするサジェストしてくれる。 グレーの部分は未確定の部分であるためこのままリターンキーを押した場合コマンドとして解釈されるのは白字の部分のみとなる。

>ls /var/log

サジェスチョンが表示されている状態で、 、または CTRL f キーを押すとサジェスチョンを受け入れグレーから白字に色が変わる。

>ls /var/log
# [→] または [CTRL] [f]キーを押す
>ls /var/log

同様にサジェスチョンが表示されている状態で、ALT 、または ALT f キーを押すと単語単位にサジェスチョンを受け入れ、受け入れた部分がグレーから白字に色が変わる。

>ls /var/log
# [ALT] [→] または [ALT] [f]キーを押す
>ls /var/log

シンタックスハイライト

入力中のコマンドが存在しない場合は特有の色(例では赤字)で表示される。

>/bin/mkdir

存在する場合は別の色で表示される。(例では白字)

>/bin/mkdir

存在するパスの場合はアンダーラインが引かれる。

# 存在しない場合
>ls /Hoge
# 存在する場合
>ls /Documents

タブ補完

入力中にタブを押すことで補完処理が実施される。
補完対象となるコンテクストには以下がある。

  • コマンド(ビルトイン、関数、一般的な外部コマンド)
  • シェル変数名
  • ファイル名(ワイルドカード付きでもOK)
  • ジョブID、ジョブ名、プロセス名

また上記以外にもコンテクストに応じた高度な補完が行われるケースもある。例えばsshは接続先の補完にknown_hostsに登録されたホスト名が利用される。

候補が複数ある場合は候補リストが表示される。
候補リスト表示中に TAB CTRL fCTRL bCTRL nCTRL p で候補を選択できる。 また選択中に文字列を入力するとマッチする候補リストが絞り込まれる。

組み込みコマンド complete を利用することで独自の補完処理を作成することができる。 $__fish_datadir/completionsには多くの独自補完処理のためのスクリプトがあるためこれを参考にすると良い。

シェル変数と環境変数

シェル変数、環境変数ともに set コマンドで定義、削除を行う。

# シェル変数を定義
> set hoge ほげ
> echo $hoge
ほげ

環境変数は-xオプションを付与することで定義できる。

# 環境変数を定義
set -x FUGA ふが
> echo $FUGA
ふが

定義済みのシェル変数、環境変数は-eオプションを付与することで削除できる。

# 定義した変数を削除
> set -e hoge FUGA

fishにおける全ての引数はリストで表現される。
setコマンドにおいても PATH のような複数の要素を扱う変数はセパレータ付きの文字列で表現するのではなくリストで扱う。

# リストを作成
> set HOGE hoge1 hoge2 hoge3
> echo $HOGE
hoge1 hoge2 hoge3
# リストに追加
set HOGE $HOGE hoge4 hoge5
> echo $HOGE
hoge1 hoge2 hoge3 hoge4 hoge5

ユニバーサル変数

ユニバーサル変数は特殊変数で以下の二つの特徴がある。

共有
ユニバーサル変数は異なるfishプロセス間で透過的に共有される。宣言と同時に即時に他のfishプロセスから参照できる。
永続
ユニバーサル変数は宣言すると明示的に削除しない限り永続する。fishプロセスを全て終了したり、OSを再起動したりしても失われない。

環境変数は-Uオプションを付与することで定義できる。削除は同じように-eオプションで行う。

# ユニバーサル変数を定義
set -U EDITOR vim
# ユニバーサル変数を削除
set -e EDITOR

設定を即座に全fishプロセスへ反映させたいような設定に対しては便利そうだが安易にリスト型の値を持つ変数ををユニバーサル化すると消えずに追加され続けるようなバグを生み出してしまいそうだ。

ワイルドカード

通常のワイルドカード*に加えてサブディレクトリ配下を再帰的に辿る**が利用できる。 時間が掛かるようなケースで中断したい場合は CTRL c で中断できる。

# HOME直下のjpgファイルをリストアップ
> ls ~/*.jpg
# HOME配下の全てjpgファイルをリストアップ
> ls ~/**.jpg

コマンド履歴の利用

コマンド入力中にCTRL p キーを押すことで入力済みの文字列にマッチする履歴を過去へ向かって検索することができる。 逆にCTRL n キーを押すことで現在へ向かって検索する。

# lsまで入力
>ls /var/log
# [CTRL] [p]キーを押す事でマッチする履歴を表示
>ls /tmp

例えばlsと入力した状態で CTRL p キーを押すと履歴から最も最近のlsが含まれるコマンドが表示される。

終了ステータス

fishでは最後に実行したコマンドの終了ステータスを $status へ格納する。
0が成功で1以上が失敗を意味する。

>cd NONE_EXISTENT_DIR
cd: The directory ‘NONE_EXISTENT_DIR’ does not exist
>echo $status
1

リダイレクション

標準入力と標準出力へのリダイレクトは他のシェルと同様に < > >> だが標準エラーへのリダイレクトは ^ を利用する。

>cd NONE_EXISTENT_DIR ^err.txt

最後に

fish上で生きていくために最低限必要そうな点をまとめてみた。
素の状態で十分実用的なfishではあるがfishermanというプラグインマネージャもあるのでよりカスタマイズしていく場合はこちらを利用すると良さそうだ。