Skip to content
This repository has been archived by the owner on Sep 14, 2023. It is now read-only.

When repeated short and long =value flags are aliases, only one is deserialised #243

Open
OJFord opened this issue Sep 3, 2018 · 2 comments

Comments

@OJFord
Copy link

OJFord commented Sep 3, 2018

Sorry for the title... essentially when [-a... | --long-a=<val>] the value is only deserialised for the one specified in the struct. Contrast [-b | --bee] as Boolean flags, when the value of whichever is given is available as e.g. flag_bee; flag_b need not be specified.


Here's a reproduction:

[dependencies]
docopt = { version = "1.0.1"}
log = {version = "0.4.5"}
serde = { version = "1.0.76" }
serde_derive = { version = "1.0.76" }
stderrlog = { version = "0.4.1"}
extern crate docopt;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate stderrlog;

use docopt::Docopt;

const USAGE: &'static str = "
Reproduction.

Usage:
  repro [-q | --quiet | -v... | --verbosity=<v>]

Options:
  -q --quiet                Disable stderr logging.
  -v... --verbosity=<v>     Verbosity of stderr logging.
";

#[derive(Debug, Deserialize)]
struct Args {
    flag_quiet: bool,
    flag_verbosity: usize,
}

fn main() {
   let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    println!("{:?}", args);

    stderrlog::new()
            .module(module_path!())
            .quiet(args.flag_quiet)
            .timestamp(stderrlog::Timestamp::Second)
            .verbosity(args.flag_verbosity)
            .init()
            .unwrap();
    trace!("trace message");
    debug!("debug message");
    info!("info message");
    warn!("warn message");
    error!("error message");
}

Then:

$ cargo run -- --verbosity=2
Args { flag_quiet: false, flag_verbosity: 2 }
2018-09-03T20:50:56+01:00 - INFO - info message
2018-09-03T20:50:56+01:00 - WARN - warn message
2018-09-03T20:50:56+01:00 - ERROR - error message

so far so good.

$ cargo run -- -vvv
Args { flag_quiet: false, flag_verbosity: 0 }
2018-09-03T20:51:43+01:00 - ERROR - error message

Not so good. I thought maybe the issue was using the short while deserialising the long name, but:

$ cargo run -- -q
Args { flag_quiet: true, flag_verbosity: 0 }

so it does appear to be the interaction between ... and =<v>.


Less-than-ideal workaround with particular respect to integer flags, just in case someone stumbles here with a similar use case:

  • separate lines in Options
  • add flag_v: usize, toArgs
  • .verbosity(args.flag_verbosity + args.flag_v) (since docopt takes care of at most one being non-zero)
@BurntSushi
Copy link
Member

I don't think this is a bug. A flag can't both simultaneously accept a value and be a countable switch AFAIK.

@OJFord
Copy link
Author

OJFord commented Sep 4, 2018

Thanks for the fast response. I could readily accept that, when you put it like that, but it does seem to work in the Python implementation.

See here - not allowed both, but works when you delete one or other.

Of course, the python implementation (and by extension the online thing) differ in not having serde build a struct of args and flags.

So I suppose it's really a question for you & team whether it should be allowed or not.

If I may advocate for my desired behaviour: I'd say it's consistent with:

-q --quiet  Be quiet.

implying that either flag can be used and be accessible on Args#<either>.

Supporting it would of course mean that it'd only work for integer value flags; not a mix of countable switch and string flag, for example.


Feel free to close if not something you want to support, understood.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants