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

subcommands cannot have the same option as top level commands #1307

Closed
danielr1996 opened this issue Jul 20, 2020 · 5 comments
Closed

subcommands cannot have the same option as top level commands #1307

danielr1996 opened this issue Jul 20, 2020 · 5 comments

Comments

@danielr1996
Copy link

Consider the following piece of code

import commander from 'commander';

const program = new commander.Command();
program.passCommandToAction(false);

program
    .option('-f, --file <config-file>', ``, 'default1')
    .action(console.log)

program.command('init')
    .option('-f, --file <config-file>', ``, `default2`)
    .action(console.log)

program.parseAsync(process.argv);

expected behaviour

Running node bug.mjs -f config.js should output {file: 'config.js'} because the -f flag was specified
Running node bug.mjs init -f config.js should output {file: 'config.js'} because the -f flag was specified

actual behaviour

Running node bug.mjs -f config.js outputs {file: 'config.js'} which is expected
Running node bug.mjs init -f config.js outputs {file: default2'} which is not expected because the -f flag was specified but the default value is used

After reading #1229 and its linked issues I'm not sure if what I described is an actual bug or expeted behaviour.

For the case that it is a bug I'd be happy to try and fix the bug.

For the case that it is an expected behaviour I found a workarround:
You just don't use top level commands at all and use the {isDefault: true} option for the subcommand that should get executed when there is no sub command specified, effectively making it a top level command.

program
    .command('bump', {isDefault: true})
    .option('-f, --file <config-file>', ``, 'default')
    .action(o=>console.log('bump'))
@shadowspawn
Copy link
Collaborator

shadowspawn commented Jul 20, 2020

Short version: expected behaviour.


Long version

Well researched!

This is currently expected behaviour as the program options are considered first and are not positional, and grab the option before the subcommand is considered. As you found, #1229 is the high level issue covering related issues.

As you suggested, a good work-around for options which are not really global is to define a default command rather than attach the options to the top-level command (program).

@danielr1996
Copy link
Author

Thanks for the clarification.

Should we add this behaviour and the workaround to the documentation if somebody comes across the same problem as me?

@shadowspawn
Copy link
Collaborator

shadowspawn commented Jul 21, 2020

Should we add this behaviour and the workaround to the documentation if somebody comes across the same problem as me?

This hasn't come up much in the past, so I don't currently want to try extending the README coverage.

Using a default command with an action handler is a fairly new feature. I had noticed that besides allowing that explicit program structure, it provides a separation between the top level options and subcommands when they are not related. This is a possible direction for extending the README in the future.

The open wider issue is #1229 and I have added this issue to it.

@danielr1996
Copy link
Author

Ok, then I'm closing the issue. Thanks again for your feedback.

@shadowspawn
Copy link
Collaborator

Pull Request opened to add .enablePositionalOptions() and .passThroughOptions(): #1427

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

2 participants