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 HScroll(i8),
47 VScroll(i8),
52
53 CyclePreview,
56 Preview(String),
58 Help(String),
60 SetPreview(Option<u8>),
63 SwitchPreview(Option<u8>),
66 TogglePreviewWrap,
68
69 PreviewUp(u16),
72 PreviewDown(u16),
74 PreviewHalfPageUp,
77 PreviewHalfPageDown,
80
81 PreviewHScroll(i8),
85 PreviewScroll(i8),
88 PreviewJump,
90
91 NextColumn,
93 PrevColumn,
95 SwitchColumn(String),
97 ToggleColumn(Option<String>),
99 ShowColumn(Option<String>),
101 ScrollLeft,
102 ScrollRight,
103
104 Execute(String),
107 ExecuteSilent(String),
109 Become(String),
111 Reload(String),
113 Print(String),
115 PrintKey,
117 Store(String),
119
120 ForwardChar,
123 BackwardChar,
125 ForwardWord,
127 BackwardWord,
129 DeleteChar,
131 DeleteWord,
133 DeleteLineStart,
135 DeleteLineEnd,
137 Cancel,
139 SetQuery(String),
141 QueryPos(i32),
143
144 Char(char),
147 Redraw,
149 Custom(A),
151 Overlay(usize),
153 Semantic(String),
155}
156
157#[macro_export]
176macro_rules! acs {
177 ( $( $x:expr ),* $(,)? ) => {
178 {
179 $crate::action::Actions::from([$($x),*])
180 }
181 };
182}
183pub use crate::acs;
184
185#[macro_export]
199macro_rules! bindmap {
200 ( $( $( $k:expr ),+ => $v:expr ),* $(,)? ) => {{
201 let mut map = $crate::binds::BindMap::new();
202 $(
203 let action = $crate::action::Actions::from($v);
204 $(
205 map.insert($k.into(), action.clone());
206 )+
207 )*
208 map
209 }};
210} pub trait ActionExt: Debug + Clone + PartialEq + SSS {}
215impl<T: Debug + Clone + PartialEq + SSS> ActionExt for T {}
216
217impl<T> From<T> for Action<T>
218where
219 T: ActionExt,
220{
221 fn from(value: T) -> Self {
222 Self::Custom(value)
223 }
224}
225#[derive(Debug, Clone, PartialEq)]
226pub enum NullActionExt {}
227
228impl fmt::Display for NullActionExt {
229 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
230 Ok(())
231 }
232}
233
234impl std::str::FromStr for NullActionExt {
235 type Err = ();
236
237 fn from_str(_: &str) -> Result<Self, Self::Err> {
238 Err(())
239 }
240}
241
242pub use arrayvec::ArrayVec;
244
245#[derive(Debug, Clone, PartialEq)]
246pub struct Actions<A: ActionExt = NullActionExt>(pub ArrayVec<Action<A>, MAX_ACTIONS>);
247
248impl<A: ActionExt> Default for Actions<A> {
249 fn default() -> Self {
250 Self(ArrayVec::new())
251 }
252}
253
254macro_rules! repeat_impl {
255 ($($len:expr),*) => {
256 $(
257 impl<A: ActionExt> From<[Action<A>; $len]> for Actions<A> {
258 fn from(arr: [Action<A>; $len]) -> Self {
259 Actions(ArrayVec::from_iter(arr))
260 }
261 }
262
263 impl<A: ActionExt> From<[A; $len]> for Actions<A> {
264 fn from(arr: [A; $len]) -> Self {
265 Actions(arr.into_iter().map(Action::Custom).collect())
266 }
267 }
268 )*
269 }
270}
271impl<A: ActionExt> From<[Action<A>; 0]> for Actions<A> {
272 fn from(empty: [Action<A>; 0]) -> Self {
273 Actions(ArrayVec::from_iter(empty))
274 }
275}
276repeat_impl!(1, 2, 3, 4, 5, 6);
277
278impl<A: ActionExt> From<Action<A>> for Actions<A> {
279 fn from(action: Action<A>) -> Self {
280 acs![action]
281 }
282}
283impl<A: ActionExt> From<A> for Actions<A> {
285 fn from(action: A) -> Self {
286 acs![Action::Custom(action)]
287 }
288}
289
290impl<A: ActionExt + Display> serde::Serialize for Action<A> {
293 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
294 where
295 S: serde::Serializer,
296 {
297 serializer.serialize_str(&self.to_string())
298 }
299}
300
301impl<'de, A: ActionExt + FromStr> Deserialize<'de> for Actions<A> {
302 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
303 where
304 D: serde::Deserializer<'de>,
305 {
306 let helper = StringOrVec::deserialize(deserializer)?;
307 let strings = match helper {
308 StringOrVec::String(s) => vec![s],
309 StringOrVec::Vec(v) => v,
310 };
311
312 if strings.len() > MAX_ACTIONS {
313 return Err(serde::de::Error::custom(format!(
314 "Too many actions, max is {MAX_ACTIONS}."
315 )));
316 }
317
318 let mut actions = ArrayVec::new();
319 for s in strings {
320 let action = Action::from_str(&s).map_err(serde::de::Error::custom)?;
321 actions.push(action);
322 }
323
324 Ok(Actions(actions))
325 }
326}
327
328impl<A: ActionExt + Display> Serialize for Actions<A> {
329 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
330 where
331 S: Serializer,
332 {
333 match self.0.len() {
334 1 => serializer.serialize_str(&self.0[0].to_string()),
335 _ => {
336 let strings: Vec<String> = self.0.iter().map(|a| a.to_string()).collect();
337 strings.serialize(serializer)
338 }
339 }
340 }
341}
342
343enum_from_str_display!(
345 units:
346 Select, Deselect, Toggle, CycleAll, ClearSelections, Accept,
347
348 PageDown, PageUp, ScrollLeft, ScrollRight,
349
350 ToggleWrap, TogglePreviewWrap, CyclePreview, PreviewJump,
351
352 PreviewHalfPageUp, PreviewHalfPageDown,
353
354 ForwardChar,BackwardChar, ForwardWord, BackwardWord, DeleteChar, DeleteWord, DeleteLineStart, DeleteLineEnd, Cancel, Redraw, NextColumn, PrevColumn, PrintKey;
355
356 tuples:
357 Execute, ExecuteSilent, Become, Preview,
358 SetQuery, Pos, QueryPos, SwitchColumn, Store;
359
360 defaults:
361 (Up, 1), (Down, 1), (PreviewUp, 1), (PreviewDown, 1), (Quit, 1), (Overlay, 0), (Print, String::new()), (Help, String::new()), (Reload, String::new()), (PreviewScroll, 1), (PreviewHScroll, 1), (HScroll, 0), (VScroll, 0);
362
363 options:
364 SwitchPreview, SetPreview, ToggleColumn, ShowColumn
365);
366
367macro_rules! enum_from_str_display {
368 (
369 units: $($unit:ident),*;
370 tuples: $($tuple:ident),*;
371 defaults: $(($default:ident, $default_value:expr)),*;
372 options: $($optional:ident),*
373 ) => {
374 impl<A: ActionExt + Display> std::fmt::Display for Action<A> {
375 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
376 match self {
377 $( Self::$unit => write!(f, stringify!($unit)), )*
378
379 $( Self::$tuple(inner) => write!(f, concat!(stringify!($tuple), "({})"), inner), )*
380
381 $( Self::$default(inner) => {
382 if *inner == $default_value {
383 write!(f, stringify!($default))
384 } else {
385 write!(f, concat!(stringify!($default), "({})"), inner)
386 }
387 }, )*
388
389 $( Self::$optional(opt) => {
390 if let Some(inner) = opt {
391 write!(f, concat!(stringify!($optional), "({})"), inner)
392 } else {
393 write!(f, stringify!($optional))
394 }
395 }, )*
396
397 Self::Custom(inner) => {
398 write!(f, "{}", inner.to_string())
399 }
400 Self::Char(c) => {
401 write!(f, "{c}")
402 }
403 Self::Semantic(s) => {
404 write!(f, "{}", s)
405 }
406 }
407 }
408 }
409
410 impl<A: ActionExt + FromStr> std::str::FromStr for Action<A> {
411 type Err = String;
412
413 fn from_str(s: &str) -> Result<Self, Self::Err> {
414 let s = s.trim();
415 if let Ok(x) = s.parse::<A>() {
416 return Ok(Self::Custom(x))
417 }
418
419 if let Some(rest) = s.strip_prefix("::") {
420 return Ok(Self::Semantic(rest.to_string()));
421 }
422
423 let (name, data) = if let Some(pos) = s.find('(') {
424 if s.ends_with(')') {
425 (&s[..pos], Some(&s[pos + 1..s.len() - 1]))
426 } else {
427 (s, None)
428 }
429 } else {
430 (s, None)
431 };
432
433 match name {
434 $( n if n.eq_ignore_ascii_case(stringify!($unit)) => {
435 if data.is_some() {
436 Err(format!("Unexpected data for unit variant {}", name))
437 } else {
438 Ok(Self::$unit)
439 }
440 }, )*
441
442 $( n if n.eq_ignore_ascii_case(stringify!($tuple)) => {
443 let d = data
444 .ok_or_else(|| format!("Missing data for {}", stringify!($tuple)))?
445 .parse()
446 .map_err(|_| format!("Invalid data for {}", stringify!($tuple)))?;
447 Ok(Self::$tuple(d))
448 }, )*
449
450 $( n if n.eq_ignore_ascii_case(stringify!($default)) => {
451 let d = match data {
452 Some(val) => val
453 .parse()
454 .map_err(|_| format!("Invalid data for {}", stringify!($default)))?,
455 None => $default_value,
456 };
457 Ok(Self::$default(d))
458 }, )*
459
460 $( n if n.eq_ignore_ascii_case(stringify!($optional)) => {
461 let d = match data {
462 Some(val) if !val.is_empty() => {
463 Some(
464 val.parse()
465 .map_err(|_| format!("Invalid data for {}", stringify!($optional)))?,
466 )
467 }
468 _ => None,
469 };
470 Ok(Self::$optional(d))
471 }, )*
472
473 _ => Err(format!("Unknown action: {}.", s)),
474 }
475 }
476 }
477 };
478}
479use enum_from_str_display;
480
481impl<A: ActionExt> IntoIterator for Actions<A> {
482 type Item = Action<A>;
483 type IntoIter = <ArrayVec<Action<A>, MAX_ACTIONS> as IntoIterator>::IntoIter;
484
485 fn into_iter(self) -> Self::IntoIter {
486 self.0.into_iter()
487 }
488}
489
490impl<'a, A: ActionExt> IntoIterator for &'a Actions<A> {
491 type Item = &'a Action<A>;
492 type IntoIter = <&'a ArrayVec<Action<A>, MAX_ACTIONS> as IntoIterator>::IntoIter;
493
494 fn into_iter(self) -> Self::IntoIter {
495 self.0.iter()
496 }
497}
498
499impl<A: ActionExt> FromIterator<Action<A>> for Actions<A> {
500 fn from_iter<T: IntoIterator<Item = Action<A>>>(iter: T) -> Self {
501 let mut inner = ArrayVec::<Action<A>, MAX_ACTIONS>::new();
502 inner.extend(iter);
503 Actions(inner)
504 }
505}
506
507use std::ops::{Deref, DerefMut};
508
509impl<A: ActionExt> Deref for Actions<A> {
510 type Target = ArrayVec<Action<A>, MAX_ACTIONS>;
511
512 fn deref(&self) -> &Self::Target {
513 &self.0
514 }
515}
516
517impl<A: ActionExt> DerefMut for Actions<A> {
518 fn deref_mut(&mut self) -> &mut Self::Target {
519 &mut self.0
520 }
521}