docopt.rs icon indicating copy to clipboard operation
docopt.rs copied to clipboard

confusing failure mode when usage and option sections are inconsistent

Open xTibor opened this issue 8 years ago • 2 comments

When the following test program is executed with --output out --input in arguments, the values switch places, the input variable in Args gets "out" and the output one gets the "in" value.

I encountered this issue with 0.8.1 and the latest nightly (rustc 1.21.0-nightly).

Test program

extern crate docopt;
#[macro_use]
extern crate serde_derive;

use docopt::Docopt;

const USAGE: &'static str = "
Usage:
    xxxx [--input <input>] [--output <output>]
    xxxx --help

Options:
    -i, --input   Input file
    -o, --output  Output file
    -h, --help    Display this message
";

#[derive(Debug, Deserialize)]
struct Args {
    arg_input: Option<String>,
    arg_output: Option<String>,
}

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

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

Result

Args { arg_input: Some("out"), arg_output: Some("in") }

Expected result

Args { arg_input: Some("in"), arg_output: Some("out") }

xTibor avatar Aug 04 '17 22:08 xTibor

I don't think there's any bug here, but the failure mode is obviously bad.

There are two errors in your example code. Firstly, your option description section needs to indicate that a flag takes an argument. So instead of -i, --input, you'd write -i, --input <input>. Secondly, your members in your Args struct have an arg prefix, but they are flags, which means they need a flag prefix. arg is for positional arguments. This behavior is documented on the ArgvMap::deserialize method.

Ideas on how to improve the failure modes here would be appreciated. It seems like the least we could do is report the inconsistency between the flag definition --input <input> in the USAGE section and the inconsistent -i, --input definition in the option description section.

BurntSushi avatar Aug 04 '17 23:08 BurntSushi

Oh, sorry for mixing these things up in the example. I just assumed something's wrong with the crate because it acted weird in this case and didn't throw errors at me (like it does for the missing args).

xTibor avatar Aug 04 '17 23:08 xTibor