1use super::Error;
2use super::Key;
3use std::result::Result;
4use std::str::FromStr;
5
6#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
24pub struct Jargon(pub(crate) Vec<String>);
25
26impl Jargon {
27 pub fn from_env() -> Self {
29 Self(std::env::args().collect())
30 }
31
32 pub fn from_vec<T: ToString>(v: Vec<T>) -> Self {
35 Self(v.iter().map(|x| x.to_string()).collect())
36 }
37
38 pub fn contains<K: Into<Key>>(&mut self, key: K) -> bool {
40 let key: Key = key.into();
41 let len: usize = self.0.len();
42
43 match key {
44 Key::Dual {
45 char: c,
46 s_txt: s,
47 l_txt: l,
48 } => {
49 let s: Key = Key::Short { char: c, txt: s };
50 let l: Key = Key::Long { char: c, txt: l };
51 for i in 0..len {
52 let cont: Key = self.0[i].clone().into();
53 if cont == s || cont == l {
54 self.0.remove(i);
55 return true;
56 }
57 }
58 }
59 key => {
60 for i in 0..len {
61 let cont: Key = self.0[i].clone().into();
62 if cont == key {
63 self.0.remove(i);
64 return true;
65 }
66 }
67 }
68 }
69
70 false
71 }
72
73 #[cfg(feature = "no_mut")]
74 pub fn contains_nomut<K: Into<Key>>(&self, key: K) -> bool {
76 let m = self.0.clone();
77 let mut m = Self(m);
78 m.contains(key)
79 }
80
81 pub fn on_subcommand<K: Into<Key>, F: FnMut(Vec<String>)>(&mut self, key: K, mut f: F) {
84 let key: Key = key.into();
85 for i in 0..self.0.len() {
86 let cont: Key = self.0[i].clone().into();
87 if cont.is_sub() && cont == key {
88 return f(self.clone().finish());
89 }
90 }
91 }
92
93 pub fn opt_on_subcommand<K: Into<Key>, F: FnMut(Vec<String>) -> Option<T>, T>(
96 &mut self,
97 key: K,
98 mut f: F,
99 ) -> Option<T> {
100 let key: Key = key.into();
101 for i in 0..self.0.len() {
102 let cont: Key = self.0[i].clone().into();
103 if cont.is_sub() && cont == key {
104 return f(self.clone().finish());
105 }
106 }
107 None
108 }
109
110 pub fn res_on_subcommand<K: Into<Key>, F: FnMut(Vec<String>) -> Result<T, Error>, T>(
113 &mut self,
114 key: K,
115 mut f: F,
116 ) -> Result<T, Error> {
117 let key: Key = key.into();
118 for i in 0..self.0.len() {
119 let cont: Key = self.0[i].clone().into();
120 if cont.is_sub() && cont == key {
121 return f(self.clone().finish());
122 }
123 }
124
125 Err(Error::MissingArg(key))
126 }
127
128 pub fn subcommand<K: Into<Key>>(&mut self, key: K) -> Option<Vec<String>> {
131 let mut v: Vec<String> = Vec::new();
132 self.on_subcommand(key, |vv| v = vv);
133 if v.is_empty() {
134 None
135 } else {
136 Some(v)
137 }
138 }
139
140 #[cfg(feature = "no_mut")]
141 pub fn subcommand_nomut<K: Into<Key>>(&self, key: K) -> Option<Vec<String>> {
145 Jargon::from_vec(self.0.clone()).subcommand(key)
146 }
147
148 pub fn option_arg<T: FromStr, K: Into<Key>>(&mut self, key: K) -> Option<T> {
151 let key: Key = key.into();
152 let len: usize = self.0.len();
153
154 match key {
155 Key::Dual {
156 char: c,
157 s_txt: s,
158 l_txt: l,
159 } => {
160 let s: Key = Key::Short { char: c, txt: s };
161 let l: Key = Key::Long { char: c, txt: l };
162 for i in 0..len {
163 let cont: Key = self.0[i].clone().into();
164 if cont == s || cont == l {
165 if i >= self.0.len() - 1 {
166 return None;
167 }
168 return if !self.0[i + 1].starts_with(s.char())
169 || !self.0[i + 1].starts_with(l.char())
170 {
171 self.0.remove(i);
172 self.0.remove(i).parse().ok()
173 } else {
174 None
175 };
176 }
177 }
178 }
179 key => {
180 for i in 0..len {
181 let cont: Key = self.0[i].clone().into();
182 if cont == key {
183 if i >= self.0.len() - 1 {
184 return None;
185 }
186 return if !self.0[i + 1].starts_with(key.char()) {
187 self.0.remove(i);
188 self.0.remove(i).parse().ok()
189 } else {
190 None
191 };
192 }
193 }
194 }
195 }
196
197 None
198 }
199
200 pub fn result_arg<T: FromStr, K: Into<Key>>(&mut self, key: K) -> Result<T, Error> {
203 let key: Key = key.into();
204 self.option_arg(key.clone()).ok_or(Error::MissingArg(key))
205 }
206
207 pub fn opt_next<T: FromStr>(&mut self) -> Option<T> {
209 if self.0.len() == 0 {
210 return None;
211 }
212
213 self.0.remove(0).parse().ok()
214 }
215
216 pub fn finish(self) -> Vec<String> {
218 self.0.iter().skip(1).map(|s| s.to_string()).collect()
219 }
220}