1mod i;
2mod parse;
3mod util;
4
5mod com {
6 pub use crate::*;
7 pub use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher};
8 pub use inquire::{
9 autocompletion::Replacement, list_option::ListOption, validator::CustomTypeValidator,
10 validator::ErrorMessage, Autocomplete, CustomType, CustomUserError, InquireError,
11 MultiSelect, Select, Text,
12 };
13 pub use itertools::Itertools;
14 pub use std::{env::args, fmt::Display, path::PathBuf, str::FromStr};
15}
16
17pub use util::*;
18
19pub use fpr_cli_derives::*;
20pub use i::*;
21pub use parse::*;
22
23use com::*;
24
25pub enum ActsErr<'a> {
26 Run(ParseCtx<'a>, String),
27 Inquire(String),
28 ExpectedAct(ParseCtx<'a>, String),
29 UnknownAct(ParseCtx<'a>, &'a str),
30 Args(ParseCtx<'a>, ArgsParseErr<'a>, String),
31}
32
33#[derive(Clone, Debug)]
34pub struct ParseCtx<'a> {
35 pub pfx: Vec<Arg<'a>>,
36}
37
38impl<'a> ActsErr<'a> {
39 fn display(self, arg0: &'a Arg) -> DActsErr<'a> {
40 DActsErr { e: self, arg0 }
41 }
42}
43struct DActsErr<'a> {
44 e: ActsErr<'a>,
45 arg0: Arg<'a>,
46}
47
48impl<'a> Display for ActsErr<'a> {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 use ActsErr::*;
51 match self {
52 Run(_, ref e) => write!(f, "Failed to run:\n{e}"),
53 Inquire(ref e) => write!(f, "{e}"),
54 ExpectedAct(_, _) => write!(f, "Expected an act.\n"),
55 UnknownAct(_, ref e) => write!(f, "Unknown act '{e}.'\n"),
56 Args(_, ref e, _) => match e {
57 ArgsParseErr::Help(_) => write!(f, "{e}"),
58 _ => write!(f, "Failed to parse opts.\n{e}\n"),
59 },
60 }
61 }
62}
63impl<'a> Display for DActsErr<'a> {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 use ActsErr::*;
66 write!(f, "{}", self.e)?;
67 match self.e {
68 ExpectedAct(ref c, ref u) => {
69 write!(f, "Usage: {} {} <action>\n{u}", self.arg0, c.pfx.join(" "))?;
70 }
71 UnknownAct(ref c, ref u) => {
72 write!(f, "Usage: {} {} <action>\n{u}", self.arg0, c.pfx.join(" "))?;
73 }
74 Args(ref c, _, ref u) => {
75 write!(
76 f,
77 "Usage: {} {} <opts...>\nOpts:\n{u}",
78 self.arg0,
79 c.pfx.join(" ")
80 )?;
81 }
82 _ => (),
83 };
84 Ok(())
85 }
86}
87impl<'a> From<InquireError> for ActsErr<'a> {
88 fn from(v: InquireError) -> Self {
89 Self::Inquire(format!("{v}"))
90 }
91}
92
93pub type Arg<'a> = &'a str;
94pub trait Acts<C>: Sized {
95 fn run(c: &C) -> Result<(), String> {
96 let args = args().collect_vec();
97 let a: Vec<_> = args.iter().map(|e| e.as_str()).collect();
98 let mut s = ParseCtx { pfx: vec![] };
99 Self::next(c, &mut s, &a[1..]).map_err(|e| format!("{}", e.display(&a[0])))
100 }
101
102 fn next<'a>(c: &C, s: &mut ParseCtx<'a>, args: &[Arg<'a>]) -> Result<(), ActsErr<'a>> {
103 if args.is_empty() {
104 print!("{}", ActsErr::ExpectedAct(s.to_owned(), Self::usage()));
105 return Self::next(c, s, &[Self::select_act()?]);
106 };
107 let a = &args[0];
108 let args = &args[1..];
109
110 use ActsErr::*;
111 match Self::next_impl(c, s, a, args) {
112 Err(e) => match e {
113 UnknownAct(_, _) => {
114 print!("{e}");
115 Self::next(c, s, &[Self::select_act()?])
116 }
117 _ => return Err(e),
118 },
119 e => return e,
120 }
121 }
122 fn select_act<'a>() -> Result<&'static str, ActsErr<'a>> {
123 let opts: Vec<_> = to_lines(&Self::usage_v())
124 .into_iter()
125 .enumerate()
126 .map(|(i, o)| ListOption::new(i, o))
127 .collect();
128 Ok(Self::opts()[Select::new("Choose an action.", opts)
129 .with_page_size(50)
130 .prompt()?
131 .index])
132 }
133
134 fn list<'a>() -> Vec<Vec<Arg<'a>>> {
135 let pfx = vec![];
136 let mut res: Vec<Vec<Arg<'a>>> = vec![];
137 Self::add_paths(&pfx, &mut res);
138 return res;
139 }
140 fn usage() -> String {
141 to_table(&Self::usage_v())
142 }
143
144 fn opts() -> Vec<&'static str>;
145 fn next_impl<'a>(
146 c: &C,
147 s: &mut ParseCtx<'a>,
148 a: &Arg<'a>,
149 args: &[Arg<'a>],
150 ) -> Result<(), ActsErr<'a>>;
151 fn desc_act() -> &'static str;
152 fn usage_v() -> Vec<[&'static str; 2]>;
153 fn add_paths<'a>(pfx: &Vec<Arg<'a>>, p: &mut Vec<Vec<Arg<'a>>>);
154}
155pub trait Args<C>: Sized {
156 fn next_impl<'a>(c: &C, args: &[Arg<'a>]) -> Result<(), ArgsErr<'a>> {
157 let mut args = ParsedArgs::new(args).map_err(|e| {
158 use ParsedArgsErr::*;
159 match e {
160 UnexpectedToken(a) => ArgsParseErr::UnexpectedToken(a, Self::usage(c)),
161 }
162 })?;
163
164 if args.consume(&format!("{PFX}help")).is_some() {
165 return Err(ArgsParseErr::Help(Self::usage(c)).into());
166 }
167
168 let a = Self::new(c, &mut args)?;
169
170 let u = args
171 .k
172 .iter()
173 .filter(|k| !k.used && !k.k.is_none_or(|x| x == PFX))
174 .map(|k| {
175 match k.k {
176 Some(e) => vec![e],
177 None => vec![],
178 }
179 .into_iter()
180 .chain(k.v.iter().map(|e| *e))
181 })
182 .flatten()
183 .collect::<Vec<_>>();
184 if !u.is_empty() {
185 return Err(ArgsParseErr::UnknownArgs(u, Self::usage(c)).into());
186 }
187
188 let r = args
189 .k
190 .iter()
191 .filter(|k| k.k.is_none_or(|x| x == PFX))
192 .map(|k| k.v.iter())
193 .flatten()
194 .map(|e| *e)
195 .collect();
196
197 let _ = a.run(c, r).map_err(|s| ArgsErr::Run(s))?;
198 Ok(())
199 }
200 fn next<'a>(c: &C, s: &mut ParseCtx<'a>, args: &[Arg<'a>]) -> Result<(), ActsErr<'a>> {
201 match Self::next_impl(c, args) {
202 Err(e) => match e {
203 ArgsErr::Run(r) => Err(ActsErr::Run(s.to_owned(), r)),
204 ArgsErr::Parse(e) => Err(ActsErr::Args(s.to_owned(), e, Self::usage(c))),
205 },
206 Ok(o) => Ok(o),
207 }
208 }
209 fn usage(c: &C) -> String {
210 let mut r: Vec<[String; 4]> = vec![];
211 Self::add_usage(c, &mut r);
212 to_table(&r)
213 }
214 fn new<'a, 'b>(c: &C, args: &mut ParsedArgs<'b>) -> Result<Self, ArgsParseErr<'b>>;
215 fn desc_act() -> &'static str;
216 fn add_paths<'a>(pfx: &Vec<Arg<'a>>, p: &mut Vec<Vec<Arg<'a>>>);
217 fn add_usage(c: &C, r: &mut Vec<[String; 4]>);
218 fn default(c: &C) -> Self;
219
220 fn run(self, c: &C, r: Vec<&str>) -> Result<(), String>;
221}
222
223pub trait Parse<'a>
224where
225 Self: Sized + Display,
226{
227 fn parse(i: Arg<'a>) -> Result<Self, ParseErr<'a>>;
228 fn desc() -> &'static str;
229}
230#[derive(Debug)]
231pub struct ParseErr<'a> {
232 pub ty: &'static str,
233 pub i: Arg<'a>,
234 pub e: String,
235}
236
237pub struct DisplayVec<T: Display>(Vec<T>);
238impl<T: Display> Display for DisplayVec<T> {
239 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
240 write!(f, "{}", self.0.iter().map(|t| format!("{t}")).join(", "))
241 }
242}
243impl<T: Display> From<Vec<T>> for DisplayVec<T> {
244 fn from(v: Vec<T>) -> Self {
245 Self(v)
246 }
247}
248impl<T: Display> Into<Vec<T>> for DisplayVec<T> {
249 fn into(self) -> Vec<T> {
250 self.0
251 }
252}