Skip to content

default_value and Option? #123

Closed

Description

@lnicola

Right now, they are incompatible, but I'm not sure that's right. For example, I wanted something like my-app --db-path [DB], where there's a default database path if not set.

Is there another way to achieve that?

Activity

  1. TeXitoi commented on Jul 9, 2018

    @TeXitoi
    Owner

    Can you give example of command line and corresponding struct, because I don't understand what you expect.

  2. lnicola commented on Jul 9, 2018

    @lnicola
    Author
    #[derive(Clone, Debug, StructOpt)]
    pub struct Options {
        #[structopt(long = "db", help = "Database path", default_value = "my-app.db")]
        pub db: Option<String>,
    }

    Example usage:

    $ my-app # db is None
    $ my-app --db # db is Some("my-app.db")
    $ my-app --db foo.db # db is Some("foo.db")
    
  3. TeXitoi commented on Jul 9, 2018

    @TeXitoi
    Owner

    In clap, an argument takes value or not: https://docs.rs/clap/2.32.0/clap/struct.Arg.html#method.takes_value

    Thus, I don't think that's possible to have an argument that can optionally take value, That's why default_value is prohibited in Option, as it will always have a value, and thus will always be Some(a).

  4. lnicola commented on Jul 9, 2018

    @lnicola
    Author

    I suppose default_value and occurrences_of could be used in this case. The latter will return zero if the argument wasn't passed at all.

  5. TeXitoi commented on Jul 10, 2018

    @TeXitoi
    Owner

    I can't find any way to do it using clap. If you can show me a working program doing what you want with clap, I'll try to allow using the feature in structopt.

  6. lnicola commented on Jul 10, 2018

    @lnicola
    Author
    extern crate clap;
    
    use clap::{App, Arg, ArgMatches};
    
    fn get_optional_value<'a, 'b>(m: &'a ArgMatches, name: &'b str) -> Option<&'a str> {
        if m.occurrences_of(name) == 0 {
            None
        } else {
            m.value_of(name)
        }
    }
    
    fn main() {
        let app = App::new("my-app").arg(Arg::with_name("db").long("db").default_value("my-app.db"));
    
        let m = app.clone().get_matches_from(vec!["my-app", "--db"]);
        assert!(get_optional_value(&m, "db") == Some("my-app.db"));
    
        let m = app
            .clone()
            .get_matches_from(vec!["my-app", "--db", "foo.db"]);
        assert!(get_optional_value(&m, "db") == Some("foo.db"));
    
        let m = app.clone().get_matches_from(vec!["my-app"]);
        assert!(get_optional_value(&m, "db") == None);
    }
  7. TeXitoi commented on Jul 10, 2018

    @TeXitoi
    Owner

    I'll try to see how I can do it cleanly in structopt. Thanks for the example.

  8. added
    enhancementWe would love to have this feature! Feel free to supply a PR
    on Jul 10, 2018
  9. sphynx commented on May 25, 2019

    @sphynx
    Contributor

    Another way of achieving optional value of the long argument in clap is to use Arg::min_values(0) as described here: clap-rs/clap#892

    Then we can distinguish between say --help and --help topic by checking matches.is_present("help") and pattern matching matches.value_of("help") against Some (as demonstrated in the code from the issue linked above).

    I am now trying to describe this behaviour with structopt, but can't find a way :( It sets the field of the datatype to None in both cases when it's omitted and when its value is empty, so I can't tell the difference.

  10. TeXitoi commented on May 27, 2019

    @TeXitoi
    Owner

    @sphynx That's a quite different topic. You'd want support for Option<Option<T>> or Option<Vec<T>>. If that's what you're looking for, then you can create an issue about this.

    As a workaround, you can do the parsing "by hand":

    let app = Opt::clap();
    let matches = app.get_matches();
    // do something special to retrive the needed information
    let opt = Opt::from_matches(&matches);
  11. sphynx commented on May 27, 2019

    @sphynx
    Contributor

    @TeXitoi Thanks for your reply! As suggested, I've created a new issue: #188

    I think I'll either have to use the workaround or restructure the arguments differently for now.

  12. andronat commented on Nov 22, 2022

    @andronat

    Hello, could someone post how the above example can be currently implemented in structopt? I don't really get how default values with Option can be combined. I have a similar use case that I would like to accommodate.

    Just pasting the example again here:

    $ my-app # db is None
    $ my-app --db # db is Some("my-app.db")
    $ my-app --db foo.db # db is Some("foo.db")
    
  13. epage commented on Nov 22, 2022

    @epage
    Contributor

    I've not checked but hopefully it works if you use Option<Option> for the type

    Though, keep in mind that structopt is deprecated in favor of clap v3+ supporting derives directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementWe would love to have this feature! Feel free to supply a PR

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions