Short arguments are incorrectly handled

Issue #19 resolved
gwern branwen created an issue

The argparser documentation for ‘short’ arguments do not mention any limits on them. It’s fairly common to have two or three-letter abbreviations as the short option form of a long option which is a phrase of multiple words. A user just reported that in my use of it in Resorter, it’s broken.

Consider this shortened example:

#!/usr/bin/Rscript

library(argparser)
p <- arg_parser("foo", name="bar")
p <- add_argument(p, "--no-scale", short="-ns", flag=TRUE, "Do not discretize/bucket the final estimated latent ratings into 1-l levels/ratings; print out inferred latent scores.")
argv <- parse_args(p)

print(argv)

If you run it with -h, it looks exactly as you would expect, the short version is identical to the long version:

$ ./foo.R -h
Loading required package: methods
usage: bar [--] [--help] [--no-scale] [--opts OPTS]

foo

flags:
  -h, --help       show this help message and exit
  -ns, --no-scale  Do not discretize/bucket the final estimated latent ratings into 1-l levels/ratings; print out inferred latent scores.

optional arguments:
  -x, --opts       RDS file containing argument values

If you try to run it, however, it becomes clear that -ns is, contrary to -h, not handled as it’s supposed to be:

$ ./foo.R -ns
Loading required package: methods
usage: bar [--] [--help] [--no-scale] [--opts OPTS]

foo

flags:
  -h, --help       show this help message and exit
  -ns, --no-scale  Do not discretize/bucket the final estimated latent ratings into 1-l levels/ratings; print out inferred latent scores.

optional arguments:
  -x, --opts       RDS file containing argument values

Error in parse_args(p) : 
  Extra arguments supplied: expecting 0 values but got 2 values: (-n, -s).
Execution halted
$ ./foo.R --no-scale
Loading required package: methods
[[1]]
[1] FALSE

$help
[1] FALSE

$no_scale
[1] TRUE

$opts
[1] NA

argparser should handle short arguments as expected and indicated by -h; failing that, it should not allow short arguments it cannot handle, and the documentation should explain what limits there are on short arguments.

Comments (5)

  1. David Shih repo owner

    This behaviour is due to the partial support of the POSIX standard requested quite a few versions ago.

    As per POSIX standard, flags can be concatenated together, so -ns is interpreted as -n and -s.

    Therefore, it is illegal for the short forms to contain multiple characters. You should be using the long-form instead.

    I’ll add a check in add_argument to prevent the developer from specifying arguments having short-forms that contain multiple characters, and additional documentation describing this behaviour. This will however technically be a compatibility breaking change, which will delay release to CRAN. (Granted, I don’t think any existing programs that rely short-form flags with multiple characters are working as intended.)

  2. David Shih repo owner

    To be clear, the intended fix will not make your program functional. It will only throw an error for your program due to incompatibility with POSIX standard, so you should change your program to only use a single character for each short-form.

  3. David Shih repo owner

    For your reference, --no-scale might be abbreviated to -S, just as --scalemight be abbreviated -s, based on typical behaviours for POSIX compliant programs.

  4. gwern branwen reporter

    I see, thanks for adding the checks.

    I did think about having a -Sand the user who pointed out the bug suggested as much, but I dislike it as it is inherently misleading; ‘S' suggests ‘scale’, as in, the opposite of ‘no scale’. Making it ‘S’ (not scaling) vs ‘s' (scaling) may be what some programs do but I find that very unintuitive and didn’t realize that was how one might deal with POSIX, and I’ve used the CLI for ~15 years now. Better to just not provide a short argument for that.

  5. Log in to comment