c-blake / cligen

Nim library to infer/generate command-line-interfaces / option / argument parsing; Docs at
https://c-blake.github.io/cligen/
ISC License
509 stars 24 forks source link

`-fbar` is ambiguous and not self consistent; should that be disallowed? #82

Closed timotheecour closed 5 years ago

timotheecour commented 5 years ago

-fbar currently means --foo=bar -f:bar also means --foo=bar

so when you have: ./main -f$myfoo in a shell, it'll strip the 1st char from $myfoo depending on whether env variable myfoo starts with : or = likewise if assembling cmd from a program, eg:

let cmd = "-f" & val # same issue

that's not so good

But there are other issues: -f-=bar prefers the interpretation of ( -= operator with bar argument), but clang would give it interpretation of -=bar argument

in summary:

what are your thoughts?

alternative proposal

introduce a new always available meta flag (along with --help and --help-syntax) that user can set to choose strict mode or lax mode: --cligen-mode:strict|lax (defaulting to strict, so that when -fbar is passed, the error msg will say : pass --cligen-mode:lax or specify -f:bar; that would make it easy to port existing cmdline to cligen: all needed is to pass --cligen-mode:lax if needed)

c-blake commented 5 years ago

Personally, I am very used to -fbar without a separator..even -abcdfbar with a bunch of bools and trailing f. It's lack in the main Nim parseopts was one of my main motivations writing cligen in the first place, actually. I even got longNoVal and shortNoVal into the main Nim stdlib parseopt. So, this is ambiguity very much all on purpose.

Multiple ways to spell things can always be considered either error prone if you don't know them all or a feature if you do. Most of this syntax goes back to the old Unix getopt anyway, but just for short options. That would let you go -f<space>arg or -farg. long options added the = and Nim/Windows added the :. We have a permissive syntax that accepts all these. I think that's the right default/leads to the least CLI user frustration..certainly to the least frustration by me.

A concerned CLI enter-er/string builder can always just enter the operators in a stylized way like -f=bar if they're worried..that seems actually easier than using some --cligen-mode thing. In your cmd & val example you can just go cmd & "=" & val or make sure options that take values end with an = or : or put it in a separate array slot if you're building a seq[string]. You've given an example of a way to mess up by accident, but there are also ways to not mess up. So, it's not irresolvable ambiguity or ambiguity with no workaround.

A concerned CLI author can also already take the choice away with requireSeparator=true. I'm against changing that default in dispatch. I'm not wanting to be a petty tyrant about it, but it would take quite a lot more than just 1 person asking for a flip because it might cause trouble to get me to do it. Sure, I could change all my own dispatch-using programs because for certain my programs will have requireSeparator=false, but there are like 84 star-ers on the repo and probably most of them are fine with that default as-is.

Of course clang (which has no -= or += or ^=) treats them as just option arguments. That's just an artifact of our having advanced/more syntax. There are just going to be things we treat a little differently, but we accrue value from those differences like prepending and split mode and so on. We have --help-syntax now. It's just an explanation/condensation challenge.

So, I just don't see any "real" problem in this bundle of concerns. TL;DR - -fbar is awesome. It should totally work as it does now.

c-blake commented 5 years ago

Another "TL;DR" is "just always use = or another arg slot if you're worried". IMO, that rule is way easier to keep track of than --cligen-mode complexities and generalizes to commands using other CLI toolkits. Admittedly, there is lack of standardization that in other toolktis sometimes you need = and sometimes you need a 2nd argument whereas cligen allows both (sort of the CLI version of UFCS).

I also feel like overall command syntax determination is a CLI author choice. Very few/no CLI users would ever want to adjust their syntax as they go on a per-command basis. Maaaybe some set&mostly forget environment variable $CLIGEN could, but not per-invocation basis with an extra meta-flag. Sure, we have the new DPSV, but with that external data like files & strings drive the need (and we could probably do everything with just a truncate operator that ignored the val and make people re-issue and learn shell quoting, but I like what we did). Your concern is more about ignorance of syntax optionality which means a CL user learning rules, but we already have simple rules/remedies.

One thing we don't do, but maybe could in this space of what CL syntax should be/controlling optionality|multiple ways to spell things, would be to support long-options with just one dash like gcc. This would be a parseopt3 extension that could perhaps even be activated by short={"": 'x'} (currently that disables all short options, but -- is still required). If we did that, I'd probably lean toward allowing both - and -- by default (even though yeah, yeah, any optionality makes "building up" strings more fragile). Nobody's asked for this single-dash-long, and I would not use it myself, but it could probably be supported in a way that was invisible to any existing CLI authors who didn't care. So, I'd probably just defer that work and say PRs welcome on it.

c-blake commented 4 years ago

It is now possible, incidentally, for end-CLI users to alter cligen syntax to requireSeparator in the main config file if they hate this default. A tyrannical CL author should still be able override that (or anything in the config) to demand a separator, though.