1use std::{
2 fmt::{self, Debug, Display},
3 mem::discriminant,
4 str::FromStr,
5};
6
7use cli_boilerplate_automation::impl_transparent_wrapper;
8use serde::{Deserialize, Serialize, Serializer};
9
10use crate::{
11 MAX_ACTIONS, SSS,
12 render::{Effects, MMState},
13 utils::serde::StringOrVec,
14};
15
16#[derive(Debug, Clone, Default)]
17pub enum Action<A: ActionExt = NullActionExt> {
18 #[default] Select,
21 Deselect,
23 Toggle,
25 CycleAll,
26 ClearAll,
27 Accept,
28 Quit(Exit),
30
31 CyclePreview,
33 Preview(String), Help(String), SwitchPreview(Option<u8>), SetPreview(Option<u8>), ToggleWrap,
39 ToggleWrapPreview,
40
41 Execute(String),
45 Become(String),
47 Reload(String),
49
50 Print(String),
53
54 SetInput(String),
55 SetHeader(Option<String>),
56 SetFooter(Option<String>),
57 SetPrompt(Option<String>),
58 Column(usize),
59 CycleColumn,
60
61 HistoryUp,
63 HistoryDown,
64 ChangePrompt,
65 ChangeQuery,
66
67 ForwardChar,
69 BackwardChar,
70 ForwardWord,
71 BackwardWord,
72 DeleteChar,
73 DeleteWord,
74 DeleteLineStart,
75 DeleteLineEnd,
76 Cancel, InputPos(i32),
78
79 Up(Count),
81 Down(Count),
82 PreviewUp(Count),
83 PreviewDown(Count),
84 PreviewHalfPageUp,
85 PreviewHalfPageDown,
86 Pos(i32),
87
88 Input(char),
90 Redraw,
91 Custom(A),
92 Overlay(usize),
93}
94
95impl<A: ActionExt> serde::Serialize for Action<A> {
96 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
97 where
98 S: serde::Serializer,
99 {
100 serializer.serialize_str(&self.to_string())
101 }
102}
103
104impl<A: ActionExt> PartialEq for Action<A> {
105 fn eq(&self, other: &Self) -> bool {
106 discriminant(self) == discriminant(other)
107 }
108}
109impl<A: ActionExt> Eq for Action<A> {}
110
111#[derive(Debug, Clone, Default, PartialEq)]
113pub struct NullActionExt {}
114
115impl ActionExt for NullActionExt {}
116
117impl fmt::Display for NullActionExt {
118 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
119 Ok(())
120 }
121}
122
123impl std::str::FromStr for NullActionExt {
124 type Err = ();
125
126 fn from_str(_: &str) -> Result<Self, Self::Err> {
127 Err(())
128 }
129}
130
131pub trait ActionExt: Debug + Clone + FromStr + Display + PartialEq + SSS {}
132
133pub type ActionExtHandler<T, S, A> = fn(A, &MMState<'_, T, S>) -> Effects;
134pub type ActionAliaser<T, S, A> = fn(Action<A>, &MMState<'_, T, S>) -> Actions<A>;
135pub use arrayvec::ArrayVec;
136#[macro_export]
153macro_rules! acs {
154 ( $( $x:expr ),* $(,)? ) => {
155 {
156 $crate::action::Actions::from([$($x),*])
157 }
158 };
159}
160pub use crate::acs;
161
162#[macro_export]
171macro_rules! bindmap {
172 ( $( $k:expr => $v1:expr ),* $(,)? ) => {{
173 let mut map = $crate::binds::BindMap::new();
174 $(
175 map.insert($k.into(), $crate::action::Actions::from($v1));
176 )*
177 map
178 }};
179}
180#[derive(Debug, Clone, PartialEq)]
182pub struct Actions<A: ActionExt = NullActionExt>(pub ArrayVec<Action<A>, MAX_ACTIONS>);
183impl<A: ActionExt> Default for Actions<A> {
184 fn default() -> Self {
185 Self(ArrayVec::new())
186 }
187}
188
189macro_rules! repeat_impl {
190 ($($len:expr),*) => {
191 $(
192 impl<A: ActionExt> From<[Action<A>; $len]> for Actions<A> {
193 fn from(arr: [Action<A>; $len]) -> Self {
194 Actions(ArrayVec::from_iter(arr))
195 }
196 }
197
198 impl<A: ActionExt> From<[A; $len]> for Actions<A> {
199 fn from(arr: [A; $len]) -> Self {
200 Actions(arr.into_iter().map(Action::Custom).collect())
201 }
202 }
203 )*
204 }
205}
206impl<A: ActionExt> From<[Action<A>; 0]> for Actions<A> {
207 fn from(empty: [Action<A>; 0]) -> Self {
208 Actions(ArrayVec::from_iter(empty))
209 }
210}
211repeat_impl!(1, 2, 3, 4, 5, 6);
212
213impl<A: ActionExt> From<Action<A>> for Actions<A> {
214 fn from(action: Action<A>) -> Self {
215 acs![action]
216 }
217}
218impl<A: ActionExt> From<A> for Actions<A> {
220 fn from(action: A) -> Self {
221 acs![Action::Custom(action)]
222 }
223}
224
225impl<'de, A: ActionExt> Deserialize<'de> for Actions<A> {
228 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
229 where
230 D: serde::Deserializer<'de>,
231 {
232 let helper = StringOrVec::deserialize(deserializer)?;
233 let strings = match helper {
234 StringOrVec::String(s) => vec![s],
235 StringOrVec::Vec(v) => v,
236 };
237
238 if strings.len() > MAX_ACTIONS {
239 return Err(serde::de::Error::custom(format!(
240 "Too many actions, max is {MAX_ACTIONS}."
241 )));
242 }
243
244 let mut actions = ArrayVec::new();
245 for s in strings {
246 let action = Action::from_str(&s).map_err(serde::de::Error::custom)?;
247 actions.push(action);
248 }
249
250 Ok(Actions(actions))
251 }
252}
253
254impl<A: ActionExt> Serialize for Actions<A> {
255 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
256 where
257 S: Serializer,
258 {
259 match self.0.len() {
260 1 => serializer.serialize_str(&self.0[0].to_string()),
261 _ => {
262 let strings: Vec<String> = self.0.iter().map(|a| a.to_string()).collect();
263 strings.serialize(serializer)
264 }
265 }
266 }
267}
268
269macro_rules! impl_display_and_from_str_enum {
272 (
273 $($unit:ident),*;
274 $($tuple:ident),*;
275 $($tuple_default:ident),*;
276 $($tuple_option:ident),*;
277 $($tuple_string_default:ident),*
278 ) => {
279 impl<A: ActionExt> std::fmt::Display for Action<A> {
280 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
281 match self {
282 $( Self::$unit => write!(f, stringify!($unit)), )*
284
285 $( Self::$tuple(inner) => write!(f, concat!(stringify!($tuple), "({})"), inner), )*
287
288 $( Self::$tuple_default(inner) => {
290 if *inner == core::default::Default::default() {
291 write!(f, stringify!($tuple_default))
292 } else {
293 write!(f, concat!(stringify!($tuple_default), "({})"), inner)
294 }
295 }, )*
296
297 $( Self::$tuple_option(opt) => {
299 if let Some(inner) = opt {
300 write!(f, concat!(stringify!($tuple_option), "({})"), inner)
301 } else {
302 write!(f, stringify!($tuple_option))
303 }
304 }, )*
305
306 $( Self::$tuple_string_default(inner) => {
307 if inner.is_empty() {
308 write!(f, stringify!($tuple_string_default))
309 } else {
310 write!(f, concat!(stringify!($tuple_string_default), "({})"), inner)
311 }
312 }, )*
313
314 Self::Custom(inner) => {
315 write!(f, "{}", inner.to_string())
316 }
317 Self::Input(c) => {
318 write!(f, "{c}")
319 }
320 }
321 }
322 }
323
324 impl<A: ActionExt> std::str::FromStr for Action<A> {
325 type Err = String;
326
327 fn from_str(s: &str) -> Result<Self, Self::Err> {
328 let (name, data) = if let Some(pos) = s.find('(') {
329 if s.ends_with(')') {
330 (&s[..pos], Some(&s[pos + 1..s.len() - 1]))
331 } else {
332 (s, None)
333 }
334 } else {
335 (s, None)
336 };
337
338 if let Ok(x) = name.parse::<A>() {
339 return Ok(Self::Custom(x))
340 }
341 match name {
342 $( stringify!($unit) => {
343 if data.is_some() {
344 Err(format!("Unexpected data for unit variant {}", name))
345 } else
346 {
347 Ok(Self::$unit)
348 }
349 }, )*
350
351 $( stringify!($tuple) => {
352 let d = data
353 .ok_or_else(|| format!("Missing data for {}", stringify!($tuple)))?
354 .parse()
355 .map_err(|_| format!("Invalid data for {}", stringify!($tuple)))?;
356 Ok(Self::$tuple(d))
357 }, )*
358
359 $( stringify!($tuple_default) => {
360 let d = match data {
361 Some(val) => val.parse()
362 .map_err(|_| format!("Invalid data for {}", stringify!($tuple_default)))?,
363 None => Default::default(),
364 };
365 Ok(Self::$tuple_default(d))
366 }, )*
367
368 $( stringify!($tuple_option) => {
369 let d = match data {
370 Some(val) if !val.is_empty() => {
371 Some(val.parse().map_err(|_| format!("Invalid data for {}", stringify!($tuple_option)))?)
372 }
373 _ => None,
374 };
375 Ok(Self::$tuple_option(d))
376 }, )*
377
378 $( stringify!($tuple_string_default) => {
379 let d = match data {
380 Some(val) if !val.is_empty() => val.to_string(),
381 _ => String::new(),
382 };
383 Ok(Self::$tuple_string_default(d))
384 }, )*
385
386 _ => Err(format!("Unknown variant {}", s))
387 }
388 }
389 }
390 };
391}
392
393impl_display_and_from_str_enum!(
395 Select, Deselect, Toggle, CycleAll, ClearAll, Accept, CyclePreview, CycleColumn,
396 PreviewHalfPageUp, PreviewHalfPageDown, HistoryUp, HistoryDown,
397 ChangePrompt, ChangeQuery, ToggleWrap, ToggleWrapPreview, ForwardChar,
398 BackwardChar, ForwardWord, BackwardWord, DeleteChar, DeleteWord,
399 DeleteLineStart, DeleteLineEnd, Cancel, Redraw;
400 Execute, Become, Reload, Preview, SetInput, Column, Pos, InputPos;
402 Up, Down, PreviewUp, PreviewDown, Quit, Overlay;
404 SwitchPreview, SetPreview, SetPrompt, SetHeader, SetFooter;
406 Print, Help
408);
409
410impl_transparent_wrapper!(Exit, i32, 1);
411impl_transparent_wrapper!(Count, u16, 1; derive(Copy));
412
413impl<A: ActionExt> IntoIterator for Actions<A> {
415 type Item = Action<A>;
416 type IntoIter = <ArrayVec<Action<A>, MAX_ACTIONS> as IntoIterator>::IntoIter;
417
418 fn into_iter(self) -> Self::IntoIter {
419 self.0.into_iter()
420 }
421}
422
423impl<'a, A: ActionExt> IntoIterator for &'a Actions<A> {
424 type Item = &'a Action<A>;
425 type IntoIter = <&'a ArrayVec<Action<A>, MAX_ACTIONS> as IntoIterator>::IntoIter;
426
427 fn into_iter(self) -> Self::IntoIter {
428 self.0.iter()
429 }
430}