1use std::{
2 fmt::{self, Debug, Display},
3 str::FromStr,
4};
5
6use serde::{Deserialize, Serialize, Serializer};
7
8use crate::{MAX_ACTIONS, SSS, utils::serde::StringOrVec};
9
10#[derive(Debug, Clone, PartialEq)]
14pub enum Action<A: ActionExt = NullActionExt> {
15 Select,
17 Deselect,
19 Toggle,
21 CycleAll,
23 ClearSelections,
25 Accept,
27 Quit(i32),
29
30 ToggleWrap,
33 CycleSort,
34
35 CyclePreview,
38 Preview(String),
40 Help(String),
42 SetPreview(Option<u8>),
45 SwitchPreview(Option<u8>),
47 ToggleWrapPreview,
49 HScroll(i8),
52
53 PreviewHScroll(i8),
57 PreviewScroll(i8),
60 PreviewJump,
62
63 SetInput(String),
66 SetHeader(Option<String>),
68 SetFooter(Option<String>),
70 SetPrompt(Option<String>),
72
73 Column(usize),
76 CycleColumn,
78 ColumnLeft,
80 ColumnRight,
81 ScrollLeft,
82 ScrollRight,
83
84 Execute(String),
87 Become(String),
89 Reload(String),
91 Print(String),
93
94 HistoryUp,
97 HistoryDown,
99 ChangePrompt,
101 ChangeQuery,
103
104 ForwardChar,
107 BackwardChar,
109 ForwardWord,
111 BackwardWord,
113 DeleteChar,
115 DeleteWord,
117 DeleteLineStart,
119 DeleteLineEnd,
121 Cancel,
123 InputPos(i32),
125
126 Up(u16),
129 Down(u16),
131 PreviewUp(u16),
133 PreviewDown(u16),
135 PreviewHalfPageUp,
137 PreviewHalfPageDown,
139 Pos(i32),
141
142 Input(char),
145 Redraw,
147 Custom(A),
149 Overlay(usize),
151}
152
153#[macro_export]
172macro_rules! acs {
173 ( $( $x:expr ),* $(,)? ) => {
174 {
175 $crate::action::Actions::from([$($x),*])
176 }
177 };
178}
179pub use crate::acs;
180
181#[macro_export]
195macro_rules! bindmap {
196 ( $( $( $k:expr ),+ => $v:expr ),* $(,)? ) => {{
197 let mut map = $crate::binds::BindMap::new();
198 $(
199 let action = $crate::action::Actions::from($v);
200 $(
201 map.insert($k.into(), action.clone());
202 )+
203 )*
204 map
205 }};
206} pub trait ActionExt: Debug + Clone + PartialEq + SSS {}
211impl<T: Debug + Clone + PartialEq + SSS> ActionExt for T {}
212
213impl<T> From<T> for Action<T>
214where
215 T: ActionExt,
216{
217 fn from(value: T) -> Self {
218 Self::Custom(value)
219 }
220}
221#[derive(Debug, Clone, Default, PartialEq)]
222pub struct NullActionExt {}
223
224impl fmt::Display for NullActionExt {
225 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
226 Ok(())
227 }
228}
229
230impl std::str::FromStr for NullActionExt {
231 type Err = ();
232
233 fn from_str(_: &str) -> Result<Self, Self::Err> {
234 Err(())
235 }
236}
237
238pub use arrayvec::ArrayVec;
240
241#[derive(Debug, Default, Clone, PartialEq)]
242pub struct Actions<A: ActionExt = NullActionExt>(ArrayVec<Action<A>, MAX_ACTIONS>);
243
244macro_rules! repeat_impl {
245 ($($len:expr),*) => {
246 $(
247 impl<A: ActionExt> From<[Action<A>; $len]> for Actions<A> {
248 fn from(arr: [Action<A>; $len]) -> Self {
249 Actions(ArrayVec::from_iter(arr))
250 }
251 }
252
253 impl<A: ActionExt> From<[A; $len]> for Actions<A> {
254 fn from(arr: [A; $len]) -> Self {
255 Actions(arr.into_iter().map(Action::Custom).collect())
256 }
257 }
258 )*
259 }
260}
261impl<A: ActionExt> From<[Action<A>; 0]> for Actions<A> {
262 fn from(empty: [Action<A>; 0]) -> Self {
263 Actions(ArrayVec::from_iter(empty))
264 }
265}
266repeat_impl!(1, 2, 3, 4, 5, 6);
267
268impl<A: ActionExt> From<Action<A>> for Actions<A> {
269 fn from(action: Action<A>) -> Self {
270 acs![action]
271 }
272}
273impl<A: ActionExt> From<A> for Actions<A> {
275 fn from(action: A) -> Self {
276 acs![Action::Custom(action)]
277 }
278}
279
280impl<A: ActionExt + Display> serde::Serialize for Action<A> {
283 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
284 where
285 S: serde::Serializer,
286 {
287 serializer.serialize_str(&self.to_string())
288 }
289}
290
291impl<'de, A: ActionExt + FromStr> Deserialize<'de> for Actions<A> {
292 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
293 where
294 D: serde::Deserializer<'de>,
295 {
296 let helper = StringOrVec::deserialize(deserializer)?;
297 let strings = match helper {
298 StringOrVec::String(s) => vec![s],
299 StringOrVec::Vec(v) => v,
300 };
301
302 if strings.len() > MAX_ACTIONS {
303 return Err(serde::de::Error::custom(format!(
304 "Too many actions, max is {MAX_ACTIONS}."
305 )));
306 }
307
308 let mut actions = ArrayVec::new();
309 for s in strings {
310 let action = Action::from_str(&s).map_err(serde::de::Error::custom)?;
311 actions.push(action);
312 }
313
314 Ok(Actions(actions))
315 }
316}
317
318impl<A: ActionExt + Display> Serialize for Actions<A> {
319 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
320 where
321 S: Serializer,
322 {
323 match self.0.len() {
324 1 => serializer.serialize_str(&self.0[0].to_string()),
325 _ => {
326 let strings: Vec<String> = self.0.iter().map(|a| a.to_string()).collect();
327 strings.serialize(serializer)
328 }
329 }
330 }
331}
332
333enum_from_str_display!(
335 units:
336 Select, Deselect, Toggle, CycleAll, ClearSelections, Accept, CyclePreview, CycleColumn, ScrollLeft, ScrollRight, ColumnLeft, ColumnRight, PreviewJump, CycleSort,
337 PreviewHalfPageUp, PreviewHalfPageDown, HistoryUp, HistoryDown,
338 ChangePrompt, ChangeQuery, ToggleWrap, ToggleWrapPreview, ForwardChar,
339 BackwardChar, ForwardWord, BackwardWord, DeleteChar, DeleteWord,
340 DeleteLineStart, DeleteLineEnd, Cancel, Redraw;
341
342 tuples:
343 Execute, Become, Reload, Preview, SetInput, Column, Pos, InputPos;
344
345 defaults:
346 (Up, 1), (Down, 1), (PreviewUp, 1), (PreviewDown, 1), (Quit, 1), (Overlay, 0), (Print, String::new()), (Help, String::new()), (PreviewScroll, 1), (PreviewHScroll, 1), (HScroll, 0);
347
348 options:
349 SwitchPreview, SetPreview, SetPrompt, SetHeader, SetFooter
350);
351
352macro_rules! enum_from_str_display {
353 (
354 units: $($unit:ident),*;
355 tuples: $($tuple:ident),*;
356 defaults: $(($default:ident, $default_value:expr)),*;
357 options: $($optional:ident),*
358 ) => {
359 impl<A: ActionExt + Display> std::fmt::Display for Action<A> {
360 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
361 match self {
362 $( Self::$unit => write!(f, stringify!($unit)), )*
363
364 $( Self::$tuple(inner) => write!(f, concat!(stringify!($tuple), "({})"), inner), )*
365
366 $( Self::$default(inner) => {
367 if *inner == $default_value {
368 write!(f, stringify!($default))
369 } else {
370 write!(f, concat!(stringify!($default), "({})"), inner)
371 }
372 }, )*
373
374 $( Self::$optional(opt) => {
375 if let Some(inner) = opt {
376 write!(f, concat!(stringify!($optional), "({})"), inner)
377 } else {
378 write!(f, stringify!($optional))
379 }
380 }, )*
381
382 Self::Custom(inner) => {
383 write!(f, "{}", inner.to_string())
384 }
385 Self::Input(c) => {
386 write!(f, "{c}")
387 }
388 }
389 }
390 }
391
392 impl<A: ActionExt + FromStr> std::str::FromStr for Action<A> {
393 type Err = String;
394
395 fn from_str(s: &str) -> Result<Self, Self::Err> {
396 let (name, data) = if let Some(pos) = s.find('(') {
397 if s.ends_with(')') {
398 (&s[..pos], Some(&s[pos + 1..s.len() - 1]))
399 } else {
400 (s, None)
401 }
402 } else {
403 (s, None)
404 };
405
406 if let Ok(x) = name.parse::<A>() {
407 return Ok(Self::Custom(x))
408 }
409 match name {
410 $( n if n.eq_ignore_ascii_case(stringify!($unit)) => {
411 if data.is_some() {
412 Err(format!("Unexpected data for unit variant {}", name))
413 } else {
414 Ok(Self::$unit)
415 }
416 }, )*
417
418 $( n if n.eq_ignore_ascii_case(stringify!($tuple)) => {
419 let d = data
420 .ok_or_else(|| format!("Missing data for {}", stringify!($tuple)))?
421 .parse()
422 .map_err(|_| format!("Invalid data for {}", stringify!($tuple)))?;
423 Ok(Self::$tuple(d))
424 }, )*
425
426 $( n if n.eq_ignore_ascii_case(stringify!($default)) => {
427 let d = match data {
428 Some(val) => val
429 .parse()
430 .map_err(|_| format!("Invalid data for {}", stringify!($default)))?,
431 None => $default_value,
432 };
433 Ok(Self::$default(d))
434 }, )*
435
436 $( n if n.eq_ignore_ascii_case(stringify!($optional)) => {
437 let d = match data {
438 Some(val) if !val.is_empty() => {
439 Some(
440 val.parse()
441 .map_err(|_| format!("Invalid data for {}", stringify!($optional)))?,
442 )
443 }
444 _ => None,
445 };
446 Ok(Self::$optional(d))
447 }, )*
448
449 _ => Err(format!("Unknown variant {}", s)),
450 }
451 }
452 }
453 };
454}
455use enum_from_str_display;
456
457impl<A: ActionExt> IntoIterator for Actions<A> {
458 type Item = Action<A>;
459 type IntoIter = <ArrayVec<Action<A>, MAX_ACTIONS> as IntoIterator>::IntoIter;
460
461 fn into_iter(self) -> Self::IntoIter {
462 self.0.into_iter()
463 }
464}
465
466impl<'a, A: ActionExt> IntoIterator for &'a Actions<A> {
467 type Item = &'a Action<A>;
468 type IntoIter = <&'a ArrayVec<Action<A>, MAX_ACTIONS> as IntoIterator>::IntoIter;
469
470 fn into_iter(self) -> Self::IntoIter {
471 self.0.iter()
472 }
473}