1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
use std::{ffi::OsString, fmt, str::FromStr};
use crate::{Error, Result};
macro_rules! format_err {
($($tt:tt)*) => {
Error { msg: format!($($tt)*), help: false }
};
}
macro_rules! bail {
($($tt:tt)*) => {
return Err(format_err!($($tt)*))
};
}
pub struct Parser {
rargs: Vec<OsString>,
}
impl Parser {
pub fn new(mut args: Vec<OsString>) -> Self {
args.reverse();
Self { rargs: args }
}
pub fn new_from_env() -> Self {
let mut args = std::env::args_os().collect::<Vec<_>>();
args.reverse();
args.pop();
Self { rargs: args }
}
pub fn is_empty(&self) -> bool {
self.rargs.is_empty()
}
pub fn peek_flag(&self) -> Option<&str> {
self.rargs.last().and_then(|it| it.to_str()).filter(|it| it.starts_with('-'))
}
pub fn pop_flag(&mut self) -> Option<Result<String, OsString>> {
if self.peek_flag().is_some() {
self.next().map(|it| it.into_string())
} else {
self.next().map(Err)
}
}
pub fn push_back(&mut self, arg: Result<String, OsString>) {
let arg = match arg {
Ok(it) => it.into(),
Err(it) => it,
};
self.rargs.push(arg)
}
pub fn next(&mut self) -> Option<OsString> {
self.rargs.pop()
}
pub fn next_value(&mut self, flag: &str) -> Result<OsString> {
if self.peek_flag().is_some() {
bail!("expected a value for `{}`", flag)
}
self.next().ok_or_else(|| format_err!("expected a value for `{}`", flag))
}
pub fn next_value_from_str<T: FromStr>(&mut self, flag: &str) -> Result<T>
where
T::Err: fmt::Display,
{
let value = self.next_value(flag)?;
self.value_from_str(flag, value)
}
pub fn value_from_str<T: FromStr>(&mut self, flag: &str, value: OsString) -> Result<T>
where
T::Err: fmt::Display,
{
match value.into_string() {
Ok(str) => {
str.parse::<T>().map_err(|err| format_err!("can't parse `{}`, {}", flag, err))
}
Err(it) => {
bail!("can't parse `{}`, invalid utf8: {:?}", flag, it)
}
}
}
pub fn unexpected_flag(&self, flag: &str) -> Error {
format_err!("unexpected flag: `{}`", flag)
}
pub fn unexpected_arg(&self, arg: OsString) -> Error {
format_err!("unexpected argument: {:?}", arg)
}
pub fn subcommand_required(&self) -> Error {
format_err!("subcommand is required")
}
pub fn help(&self, help: &'static str) -> Error {
Error { msg: help.to_string(), help: true }
}
pub fn optional<T>(&self, flag: &str, mut vals: Vec<T>) -> Result<Option<T>> {
if vals.len() > 1 {
bail!("flag specified more than once: `{}`", flag)
}
Ok(vals.pop())
}
pub fn required<T>(&self, flag: &str, mut vals: Vec<T>) -> Result<T> {
if vals.len() > 1 {
bail!("flag specified more than once: `{}`", flag)
}
vals.pop().ok_or_else(|| format_err!("flag is required: `{}`", flag))
}
}
|