Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

passThroughOptions with command #1461

Closed
nidhi-tandon opened this issue Feb 3, 2021 · 9 comments
Closed

passThroughOptions with command #1461

nidhi-tandon opened this issue Feb 3, 2021 · 9 comments

Comments

@nidhi-tandon
Copy link

Trying to use passThroughOptions with command

Code:

program.enablePositionalOptions();

program
  .command('prettier')
  .description('runs prettier')
  .passThroughOptions()
  .action((env, options) => {
    console.log(`Running: ${options.args.join(' ')}`);
  });

program.parse();

Using as
node <path_to_file> prettier --write .

Error
error: unknown option '--write'

What's working
node <path_to_file> prettier -- --write .

Output:
Running: prettier -- --write .

-- should not be required to make it work as passThroughOptions is used

References used: https://github.com/tj/commander.js/blob/master/examples/pass-through-options.js
https://github.com/tj/commander.js/blob/master/examples/positional-options.js

@shadowspawn
Copy link
Collaborator

shadowspawn commented Feb 3, 2021

Good description, thanks.

This is intended behaviour, but is a little subtle. .passThroughOptions() means the options after the first command-argument are ignored. The options before the first command-argument are processed as normal, so the subcommand can still have its own options. Your use case does not have a command-argument for prettier so the option is getting processed.

The work-around is to also specify .allowUnknownOption(). This suppresses the error and effectively turns the unknown option into a command-argument. I think this will give you the behaviour you want.

(If that is unclear, I can write some examples. It is late here so I am doing a quick reply!)

@nidhi-tandon
Copy link
Author

Will be better if you can give some examples. Also in this example, you are using arguments and in the above code, I am using command.

@shadowspawn
Copy link
Collaborator

I will post some more examples here for comment.

@shadowspawn
Copy link
Collaborator

shadowspawn commented Feb 4, 2021

If your subcommand does not have any of your own options, you could just allow unknown options:

const { program } = require('commander');

program.enablePositionalOptions();

program
  .command('prettier')
  .description('runs prettier')
  .allowUnknownOption()
  .action((options, cmd) => {
    console.log(`Running: ${cmd.args.join(' ')}`);
  });

program.parse();
% node simple.js prettier --write .
Running: --write .
% node simple.js prettier foo      
Running: foo

@shadowspawn
Copy link
Collaborator

If your subcommand may have your own options at the start of the arguments, you can use .allowUnknownOption() and .passThroughOptions():

const { program } = require('commander');

program.enablePositionalOptions();

program
  .command('prettier')
  .description('runs prettier')
  .option('-p, --prompt <value>', )
  .passThroughOptions()
  .allowUnknownOption()
  .action((options, cmd) => {
    const prompt = options.prompt || 'Running';
    console.log(`${prompt}: ${cmd.args.join(' ')}`);
  });

program.parse();
% node index.js prettier --prompt=Debugging --write . --prompt=prettier
Debugging: --write . --prompt=prettier

@iampluque
Copy link

iampluque commented Feb 5, 2021

And what if I have a cli command like this: $ cli parentCmd --dry-run subCmd <someArg> --some-option... how would I make my subCmd subcommand interpret the --dry-run parent option as well as it's own options? Is possible or just illogic?

@iampluque
Copy link

iampluque commented Feb 5, 2021

nvm, I saw you answer it @ #1229

@shadowspawn
Copy link
Collaborator

@pluqueTheLuxe
To be clear, parsing a parent option is supported but you need to access the option value yourself and it is not passed into the action handler for subCmd explicitly.

// assuming you have have variable for parentCmd you can access dryRun using
parentCmd.opts().dryRun
// or in subCmd action handler using command passed into handler (i.e. subCmd)
subCmd.parent.opts().dryRun

@shadowspawn
Copy link
Collaborator

An answer was provided, and no further activity in a month. Closing this as resolved.

I will be watching to see if more people confused that .passThroughOptions() only applies after first command-argument, and whether should build up the examples.

Feel free to open a new issue if it comes up again, with new information and renewed interest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants