タブ補完でpecoでnpm-scriptsをもっと超簡単に実行したい

便乗ネタです。

pecoでnpm-scriptsを超簡単に実行したい - Qiita

という素晴らしい記事が公開されたので実際に使ってみたのですが、
npm runまで打ってから「あれ、コマンドなんだっけ」と思い、入力内容を消しnrunを実行するという一手間を省略したいと思いました。
もっと超簡単に実行できるようにnpm run <TAB>でpecoが起動するようにしてみました。

CHANGELOG

2018/06/01: yarnにも対応しました

まえおき

Bashでのみ動作確認してます。
ZやFの方は別途記事書いていただけるとありがたいです。

また、元記事の通りにセットアップができていることを前提とします。

pecoでnpm-scriptsを超簡単に実行したい - Qiita

npm run でpecoを作動させる

タブ補完に関しては、こちらの記事を参考にしました。

Bashタブ補完自作入門 - Cybozu Inside Out | サイボウズエンジニアのブログ

で、実際に書いたシェルがこちら。

_npm_run_peco() {
    local cur prev cword
    _get_comp_words_by_ref -n : cur prev cword
    if [ "$prev" = "run" ] || [ "$prev" = "yarn" ]; then
        COMPREPLY=$(cat package.json | jq -r '.scripts | keys[]' | peco --initial-filter=Fuzzy --query=$cur)
    fi
}
complete -F _npm_run_peco npm yarn

このコードをbash_profileなどに貼り付け、

source ~/.bash_profile

などと実行すれば反映されます。 コードは短いですが一応解説です。

Tab補完の定義方法

complete -F フックさせたい関数名 補完対象にするコマンド(可変長)を実行すると、タブ補完が有効になります。
例えばcomplete -F hoge npm yarnと書けばnpmyarnコマンドに対して関数hogeをフックするタブ補完になります。

_get_comp_words_by_ref

便利関数。現在カーソルがある手前の単語が何かわかります。
例えば、prevがrunだった時だけ処理するみたいにフィルタできます。
curは現在カーソルがある単語を指すので、入力途中のスクリプト名をpecoの初期クエリに渡せます。

npm run <TAB>  # Tabの位置に単語はないので、クエリは空文字列。全script一覧が表示される
npm run b<TAB> # Tabのいちに`b`があるので、bにマッチするscript一覧が表示される

COMPREPLY

COMPREPLYに値をセットすると、補完される文字列になります。
例えばCOMPREPLYにbuildという値をセットすると、

npm run build

のような補完になります。
これにpecoを組み合わせて、pecoで選ばれたscriptがCOMPREPLYにセットされるようにすれば良い

設定次第ですが、オプション指定なしでpecoを呼ぶとIgnoreCaseというフィルタになっています。
個人的にはFuzzy searchなら適当にタイプしても見つかるので設定しています。
この設定は好みなので、pecoのオプションを読みつつ、手に馴染む設定をすると良いと思います。

動作デモ

動作デモ

タブ補完でpecoでnpm-scriptsをもっと超簡単に実行したい - asciinema

快適٩( 'ω' )و
作ってみたらBashのTab補完とても簡単だったので、これからは積極的に補完していきたい