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
のグローバルエイリアスもどきを定義してみます.
## カーソル上の単語が正規表現'^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"' # 黙ってやれ
展開のルールを登録するにはexpand-word
コマンドを使います.-p, --pettern
オプションで正規表現を,-e, --expander
オプションで式を渡すと,Tab
を押したときに単語の展開をしてくれるようになります.
カーソル下の単語が登録された複数の正規表現にマッチしたり,一つの正規表現に複数の展開方法が登録されていたりする場合は,fzf
, peco
などのインタラクティブフィルタリングツールが起動し,選択を促されます1.
oh-my-fish/marlin
工夫次第で色々な展開ができそうなプラグインですが,oh-my-fish
にもこれを利用したプラグインoh-my-fish/marlin
があります2.
これはカンマ,
に続けて正義表現を入力すると,過去のディレクトリ移動履歴からそれにマッチするものを見つけて展開してくれるプラグインです.
展開候補が複数ある場合にフィルタリングツールが起動する,というplugin-expand
の特性が非常に有効に働きます.
上記のデモでは仮想のパスを使ってますが,実在するパスならそのままエンターを押すことでディレクトリ移動できます.
トリガーがカンマ,
で手軽に使える上,ディレクトリ移動履歴の作成も勝手にやってもらえるのでかなり便利です.
zsh
からfish
に移行した際にenhancdという強力なプラグインを失い,移動系プラグイン難民となっていたため,merlin
にはかなり期待できそうでした.
...が,どうもパスに空白や日本語が混じっていたりする場合にうまく扱えないことが判明しました.普段そういったパスを使わない方なら便利に使えると思いますが,残念.
enhancdライクなplugin-expandの設定
しかしplugin-expand
は応用すればディレクトリ移動にも使える,と分かったので,せっかくなのでenhancdっぽい使い方ができる設定を書いてみようと思いました.
## 設定
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
の中で履歴を逆順にできていなかったのを修正.