Implement methods for adding command line arguments to the parser.
This commit is contained in:
parent
3d198452c9
commit
db277c7805
112
src/lib.rs
112
src/lib.rs
|
@ -1,6 +1,8 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::env::args_os;
|
||||
use std::ops::RangeBounds;
|
||||
|
||||
/// A command line argument parser.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Parser {
|
||||
flags: Vec<Flag>,
|
||||
|
@ -12,17 +14,107 @@ pub struct Parser {
|
|||
short_set: HashSet<String>,
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
pub fn new() -> Parser {
|
||||
Parser {
|
||||
flags: Vec::new(),
|
||||
args: Vec::new(),
|
||||
pos_args: Vec::new(),
|
||||
long_set: HashSet::new(),
|
||||
short_set: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a flag argument.
|
||||
pub fn flag(&mut self, long: &str, short: Option<&str>, doc_string: &str) {
|
||||
self.ensure_not_duplicate(long, short);
|
||||
|
||||
self.flags.push(Flag {
|
||||
long: long.into(),
|
||||
short: short.map(|s| s.into()),
|
||||
doc_string: doc_string.into(),
|
||||
});
|
||||
}
|
||||
|
||||
/// Add a standard argument.
|
||||
pub fn argument<R: RangeBounds<usize>>(
|
||||
&mut self,
|
||||
long: &str,
|
||||
short: Option<&str>,
|
||||
doc_string: &str,
|
||||
value_name: &str,
|
||||
acceptable_count: R,
|
||||
) {
|
||||
self.ensure_not_duplicate(long, short);
|
||||
|
||||
use std::ops::Bound;
|
||||
let count_start: Option<usize> = match acceptable_count.start_bound() {
|
||||
Bound::Included(&n) => Some(n),
|
||||
Bound::Excluded(&n) => Some(n + 1),
|
||||
Bound::Unbounded => None,
|
||||
};
|
||||
let count_end: Option<usize> = match acceptable_count.end_bound() {
|
||||
Bound::Included(&n) => Some(n + 1),
|
||||
Bound::Excluded(&n) => Some(n),
|
||||
Bound::Unbounded => None,
|
||||
};
|
||||
|
||||
self.args.push(Arg {
|
||||
long: long.into(),
|
||||
short: short.map(|s| s.into()),
|
||||
acceptable_count: (count_start, count_end),
|
||||
value_name: value_name.into(),
|
||||
doc_string: doc_string.into(),
|
||||
});
|
||||
}
|
||||
|
||||
/// Add a positional argument.
|
||||
///
|
||||
/// There can only be one positional argument with `count == None`,
|
||||
/// which represents any left over positional arguments after those
|
||||
/// with explicit counts have been parsed.
|
||||
pub fn positional_argument(
|
||||
&mut self,
|
||||
doc_string: &str,
|
||||
value_name: &str,
|
||||
count: Option<usize>,
|
||||
) {
|
||||
self.pos_args.push(PosArg {
|
||||
count: count,
|
||||
value_name: value_name.into(),
|
||||
doc_string: doc_string.into(),
|
||||
});
|
||||
}
|
||||
|
||||
//----------------
|
||||
|
||||
fn ensure_not_duplicate(&mut self, long: &str, short: Option<&str>) {
|
||||
if self.long_set.contains(long) {
|
||||
panic!("Attempted to add duplicate long argument \"--{}\".", long);
|
||||
}
|
||||
self.long_set.insert(long.into());
|
||||
|
||||
if let Some(short) = short {
|
||||
if self.short_set.contains(short) {
|
||||
panic!("Attempted to add duplicate short argument \"-{}\".", short);
|
||||
}
|
||||
self.short_set.insert(short.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parsed command line arguments.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Arguments {
|
||||
// TODO: allow OsString argument values.
|
||||
/// Positional arguments, in the order passed.
|
||||
pub positional: Vec<String>,
|
||||
|
||||
/// The flags that were passed.
|
||||
/// The flags that were passed, indexed by `long`.
|
||||
pub flags: HashSet<String>,
|
||||
|
||||
/// Non-positional arguments that were passed.
|
||||
pub args: HashMap<String, String>,
|
||||
/// Non-positional arguments that were passed, indexed by `long`.
|
||||
pub args: HashMap<String, Vec<String>>,
|
||||
|
||||
/// Positional arguments, indexed by `value_name`.
|
||||
pub positional: HashMap<String, Vec<String>>,
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
|
@ -30,7 +122,7 @@ pub struct Arguments {
|
|||
/// Flag spec.
|
||||
#[derive(Debug, Clone)]
|
||||
struct Flag {
|
||||
long: Option<String>,
|
||||
long: String,
|
||||
short: Option<String>,
|
||||
|
||||
// For documentation.
|
||||
|
@ -40,9 +132,9 @@ struct Flag {
|
|||
/// Argument spec.
|
||||
#[derive(Debug, Clone)]
|
||||
struct Arg {
|
||||
long: Option<String>,
|
||||
long: String,
|
||||
short: Option<String>,
|
||||
is_required: bool,
|
||||
acceptable_count: (Option<usize>, Option<usize>),
|
||||
|
||||
// For documentation.
|
||||
value_name: String,
|
||||
|
@ -52,7 +144,7 @@ struct Arg {
|
|||
/// Positional argument spec.
|
||||
#[derive(Debug, Clone)]
|
||||
struct PosArg {
|
||||
is_required: bool,
|
||||
count: Option<usize>,
|
||||
|
||||
// For documentation.
|
||||
value_name: String,
|
||||
|
|
Loading…
Reference in New Issue
Block a user