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