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