Skip to content

Instantly share code, notes, and snippets.

@gibatronic
Last active January 25, 2024 21:46
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save gibatronic/44073260ffdcbd122e9520756c8e35a1 to your computer and use it in GitHub Desktop.
Save gibatronic/44073260ffdcbd122e9520756c8e35a1 to your computer and use it in GitHub Desktop.
Tab completion for the npx command

complete_npx

Bash tab completion for the npx command

Usage

Save complete_npx in your home folder and then source it on your .bash_profile with:

. ~/complete_npx.sh
no_modules() {
local project_root=$1
[ ! -r "$project_root/node_modules" ]
}
complete_npx() {
local project_root=$(pwd -P)
while no_modules "$project_root"; do
if [ "$project_root" = '/' ]; then
return 1
fi
project_root=$(dirname "$project_root")
done
local words=$(find "$project_root/node_modules/.bin" | tail -n +2 | xargs -L 1 -- basename)
local current_word=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W "${words[@]}" -- "$current_word" ) )
}
complete -F complete_npx npx
@vidhill
Copy link

vidhill commented Apr 27, 2018

Brilliant, just what I neeeded!

@jmarucha
Copy link

I suggest changing last part of L19 from
xargs basename
to
xargs basename -a
as some distros (including mine) require it to work properly with multiple suggestions

@sentilesdal
Copy link

Amazing! also thanks @jmarucha. Needed to add xargs basename -a for osx.

@gibatronic
Copy link
Author

Thanks folks, I've updated the code!
It was never meant to pass multiple arguments at once to basename, so I added a flag to xargs to invoke basename line by line instead.

@vukbgit
Copy link

vukbgit commented Sep 15, 2021

thank you, great job!

@gavenkoa
Copy link

gavenkoa commented Sep 15, 2021

Cleaner solution is:

_npx() {
  local dir=$(pwd -P)
  while [[ -n "$dir" ]]; do
    if [[ ! -d $dir/node_modules/.bin ]]; then
      dir=${dir%/*}
      continue
    fi
    local execs=( `cd $dir/node_modules/.bin; find -L . -type f -executable` )
    execs=( ${execs[@]/#.\//} )
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $(compgen -W "${execs[*]}" -- "$cur" ) )
    break
  done
}

complete -F _npx npx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment