structopt v0.3.0 Release Notes

Release Date: 2019-08-30 // over 4 years ago
  • ๐Ÿ’ฅ Breaking changes

    โฌ†๏ธ Bump minimum rustc version to 1.36 by @TeXitoi

    ๐Ÿ‘ Now rustc 1.36 is the minimum compiler version supported by structopt, it likely won't work with older compilers.

    โœ‚ Remove "nightly" feature

    Once upon a time this feature had been used to enable some of improvements in proc-macro2 crate that were available only on nightly. Nowadays this feature doesn't ๐Ÿšš mean anything so it's now removed.

    ๐Ÿ‘Œ Support optional vectors of arguments for distinguishing between -o 1 2, -o and no option provided at all by @sphynx (#180).

    #[derive(StructOpt)]
    struct Opt {
      #[structopt(long)]
      fruit: Option<Vec<String>>,
    }
    
    fn main() {
      assert_eq!(Opt::from_args(&["test"]), None);
      assert_eq!(Opt::from_args(&["test", "--fruit"]), Some(vec![]));
      assert_eq!(Opt::from_args(&["test", "--fruit=apple orange"]), Some(vec!["apple", "orange"]));
    }
    

    If you need to fall back to the old behavior you can use a type alias:

    type Something = Vec<String>;
    
    #[derive(StructOpt)]
    struct Opt {
      #[structopt(long)]
      fruit: Option<Something>,
    }
    

    ๐Ÿ”„ Change default case from 'Verbatim' into 'Kebab' by @0ndorio (#202).

    structopt 0.3 uses field renaming to deduce a name for long options and subcommands.

    #[derive(StructOpt)]
    struct Opt {
      #[structopt(long)]
      http_addr: String, // will be renamed to `--http-addr`
    
      #[structopt(subcommand)]
      addr_type: AddrType // this adds `addr-type` subcommand
    }
    

    structopt 0.2 used to leave things "as is", not renaming anything. If you want to keep old behavior add #[structopt(rename_all = "verbatim")] on top of a struct/enum.

    ๐Ÿ”„ Change version, author and about attributes behavior.

    Proposed by @TeXitoi (#217), implemented by @CreepySkeleton (#229).

    structopt have been deducing version, author, and about properties from Cargo.toml for a long time (more accurately, from CARGO_PKG_... environment variables). But many users found this behavior somewhat confusing, and a hack was added to cancel out this behavior: #[structopt(author = "")].

    In structopt 0.3 this has changed.

    • 0๏ธโƒฃ author and about are no longer deduced by default. You should use #[structopt(author, about)] to explicitly request structopt to deduce them.
    • 0๏ธโƒฃ Contrary, version is still deduced by default. You can use #[structopt(no_version)] to cancel it out.
    • #[structopt(author = "", about = "", version = "")] is no longer a valid syntax and will trigger an error.
    • #[structopt(version = "version", author = "author", about = "about")] syntax stays unaffected by this changes.

    ๐Ÿšš Raw attributes are removed (#198) by @sphynx

    In structopt 0.2 you were able to use any method from clap::App and clap::Arg via raw attribute: #[structopt(raw(method_name = "arg"))]. This syntax was kind of awkward.

    #[derive(StructOpt, Debug)]
    #[structopt(raw(
        global_settings = "&[AppSettings::ColoredHelp, AppSettings::VersionlessSubcommands]"
    ))]
    struct Opt {
        #[structopt(short = "l", long = "level", raw(aliases = r#"&["set-level", "lvl"]"#))]
        level: Vec<String>,
    }
    

    Raw attributes were removed in 0.3. Now you can use any method from App and Arg directly:

    #[derive(StructOpt)]
    #[structopt(global_settings(&[AppSettings::ColoredHelp, AppSettings::VersionlessSubcommands]))]
    struct Opt {
        #[structopt(short = "l", long = "level", aliases(&["set-level", "lvl"]))]
        level: Vec<String>,
    }
    

    ๐Ÿ‘Œ Improvements

    ๐Ÿ‘Œ Support skipping struct fields

    Proposed by @Morganamilo in (#174) implemented by @sphynx in (#213).

    Sometimes you want to include some fields in your StructOpt struct that are not options and clap should know nothing about them. In structopt 0.3 it's possible via the 0๏ธโƒฃ #[structopt(skip)] attribute. The field in question will be assigned with Default::default() value.

    #[derive(StructOpt)]
    struct Opt {
        #[structopt(short, long)]
        speed: f32,
    
        car: String,
    
        // this field should not generate any arguments
        #[structopt(skip)]
        meta: Vec<u64>
    }
    

    โž• Add optional feature to support paw by @gameldar (#187)

    Significantly improve error reporting by @CreepySkeleton (#225)

    Now (almost) every error message points to the location it originates from:

    error: default_value is meaningless for bool
      --> $DIR/bool_default_value.rs:14:24
       |
    14 |     #[structopt(short, default_value = true)]
       |                        ^^^^^^^^^^^^^