Description
Several parsers, including minimist (stopEarly
), getOpts (stopEarly
), command-line-args(stopAtFirstUnknown
), and yargs (halt-at-non-option
), have an option which says to treat everything after the first positional (including that argument) as being either positional or otherwise a not parsed as a normal option.
This is helpful for building git
/npm
style subcommands (read the first positional, treat it as naming the subcommand, then parse everything after using an options config specific to that subcommand), and also for things like node
itself where e.g. node --inspect script.js --bar
is treated as passing --inspect
to node, but --bar
is sliced out and passed to script.js
.
This was mentioned by @julien-f on the PR, which is now merged (🎉 ), and I wanted to make sure it didn't get lost.
I note that it is possible to get this behavior just by reporting indices: parse once with strict: false
, find the index of the first positional, split the original array at that point, then re-parse the stuff before that with strict: true
. With this prototype, that would look something like
let options = {
inspect: { type: 'boolean' },
};
let args = process.mainArgs;
let { elements } = util.parseArgs({ options, args, strict: false });
let firstPositionalIndex = elements.find(e => e.kind === 'positional')?.argIndex ?? args.length;
let { values } = util.parseArgs({ options, args: args.slice(0, firstPositionalIndex), strict: true });
let tail = args.slice(firstPositionalIndex);
// and then do whatever you want with `values` and `tail`
Maybe that's good enough? It feels somewhat awkward, but maybe this is a niche enough case that we should call that sufficient.