blyxxyz / lexopt

Minimalist pedantic command line parser
MIT License
294 stars 9 forks source link

Parser's value() method and dashes #14

Closed mllken closed 1 year ago

mllken commented 1 year ago

The docs for Parser's value() method state:

"A value is collected even if it looks like an option (i.e., starts with -)."

This causes friction when parsing an option that takes a value. e.g. say I have a

usage: prog [-v] [-o file]

handling the -o case:

Short('o') => filename = parser.value()?,

If the user runs "prog -o -v", then '-v' becomes the filename, without any error. I would expect calling .value() to return an Err if the value starts with '-'.

I think returning an error would make it more consistent with Parser's values() method, which returns an error if the first value contains a dash. And also with Parser's next() method, which cannot return a Value(value), where value contains a dash.

Could we error if the return value to parser.value() starts with a '-' ? Or let me know if I'm missing something here. Thanks

BurntSushi commented 1 year ago

Why do you want it to return an error? I think that would imply that a flag's value could never start with a -, which seems... not great? Consider, for example, how grep -e -foo is used to search for the literal -foo since grep -foo won't work since the -f is interpreted as a flag. (There are other work-arounds, but using -e -foo is a very popular one.)

Also, presumably, if you want an error to occur for your use case, then you need only check if - is a prefix of the value you get back and return your own error.

mllken commented 1 year ago

Good point - I just checked a bunch of gnu coreutils commands and most do indeed allow flag values (the flag's argument) that start with a dash. I'll use the suggested workaround when I need the stricter checking for dash.

blyxxyz commented 1 year ago

Yeah, my thinking was that

But there are parsers that support it. It's worth thinking about. Some ideas, in descending order of impact:

  1. Configuration on Parser.
  2. A helper function or method in the library.
  3. An example helper function in the repository that you can copy/paste into your own codebase.

(I'm not sure if any of these meet the bar to be included.)

Ideally it should be aware of the previous option so it can give a good error message. That's problematic for 3 since you have to drop the Arg before calling parser.value(), but that could be solved with a new method on Parser to retrieve the last option (which it remembers anyway).

blyxxyz commented 1 year ago

Also, presumably, if you want an error to occur for your use case, then you need only check if - is a prefix of the value you get back and return your own error.

The best workaround is probably parser.values()?.next().unwrap(). It accepts --option=-value and returns an error if not at least one value can be found (so the unwrap never fails).