Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Commander.js collect multiple options always include default

I'm using commander.js to parse the command line args and I'm trying to collect an optional param that can appear multiple times and it always returns the options I set plus the default one.

function collect (val, memo) {
    memo.push(val);
    return memo;
}

program
    .command('run <param>')
    .action(function run(param, options) {
        console.log(param);
        console.log(options.parent.config);
    });

program
    .option('-c, --config <path>', 'Config', collect, ["/path/to/default"])
    .parse(process.argv);

When I call the script like this:

index.js run some -c "/some/path" -c "/other/path"

It prints:

[ '/path/to/default', '/some/path', '/other/path' ]

But it should only print:

['/some/path', '/other/path' ]`

When I call it without the -c param it works correctly, printing the array with the default value. How can I fix this?

like image 450
borgespires Avatar asked Aug 02 '26 04:08

borgespires


1 Answers

The commander"Repeatable value" option doesn't support a default value, at least in a way that prevents you from having to write your own logic to handle the scenario where the user pass one or more values. The way you wrote your code, you're gonna have to check the size of the program.config attribute:

  • If the user pass one or more -c option value, the size is > 1;
  • Otherwise, it's === 1.

IMO, this scenario calls for the "A list" option, which supports the default value, and saves you some extra work. Like:

const buildList = (item, list) => [...(list ?? []), ...item.split(',')]

program
      .option('-l, --list <items>', 'A list', buildList, [ "/path/to/default" ])
      .parse(process.argv);

To have access to the values passed, just call program.list, and in the command line, call it with values:

$ index.js run some -l "/some/path","/other/path"
// where console.log(program.list) prints [ "/some/path", "/other/path" ]

You can also repeat the option:

$ index.js run some -l "/some/path" -l "/other/path"
// where console.log(program.list) prints [ "/some/path", "/other/path" ]

Or, without values:

$ index.js run some
// where console.log(program.list) prints [ "/path/to/default" ]

If you use the Option class instead, then the code looks like:

import { Option, program } from 'commander'

const buildList = (item, list) => [...(list ?? []), ...item.split(',')]

program
    .addOption(
        new Option('-l, --list <items>', 'A list')
            .argParser(buildList)
            .default([ "/path/to/default" ])
    )
    ...
like image 183
Rodrigo Medeiros Avatar answered Aug 03 '26 17:08

Rodrigo Medeiros



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!