fish
Peco
fzf

fishで適当なfuzzy finder的なツールと連携するプラグイン作った

More than 1 year has passed since last update.

とりあえずデモをご覧ください。

anyfff_demo.gif


これはなに?

CLIを普段からご利用の方にはおなじみのいつものやつです。

なんとなく思い立ってfish shellを使ってみよう!となったのですが、zshでenhancdに甘えきってしまっていた身としては、zとかautojumpなんて今更使ってられないわけです。

なんか代替ツール無いのか・・!と思って色々探しはしたものの、満足できそうなプラグインは見つけられず、しゃーなしで自作してしまった、という感じです。

で、どうせ作るならと思い、mollifier/anyframeb4b4r07/enhancdを足して3で割ったくらいの機能にしてみました。

機能的にはanyframeのfish版という感じなので、

ANYFrame For Fish shell

略してanyfff、と名付けました。


なにができるの?

コンセプト的にはanyframeとだいたい同じなので、こちらの記事から引用させていただきますと、



  • 普通の人が使いたいと思う関数がだいたい入ってる

  • peco、percol、fzfに対応してる

  • aliasでもbindkey(キーボード ショートカットから呼び出すやつ)でも、どちらからでも使える

  • 選んだ結果をすぐに実行するのも、コマンドラインに挿入するのもできる

  • 拡張しやすい


ここから、


  • anyframeで自分も使ってるor実装が簡単だと思った関数が入ってる

  • pecoでもfzfでも、多少マイナーなfuzzy finderでも、環境変数で指定さえすればなんとなく使える

  • aliasでもbindkey(キーボード ショートカットから呼び出すやつ)でも、どちらからでも使える

  • anyfffの各関数は(不本意ながら)グローバルスコープで参照できるので、適当に組み合わせれば手元で拡張できる

  • change directoryの拡張はわりと頑張ったので、たぶん気持ちよく使えるはず

こんなふうになりました。


使い方

以下READMEのダイジェスト版になりますので、詳しく知りたい方はぜひこちらまでお越しください :bow:


インストール方法

fundle推奨します!!理由は後述。

fundle plugin hagiyat/anyfff

これをconfig.fishに書いて、fundle installすればOK :thumbsup:


使い方

bind \cr 'anyfff_widget put_history'

bind \cx\cx 'anyfff_widget put_filename'
bind \cx\cg 'anyfff_widget checkout_git_branch'
bind \cx\cb 'anyfff_widget put_git_branch'

alias cd 'anyfff_widget cdr'

自分の場合はこれを ~/.config/fish/conf.d/keybinds.fish に書いてます。

config.fishに直書きでも良い気がするし、定番の設定方法がよくわからないですねえ :cry:


カスタマイズ

デモgifにさらっと入れておいたんですが、環境変数で動作が変わるようになってます。

これも詳しくはこちら

fish > set -gx ANYFFF__FINDER_APP peco

と設定すればpecoを使って絞り込みますし、fzfと設定すればfzfが出てきます。

まあそうそう変えるものでもないでしょうし、こちらはconfig.fishに書いておくのが良さそうですね。


 まとめ

というわけで、anyframeとかenhancdがないからfishに移行なんてできないよ・・・:sob:とお嘆きの超ニッチな方には多少の助けになるかと思いますので、よかったらお試しください!!


おまけ / fish shell実装で得た知見や不満点など

こんな小さいツールですが、だいたい形になるまで色々ハマらせていただきました。。

これからfish shellであれこれ便利なものを作りたい!と思う方の助けになれば幸いです


プラグインマネージャはfundleがおすすめです!

※個人の感想です

oh-my-fishは名前的にトラウマを呼び起こすので使いづらい。

かといってfihsermanは(デフォルトだと)~/.config/fish/functionsにsymlinkをぶちまけるのでつらい。。

ということで他にナイスなプラグインマネージャーはないものかなーと思って探した結果、fundleを見つけた次第です。

