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, MultiSelect, Select,
11 Text,
12 };
13 pub use itertools::Itertools;
14 pub use std::{env::args, fmt::Display, path::PathBuf, str::FromStr};
15 pub use thiserror::Error;
16}
17
18pub use util::*;
19
20pub use fpr_cli_derives::*;
21pub use i::*;
22pub use parse::*;
23
24use com::*;
25
26#[derive(Clone, Debug)]
27pub struct ParseCtx<'a> {
28 pub pfx: Vec<Arg<'a>>,
29}
30
31#[derive(Error, Debug)]
32pub enum ErrActs {
33 #[error("Needs help")]
34 Help,
35 #[error("Unknown act '{act}'")]
36 Unknown { act: String },
37 #[error("Expected act.")]
38 Missing,
39 #[error("{e}")]
40 Args {
41 #[from]
42 e: ErrArgs,
43 },
44}
45pub type Arg<'a> = &'a str;
46pub trait Acts<C>: Sized {
47 fn run(c: &C) -> Result<(), ErrActs> {
48 let args = args().collect_vec();
49 let a: Vec<_> = args.iter().map(|e| e.as_str()).collect();
50 let mut s = ParseCtx { pfx: vec![] };
51 let r = Self::next(c, &mut s, &a[1..]);
52 if let Err(e) = &r {
53 println!("Available acts:\n{}", Self::usage());
54 match e {
55 ErrActs::Help => return Ok(()),
56 _ => (),
57 }
58 }
59 r
60 }
61
62 fn next<'a>(c: &C, s: &mut ParseCtx<'a>, args: &[Arg<'a>]) -> Result<(), ErrActs> {
63 if args.is_empty() {
64 return Err(ErrActs::Missing)?;
65 };
66 let a = &args[0];
67 let args = &args[1..];
68 Self::next_impl(c, s, a, args)
69 }
70 fn list<'a>() -> Vec<Vec<Arg<'a>>> {
71 let pfx = vec![];
72 let mut res: Vec<Vec<Arg<'a>>> = vec![];
73 Self::add_paths(&pfx, &mut res);
74 return res;
75 }
76 fn usage() -> String {
77 to_table(&Self::usage_v())
78 }
79
80 fn opts() -> Vec<&'static str>;
81 fn next_impl<'a>(
82 c: &C,
83 s: &mut ParseCtx<'a>,
84 a: &Arg<'a>,
85 args: &[Arg<'a>],
86 ) -> Result<(), ErrActs>;
87 fn desc_act() -> &'static str;
88 fn usage_v() -> Vec<[&'static str; 2]>;
89 fn add_paths<'a>(pfx: &Vec<Arg<'a>>, p: &mut Vec<Vec<Arg<'a>>>);
90}
91
92#[derive(Error, Debug)]
93pub enum ErrArgs {
94 #[error("Needs help")]
95 Help,
96 #[error("Unknown args '{}'", arg.join(", "))]
97 Unknown { arg: Vec<String> },
98 #[error("Failed while parsing arg '{arg}': '{e}'")]
99 Arg { arg: String, e: ErrArg },
100 #[error("{e}")]
101 Run { e: String },
102}
103pub trait Args<C>: Sized {
104 fn next_impl<'a>(c: &C, args: &[Arg<'a>]) -> Result<(), ErrArgs> {
105 let mut args = ParsedArgs::new(args);
106 if args.consume(&format!("{PFX}help")).is_some() {
107 return Err(ErrArgs::Help);
108 }
109
110 let a = Self::new(c, &mut args)?;
111
112 let u = args
113 .k
114 .iter()
115 .filter(|k| !k.used && !k.k.is_none_or(|x| x == PFX))
116 .map(|k| {
117 match k.k {
118 Some(e) => vec![e],
119 None => vec![],
120 }
121 .into_iter()
122 .chain(k.v.iter().map(|e| *e))
123 })
124 .flatten()
125 .map(|e| e.to_owned())
126 .collect_vec();
127 if !u.is_empty() {
128 return Err(ErrArgs::Unknown { arg: u });
129 }
130
131 let r = args
132 .k
133 .iter()
134 .filter(|k| k.k.is_none_or(|x| x == PFX))
135 .map(|k| k.v.iter())
136 .flatten()
137 .map(|e| *e)
138 .collect();
139
140 let _ = a.run(c, r).map_err(|e| ErrArgs::Run { e })?;
141 Ok(())
142 }
143 fn next<'a>(c: &C, _: &mut ParseCtx<'a>, args: &[Arg<'a>]) -> Result<(), ErrArgs> {
144 Self::next_impl(c, args)
145 }
146 fn usage(c: &C) -> String {
147 let mut r: Vec<[String; 4]> = vec![];
148 Self::add_usage(c, &mut r);
149 to_table(&r)
150 }
151 fn new<'a, 'b>(c: &C, args: &mut ParsedArgs<'b>) -> Result<Self, ErrArgs>;
152 fn desc_act() -> &'static str;
153 fn add_paths<'a>(pfx: &Vec<Arg<'a>>, p: &mut Vec<Vec<Arg<'a>>>);
154 fn add_usage(c: &C, r: &mut Vec<[String; 4]>);
155 fn default(c: &C) -> Self;
156
157 fn run(self, c: &C, r: Vec<&str>) -> Result<(), String>;
158}
159
160#[derive(Error, Debug)]
161pub enum ErrVal {
162 #[error("Failed to parse '{input}' as type '{typename}': {error}")]
163 Err {
164 input: String,
165 typename: String,
166 error: String,
167 },
168}
169pub trait Parse<'a>
170where
171 Self: Sized + Display,
172{
173 fn parse(i: Arg<'a>) -> Result<Self, ErrVal>;
174 fn desc() -> &'static str;
175}
176#[derive(Debug)]
177pub struct ParseErr<'a> {
178 pub ty: &'static str,
179 pub i: Arg<'a>,
180 pub e: String,
181}
182
183pub struct DisplayVec<T: Display>(Vec<T>);
184impl<T: Display> Display for DisplayVec<T> {
185 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
186 write!(f, "{}", self.0.iter().map(|t| format!("{t}")).join(", "))
187 }
188}
189impl<T: Display> From<Vec<T>> for DisplayVec<T> {
190 fn from(v: Vec<T>) -> Self {
191 Self(v)
192 }
193}
194impl<T: Display> Into<Vec<T>> for DisplayVec<T> {
195 fn into(self) -> Vec<T> {
196 self.0
197 }
198}