From d5d48bcf463a4e494ef758836bd69a4c220bbbb5 Mon Sep 17 00:00:00 2001 From: Kevin K Date: Mon, 13 Apr 2015 14:32:27 -0400 Subject: [PATCH] feat(app): add support for building args from usage strings --- src/app.rs | 37 +++++++++++++++++++++++++++++++++++++ src/args/arg.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/app.rs b/src/app.rs index f4ef9c9e..8025bdcf 100644 --- a/src/app.rs +++ b/src/app.rs @@ -365,6 +365,43 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{ self } + /// Adds an argument from a usage string. See Arg::from_usage() for details + /// + /// # Example + /// + /// ```no_run + /// # use clap::{App, Arg}; + /// # let app = App::new("myprog") + /// .arg_from_usage("-c --conf= 'Sets a configuration file to use'") + /// # .get_matches(); + /// ``` + pub fn arg_from_usage(mut self, usage: &'ar str) -> App<'a, 'v, 'ab, 'u, 'ar> { + self = self.arg(Arg::from_usage(usage)); + self + } + + /// Adds multiple arguments from a usage string, one per line. See Arg::from_usage() for + /// details + /// + /// # Example + /// + /// ```no_run + /// # use clap::{App, Arg}; + /// # let app = App::new("myprog") + /// .args_from_usage( + /// "-c --conf=[config] 'Sets a configuration file to use' + /// [debug]... -d 'Sets the debugging level' + /// 'The input file to use'") + /// # .get_matches(); + /// ``` + pub fn args_from_usage(mut self, usage: &'ar str) -> App<'a, 'v, 'ab, 'u, 'ar> { + for l in usage.lines() { + self = self.arg(Arg::from_usage(l)); + } + self + } + + /// Adds a subcommand to the list of valid possibilties. Subcommands are effectively sub apps, /// because they can contain their own arguments, subcommands, version, usage, etc. They also /// function just like apps, in that they get their own auto generated help and version diff --git a/src/args/arg.rs b/src/args/arg.rs index 37dcf1c4..2000c7fe 100644 --- a/src/args/arg.rs +++ b/src/args/arg.rs @@ -139,6 +139,51 @@ impl<'n, 'l, 'h, 'b, 'p, 'r> Arg<'n, 'l, 'h, 'b, 'p, 'r> { } } + /// Creates a new instace of `Arg` using a usage string. Allows creation of basic settings + /// for Arg (i.e. everything except relational rules). The syntax is flexible, but there are + /// some rules to follow. + /// + /// The syntax should be as follows (only properties which you wish to set must be present): + /// + /// 1. Name (arguments with a `long` or that take a value can ommit this if desired), + /// use `[]` for non-required arguments, or `<>` for required arguments. + /// 2. Short preceded by a `-` + /// 3. Long preceded by a `--` (this may be used as the name, if the name is omitted. If the + /// name is *not* omittied, the name takes precedence) + /// 4. Value (this can be used as the name, if the name is not manually specified. If the name + /// is manually specified, it takes precence. If this value is used as the name, it uses the + /// same `[]` and `<>` requirement rules. If it is *not* used as the name, it still needs to + /// be surrounded by either `[]` or `<>` but the effect is the same, as the requirement rule + /// is determined by the name. The value may follow the `short` or `long`. If it + /// follows the `long`, it may follow either a `=` or ` ` with the same effect, personal + /// preference only, but may only follow a ` ` after a `short`) + /// 5. Multiple specifier `...` (for flags or positional arguments the `...` may follow the + /// name or `short` or `long`) + /// 6. The help info surrounded by `'` + /// 7. The index of a positional argument will be the next available index (you don't need to + /// specify one) + /// + /// + /// Example: + /// + /// ```no_run + /// # use clap::{App, Arg}; + /// # let matches = App::new("myprog") + /// .args(vec![ + /// // A option argument with a long, named "conf" (note: because the name was specified + /// // the portion after the long can be called anything, only the first name will be displayed + /// // to the user. Also, requirement is set with the *name*, so the portion after the long could + /// // be either <> or [] and it wouldn't matter, so long as it's one of them. Had the name been + /// // omitted, the name would have been derived from the portion after the long and those rules + /// // would have mattered) + /// Arg::from_usage("[conf] --config=[c] 'a required file for the configuration'"), + /// // A flag with a short, a long, named "debug", and accepts multiple values + /// Arg::from_usage("-d --debug... 'turns on debugging information"), + /// // A required positional argument named "input" + /// Arg::from_usage(" 'the input file to use'") + /// ]) + /// # .short("c") + /// # ).get_matches(); pub fn from_usage(u: &'n str) -> Arg<'n, 'n, 'n, 'b, 'p, 'r> { assert!(u.len() > 0, "Arg::from_usage() requires a non-zero-length usage string but none was provided");