-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
Is your feature request related to a problem?
As it currently stands, a chain of short command-line options is expanded and treated as if the chained options were provided separately. That is:
- a
-vvvoption is expanded as 3 arguments:-v -v -v - a
-vcoption is expanded as 2 arguments:-v -c - a
-cvoption is expanded as 2 arguments:-c -v
While this behaviour is fine for nullary options like -v, it causes issues with options which take additional arguments.
In particular, if we take the last example from the previous list, it causes issues with nix shell where -c is the short option of --command which takes arguments:
nix shell nixpkgs#hello -cv hellogets expanded tonix shell nixpkgs#hello -c -v helloand nix tries to run-vas the executable.
This behaviour is:
- as far as I'm aware undocumented;
- and (in my opinion) very unintuitive.
Note that while -c is a bit special (as it consumes all of the following arguments), this issue persists with unary and binary options as well, in both flake'y and non-flake'y commands – for an incomplete list of examples:
-k, -s, -iinnix shell&nix run-Aand-Iinnix-shell
Proposed solution
Make the argument parser throw a human-readable error when a non-nullary short option is provided as part of the chain in any position other than the last.
That is, taking nix shell as an example:
-cvwould throw an error, as the non-nullary-cis not the last option in the chain;-vcwould still work, as the non-nullary-cis the last option in
the chain;-vvvwould still work, as it contains no non-nullary options.
As another example, for nix-shell:
-EI,-KAand-vj10would still work;- while
-IA,-Ikand-Ajwould throw the new error message.
Alternative solutions
- Treat everything after the first non-nullary option as the argument to said option
- This would make
-chelloor-Ihereequivalent to-c helloand-I here; - Some existing command-line tools (e.g. GNU tar's
-f, gcc's-I) use this logic; - However, this also causes some issues:
- a transposition like
-cvinstead of-vcwould callv– this is arguably more risky than the status-quo, as single-letter commands might exist and have undesired side-effects, while commands starting with-are almost never seen. - syntax for binary options like
-s/--set-env-varmight be a bit weird.
- a transposition like
- This would make
- Disallow short-option chaining
- Too inconvenient, especially for verbosity (
-vvv)
- Too inconvenient, especially for verbosity (
- Disallow short-option chaining for non-nullary options
- That is, reject
-vcas well and only allow-vvvand similar chains of nullary options - This is a bit inconvenient and inconsistent with other command-line utilities
- That is, reject
- Document the current behaviour
- I believe this to be inadequate, as the current behaviour is unintuitive and is a consequence of the internal parsing implementation details leaking into the outward interface.
Additional context
If this gets accepted, I plan to implement this and send in a patch (I believe it's enough to change the logic src/libutil/args.cc to make the proposed solution work).
The main reason for creating this issue beforehand, is that I am not sure whether this is would be a breaking change or not: there may be some users which depend on the undocumented behaviour of -ci running the -i executable or on -Ik including the -k directory.
(I find it improbable, but Hyrum's law applies).
Checklist
- checked latest Nix manual (source)
- checked open feature issues and pull requests for possible duplicates
Add 👍 to
issues you find important.