Skip to content

Instantly share code, notes, and snippets.

@bakkot
Last active September 23, 2022 00:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bakkot/d14826a356fa7ac7e5d9385c2c794432 to your computer and use it in GitHub Desktop.
Save bakkot/d14826a356fa7ac7e5d9385c2c794432 to your computer and use it in GitHub Desktop.
how to implement subcommands with node's parseArgs argument parser
'use strict';
let { parseArgs } = require('util');
let mainOptions = { help: { type: 'boolean', short: 'h' } };
let subCommands = {
__proto__: null,
foo: fooCommand,
bar: barCommand,
};
// boilerplate for handling subcommands
let args = process.argv.slice(2); // would be easier with process.mainArgs...
let { tokens } = parseArgs({ options: mainOptions, args, strict: false, tokens: true });
let cmdIndex = tokens.find(e => e.kind === 'positional')?.index ?? args.length;
let command = args[cmdIndex];
let tail = args.slice(cmdIndex + 1);
// handle options intended for the main script, rather than for a subcommand
let { values } = parseArgs({ options: mainOptions, args: args.slice(0, cmdIndex) });
if (values.help || command == null) {
console.log(`usage:
node parseargs-subcommands.js --help
node parseargs-subcommands.js foo
node parseargs-subcommands.js foo --foo-arg
node parseargs-subcommands.js bar positional positional2
`);
process.exit(0);
}
// run subcommands
if (!subCommands[command]) {
throw new Error(`unknown command ${command}`)
}
subCommands[command](tail);
// subcommand implementations
// they can re-run the parser with whatever options they want
function fooCommand(args) {
let options = { 'foo-arg': { type: 'boolean' } };
let { values } = parseArgs({ options, args });
console.log(`foo subcommand, with foo-arg: ${!!values['foo-arg']}`);
}
function barCommand(args) {
let { positionals } = parseArgs({ options: {}, args, allowPositionals: true });
console.log('bar subcommand');
console.log(`bar subcommand, with positionals: ${positionals.join(', ')}`);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment