Eg in hledger 0.21.3, -w50 or --width=50 work, but -w 50 or --width 50 don't (the 50 is parsed as a command argument). The space works as expected with other options like -b, though.
This seems to be an issue with optional-value flags in cmdargs, cf ndmitchell/cmdargs#2.
docs: update manual note re #149
Taking a look at the code, I see https://github.com/simonmichael/hledger/blob/044ba7869353d9dab0e655535867f65cf83d59d0/hledger/Hledger/Cli/Options.hs#L317 . I am pretty sure flagOpt should actually be flagReq and you can delete the first argument. The idea is that with flagOpt "80" (in your case) you are saying that if the user types --width without an argument then that should be equivalent to --width=80. In your case, 80 is the default, so there is really no advantage to ever typing --width or --width=80, so you might as well say if you type --width then you have to have a required argument. As soon as the argument is required cmdargs will look for it in the next argument position if necessary (just like GNU programs etc).
This difference between an optional flag (all flags are optional) and an optional argument to a flag (which is what flagOpt gives) is subtle. I recently revamped the docs for opt to address that point with examples. I guess (if my diagnosis is correct) I should move some of the docs over to flagOpt and flagReq as well.
Thanks for looking at it Neil. But I use -w without an argument to mean
"wider", ie 120 instead of 80.
Ah, ok, I understand now. So it's expected behaviour - you are saying that --width doesn't have to be followed by an argument. e.g. --width --foo should be interpretted as two arguments. As a result, if you do want to give a --width argument you have to do --width=12 or -w=12. All the GNU programs work like this for optional arguments, for example tar --checkpoint.
As a separate suggestion, I would have expected you do do flagOpt with "" as the optional argument, and then make "" be treated specially in your update, likely by multiplying by 3/2. That way -www would give you a Width of 270. I often do this trick with -v for verbosity, so -v=3 or -vvv.
I'm a bit confused, and I'd like to restart this. My wish is that cmdargs' flagOpt will parse -f VAL and --ff VAL the same way it parses -fVAL and --ff=VAL. Ie it would recognise that an argument (not beginning with -) following a flagOpt belongs to that flag. Is this reasonable ?
Documented for users.
I should have mentioned @ndmitchell in that last comment.
So you want -f <X> to parse as -f=<X> if <X> does not start with - and as two separate pieces -f <X> if it doesn't? It's now how things work at the moment, but it's a plausible addition. My concern is that if your command takes files, you could get advice from one place saying "add -f to make the width wider" and from another saying "add test.dat to make it read the file test", but when you put them together it doesn't compose.
Yes. I suppose this kind of optional-value flag is not that common so I don't have a sense of the common practice in other tools. It seems more intuitive to me; as a user I'll be just expecting all flags to follow consistent rules, eg "-b DATE works, why doesn't -w WIDTH ??".
So I'm glad you think it's plausible. I did start to look at the code yesterday.
I'm not quite understanding the problem you mention. In my concrete case, -f/--file and -w/--width are different flags. Am I missing your point ?
What if someone wants to open the --comment file? If they write -f <file> it works, unless that file happens to start with a -, in which case its going to be a flag instead. This approach will only work for flags you know can't legitimately start with a -. Since that basically applies to most flags, I am becoming increasingly convinced that's worth supporting.
Yes, with other unix tools, when dealing with unusual file names such as --comment, I'm used to having to write -f \--comment to disambiguate that.
make --width and --debug require an argument (fixes #149)
This is a workaround for a cmdargs limitation. Having "--debug 2"
or "--width 100" produce no output (because the number is parsed
as a separate argument) is too annoying.
Worked around by making the argument required.