Commander.js: Get remaining arguments

Created on 11 May 2018  路  11Comments  路  Source: tj/commander.js

program
  .version(version)
  .allowUnknownOption()
  .option('-a --option-a', 'Option A')
  .parse(process.argv);

I call my program with ./my/program --option-a 123 --option-b --option-c 567. Is there a way to get the remaining options (b & c), either as an object or as an rawArgs array?

Most helpful comment

Commander v5.0.0 has been released with significant changes to how unknown arguments are handled, which make this issue if not resolved, at least dated. 馃檪

https://github.com/tj/commander.js/releases/tag/v5.0.0

All 11 comments

IIRC you may retrieve them using program.optionB and program.optionC.

Not in 2.15.1.

Also, I would ideally like to have an array or an object containing only those arguments.

I think the unknown options are ignored and not available separately.

(The remaining arguments after removing options are available as program.args, and the full arguments are in program.rawArgs. But neither are what you asked for.)

After some trial and error I ended up with a small script.

const remaining = cli.rawArgs
  .splice(Math.max(cli.rawArgs.findIndex(item => item.startsWith('--')), 0)) // Remove all arguments until one --option
  .filter((item, index, array) => {
    const key = camelcase(item.replace('--', '').replace('no','')); // Remove first 2 '--' and then camelCase

    if (key in cli) {
      // If the option is consumed by commander.js, then we skip it
      return false;
    }

    // If it's not consumed by commander.js, and starts with '--', then we keep
    // it. This step is optional, used for optimization only.
    if (item.startsWith('--')) {
      return true;
    }

    const previousKey = camelcase(array[index - 1].replace('--', '').replace('no',''));
    if (cli[previousKey] === item) {
      // If it's an argument of an option consumed by commander.js, then we
      // skip it too
      return false;
    }

    return true;
  });

Where cli = require('commander') and camelCase is this.

Thanks @amaurymartiny! This was really bugging me. Unfortunately I had a case with short flags that was not being handled. Also found it easier to use the cli.options array.

  const remaining = cli.rawArgs
    .splice(Math.max(cli.rawArgs.findIndex(item => item.startsWith('--')), 0)) // Remove all arguments until one --option
    .filter((item, index, array) => {
      // If the option is consumed by commander.js, then we skip it
      if (cli.options.find(o => o.short === item || o.long === item)) {
        return false
      }

      // If it's an argument of an option consumed by commander.js, then we
      // skip it too
      const prevKeyRaw = array[index - 1]
      if (prevKeyRaw) {
        const previousKey = camelcase(
          prevKeyRaw.replace('--', '').replace('no', '')
        )
        if (cli[previousKey] === item) {
          return false
        }
      }

      return true
    })

made an npm module out of it: commander-remaining-args

@amaurymartiny That's because you forgot to specifiy what the argument b and c are as opposed to what you did for a.

I'm working on a small project where the end-user is in control of the number and names of command line options. So as a developer of the tool I don't have this information. But I need to pass all user-defined options to an also user-defined script. Therefore it would be incredibly helpful if I was able to access all remaining unknown options as an object, just like the known ones.

I have a Pull Request open that will change the behaviour so that unknown options are included in program.args after parsing (and passed to the program action handler too).

I think this may work nicely for cases where you want to remove some known options and pass the rest through to another command.

See #1138

The unknown options are now left in the arguments in the published pre-release of Commander v5.0.0 (#1163)

Commander v5.0.0 has been released with significant changes to how unknown arguments are handled, which make this issue if not resolved, at least dated. 馃檪

https://github.com/tj/commander.js/releases/tag/v5.0.0

Was this page helpful?
0 / 5 - 0 ratings