1use crokey::KeyCombination;
2use crossterm::event::{KeyModifiers, MouseEventKind};
3use serde::Deserializer;
4use std::{collections::HashMap, fmt, str::FromStr};
5
6use crossterm::event::MouseButton;
7use serde::de::{self, Visitor};
8
9use crate::{action::Actions, message::Event};
10
11pub type BindMap = HashMap<Trigger, Actions>;
12
13#[derive(Debug, Hash, PartialEq, Eq, Clone)]
14pub enum Trigger {
15 Key(KeyCombination),
16 Mouse(MouseEvent),
17 Event(Event),
18}
19
20#[derive(Debug, Hash, PartialEq, Eq, Clone)]
21pub struct MouseEvent {
22 pub kind: MouseEventKind,
23 pub modifiers: KeyModifiers,
24}
25
26impl From<crossterm::event::MouseEvent> for Trigger {
28 fn from(e: crossterm::event::MouseEvent) -> Self {
29 Trigger::Mouse(MouseEvent {
30 kind: e.kind,
31 modifiers: e.modifiers,
32 })
33 }
34}
35
36impl From<KeyCombination> for Trigger {
37 fn from(key: KeyCombination) -> Self {
38 Trigger::Key(key)
39 }
40}
41
42impl From<Event> for Trigger {
43 fn from(event: Event) -> Self {
44 Trigger::Event(event)
45 }
46}
47impl<'de> serde::Deserialize<'de> for Trigger {
50 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
51 where
52 D: Deserializer<'de>,
53 {
54 struct TriggerVisitor;
55
56 impl<'de> Visitor<'de> for TriggerVisitor {
57 type Value = Trigger;
58
59 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
60 write!(f, "a string representing a Trigger")
61 }
62
63 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
64 where
65 E: de::Error,
66 {
67 if let Ok(key) = KeyCombination::from_str(value) {
69 return Ok(Trigger::Key(key));
70 }
71
72 let parts: Vec<&str> = value.split('+').collect();
74 if let Some(last) = parts.last() {
75 if let Some(kind) = match last.to_lowercase().as_str() {
76 "left" => Some(MouseEventKind::Down(MouseButton::Left)),
77 "middle" => Some(MouseEventKind::Down(MouseButton::Middle)),
78 "right" => Some(MouseEventKind::Down(MouseButton::Right)),
79 "scrolldown" => Some(MouseEventKind::ScrollDown),
80 "scrollup" => Some(MouseEventKind::ScrollUp),
81 "scrollleft" => Some(MouseEventKind::ScrollLeft),
82 "scrollright" => Some(MouseEventKind::ScrollRight),
83 _ => None,
84 } {
85 let mut modifiers = KeyModifiers::empty();
86 for m in &parts[..parts.len() - 1] {
87 match m.to_lowercase().as_str() {
88 "shift" => modifiers |= KeyModifiers::SHIFT,
89 "ctrl" => modifiers |= KeyModifiers::CONTROL,
90 "alt" => modifiers |= KeyModifiers::ALT,
91 "super" => modifiers |= KeyModifiers::SUPER,
92 "hyper" => modifiers |= KeyModifiers::HYPER,
93 "meta" => modifiers |= KeyModifiers::META,
94 "none" => {}
95 unknown => {
96 return Err(E::custom(format!(
97 "Unknown modifier: {}",
98 unknown
99 )));
100 }
101 }
102 }
103 return Ok(Trigger::Mouse(MouseEvent { kind, modifiers }));
104 }
105 }
106
107 if let Ok(evt) = value.parse::<Event>() {
109 return Ok(Trigger::Event(evt));
110 }
111
112 Err(E::custom(format!(
113 "failed to parse trigger from '{}'",
114 value
115 )))
116 }
117 }
118
119 deserializer.deserialize_str(TriggerVisitor)
120 }
121}