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

Short options with arguments conflicts with AllowHyphenValues #3410

Open
2 tasks done
HeroicKatora opened this issue Feb 6, 2022 · 2 comments
Open
2 tasks done

Short options with arguments conflicts with AllowHyphenValues #3410

HeroicKatora opened this issue Feb 6, 2022 · 2 comments
Labels
A-parsing Area: Parser's logic and needs it changed somehow. C-enhancement Category: Raise on the bar on expectations E-medium Call for participation: Experience needed to fix: Medium / intermediate

Comments

@HeroicKatora
Copy link
Contributor

HeroicKatora commented Feb 6, 2022

Please complete the following tasks

Clap Version

3.0

Describe your use case

The program GNU seq requires us to parse floating point values as arguments, which may be negative or have formatting different from the standard <f64 as FromStr> style. At the same time it accepts some short options to control the output. The problematic case is combining those two: we must utilize AllowHyphenValues while also accepting short option values.

$ seq -s, -1 2
-1,0,1,2
$ # Demonstrating non-f64-style arguments that must also match positional values:
$ seq -0x.ep-3 -0x.1p-3 -0x.fp-3
-0,109375
-0,117188

This is solved in GNU by external iteration over the arguments where seq itself decides what constitutes a flag, and what starts the value arguments: https://github.com/coreutils/coreutils/blob/master/src/seq.c#L593-L604

In clap, however, when AllowHyphenValues is active then only short options character are allowed to appear in an option. Otherwise, it is interpreted as a position argument. See

clap/src/parse/parser.rs

Lines 994 to 995 in 5c3868e

} else if self.is_set(AS::AllowHyphenValues)
&& arg.chars().any(|c| !self.app.contains_short(c))

Describe the solution you'd like

Now, I would propose to add a new setting that slightly modifies these rules. Where an hyphenated argument may start with short options but where short option parsing stops at the first value-taking option, and any other characters are permitted when such an option is recognized. That is, in this context, where the short options w and s exist, -ws, would be interpreted as:

  1. w matches a short option without argument, continue.
  2. s matches a short option that does take an argument, switching to value mode because this option takes a value.
  3. - is ignored as part of the value.
  4. The argument -ws, is interpreted as options.

Alternatives, if applicable

A more intricate solution would be to enable external iteration, where arguments are consumed by clap one-by-one. That is, more like the GNU style parsing loop where some get_first_argument(iterator) consumes only some arguments from the iterator but returns control to the caller after the first option has been consumed. This could enable an iteration loop in the style of GNU seq where the arguments are pre-tested by the program logic on whether they constitute a positional argument; allowing us to break manually instead of require AllowHyphenValues to control clap to do this internally.

Additional Context

@HeroicKatora HeroicKatora added the C-enhancement Category: Raise on the bar on expectations label Feb 6, 2022
@HeroicKatora
Copy link
Contributor Author

HeroicKatora commented Feb 6, 2022

Sorry, I forgot to fill out additional context: It's mentioned in uutils/coreutils: uutils/coreutils#3081

@epage epage added A-parsing Area: Parser's logic and needs it changed somehow. E-medium Call for participation: Experience needed to fix: Medium / intermediate labels Feb 7, 2022
@epage
Copy link
Member

epage commented Feb 7, 2022

Now, I would propose to add a new setting that slightly modifies these rules. Where an hyphenated argument may start with short options but where short option parsing stops at the first value-taking option, and any other characters are permitted when such an option is recognized

I think this makes sense

A more intricate solution would be to enable external iteration, where arguments are consumed by clap one-by-one. That is, more like the GNU style parsing loop where some get_first_argument(iterator) consumes only some arguments from the iterator but returns control to the caller after the first option has been consumed. This could enable an iteration loop in the style of GNU seq where the arguments are pre-tested by the program logic on whether they constitute a positional argument; allowing us to break manually instead of require AllowHyphenValues to control clap to do this internally.

This sounds more like lexopt. We have plans to modularize clap so we provide a lexopt-like crate and allow you to use all of the other parts of clap built up together.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-parsing Area: Parser's logic and needs it changed somehow. C-enhancement Category: Raise on the bar on expectations E-medium Call for participation: Experience needed to fix: Medium / intermediate
Projects
None yet
Development

No branches or pull requests

2 participants