LoginSignup
3
3

More than 5 years have passed since last update.

oh-my-fishのプラグインで色々展開&ディレクトリ移動を便利に!

Last updated at Posted at 2017-04-02

TL;DR

  • fishのプラグイン oh-my-fish/plugin-expand を使うと,Tabで色んなものを展開できるようになります!
  • それを利用したディレクトリ移動系プラグイン oh-my-fish/marlin もあります
  • でもパスに日本語が混じると使えなかったので,enhancdライクなplugin-expand設定を書くことにしました

oh-my-fish/plugin-expand

oh-my-fishの公式プラグインを物色していたところ,非常に面白いものを見つけました.

oh-my-fish/plugin-expand - Provides interactive word expansions in real-time

これはTabにキーバインドして,カーソル上の単語を指定したルールに従って展開できるようにしてくれるものです.

READMEにも例はあるのですが,ここではzshのグローバルエイリアスもどきを定義してみます.

~/.config/fish/config.fish
## カーソル上の単語が正規表現'^G$'にマッチするとき,'echo "| grep "'の実行結果でその単語を置き換える
expand-word -p '^G$' -e 'echo "| grep "'

## 同じ正規表現に複数の展開方法を指定できる
expand-word -p '^L$' -e 'echo "| less "'
expand-word -p '^L$' -e 'echo "| vimpager "'

expand-word -p '^_$' -e 'echo ">/dev/null"' # エラー読みたい
expand-word -p '^_$' -e 'echo "^/dev/null"' # エラーいらない
expand-word -p '^_$' -e 'echo ">/dev/null ^/dev/null"' # 黙ってやれ

plugin-expand.mov.gif

展開のルールを登録するにはexpand-wordコマンドを使います.-p, --petternオプションで正規表現を,-e, --expanderオプションで式を渡すと,Tabを押したときに単語の展開をしてくれるようになります.

カーソル下の単語が登録された複数の正規表現にマッチしたり,一つの正規表現に複数の展開方法が登録されていたりする場合は,fzf, pecoなどのインタラクティブフィルタリングツールが起動し,選択を促されます1

oh-my-fish/marlin

工夫次第で色々な展開ができそうなプラグインですが,oh-my-fishにもこれを利用したプラグインoh-my-fish/marlinがあります2

これはカンマ,に続けて正義表現を入力すると,過去のディレクトリ移動履歴からそれにマッチするものを見つけて展開してくれるプラグインです.
展開候補が複数ある場合にフィルタリングツールが起動する,というplugin-expandの特性が非常に有効に働きます.

omf-marlin.mov.gif

上記のデモでは仮想のパスを使ってますが,実在するパスならそのままエンターを押すことでディレクトリ移動できます.

トリガーがカンマ,で手軽に使える上,ディレクトリ移動履歴の作成も勝手にやってもらえるのでかなり便利です.
zshからfishに移行した際にenhancdという強力なプラグインを失い,移動系プラグイン難民となっていたため,merlinにはかなり期待できそうでした.

...が,どうもパスに空白や日本語が混じっていたりする場合にうまく扱えないことが判明しました.普段そういったパスを使わない方なら便利に使えると思いますが,残念.

enhancdライクなplugin-expandの設定

しかしplugin-expandは応用すればディレクトリ移動にも使える,と分かったので,せっかくなのでenhancdっぽい使い方ができる設定を書いてみようと思いました.

~/.config/fish/config.fish
## 設定
set -x cdhist_file "$HOME/.cdhist"
set -x cdhist_size 100
touch $cdhist_file

## 移動履歴記録
## PWD変数を監視して,値をファイルに追記
function __cd_add_log --on-variable PWD
    echo $PWD >> $cdhist_file
end

## 移動履歴取得 & 取得時にファイル更新
function __cd_get_log
    set -l logs (cat $cdhist_file)
    if set -q logs[2]
        string join \n $logs[-1..1] # 新しいものを上に
    end \
    | awk '!a[$0]++' \ # 要素を一意に
    | head -n $cdhist_size \ # 要素数制限
    | read -z logs

    string join \n $logs | string escape -n # 新しいものを上にして出力へ

    string join \n $logs | tail -r > $cdhist_file # 新しいものを下にしてファイルへ
end

## 親ディレクトリ一覧の取得
function __cd_parents
    set -l dirs (string split '/' "$PWD")

    for i in (seq (math (count $dirs) -1) 1)
        string join '/' $dirs[2..$i]
    end
    echo "/"
end

## 展開式を取得
expand-word -c "test (commandline -p) = 'cd -'" -e __cd_get_log
expand-word -c "test (commandline -p) = 'cd ..'" -e __cd_parents

ディレクトリ移動の記録はmarlinと同じく変数PWDを監視する方法を採用.enhancdの実装に関する記事を参考に,履歴をひっくり返したり戻したりしながら履歴の出力と更新を行っています.

使い方としては, cd -と打ってタブを押すとこれまでの検索履歴,cd ..と打ってタブを押すとルートまでの親ディレクトリ一覧が表示されます.

ただ,enhancdには移動履歴がどんどん蓄積する仕組みがあって便利だったのですが,そこまではとても実現できそうにありません.
ので,以下のように対処.

cat ~/.enhancd/enhancd.log >> ~/.cdhist 

おわりに

以前fishで{1..9}を展開する記事を書きましたけど,やっぱり同じようなことを考える方はいるようで,oh-my-fishにそのものズバリなプラグインがありました.

今回はそのプラグインを使い,marlinをヒントにenhancdっぽい設定を作りました.簡素ですが個人的には大満足です.

plugin-expand,他にも色々応用が考えられそうです.

補足

...とここまで書いてきて今更なのですけど,私の環境でplugin-expandを入れると,普通に補完をするときのTabがうまく働かなくなってしまいました.

なので,プラグインに少し手を加えたものを使っています.

Tabにキーバインドする関数を自作していたり,色々なプラグインマネージャを試してプラグインを入れたり消したりしていたので何かが干渉しているのかも.
本当にTabが効かなくなるのなら,プルリクを出したいところですが...

追記 (2017/4/14)

__cd_get_logの中でtailを使っていたのをheadに改めました.

追記 (2017/4/27)

__cd_get_logの中で履歴を逆順にできていなかったのを修正.


  1. フィルタリングツールを指定するにはFILTER変数を使います.フィルタリングツールが見つからなかった場合や,set FILTER ''のように明示的に指定されていない場合は,Tabを連打することで複数の候補を切り替えられます.むしろこちらの挙動の方が好きな人もいるかもしれません. 

  2. oh-my-fish公式なのに名前がplugin-でもthema-でも始まらない稀有なプラグインです.単なるミスなのか,何かの気概を表しているのか... なおmarlinはカジキのことだそうです. 

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3