Skip to content

Commit

Permalink
feat(args): add ability to create basic arguments from a usage string
Browse files Browse the repository at this point in the history
  • Loading branch information
kbknapp committed Apr 13, 2015
1 parent 5fc6050 commit ab409a8
Show file tree
Hide file tree
Showing 6 changed files with 768 additions and 2 deletions.
12 changes: 12 additions & 0 deletions gede.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
TcpPort="2000"
TcpHost="localhost"
Mode="0"
LastProgram="/home/kevin/Projects/clap-rs/target/debug/clap-fd2d4002ca38536a"
TcpProgram=""
InitCommands=""
GdpPath="gdb"
LastProgramArguments=""
Font="Monospace"
FontSize="8"
ReuseBreakpoints="0"
Breakpoints=":0;:0;:0;:0;:0;:0;:0;:0;/home/kevin/Projects/clap-rs/src/usageparser.rs:51;:0"
9 changes: 7 additions & 2 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,17 +219,21 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
if a.required {
self.required.insert(a.name);
}
if let Some(i) = a.index {
if a.index.is_some() || (a.short.is_none() && a.long.is_none()) {
let i = if a.index.is_none() {(self.positionals_idx.len() + 1) as u8 } else { a.index.unwrap() };

if a.short.is_some() || a.long.is_some() {
panic!("Argument \"{}\" has conflicting requirements, both index() and short(), or long(), were supplied", a.name);
}

if self.positionals_idx.contains_key(&i) {
panic!("Argument \"{}\" has the same index as another positional argument", a.name);
}
if a.takes_value {
panic!("Argument \"{}\" has conflicting requirements, both index() and takes_value(true) were supplied", a.name);
}


// Create the Positional Arguemnt Builder with each HashSet = None to only allocate those that require it
let mut pb = PosBuilder {
name: a.name,
Expand Down Expand Up @@ -304,7 +308,8 @@ impl<'a, 'v, 'ab, 'u, 'ar> App<'a, 'v, 'ab, 'u, 'ar>{
self.opts.insert(a.name, ob);
} else {
if a.short.is_none() && a.long.is_none() {
panic!("Argument \"{}\" must have either a short() and/or long() supplied since no index() or takes_value() were found", a.name);
// Could be a posistional constructed from usage string

}
if a.required {
panic!("Argument \"{}\" cannot be required(true) because it has no index() or takes_value(true)", a.name);
Expand Down
104 changes: 104 additions & 0 deletions src/args/arg.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use usageparser::{UsageParser, UsageToken};

/// The abstract representation of a command line argument used by the consumer of the library.
/// Used to set all the options and relationships that define a valid argument for the program.
///
Expand Down Expand Up @@ -74,6 +76,9 @@ impl<'n, 'l, 'h, 'b, 'p, 'r> Arg<'n, 'l, 'h, 'b, 'p, 'r> {
/// and positional arguments (i.e. those without a `-` or `--`) the name will also
/// be displayed when the user prints the usage/help information of the program.
///
/// **NOTE:** this function is deprecated in favor of Arg::with_name() to stay in line with
/// Rust APIs
///
/// Example:
///
/// ```no_run
Expand All @@ -83,6 +88,8 @@ impl<'n, 'l, 'h, 'b, 'p, 'r> Arg<'n, 'l, 'h, 'b, 'p, 'r> {
/// Arg::new("conifg")
/// # .short("c")
/// # ).get_matches();
#[deprecated(since = "0.5.15",
reason = "use Arg::with_name() instead")]
pub fn new(n: &'n str) -> Arg<'n, 'l, 'h, 'b, 'p, 'r> {
Arg {
name: n,
Expand All @@ -99,6 +106,103 @@ impl<'n, 'l, 'h, 'b, 'p, 'r> Arg<'n, 'l, 'h, 'b, 'p, 'r> {
}
}

/// Creates a new instace of `Arg` using a unique string name.
/// The name will be used by the library consumer to get information about
/// whether or not the argument was used at runtime.
///
/// **NOTE:** in the case of arguments that take values (i.e. `takes_value(true)`)
/// and positional arguments (i.e. those without a `-` or `--`) the name will also
/// be displayed when the user prints the usage/help information of the program.
///
/// Example:
///
/// ```no_run
/// # use clap::{App, Arg};
/// # let matches = App::new("myprog")
/// # .arg(
/// Arg::with_name("conifg")
/// # .short("c")
/// # ).get_matches();
pub fn with_name(n: &'n str) -> Arg<'n, 'l, 'h, 'b, 'p, 'r> {
Arg {
name: n,
short: None,
long: None,
help: None,
required: false,
takes_value: false,
multiple: false,
index: None,
possible_vals: None,
blacklist: None,
requires: None,
}
}

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");

let mut name = None;
let mut short = None;
let mut long = None;
let mut help = None;
let mut required = false;
let mut takes_value = false;
let mut multiple = false;

let parser = UsageParser::with_usage(u);
for_match!{ parser,
UsageToken::Name(n, req) => {
if name.is_none() {
name = Some(n);
if let Some(m) = req {
required = m;
}
}
if short.is_some() || long.is_some() {
takes_value = true;
}
if let Some(l) = long {
if n != name.unwrap() && name.unwrap() == l {
name = Some(n);
if let Some(m) = req {
required = m;
}
}
}
},
UsageToken::Short(s) => {
short = Some(s);
},
UsageToken::Long(l) => {
long = Some(l);
if name.is_none() {
name = Some(l);
}
},
UsageToken::Help(h) => {
help = Some(h);
},
UsageToken::Multiple => {
multiple = true;
}
}

Arg {
name: name.unwrap(),
short: short,
long: long,
help: help,
required: required,
takes_value: takes_value,
multiple: multiple,
index: None,
possible_vals: None,
blacklist: None,
requires: None,
}
}

/// Sets the short version of the argument without the preceding `-`.
///
///
Expand Down
Loading

0 comments on commit ab409a8

Please sign in to comment.