fzfを使いnpm run 〇〇を一覧から選んで実行
どうも。 えーたん(@eetann092)です。
npm run start
やnpm run dev
など、npm run 〇〇
はプロジェクトによって違います。
忘れるたびにpackage.json
のscripts
を見るのが面倒になってきたため、fzfで一覧から選択したものを実行できるようにしました。
実装
全体
今回は.zshrc
に書き、Ctrl + x
を押してからn
を入力して実行できるようにしました。引数のあるものは想定していません。
function fzf_npm_scripts() {
if [ ! -e package.json ]; then
echo 'fzf_npm_scripts'
echo 'There is no package.json'
zle send-break
return 1
fi
if ! type jq > /dev/null; then
echo 'fzf_npm_scripts'
echo 'jq command is required'
zle send-break
return 1
fi
local scripts=`jq -r '.scripts | to_entries | .[] | .key + " = " + .value' package.json 2>/dev/null || echo ''`
if [[ -z $scripts ]]; then
echo 'fzf_npm_scripts'
echo 'There is no scripts in package.json'
zle send-break
return 1
fi
local selected=`echo $scripts | FZF_DEFAULT_OPTS='' fzf --height=50% --reverse --exit-0 | awk -F ' = ' '{ print $1}'`
zle reset-prompt
if [[ -z $selected ]]; then
return 0
fi
BUFFER="npm run $selected"
zle accept-line
}
zle -N fzf_npm_scripts
bindkey "^Xn" fzf_npm_scripts
解説
存在チェック
最初にpackage.json
があるか確認し、無ければストップします。
if [ ! -e package.json ]; then
echo 'fzf_npm_scripts'
echo 'There is no package.json'
zle send-break
return 1
fi
今回はpackage.json
のscripts
に書いてある内容を引き出すためにjqを使います。
そのため、jq
がない場合もストップします。
if ! type jq > /dev/null; then
echo 'fzf_npm_scripts'
echo 'jq command is required'
zle send-break
return 1
fi
scripts
の取得
jq
を使い、package.json
のscripts
を取得して加工します。
local scripts=`jq -r '.scripts | to_entries | .[] | .key + " = " + .value' package.json 2>/dev/null || echo ''`
今回はfzf
のpreview
オプションは使わず、以下のようなスクリプト名 = スクリプト内容
形式で表示しました。
start = react-scripts start
build = react-scripts build
test = react-scripts test
eject = react-scripts eject
fzf
のpreview
オプションを使わなかったのは、以下の画像のようにウィンドウ幅が広い場合、左右の視線の移動が増えるためです。
fzfのpreviewオプションを使う場合のjq
jq -r '.scripts | keys | .[]' package.json | fzf --preview "jq -r '.scripts | .{}' package.json"
2>/dev/null || echo ''
や次の行のif文は、
万が一scripts
が書かれていなかった場合にストップするための処理です。
fzfでの選択
いよいよfzf
での選択です。
変数selected
には、npm run 〇〇
の〇〇
の部分が入ります(start
やdev
など)。
local selected=`echo $scripts| FZF_DEFAULT_OPTS='' fzf --height=50% --reverse --exit-0 | awk -F ' = ' '{ print $1}'`
まず、FZF_DEFAULT_OPTS
の設定に左右されないように、デフォルトオプションを空にしてから実行しています。
echo $scripts | FZF_DEFAULT_OPTS='' fzf --height=50% --reverse --exit-0
続いて、awk
を使ってスクリプト名のみを取得します。
awk -F ' = ' '{ print $1}'`
npm run 〇〇 の実行
zleとBUFFER
変数を使い、どのスクリプトを選んだのか分かるように表示してから実行します。
また、何も選ばずに終了した場合は何も実行しないif文を書きました。
zle reset-prompt
if [[ -z $selected ]]; then
return 0
fi
BUFFER="npm run $selected"
zle accept-line
キーバーインドの設定
今回はzleを使っているため、キーバインドを設定しています。
zle -N fzf_npm_scripts
bindkey "^Xn" fzf_npm_scripts
実行例
↓最後にもう一度デモのGIFを貼ります。
余談:fzf-tmuxは使わないの?
以前書いた↑の記事では、fzf
の代わりにfzf-tmux
コマンドを使うことで、表示領域を広くしました。
今回fzf-tmux
を使わなかったのはfzf
のpreview
オプションを使わなかったのと同じ理由で、ウィンドウ幅が広い場合に左右の視線の移動が増えるのを防ぐためです。
リンク集
参考にしたリンクは以下です。
Discussion