fpr_cli/
parse.rs

1use crate::com::*;
2
3pub enum Parse2Err {
4    ExpectedOne,
5    Rquired,
6    ExpectedAtLeastOne,
7}
8pub enum ArgParseErr<'a> {
9    ParseErr(ParseErr<'a>),
10    Parse2Err(Parse2Err),
11}
12impl<'a> From<ParseErr<'a>> for ArgParseErr<'a> {
13    fn from(v: ParseErr<'a>) -> Self {
14        ArgParseErr::ParseErr(v)
15    }
16}
17impl<'a> From<Parse2Err> for ArgParseErr<'a> {
18    fn from(v: Parse2Err) -> Self {
19        ArgParseErr::Parse2Err(v)
20    }
21}
22pub enum ArgsParseErr<'a> {
23    UnexpectedToken(Arg<'a>, String),
24    Help(String),
25    UnknownArgs(Vec<Arg<'a>>, String),
26    Arg(&'static str, ArgParseErr<'a>, String),
27}
28impl<'a> Display for ArgsParseErr<'a> {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        use ArgsParseErr::*;
31        match self {
32            UnexpectedToken(ref a, _) => write!(f, "Unexpected token '{a}'")?,
33            Help(_) => (),
34            UnknownArgs(ref a, _) => write!(
35                f,
36                "Unknown options '{}'",
37                a.into_iter().map(|a| format!(r#""{a}""#)).join(", ")
38            )?,
39            Arg(ref a, ref e, _) => write!(f, "Error parsing option '{a}.'\n{e}")?,
40        };
41        Ok(())
42    }
43}
44impl<'a> Display for ArgParseErr<'a> {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        use ArgParseErr::*;
47        match self {
48            ParseErr(e) => write!(f, "{e}"),
49            Parse2Err(e) => write!(f, "{e}"),
50        }
51    }
52}
53impl<'a> Display for ParseErr<'a> {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        write!(
56            f,
57            "Failed to parse '{}' as '{}' because '{}'",
58            self.i, self.ty, self.e
59        )
60    }
61}
62impl Display for Parse2Err {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        use Parse2Err::*;
65        match self {
66            ExpectedOne => write!(f, "Expected one value."),
67            Rquired => write!(f, "Required."),
68            ExpectedAtLeastOne => write!(f, "Expected one value minimum."),
69        }
70    }
71}
72pub enum ArgsErr<'a> {
73    Run(String),
74    Parse(ArgsParseErr<'a>),
75}
76impl<'a> From<ArgsParseErr<'a>> for ArgsErr<'a> {
77    fn from(v: ArgsParseErr<'a>) -> Self {
78        Self::Parse(v)
79    }
80}
81
82pub const PFX: &'static str = "--";
83#[derive(Debug)]
84pub struct Key {
85    pub i: usize,
86    pub used: bool,
87}
88#[derive(Debug)]
89pub struct ParsedArgs<'b, 'c> {
90    pub args: &'b [&'c str],
91    pub keys: Vec<Key>,
92}
93
94impl<'b, 'c> ParsedArgs<'b, 'c> {
95    pub fn consume(&mut self, name: &str) -> Option<&[&'c str]> {
96        let (i, k) = self
97            .keys
98            .iter_mut()
99            .enumerate()
100            .find(|(_, k)| self.args[k.i] == name)?;
101        assert!(
102            !k.used,
103            "A token should not ever be consumed twice. Probably a duplicate argument: {name}"
104        );
105        k.used = true;
106        let idx = k.i + 1;
107        Some(if i == self.keys.len() - 1 {
108            &self.args[idx..]
109        } else if self.args[self.keys[i + 1].i] == PFX {
110            &self.args[self.keys[i + 1].i + 1..]
111        } else {
112            &self.args[idx..self.keys[i + 1].i]
113        })
114    }
115}
116
117pub enum ParsedArgsErr<'a> {
118    UnexpectedToken(Arg<'a>),
119}
120impl<'b, 'c> ParsedArgs<'b, 'c> {
121    pub fn new(args: &'b [&'c str]) -> Result<ParsedArgs<'b, 'c>, ParsedArgsErr<'c>> {
122        let mut end = false;
123        let r = ParsedArgs {
124            args,
125            keys: args
126                .iter()
127                .enumerate()
128                .filter(|&(_, a)| {
129                    if end {
130                        false
131                    } else {
132                        let pfx = a.starts_with(PFX);
133                        if pfx && a.len() == PFX.len() {
134                            end = true;
135                            true
136                        } else {
137                            pfx
138                        }
139                    }
140                })
141                .map(|(i, _)| Key { i, used: false })
142                .collect(),
143        };
144
145        if !r.keys.is_empty() && r.keys[0].i != 0 {
146            Err(ParsedArgsErr::UnexpectedToken(args[0]))
147        } else {
148            Ok(r)
149        }
150    }
151}
152
153pub enum Init<C, T: Display> {
154    None,
155    Const(T),
156    Dyn(fn(&C) -> T),
157}
158
159impl<C, T: Display> Init<C, T> {
160    pub fn get(self, c: &C) -> Option<T> {
161        match self {
162            Init::None => None,
163            Init::Const(v) => Some(v),
164            Init::Dyn(f) => Some(f(&c)),
165        }
166    }
167    fn to_string(self, c: &C) -> String {
168        match self.get(c) {
169            Some(s) => format!(" (default: {s})"),
170            None => format!(""),
171        }
172    }
173}
174
175pub trait Parse2<'a, 'b, C>
176where
177    Self: Sized,
178    Self::I: Display,
179{
180    type I;
181    fn parse2(
182        i: Init<C, Self::I>,
183        k: &'static str,
184        c: &C,
185        p: &mut ParsedArgs<'a, 'b>,
186    ) -> Result<Self, ArgParseErr<'b>>;
187    fn desc2(i: Init<C, Self::I>, d: &'static str, k: &'static str, c: &C) -> [String; 4];
188    fn default2(c: &C, i: Init<C, Self::I>) -> Self;
189}
190
191impl<'a, 'b, C, T: Parse<'a> + Default> Parse2<'b, 'a, C> for T {
192    type I = T;
193    fn parse2(
194        i: Init<C, Self::I>,
195        k: &'static str,
196        c: &C,
197        p: &mut ParsedArgs<'b, 'a>,
198    ) -> Result<Self, ArgParseErr<'a>> {
199        match p.consume(k) {
200            Some(args) => {
201                if args.len() != 1 {
202                    Err(Parse2Err::ExpectedOne)?
203                } else {
204                    Ok(T::parse(&args[0])?)
205                }
206            }
207            None => Ok(i.get(c).ok_or(Parse2Err::Rquired)?),
208        }
209    }
210
211    fn desc2(i: Init<C, Self>, d: &'static str, k: &'static str, c: &C) -> [String; 4] {
212        [
213            k.into(),
214            format!("Req<{}>", T::desc()),
215            d.into(),
216            i.to_string(c),
217        ]
218    }
219    fn default2(c: &C, i: Init<C, Self::I>) -> Self {
220        i.get(c).unwrap_or(Self::default())
221    }
222}
223
224impl<'a, 'b, Ctx, T: Parse<'a>> Parse2<'b, 'a, Ctx> for Option<T> {
225    type I = T;
226    fn parse2(
227        i: Init<Ctx, T>,
228        k: &'static str,
229        c: &Ctx,
230        p: &mut ParsedArgs<'b, 'a>,
231    ) -> Result<Self, ArgParseErr<'a>> {
232        match p.consume(k) {
233            Some(args) => {
234                if args.len() != 1 {
235                    Err(Parse2Err::ExpectedOne)?
236                } else {
237                    Ok(Some(T::parse(&args[0])?))
238                }
239            }
240            None => Ok(match i.get(c) {
241                Some(e) => Some(e),
242                None => None,
243            }),
244        }
245    }
246    fn desc2(i: Init<Ctx, T>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
247        [
248            k.into(),
249            format!("Opt<{}>", T::desc()),
250            d.into(),
251            i.to_string(c),
252        ]
253    }
254    fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
255        match i.get(c) {
256            Some(i) => Some(i),
257            None => None,
258        }
259    }
260}
261
262impl<'a, 'b, Ctx, T: Parse<'a> + Display> Parse2<'b, 'a, Ctx> for Vec<T> {
263    type I = DisplayVec<T>;
264    fn parse2(
265        i: Init<Ctx, Self::I>,
266        k: &'static str,
267        c: &Ctx,
268        p: &mut ParsedArgs<'b, 'a>,
269    ) -> Result<Self, ArgParseErr<'a>> {
270        match p.consume(k) {
271            Some(args) => {
272                let args = args
273                    .iter()
274                    .map(|a| T::parse(a))
275                    .collect::<Result<Vec<_>, _>>()?;
276                if args.is_empty() {
277                    Err(Parse2Err::ExpectedAtLeastOne)?
278                }
279                Ok(args)
280            }
281            None => Ok(match i.get(c) {
282                Some(e) => e.into(),
283                None => vec![],
284            }),
285        }
286    }
287
288    fn desc2(i: Init<Ctx, Self::I>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
289        [
290            k.into(),
291            format!("Vec<{}>", T::desc()),
292            d.into(),
293            i.to_string(c),
294        ]
295    }
296    fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
297        match i.get(c) {
298            Some(v) => v.0,
299            None => Self::default(),
300        }
301    }
302}
303
304pub struct OptVec<T: Display>(pub Vec<T>);
305impl<T: Display> From<Vec<T>> for OptVec<T> {
306    fn from(v: Vec<T>) -> Self {
307        Self(v)
308    }
309}
310impl<T: Display> From<DisplayVec<T>> for OptVec<T> {
311    fn from(v: DisplayVec<T>) -> Self {
312        Self(v.0)
313    }
314}
315impl<'a, 'b, Ctx, T: Parse<'a>> Parse2<'b, 'a, Ctx> for OptVec<T> {
316    type I = DisplayVec<T>;
317    fn parse2(
318        i: Init<Ctx, Self::I>,
319        k: &'static str,
320        c: &Ctx,
321        p: &mut ParsedArgs<'b, 'a>,
322    ) -> Result<Self, ArgParseErr<'a>> {
323        match p.consume(k) {
324            Some(args) => {
325                let args = args
326                    .iter()
327                    .map(|a| T::parse(a))
328                    .collect::<Result<Vec<_>, _>>()?;
329                Ok(args.into())
330            }
331            None => Ok(match i.get(c) {
332                Some(e) => e.into(),
333                None => vec![].into(),
334            }),
335        }
336    }
337
338    fn desc2(i: Init<Ctx, Self::I>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
339        [
340            k.into(),
341            format!("Vec<{}>", T::desc()),
342            d.into(),
343            i.to_string(c),
344        ]
345    }
346    fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
347        Self::from(match i.get(c) {
348            Some(v) => v.0,
349            None => <Vec<T>>::default(),
350        })
351    }
352}
353impl Display for DirExist {
354    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
355        write!(f, "{}", self.s)
356    }
357}
358impl Display for FileExist {
359    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
360        write!(f, "{}", self.s)
361    }
362}