aboutsummaryrefslogtreecommitdiff
path: root/src/keybinds.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/keybinds.rs')
-rw-r--r--src/keybinds.rs146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/keybinds.rs b/src/keybinds.rs
new file mode 100644
index 0000000..1b9c234
--- /dev/null
+++ b/src/keybinds.rs
@@ -0,0 +1,146 @@
1use std::convert::From;
2
3use cursive::event::Event as CursiveEvent;
4use serde::ser;
5use serde::{self, Deserialize, Serialize, Serializer};
6
7#[derive(Debug, PartialEq)]
8struct Event(CursiveEvent);
9
10macro_rules! event {
11 ($thing:expr) => {
12 Event { 0: $thing };
13 };
14}
15
16impl<T> From<T> for Event
17where
18 T: AsRef<str>,
19{
20 fn from(key: T) -> Self {
21 let key = key.as_ref();
22 if key.len() == 1 {
23 // single key
24 return event!(CursiveEvent::Char(key.chars().nth(0).unwrap()));
25 } else if (key.starts_with("c-") || key.starts_with("C-")) && key.len() == 3 {
26 // ctrl-key
27 return event!(CursiveEvent::CtrlChar(key.chars().nth(2).unwrap()));
28 } else {
29 panic!(
30 r"Invalid keybind in configuration!
31 (I intend to handle this error gracefully in the near future)"
32 );
33 }
34 }
35}
36
37enum Bind {
38 Char(char),
39 CtrlChar(char),
40 AltChar(char),
41}
42
43impl Serialize for Bind {
44 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
45 where
46 S: Serializer,
47 {
48 match self {
49 Bind::Char(c) => serializer.serialize_newtype_variant("bind", 0, "regular", &c),
50 Bind::CtrlChar(c) => serializer.serialize_newtype_variant("bind", 0, "ctrl", &c),
51 Bind::AltChar(c) => serializer.serialize_newtype_variant("bind", 0, "alt", &c),
52 }
53 }
54}
55
56impl Deserialize for Bind {
57 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58 where
59 D: Deserializer<'de>,
60 {
61 eprintln!("hell = {:#?}", hell);
62 }
63}
64
65impl From<Bind> for CursiveEvent {
66 fn from(key: Bind) -> Self {
67 match key {
68 Bind::Char(c) => CursiveEvent::Char(c),
69 Bind::CtrlChar(c) => CursiveEvent::Char(c),
70 Bind::AltChar(c) => CursiveEvent::AltChar(c),
71 }
72 }
73}
74
75#[derive(Serialize, Deserialize)]
76pub struct KeyBinds {
77 grid: Movement,
78 cursor: Movement,
79 week_mode: Bind,
80 global_week_mode: Bind,
81}
82
83#[derive(Serialize, Deserialize)]
84pub struct Movement {
85 up: Bind,
86 down: Bind,
87 left: Bind,
88 right: Bind,
89}
90
91impl Movement {
92 pub fn new(left: char, down: char, up: char, right: char) -> Self {
93 return Movement {
94 up: Bind::Char(up),
95 down: Bind::Char(down),
96 left: Bind::Char(left),
97 right: Bind::Char(right),
98 };
99 }
100}
101
102impl std::default::Default for KeyBinds {
103 fn default() -> Self {
104 let grid = Movement::new('h', 'j', 'k', 'l');
105 let cursor = Movement::new('H', 'J', 'K', 'L');
106 return KeyBinds {
107 grid,
108 cursor,
109 week_mode: Bind::Char('v'),
110 global_week_mode: Bind::Char('V'),
111 };
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn normal_keybind() {
121 let bind = "X";
122 let expected = CursiveEvent::Char('X');
123 assert_eq!(Event::from(bind), event!(expected));
124 }
125
126 #[test]
127 fn control_keybind() {
128 let bind = "C-x";
129 let expected = CursiveEvent::CtrlChar('x');
130 assert_eq!(Event::from(bind), event!(expected));
131 }
132
133 #[test]
134 fn lower_case_control_keybind() {
135 let bind = "c-x";
136 let expected = CursiveEvent::CtrlChar('x');
137 assert_eq!(Event::from(bind), event!(expected));
138 }
139
140 #[test]
141 #[should_panic]
142 fn very_long_and_wrong_keybind() {
143 let bind = "alksdjfalkjdf";
144 Event::from(bind);
145 }
146}