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