🐈

pnpmのTab補完をカスタムスクリプトでちょっと強化

に公開

Node.jsプロジェクトで作業してると、package.jsonscriptsに定義したコマンドを忘れがちで、毎回ファイルを開いて確認するのが面倒だった。

標準の補完機能を試す

pnpmには標準でTab補完機能がある。

pnpm install-completion zsh  # zshの場合

でも、これは以下のことしかできない:

  • pnpmコマンド自体のオプション(install、updateなど)の補完
  • package.jsonのscripts補完はなし
  • node_modules/.binのコマンド補完もなし

AIで補完スクリプトを作る

AIを使ってzsh用の補完スクリプトを作ってみた。15分でできた。自分で作ったら3時間はかかったし、多分やらなかった。

_pnpm_run_scripts() {
  local -a scripts
  if [[ -f package.json ]]; then
    scripts=("${(
@f
)$(jq -r '.scripts | keys[]?' package.json 2>/dev/null)}")
    _wanted scripts expl 'pnpm scripts' compadd -a scripts
  else
    _message 'No package.json found'
  fi
}

_pnpm_exec_bins() {
  local -a bins
  if [[ -d node_modules/.bin ]]; then
    bins=("${(
@f
)$(command ls -1 node_modules/.bin 2>/dev/null)}")
    _wanted bins expl 'executables in node*modules/.bin' compadd -a bins
  else
    _message 'No node*modules/.bin found'
  fi
}

_pnpm_main_completion() {
  local -a subcommands options
  
  subcommands=(
    'add:Add dependencies'
    'install:Install dependencies'
    'update:Update dependencies'
    'remove:Remove dependencies'
    'run:Run a defined script'
    'exec:Execute a binary'
    'list:List installed packages'
    'outdated:Check for outdated packages'
    'audit:Run a security audit'
    'link:Symlink a package folder'
    'publish:Publish a package'
    'pack:Create a tarball'
    'rebuild:Rebuild packages'
    'install-test:Install and test'
    'root:Show root path'
    'store:Manage pnpm store'
    'env:Print environment info'
  )
  
  options=(
    '--help[Show help]'
    '--version[Show version]'
    '--filter=[Filter workspace packages]'
    '--workspace-root[Operate from workspace root]'
    '--recursive[Run command recursively]'
    '--global[Install globally]'
    '--silent[No output]'
  )
  
  _arguments -s '1:subcommand:->subcmds' '*::options:->opts'
  
  case $state in
    subcmds)
      _describe 'pnpm commands' subcommands ;;
    opts)
      _describe 'pnpm options' options ;;
  esac
}

_pnpm_dispatcher() {
  local cmd="${words[2]}"
  case "$cmd" in
    run)
      _pnpm_run_scripts ;;
    exec)
      _pnpm_exec_bins ;;
    *)
      _pnpm_main_completion ;;
  esac
}

compdef _pnpm_dispatcher pnpm

機能

このスクリプトで次のことができるようになった:

  1. pnpm + Tabでpnpmコマンドのオプション補完
  2. pnpm run + Tabでpackage.jsonのscripts補完
  3. pnpm exec + Tabでnode_modules/.binのコマンド補完

pnpmのオプションはハードコードだけど、そう変わるものでもないしこれでいい。

使ってみた感想

期待通りに動いていて良い感じ。package.jsonを開かなくてもコマンドが分かるようになったので便利。

AIで15分でできたのは大きい。自分で作るとしたら少なくとも3時間はかかってたし、絶対にやらなかったと思う。

Discussion