Say we've a command driven app:-
program
.option('-n,--name <name>');
program
.command('sample')
.option('-a,--action <action>')
.action((options) => {
console.log(options.action);
});
program.parse(process.argv);
[cli-name] -n <name> (standalone option)[cli-name] sample -a <value> (command)The first use case doesn't seem to work.
@shadowspawn any help would be appreciated 馃憦
It seems that the cli-flag is invoked only if an available command is passed in :thinking:
Quick answer, I have not run your code to double check. If this doesn't answer your question (I am not sure what cli-flag is), please post what you are typing on the command line and what you are seeing.
You have been extra unlucky and picked TWO option names which clash with existing properties on the Command object!
Have a look at #1226 and https://github.com/tj/commander.js#avoiding-option-name-clashes
Your program is spookily similar to the example program solving this problem: https://github.com/tj/commander.js/blob/master/examples/storeOptionsAsProperties-opts.js
(On a related note, we are adding a throw in Commander v6 to detect the clash and offer advice: #1275)
Even in the above example one can't pass in stand-alone flags.
my-program-name -n <value> shows up help.
You have been extra unlucky and picked TWO option names which clash with existing properties on the Command object!
I didn't get your point here. I just have a command that goes by the name sample (takes in an option -a,--action) and a standalone flag -n, --name.
@shadowspawn hope you understood my concern.
Oh, I see your first issue now, sorry. My other remarks may or may not turn out to be useful!
Your top-level program does not have an action handler. So when you type [cli-name] -n <name> as a standalone option, Commander sees:
sample)so it displays the help since you need to specify a subcommand to do anything with this program. (This is a change in behaviour in Commander v5. Older versions would just return and display nothing, which people found unhelpful.)
% node sample.js
Usage: sample [options] [command]
Options:
-n,--name <name>
-h, --help display help for command
Commands:
sample [options]
help [command] display help for command
% node sample.js -n John sample
[Function: action]
Note that action seems to be a function... Those other comments I was making will be relevant...
I assume commander.js won't be the way to go based on my use cases (standalone flags).
no action handler to call on the main program
@shadowspawn can you please elaborate on this?
no action handler to call on the main program
@shadowspawn can you please elaborate on this?
Your first/root command chain doesn't specify an action handler so it doesn't do anything.
I.e. this part of your example
program
.option('-n,--name <name>');
It's probably expecting:
program
.option('-n,--name <name>');
.action((options) => console.log(options.name));
[...]
For a program with no subcommands, Commander leaves it up to you what to do when there are no arguments. Your program may not require any options to be specified, like the ls command. Often the program logic will be after the call to parse rather than putting it into an action handler
.option('-t, --test', 'run all tests');
program.parse();
console.log(program.opts());
$ node simple.js
{ test: undefined }
$ node simple.js -t
{ test: true }
For a program with subcommands and no action handler, Commander assumes the most useful thing to do is display the help when there are no arguments. If you want different behaviour then just add an action handler (even an empty one!) so Commander can tell you have it covered.
const { program } = require('commander');
program
.storeOptionsAsProperties(false)
.passCommandToAction(false);
program
.option('-n,--name <name>')
.action((options) => {
console.log(options.name);
});
program
.command('sample')
.option('-a,--action <action>')
.action((options) => {
console.log(options.action);
});
program.parse(process.argv);
% node my-way.js -n John
John
% node my-way.js sample --action jump
jump
You might also be interested in the "default" command support if --name is not intended to be global (and used by sample). When a subcommand is not specified, including when there are no arguments, the "default" command is called.
Well that is probably way more info that you were expecting! Hopefully some of it is useful and gets you going past your original question and beyond. Sorry you stumbled over a built-in behaviour.
Thanks for clarifying guys 馃檹
program.command('sample').option('-o,--output <value>').action((cmd) => console.log(cmd.output))
program.option('-o,--output <value>').action((option) => console.log(option.output))
// parse args
program.parse(process.argv);
It seems global flags take precedence when subcommand and standalone flags have the same name. Is this an intended behavior?
/cc @shadowspawn
1) Yes. Basically you don't want to have flags with the same name at different levels. The parsing runs from the root command down to the subcommand and so the global flags take precedence and prevent the subcommand flag from being set.
2) You are logging cmd.test and option.target in your example program, but I would expect you want cmd.output and option.output from your option names? (I suspect the logging is left over from checking what happens when the names are not the same!)
You are logging cmd.test and option.target in your example program, but I would expect you want cmd.output and option.output from your option names? (I suspect the logging is left over from checking what happens when the names are not the same!)
Yes indeed 馃槄
Most helpful comment
Your first/root command chain doesn't specify an action handler so it doesn't do anything.
I.e. this part of your example
It's probably expecting: