-
Notifications
You must be signed in to change notification settings - Fork 10
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
docs: ordering of positional and option does not matter #46
Conversation
@@ -150,7 +150,7 @@ const { flags, values, positionals } = parseArgs(argv, options); | |||
### F.A.Qs | |||
|
|||
- Is `cmd --foo=bar baz` the same as `cmd baz --foo=bar`? | |||
- Yes, if `withValue: ['foo']`, otherwise no | |||
- yes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some commands force positional to come after dashed args. Is this possible to configure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short version: no, not possible to configure.
For interest, ordering is a difference between the POSIX specification and what GNU does.
https://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html
It is a good idea to follow the POSIX guidelines for the command-line options of a program. The easiest way to do this is to use getopt to parse them. Note that the GNU version of getopt will normally permit options anywhere among the arguments unless the special argument ‘--’ is used. This is not what POSIX specifies; it is a GNU extension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
git
forces this; i think people will be surprised if it's not configurable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a potential difference between ordering of options relative to subcommands and ordering of options relative to positional.
I did a quick check and not seeing git
enforcing order of options and positional:
% git switch --no-guess main
Switched to branch 'main'
Your branch is up to date with 'upstream/main'.
% git switch feature/basic-short
Switched to branch 'feature/basic-short'
Your branch is up to date with 'origin/feature/basic-short'.
% git switch main --no-guess
Switched to branch 'main'
Your branch is up to date with 'upstream/main'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've never used git switch
; try git diff package.json -w
and you'll get fatal: option '-w' must come before non-option arguments
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Digging into the git behaviour. git switch
is fairly new. I do see the error with git diff
, interesting thanks. I tried another "old" command, and again ordering not enforced:
% git clone [email protected]:tj/commander.js.git --bare
Cloning into bare repository 'commander.js.git'...
I speculate that there is potential for confusion with <path>
and options, so git diff
has different rules. The help does explicitly show [--]
on each of the variations that may take a "path".
SYNOPSIS
git diff [<options>] [<commit>] [--] [<path>...]
git diff [<options>] --cached [--merge-base] [<commit>] [--] [<path>...]
git diff [<options>] [--merge-base] <commit> [<commit>...] <commit> [--] [<path>...]
git diff [<options>] <commit>...<commit> [--] [<path>...]
git diff [<options>] <blob> <blob>
git diff [<options>] --no-index [--] <path> <path>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the Big Four parsing libraries, all of them support options after positional by default. None of them support making it an error.
Three support a mode where parsing stops after the first non-option, so the remaining arguments can be passed through to another command (say).
- minimist:
opts.stopEarly
- yargs:
halt-at-non-option
- commander:
passThroughOptions
By default argParse
allows options before positionals, or options after positionals, but will display an error for inter-mixed options and positionals. You can opt-in to mixing them by using parser.parse_intermixed_args(args)
. The opt-in is because intermixing interacts with a few of the other opt-in features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if you were to build library with more complex command handling behavior, e.g., a hierarchy of commands like yargs' .command
, you will end up needing to pre-process process.argv
, at which point you could decide whether or not to remove leading dashed arguments.
For simplicity, I like the decision this PR lands on.
Options can come before or after positional. The option type does not matter for the example given.
(If it is an error or some snowflake result because not
withValue
, it will still behave the same for both argument orders!)