npm run fuzzy auto-complete with preview using fzf

10 Mar 2024

In my previous blog post, we discussed adding fuzzy search for curl options using fzf.

In this post, we will add fuzzy completion to the npm run command by reading “scripts” from package.json in the current directory. This requires jq, to available on PATH.

NPM run with fzf completion

Helpers for sub-command

Fzf _fzf_complete_COMMAND function will trigger on main command and not for sub commands like npm run. To support this, we need some helper functions.

_fzf_complete_get_command_pos() {
    local arguments=("${(Q)${(z)@}[@]}")
    local cmd=$(__fzf_extract_command "$@")
    echo ${arguments[(i)$cmd]}
}

_fzf_complete_trim_env() {
    local command_pos=$1
    shift 1
    local arguments=("${(Q)${(z)@}[@]}")
    echo ${(q)arguments[$command_pos, -1]}
}

_fzf_complete_get_env() {
    local command_pos=$1
    shift 1
    local arguments=("${${(z)@}[@]}")
    echo ${arguments[1, $command_pos - 1]}
}

fzf complete NPM run

Now, using the above helper functions, we can add _fzf_complete_npm and _fzf_complete_npm_run as below.


_fzf_complete_npm() {
    setopt local_options no_aliases
    local command_pos=$(_fzf_complete_get_command_pos "$@")
    local arguments=("${(Q)${(z)"$(_fzf_complete_trim_env "$command_pos" "$@")"}[@]}")
    local subcommand=${arguments[2]}

    if (( $command_pos > 1 )); then
        local -x "${(e)${(z)"$(_fzf_complete_get_env "$command_pos" "$@")"}[@]}"
    fi

    if (( $+functions[_fzf_complete_npm_${subcommand}] )) && _fzf_complete_npm_${subcommand} "$@"; then
        return
    fi

    _fzf_path_completion "$prefix" "$@"
}

_fzf_complete_npm_run() {
    local package=${npm_directory-$(dirname -- $(npm root))}/package.json
    if [[ ! -f $package ]]; then
        return
    fi

    local scriptContent=$(cat package.json | jq -r '.scripts')

    _fzf_complete  --prompt="npm run> " --preview="echo '$scriptContent' | jq -r '.\"{}\"'"  -- "$@" < <(
      echo $scriptContent | jq -r 'keys[]'
    )
}

Here is a small preview of the above script in action.

NPM run with fzf completion

Versions of Language/packages used in this post.

| Library/Language | Version |
| ---------------- |---------|
| jq               |   1.7   |
| fzf              |  0.45.0 |
| zsh              |   5.9   |
If you find my work helpful, You can buy me a coffee.