Skip to content

Instantly share code, notes, and snippets.

@jakub-g
Last active September 12, 2022 19:47
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jakub-g/d350f1153ab01b0cd370 to your computer and use it in GitHub Desktop.
Save jakub-g/d350f1153ab01b0cd370 to your computer and use it in GitHub Desktop.
npm run Win-compatible bash completion (for custom scripts defined in `package.json`)
#!/bin/bash
alias npmrun='npm run'
alias _npmscripts_print="node -e \"console.log(Object.keys(require('./package.json').scripts, null, ' ').join(' '))\""
_npmscripts_completion()
{
local cur=${COMP_WORDS[COMP_CWORD]}
opts=$( _npmscripts_print )
COMPREPLY=( $(compgen -W "${opts}" -- $cur) )
}
complete -F _npmscripts_completion npmrun

Usage:

  1. Copy the aliases to .profile / .bashrc / wherever you like

  2. Use npmrun instead of npm run, enjoy

$ npmrun[TAB]
run-debug  run-prod   tdd        test-bar   test-foo

$ npmrun te[TAB]
test-bar  test-foo

$ npmrun test-bar

Rationale:

On big projects, there are usually many technologies and tools used - for running builds, partial builds, tests, partial tests, etc. Often you have helper scripts to run those tools.

The common problems of all those little tools are the following:

  • they might be spread over the repo in the subfolders (to not pollute the root folder with lots of random scripts)
  • they might be run in a different way (sometimes as a shell scripts written in bash / nodejs / python etc., sometimes through third party runner like grunt / gulp)
  • your Gruntfile might have many subtasks embedded, you commonly use many of them, not only the default one
  • in each of your repos, those helper scripts / grunt task are named differently, located in different place etc.
  • you don't get autocompletion in console for grunt tasks names, parameter names etc.

Hence, it's helpful to list all your scripts in one place. A good place for this is package.json:

{
  "name": "foo",
  "scripts": {
    "run-debug": "bash scripts/run-debug.sh",
    "run-prod": "bash scripts/run-prod.sh",
    "test-foo": "grunt test:foo",
    "test-bar": "grunt test:bar",
    "tdd": "grunt tdd"
  }
}

and now you can npm run [scriptname] (npm run is a shortcut for npm run-script).

But the problem of autocompletion is still unsolved.

There comes npmrun which is just an alias to npm run, but we additionally establish bash autocompletion for it by reading package.json contents and running bash machinery (complete bash builtin) that will enable the completion.

`npmrun` gist provides bash autocompletion for `npm run` command.
It works on Windows with Git Bash, contrary to `npm completion`.
Currently it only works in the root of the repo.
{
"name": "foo",
"scripts": {
"run-debug": "bash scripts/run-debug.sh",
"run-prod": "bash scripts/run-prod.sh",
"test-foo": "grunt test:foo",
"test-bar": "grunt test:bar",
"tdd": "grunt tdd"
}
}
@racer1988
Copy link

@jedrichards
Copy link

Nice gist! Thanks for it, but if I have a script named build:css, and I type the following in my terminal,

$ npmrun build:c[TAB]

Then it autocompletes to,

$ npmrun build:build:css

Maybe it doesn't handle script names with colons in them quite properly? Any ideas where to poke around?

@jakub-g
Copy link
Author

jakub-g commented Oct 29, 2015

@jedrichards

this was a very crude completion, in fact I submitted a PR to npm to natively support npm completion for every command, since it works just fine in git bash

npm/npm#10156

however I checked, and the npm built-in completion behaves exactly the same. It seems handling colons in bash completion is non-tricky :)

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