75lb / command-line-args

A mature, feature-complete library to parse command-line options.
MIT License
679 stars 107 forks source link

Unclear behavior with defaultOption and more-than-one multiple args #125

Closed besfahbod closed 2 years ago

besfahbod commented 2 years ago

Given this config:

const optionDefinitions = [
  { name: 'verbose', alias: 'v', type: Boolean },
  { name: 'src', type: String, multiple: true },
  { name: 'foo', type: String, multiple: true, defaultOption: true },
  { name: 'timeout', alias: 't', type: Number }
]

It is not clear what would be the behavior for:

$ example --verbose --timeout=1000 --src one.js two.js three.js

What's clear here:

What's not clear here:

The common-best-practice (specifically in unix-like systems) is to have two.js and three.js as foo values. However, the examples in README.md have a light indication that these values would be considered as src's. (At least some people that I have talked to have had this understanding from the doc.)

Would be great if we could make this more clear in the docs.

75lb commented 2 years ago

Hi.. yes, multiple uses "greedy" parsing so --src and --foo will consume everything in front until the next option is found.. With your example, you have a few choices:

besfahbod commented 2 years ago

Thanks for the explanation, @75lb! Makes sense.

Question: Can you elaborate on how you ended up with this design, instead of the POSIX/*nix common-practice of args only taking at most one token after them?


Anyways, I like to note that, the main point of filing this task was to ask for update/improvement to the main documentation of the project, so that the behavior is more clear for anyone not too familiar with this library. Explicitly, I think it would worth that the docs somehow answer the question original posted here, since it's kind of an "uncommon" behavior in this area.

75lb commented 2 years ago

POSIX/*nix common-practice of args only taking at most one token after them?

How would you prefer/expect to write a command like the following which processes multiple files using multiple plugins?

$ example --files one.js two.js --plugins first.js second.js more-plugins/*.js
besfahbod commented 2 years ago

So, in POSIX proper, enabling multiple plugins would be like -p first.js -p second.js -p "more-plugins/*.js" (the command would be responsible for glob expansion).

And GNU adds the long options (doube-hyphen), allowing --plugin first.js --plugin second.js ....

https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html

I think the idea is that if you expect many arguments of some kind, you would make sure there's a short form for it, keeping the overhead low.

That said, the POSIX and GNU behaviors are kind of ancient now, and some newer major products actually use something a bit more flexible than that. However, I'm not familiar with any major system behavior the way this project does.

I wanted to refer to the docs for Rust's clap library on how they handle multiple occurrences (which I believe should be GNU-friendly), however I couldn't find it in the docs, and I think we need to write a demo for it to show how it behaves... (https://docs.rs/clap/latest/clap/)

75lb commented 2 years ago

enabling multiple plugins would be like -p first.js -p second.js -p "more-plugins/*.js" (the command would be responsible for glob expansion).

the majority of users don't quote glob expressions, meaning the shell expands the glob expression before passing the result into node.. this results in command-line-args parsing a process.argv looking something like ['-p', 'more-plugins/one.js', 'more-plugins/two.js', 'more-plugins/three.js'] (i.e. an option followed by one or more values).. We need to support this form..

And GNU adds the long options (doube-hyphen), allowing --plugin first.js --plugin second.js ....

Use lazyMultiple to get this syntax form in command-line-args..

Thanks for the feedback - if you have ideas to improve the documentation, feel free to edit the wiki or submit a PR.. i too will review the docs when I get round to working on the next version..