-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Feature discussion: Inherit options in subcommands #1753
Comments
Thanks for the detailed description. The feature which is a good match for most of your description is
With positional options, options after the subcommand belong to the subcommand.
With positional options, the |
Have a look at #1551 for some previous coverage of enhancements to global options. I have had a go at the two most popular: one turned into an example file instead, and "always populating" is similar to #1551 (comment), and was the least popular (somewhat to my surprise at the time). |
( |
Thanks for your swift reply! 🙂
I missed that, thanks for the pointer.
Out of curiosity, that is useful when running both actions?
I'm surprised too. Do you want to keep it the way it is? What about throwing when defining the same option twice? |
Yes, the command-specific option is passed into the action handler (if that is what you are asking).
I don't think "inherit" is a common or clean enough use case to try and add explicit support. But willing to discuss it in more detail if you wish.
A major consideration for throwing is it would completely break any existing programs that happen to have overlapping options across levels, and are currently working fine apart from the overlapping option in the subcommand. Commander has a big installed base, so adding throws with helpful guidance to authors of new code has to be balanced against breaking existing code. It could be considered in a major release. Can the guidance in a
|
But that action handler never runs? Am I missing something? Take this example: const commonOption = createOption("-d, --debug");
const program = new Command()
.addOption(commonOption)
.action((options) => {
console.log("program options: %O", options)
})
.enablePositionalOptions();
const print = program.command('print')
.addOption(commonOption)
.action((options) => {
console.log('print options: %O', options);
});
print.command('pdf')
.addOption(commonOption)
.action((options) => {
console.log('print pdf options: %O', options);
});
program.parse(); Running yields: ❯ ./option.js -d print -d pdf -d
print pdf options: { debug: true } Adding tests in global scope works: if (program.opts().debug) {
console.log("program debug set")
}
if (print.opts().debug) {
console.log("print debug set")
}
That is how it's intended?
Fully agree!
Sounds reasonable to try covering the likely cases 👍 The second one is probably common error (as multiple issues state).
I do not understand this sentence, but am eager to learn the use case. Can you provide an example? |
Btw, an alternative to throwing would be not showing option in help, when it isn't considered an "regular" option to that nested subcommand. Example, no
|
Aha, this is the "make sure commands using the same options never follow a chain command -> subcommand". Like this? const program = new Command()
.addOption(commonOption)
.action((options) => {
console.log("program options: %O", options)
});
program.command('print')
.addOption(commonOption)
.action((options) => {
console.log('print options: %O', options);
}); which should be changed into: const program = new Command()
program.command("main", { isDefault: true })
.addOption(commonOption)
.action((options) => {
console.log("program options: %O", options)
})
.enablePositionalOptions();
program.command('print')
.addOption(commonOption)
.action((options) => {
console.log('print options: %O', options);
}); Right? |
From #1753 (comment)
Yes, the options for each nested command are available on the command. A helper method for some setups is To access the global/inherited options from within an action handler, you can access print.command('pdf')
.addOption(commonOption)
.action((options, pdfCmdParam) => {
console.log('print pdf options: %O', options);
console.log('print options looking up: %O', pdfCmdParam.parent.opts());
console.log('program options looking up: %O', pdfCmdParam.parent.parent.opts());
}); |
Yes indeed. 😄 |
I think we covered some good ground with scenarios with options at multiple levels, and the existing support. I don't see any action items I want to followup for now. Feel free to open a new issue if it comes up again, with new information and renewed interest. Thank you for your contributions. |
Maybe a bit more in the help? I can't figure out how to share options between commands and get them to show up in the help for each command. I ended up copying the options twice. Thank you! |
Thanks, the file got refactored, and this one did the trick: https://github.com/tj/commander.js/blob/master/examples/global-options-nested.js |
Hi! Thanks for commander 🙌
Is commander considered feature complete? Any chance for a inherit options feature? Or always populating options in subcommands when same is also defined in parent commands?
I find it hard to create a hierarchy of commands that share common options. I also find the "options are global behavior" unintuitive. Especially when you are unaware of any parent command using the same option.
I've read issues like #1750, #1739, #1616 and #1229.
Take this example, where
print
andprint pdf
would have very different action-implementations:The help suggests that
--a4
is available to both "print" and "print pdf":Though, it is not:
Solvable through
optsWithGlobals
or splitting intoprint-printer
andprint-pdf
commands. Maybe also with splittingprint pdf
to separate executable?Anyhow, would be nice if options was set in subcommands when same options are defined longer up in the hierarchy.
The text was updated successfully, but these errors were encountered: