zshからfishに移行してみました。

Table of Contents

前提

以下の環境で構築しました。

  • Windows10 with WSL (Ubuntu 16.04.2 LTS (Xenial Xerus))
  • WSL Terminal
  • Ansible (2.3.2.0) (python 2.7.14)

構築手順は 全てAnsible Playbookの形 で紹介します。
Playbookを使わない方法は他の素晴らしいブログで記載されておりますので、そちらをご覧下さい。

経緯

社内のLTでfishの発表があり、デモもイイ感じだったので入れてみようと思ったのがきっかけです。
今までは bash/zshと文法が結構違う という理由で躊躇していました。

しかし、冷静に考えてみると問題なさそうだと思いました。

  • デフォルトシェルをfishにしなければスクリプトには影響が無い
  • 新しい文法は慣れの問題
  • 社内サーバはbashが基本であり、コンテキストスイッチコストもzshの時から存在する

また、fishが比較的新しいモダンなシェルであり これ以上大人の事情で目を瞑るのは良くないと思ったからです。

しばらく使ってみて、強力な補完とプラグインの虜になってしまいました。
本題に入る前に、2つほどfishの補完について紹介します。

補完の名前は適当につけました。正式名称は調べて下さい。

シャドー補完

まるで漢字ドリルをなぞるように先回りした補完がデフォルトの状態で使用できます。

曖昧補完

** で配下のエントリ全てを補完することができます。

最後のは標準機能ではなくプラグインを使っています。

インストール

PPAリポジトリからインストールします。

- name: Add fish repository from PPA and install its signing key.
  become: yes
  apt_repository:
    repo: 'ppa:fish-shell/release-2'

- name: Install fish
  become: yes
  apt:
    name: fish
    update_cache: yes
    state: latest

バージョンは version 2.6.0 です。

fzf

コマンドラインのfuzzy finderです。
曖昧な入力を元にfindコマンドを駆使して様々な検索をすることができます。

fishとは直接関係ありませんが、後でインストールするプラグイン(fisherman/fzf)を使用するために必要なのでインストールしています。
凄い便利なのでfishを使用しない場合でも是非インストールしてみてください。

インストール

cloneしてインストールスクリプトを実行します。

- name: Clone fzf
  git:
    repo: https://github.com/junegunn/fzf.git
    dest: ~/.fzf
    depth: 1

- name: Install fzf
  shell: ~/.fzf/install --all

fisherman

fishには便利なプラグインが沢山あり、プラグインマネージャを使用する事で簡単に管理することができます。
もう1つ有名なマネージャとして oh-my-fish もありますが、fisherman の方が後発で評判もいいためこちらを採用しています。

詳しくは公式のREADMEをご覧下さい。

インストール

curlでインストールです。

- name: Install fisherman
  shell: curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs git.io/fisher

Ansibleで環境構築を完了させるため、コマンドの説明は省略します。

プラグイン

インストール方法は最後にご紹介します。

theme-bobthefish

fishのテーマです。
oh-my-fish側のリポジトリで管理されているテーマ群の中で選びました。

以下から全てのテーマを閲覧することができます。

周囲を見ると ほとんどの方がagnosterを使用されていますが、私はbobthefish派です。
agnosterにしなかった理由は以下の通りです。

  • Gitに関する情報量と表現力が好みにあわなかった
  • 目立ちすぎに思える
  • 皆使っているので面白くない

フォントはSource Code Pro for Powerlineを使用しています。

fish-bd

bdコマンドでcdコマンドと全く逆の動きをすることができます。

<TAB>で上位ディレクトリが階層を越えて補完され、ディレクトリ名だけを指定すればそこまで移動することができます。

例えばカレントディレクトリが a/b/c/d/e/f/g の場合、補完候補は

a b c d e f g

となり、bd c を実行すると a/b/c に移動することができます。
もう cd ../../../../ といった暗号のようなコマンドを実行する必要はありません。

fzf

先ほど説明したfzfのfishプラグインバージョンです。
fishにマッチする形でfzfと上手く連携してくれます。

以下は以前実行したsite.ymlを編集するコマンドを履歴から検索して実行するまでの流れです。

他にも色々機能がありますが、これが一番使いますね。

z

曖昧な入力を元に、一度でも移動したことがあるディレクトリへ移動するコマンドです。
メチャクチャ便利です。

インストール

with_itemsでまとめてインストールします。
Ansibleはbashで実行しているため、fishのコマンドとして指定する必要があります。

- name: Install by fisher
  shell: fish -c "fisher {{ item }}"
  with_items:
    - omf/theme-bobthefish
    - 0rax/fish-bd
    - fisherman/fzf
    - fisherman/z

その他

wsl-terminalの起動シェルをfishに変更

wsl-terminal/etc/wsl-terminal.confshell=fish を設定しましょう。
これでfishを直接起動することができます。

config.fishの設定

bashの.bashrcやzshの.zshrcにあたるものです。
場所が.config/fish/config.fishと少し異なります。

fzfに関するデフォルトオプションだけ以下に記載します。

# 一覧の上を最新として、境目をボーダーに
set -x FZF_DEFAULT_OPTS "--reverse --border"
# ディレクトリ検索で選択した項目の配下の構成をプレビューに表示する
set -x FZF_ALT_C_OPTS   "--preview 'tree -C {} | head -200'"
# ファイル検索で選択した項目の中身をプレビューに表示する
set -x FZF_CTRL_T_OPTS  "--preview 'head -100 {}'"

# エラーコードは番号で表示する
set -g theme_show_exit_status yes
# Gitのahead情報を細かく表示する
set -g theme_display_git_ahead_verbose yes

トラブルシューティング

WSLを使っていることもあり、色々なハマリポイントがありました。

pecoが使用できない

fzfと双璧をなすpecoというツールもあるのですが、WSLのせいか(?)インストールできませんでした。

PATHが不正

環境変数をセットしたつもりでもPATHが不正と怒られる場合は、以下のように設定しているかを確認してみて下さい。
※ 例では$PYENV_ROOT/binをセットしています

set -x PATH "$PYENV_ROOT/bin" $PATH

以下はいずれも誤りです。

set -x PATH "$PYENV_ROOT/bin:$PATH" 
set -x PATH "$PYENV_ROOT/bin" "$PATH"

fishからfzfプラグインの機能 最近のコマンドから検索 が実行できない

事象としては fzf と文字列が出力されてしまいます。

/home/tadashi-aikawa/.config/fish/functions/fish_user_key_bindings.fishfzf_key_bindings 以外をコメントアウトすることで事象は解消されました。
ただ、正確な原因は不明です。。

function fish_user_key_bindings
    fzf_key_bindings
#    ### fzf ###
#    set -q FZF_LEGACY_KEYBINDINGS
#    or set -l FZF_LEGACY_KEYBINDINGS 1
... 中略 ...
#    end
#    ### fzf ###
end

tcsetpgrpのPermission deniedエラーが発生する

必ず発生するわけではありませんが、fzf使用中に度々発生しました。
まだ解決方が分かっておりません。。

wcmd: OUTBASH_PORT environment variable not set, and...エラーが発生する

wcmdを使用するとエラーになり実行できなくなりました。
Windowsを再起動したら発生しなくなりました。

総括

WSLへfishを導入する手順について紹介しました。
今のところ大きな不満はありませんので、引き続き環境を最適化してみようと思います。