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