よくあるdotfilesの管理方法だと思うけど、.configをまるごとsymlinkにして管理しているような方でも、.config/fish/functions/fundle.fish.config/fish/fundleを.gitignoreに入れておくだけなので楽チン :wink:


:cry: コーディングルール?1ファイル1関数って不便では・・

原因がプラグインマネージャーなのかなんなのか?未だによくわからず。。

適当なファイルをsourceしたとしても、そのファイルの中でファイル名と一致している関数が定義されていない限り、functionsの中に入ってこないんですよねえ。。

まあしゃーないと割り切って、編み出した技が↓のtipsです。


:smile: サブコマンド作るの簡単!

以下はwidgetの実装:

function anyfff_widget -a subcommand

test (count $argv) -gt 1; and set -l subcommand_arguments $argv[2..-1]

    # - snip -

# call subcommand
if contains $subcommand \
'put_history' 'put_filename' 'checkout_git_branch' 'put_git_branch' 'kill_process' 'cdr'
eval $subcommand
else
echo "Undefined subcommand / $subcommand"
end
end

anyfffのwidgetは、fish> anyfff_widget hoge fuga piyo bazのような形で呼ばれるわけですが、これのhoge部分をwidgetの種類(サブコマンド)、以降をサブコマンドの引数、と処理できるようにしたのが上記のコードです。

呪文っぽいですが、$argvには$subcommandを含めたすべての引数の値が入っているので、2個以上の引数が指定された場合、2個目から末尾までを切り出してlocal変数にセットするよ、というロジックです。

あとは受付可能なサブコマンドの文字列が渡されているかチェックし、呼び出すだけです。もちろんswitchでも良いですね。

でも本来はもっとイカした方法で指定したかったんだ・・:angry:!というのがこちら↓


:cry: functionはネストできるんだぜ!でもローカルスコープにはならないの・・

ネストできる:tada:!、、からのグローバルに展開されとる:fearful:の上げて落とす感じ

function hoge

function fuga
echo 'fugafuga'
end
echo 'hogehoge' fuga
end

# これを実行する
> hoge
hogehoge fugafuga <- やったー!
> fuga
fugafuga <- えっ

みたいな感じです。Issueは上がってるみたいだけど、2014年にOpenされたのがそのままってことは、あっ・・・(察し)

ということで、widgetの関数でなにがやりたかったかというと、functionsという定義済みの関数をリストで取得したりするbuiltinの関数があるので、それでローカルスコープの関数に入ってたら呼び出すってできたらなあ、と思ったというわけです。

妄想コード(動きません):

if contains $subcommand (functions --local)

eval $subcommand
end

みたいな。

というかせっかくfunctionをnamespace的に使えそうなシンタックスなのになあ、という残念な気持ちです。


:sob: historyの扱いどうなってんの・・?

anyfffの実装とは関係ない、fish shellの普段使いでの問題なんですが、tmuxとかでセッションをわけちゃうと、historyが同期・反映されなくないですか?

まずはセッション1で適当なコマンドを実行します

> pwd

/Users/hagiyat/nantara_directory

からの、セッション2で参照

> history | tail -n 1

pwd igaino nanika

:thinking:

で、これを解決するべく色々調べた結果、以下の設定:

# デフォルトでは履歴がひとつのセッションでしか保存されないので、その対応

function sync_history --on-event fish_preexec
history --save
history merge
end

で、適当なセッション(up-or_searchは、直前のコマンドをコマンドラインに展開する関数です)

> pwd

/Users/hagiyat/nantara_directory
> up-or-search
> pwd jyanai daibumaeno command

:scream:

他にもzshでいうところのhist_ignore_all_dupsが無いとかhist_ignore_spaceが無いなど・・


オチ

履歴問題が片付くまでzshに戻ります :sunglasses:

(補完関連とかめちゃくちゃ良いので、ぜひ履歴問題を解決する方法をご存じの方はコメント欄などでおしえていただければと・・・!! :bow:)