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

Add support for variadic args on options #571

Closed
develmts opened this issue Sep 18, 2016 · 22 comments
Closed

Add support for variadic args on options #571

develmts opened this issue Sep 18, 2016 · 22 comments
Milestone

Comments

@develmts
Copy link

Seems pretty obvious to me that is perfectly possible ( and even reasonable) to be able to send a unkown length list of values for an option, and agree that being that the scenario, it could only be applied to last option ( or, optionally, until we find some kind of "terminate" char combo ( "--" would be great, but probably mess with some command shells)

it's doable?

@amonks
Copy link

amonks commented Oct 5, 2016

@develmts
Copy link
Author

develmts commented Oct 5, 2016

It specifies exactly "The last argument of a command can be variadic"
And If there isn't a command ?
I was asking for something like

myapp --list-of-files-to-use file1 file2 file3

@amonks
Copy link

amonks commented Oct 5, 2016

Could you use the args value?

myapp --option value file1 file2 file3 --optionb value file4

# //=> command.parse().args === ['file1', 'file2', 'file3', 'file4']

If you needed to, you could add a --use-a-list-of-files toggle, if it's set, you treat args as a list of files.

@develmts
Copy link
Author

develmts commented Oct 6, 2016

That's what I'm using right now. but it would be nice to be able to specify

var cmdr=  require('commander')
cmdr.version('1.0.0')
        .usage('something')
        .option('-m, --mods <mod> [otherMods...]', 'some description', [ ])

and after parsing ,commander returns something like:

var modlist = cmdr.mods; // modlist contains ['item1','item2', 'item3']

This is not and "urgent" request . it's just a "nice addition if posible"

@lastmjs
Copy link

lastmjs commented Aug 5, 2017

I'm seeing the need for this as well.

@sntran
Copy link

sntran commented Oct 13, 2017

I was asking for something like

myapp --list-of-files-to-use file1 file2 file3

Another option is to use Coercion (as noted in examples):

program.
  .option('-f, --files <file>', 'A path for file.', function(file, files) {
    files.push(file);
    return files;
  }, [])

When called with:

myapp --files file1 -f file2 --files file3`

Will give you an array of files:

console.log(program.files);
// ['file1', 'file2', 'file3']

@rousan
Copy link

rousan commented Feb 14, 2018

I think support for variadic args on options should be added.

@toniopelo

This comment has been minimized.

@ericnewton76
Copy link

There might be a way to add it but I bet it breaks far more than you'd want.

And realistically it's not normal to want a variable list of values going into an option... nix getopt specs i doubt would have any specs for that... because it makes it hard to determine where to assign values.

@lastmjs
Copy link

lastmjs commented Oct 19, 2018

I've gotten around this by taking in a comma separated list for an option. I take the option value and split the list to get my variadic arguments. I kind of disagree that it's not normal to want variadic values. I have a very legitimate need for them and I'm sure there are many more use cases.

@ericnewton76
Copy link

A command separated list is a fine solution for your problem.

The real issue is when you have a variadic option, and no options between that variadic option and other arguments, they bleed into the variadic. Using a comma separated list helps define for the parser that these arbitiary characters showing up are still part of my --mods option, and not input file arguments (for example)

@shadowspawn
Copy link
Collaborator

shadowspawn commented May 1, 2019

Are there some well known commands with variadic option support? I can't think of one. (I am not suggesting it isn't potentially useful, but am interested in prior art.)

As mentioned in the previous comments, two conventional ways of doing multiple values for an option (and covered in Open Group Utility Conventions) are:

example -f alpha -f beta -f gamma
example -f alpha,beta,gamma

@gaycomputers
Copy link

This is a pretty necessary feature, you can see multiple alternatives to commander implementing it. If I make anything for a pipeline, I'm going to want to be able to pass a variadic amount of files or whatever to it. The comma and multi-flag work arounds are janky.

@shadowspawn
Copy link
Collaborator

shadowspawn commented Jul 10, 2019

I see Yargs has https://yargs.js.org/docs/#api-arraykey and uses the -- terminator suggested by the original poster.

Update: this comment says does Yargs not use -- as array terminator anymore: yargs/yargs#1527 (comment)

@shadowspawn
Copy link
Collaborator

shadowspawn commented Mar 28, 2020

I have been thinking about how this might be implemented and be as consistent as possible with existing processing. Proposal:

  1. Syntax:
program
   .option('-m, --mods <mod...>'),
   .option('-o, --optional [opts...]')
  1. If a value or values are specified then the option value is an array.

  2. The first option argument is parsed in the same way as if the ... was not specified.

  3. Subsequent option arguments are processed as for optional options ([value]), so a leading - or -- indicates an option and not a further argument. A lone -- stops the option processing as normal.

Example:

$ transpile --include *.js --exclude *.test.js -- thisIsAnOperandNotAnOptionValue

@gaycomputers
Copy link

need any help?

@shadowspawn
Copy link
Collaborator

Since you ask, I have some questions about your previous comment @trisimix , thanks!

you can see multiple alternatives to commander implementing it

What alternatives? (other than yargs which I found)

Adding variadic option values adds some ambiguities into the parsing. I am interested in seeing the syntax and trade-offs other alternatives have taken.

Variadic option values are not covered by the Open Group Utility Conventions and I am also interested if there is a common approach for terminating the option values from other implementations, or explicit coverage in other standards.

If I make anything for a pipeline, I'm going to want to be able to pass a variadic amount of files or whatever to it.

What is an example call to your command going to look like?

(I wasn't sure what you meant by a pipeline and how you want to call your command, which required variadic options and not just variadic arguments.)

@majidsajadi
Copy link

I'm seeing the need for this too.
I'm developing an Express CLI helper which creates controller and routers and models as well.

For example the command for creating a new model is:

shirdal make:model <model-name> --attributes title:string,body:text

I guess every one prefer a command like this:

shirdal make:model <model-name> --attributes title:string body:text

I can't use variadic arguments in command because i may need to add more options like associations.

The problem got more complicated in creating router files.
The command is something like this which is not nice at all:

shirdal make:router<router-name> --routes post:/,get:/,delete:/:id

@gaycomputers
Copy link

gaycomputers commented Mar 29, 2020

Sorry for delay, I actually don't even remember posting this, I just got the notification in email. I was neck deep in some typescript jenkins pipeline stuff for a company I don't currently work for when I wrote my original comment, and to be honest I don't even remember what work-around we used haha. Sorry to be of no help for your background research. Still willing to help if I can.

What is an example call to your command going to look like?

For us we were creating pipeline tools to do some wacky things like black box testing of language models, and creating of confusion matrices.

So a loose example without exactly remembering what I did...
We might want to break up our black box tests an be able to:
blackbox --tests test_file_for_english.json test_file_for_spanish.json
In our jenkins pipeline this might get called automatically when someone tries to push a change to our english and spanish language models, then either pass or blow-up and return a confusion matrix.

Sorry if I totally missed the scope of info you are looking for :P

@shadowspawn
Copy link
Collaborator

For comparison, python argparse uses nargs to specify number of expected values, including + and *:

@shadowspawn
Copy link
Collaborator

I have opened a PR with a work in progress: #1250
Fairly happy with how it has worked out so far.

@shadowspawn shadowspawn self-assigned this Apr 23, 2020
@shadowspawn shadowspawn added the pending release Merged into a branch for a future release, but not released yet label Jun 1, 2020
@shadowspawn shadowspawn added this to the v6.0.0 milestone Jun 20, 2020
@shadowspawn
Copy link
Collaborator

Released with Commander v6.0.0 : https://github.com/tj/commander.js/releases/tag/v6.0.0

@shadowspawn shadowspawn removed the pending release Merged into a branch for a future release, but not released yet label Jul 19, 2020
@shadowspawn shadowspawn removed their assignment Mar 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants