top | item 43453161

(no title)

acmj | 11 months ago

In general, command-line argument parsers should just follow the GNU style. No more, no less. Deviations confuse users as it is not immediately obvious to them what rules a parser is imposing.

> options can have multiple values: -a 1 2 3 means that a is an array/slice/struct of three numbers of value [1,2,3]

Allowing multiple values is inconsistent because you can't tell in "./cmd -a 1 2 3" whether 2 and 3 are positional arguments or arguments for -a. This is not a GNU style. The GNU way is "./cmd -a 1 -a 2 -a 3" (or "./cmd -a 1,2,3"). This package supports that, which is good.

> option values can be separated by a space, equal sign, or nothing: -a1 -a=1 -a 1 are all equal

"--a=1" is a GNU style but "-a=1" is not. This is a minor issue, though.

Also, does this package support "--"? Everything following "--" should be treated as positional arguments.

discuss

order

nloomans|11 months ago

I disagree with it being a minor issue. If I write a shell script around a program that accepts GNU-style arguments, I expect the following to be correct:

    ./cmd -a"$USER_CONTROLLED_DATA"
A program using this package would break that assumption, introducing a bug where this user-controlled data cannot start with an '='.

duckerude|11 months ago

I researched this for my own argument parser (https://github.com/blyxxyz/lexopt/issues/13) and concluded that it's a minor issue.

This syntax is supported by argparse and clap, the most popular argument parsers for Python and Rust respectively, and it seems to have caused almost no problems for them. It's a problem for the uutils implementation of cut, since `cut -d=` is common, but that's the only instance I could find after a long time scouring search engines and bug trackers and asking for examples.

If anyone does know of other examples or other places this has been discussed I'd love to hear it though, maybe I just haven't found them.

(Also, the more reliable way to write this in general is `-a "$USER_CONTROLLED_DATA"`, since that'll behave correctly if $USER_CONTROLLED_DATA is empty. As will `-a="$USER_CONTROLLED_DATA"` if you know the command supports it.)

cb321|11 months ago

It is safer to just put in the space (much like you put in the quotes to be safe). Python's argparse will also accept but not require an `=` separator (maybe optparse, too - I haven't checked that one).

Arch-TK|11 months ago

Unfortunately a lot of people nowadays don't seem to notice or care and you even get weird arguments like the one about "Go style" vs "GNU style" below. I've also heard arguments about making it more "user friendly" (at the cost of any power user wanting to re-write your tool).

I wouldn't mind if GNU style was consistently extended to allow annotated required arguments. But that's about it.

That being said. As a rule, if your command line utility has enough positional arguments that you're forgetting which one is which, it's a badly designed command line interface. Most often it's because you're doing too much, not settling on sensible defaults for things which you shouldn't need to specify every time, or just doing something outright weird.

mjevans|11 months ago

IME commands get there by expressing complexity that belongs in a full configuration file on the command line (as well / instead).

It's nice if things are simple enough that a hand-full or two of flags are sufficient. However more complex programs that do more or substantially different things from traditional bytestream filter programs often do need proper configuration files.

tdewolff|11 months ago

Just to clarify, the documentation was a bit outdated, but `./cmd -a 1 2 3` would not mean an array of `[1,2,3]` but exactly as you mentioned: option `a` with two positional arguments. And yes! The `--` is supported :-)

ants_everywhere|11 months ago

Are you saying this because you think the GNU standard is particularly well thought out, or because it's so common that deviations are confusing in general?

I'm so used to the GNU conventions that I'm not really aware of what the alternatives are or what their merits are.

acmj|11 months ago

The most important part is to have a standard, which doesn't need to be perfect. On argument parsing, I actually think the GNU way is the best so far. I have seen various deviations from GNU and I personally regard all of them inferior.

gjvc|11 months ago

GNU became the de-facto standard at least 20 years ago

marxisttemp|11 months ago

No, command tools should follow the POSIX standards, not GNU.

greyw|11 months ago

POSIX doesnt even define long opts. I conciously dont follow POSIX these days. The standard will adapt once enough pressure has built up as they mostly document existing things instead of innovate. So I need to apply pressure.

masklinn|11 months ago

You're almost right. No command tools should follow the POSIX standard. A standard which all but forbids long options deserves only scorn.

NekkoDroid|11 months ago

POSIX doesn't even provide any utilities to write long opts and it also doesn't even define any long opts for basically any of its commands, so by default it is barely usable in maintainable scripts.

cratermoon|11 months ago

Disagree. Go's style may not be GNU style, but it's consistent in the Go community. GNU style is not All That and a Bag of Chips.

arp242|11 months ago

> it's consistent in the Go community.

Except it's not? There are tons of flag packages in real use, because the stdlib one kind of sucks. Even the "go" tool itself works around some of its limitations (things like "go test ./... -v" won't work out of the box, since it will stop parsing flags at the first non-flag, so the go command reorders os.Args before sending it off to the flag package).

Things like "-a 1 2 3" are not standard "Go style" at all. I've never seen that.

treyd|11 months ago

You can't expect the user to remember upfront what language the tool they're using was written in and context switch the style they're expressing their intents in based on that. The Go community has consistently shown it's not very good at making well-thought out decisions. GNU is obviously the better approach here.

hnlmorg|11 months ago

As a heavy user of Go tooling, I still really dislike Gos style.

acmj|11 months ago

When I use a command-line tool, I don't know and don't care if it is written in Go or not. I just want to use it the same way as most of the other traditional Unix tools. The Go style gets in the way. We would have much more consistent CLI between tools if Go had just followed the GNU style at the beginning. The same can be said to many other languages like Nim that want to reinvent command-line argument parsing with their standard libraries. https://xkcd.com/927/ came to mind.