1#[cfg(feature = "crossterm_0_29_0")]
2use crossterm_0_29_0::event::{KeyCode, KeyEvent, KeyModifiers, MediaKeyCode};
3#[cfg(feature = "crossterm_0_28_1")]
4use crossterm_0_28_1::event::{KeyCode, KeyEvent, KeyModifiers, MediaKeyCode};
5
6use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
7use std::fmt;
8#[cfg(feature = "case_ignore")]
9use str_utils::StartsWithIgnoreAsciiCase;
10
11#[derive(Default, PartialEq)]
12pub enum DisplayFormat {
13 #[default]
15 Symbols,
16
17 Debug,
19
20 Full,
22
23 Abbreviation
25}
26
27#[derive(PartialEq)]
28pub struct KeyBinding {
29 pub code: KeyCode,
31 pub modifiers: KeyModifiers,
32}
33
34impl Serialize for KeyBinding {
35 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36 where
37 S: Serializer,
38 {
39 let mut s = match self.modifiers {
40 KeyModifiers::SHIFT => "Shift+".to_string(),
41 KeyModifiers::CONTROL => "Control+".to_string(),
42 KeyModifiers::ALT => "Alternate+".to_string(),
43 KeyModifiers::SUPER => "Super+".to_string(),
44 KeyModifiers::HYPER => "Hyper+".to_string(),
45 KeyModifiers::META => "Meta+".to_string(),
46 _ => String::new(),
48 };
49 match self.code {
50 KeyCode::Char(c) => s.push(c),
51 KeyCode::Backspace => s.push_str("Backspace"),
52 KeyCode::Enter => s.push_str("Enter"),
53 KeyCode::Left => s.push_str("Left"),
54 KeyCode::Right => s.push_str("Right"),
55 KeyCode::Up => s.push_str("Up"),
56 KeyCode::Down => s.push_str("Down"),
57 KeyCode::Home => s.push_str("Home"),
58 KeyCode::End => s.push_str("End"),
59 KeyCode::PageUp => s.push_str("PageUp"),
60 KeyCode::PageDown => s.push_str("PageDown"),
61 KeyCode::Tab => s.push_str("Tab"),
62 KeyCode::BackTab => s.push_str("BackTab"),
63 KeyCode::Delete => s.push_str("Delete"),
64 KeyCode::Insert => s.push_str("Insert"),
65 KeyCode::F(n) => s.push_str(&format!("F{n}")),
66 KeyCode::Esc => s.push_str("Esc"),
67 KeyCode::CapsLock => s.push_str("CapsLock"),
68 KeyCode::ScrollLock => s.push_str("ScrollLock"),
69 KeyCode::NumLock => s.push_str("NumLock"),
70 KeyCode::PrintScreen => s.push_str("PrintScreen"),
71 KeyCode::Pause => s.push_str("Pause"),
72 KeyCode::Menu => s.push_str("Menu"),
73 KeyCode::KeypadBegin => s.push_str("KeypadBegin"),
74 KeyCode::Media(media_keycode) => s.push_str(&media_keycode.to_string()),
75 _ => {
76 return Err(ser::Error::custom(format!(
77 "Unsupported KeyCode: {:}",
78 self.code
79 )))
80 }
81 }
82 serializer.serialize_str(&s)
83 }
84}
85
86fn str_to_keycode(s: &str) -> KeyCode {
87 let s = s.trim();
88 if s.len() == 1 {
89 KeyCode::Char(s.chars().next().unwrap())
90 } else if s == "Backspace" {
91 KeyCode::Backspace
92 } else if s == "Enter" {
93 KeyCode::Enter
94 } else if s == "Left" {
95 KeyCode::Left
96 } else if s == "Right" {
97 KeyCode::Right
98 } else if s == "Up" {
99 KeyCode::Up
100 } else if s == "Down" {
101 KeyCode::Down
102 } else if s == "Home" {
103 KeyCode::Home
104 } else if s == "End" {
105 KeyCode::End
106 } else if s == "PageUp" {
107 KeyCode::PageUp
108 } else if s == "PageDown" {
109 KeyCode::PageDown
110 } else if s == "Tab" {
111 KeyCode::Tab
112 } else if s == "BackTab" {
113 KeyCode::BackTab
114 } else if s == "Delete" {
115 KeyCode::Delete
116 } else if s == "Insert" {
117 KeyCode::Insert
118 } else if s == "F1" {
119 KeyCode::F(1)
120 } else if s == "F2" {
121 KeyCode::F(2)
122 } else if s == "F3" {
123 KeyCode::F(3)
124 } else if s == "F4" {
125 KeyCode::F(4)
126 } else if s == "F5" {
127 KeyCode::F(5)
128 } else if s == "F6" {
129 KeyCode::F(6)
130 } else if s == "F7" {
131 KeyCode::F(7)
132 } else if s == "F8" {
133 KeyCode::F(8)
134 } else if s == "F9" {
135 KeyCode::F(9)
136 } else if s == "F10" {
137 KeyCode::F(10)
138 } else if s == "F11" {
139 KeyCode::F(11)
140 } else if s == "F12" {
141 KeyCode::F(12)
142 } else if s == "Esc" {
143 KeyCode::Esc
144 } else if s == "CapsLock" {
145 KeyCode::CapsLock
146 } else if s == "ScrollLock" {
147 KeyCode::ScrollLock
148 } else if s == "NumLock" {
149 KeyCode::NumLock
150 } else if s == "PrintScreen" {
151 KeyCode::PrintScreen
152 } else if s == "Pause" {
153 KeyCode::Pause
154 } else if s == "Menu" {
155 KeyCode::Menu
156 } else if s == "KeypadBegin" {
157 KeyCode::KeypadBegin
158 } else if s == "Play" {
159 KeyCode::Media(MediaKeyCode::Play)
160 } else if s == "PlayPause" {
161 KeyCode::Media(MediaKeyCode::PlayPause)
162 } else if s == "Reverse" {
163 KeyCode::Media(MediaKeyCode::Reverse)
164 } else if s == "Stop" {
165 KeyCode::Media(MediaKeyCode::Stop)
166 } else if s == "FastForward" {
167 KeyCode::Media(MediaKeyCode::FastForward)
168 } else if s == "Rewind" {
169 KeyCode::Media(MediaKeyCode::Rewind)
170 } else if s == "TrackNext" {
171 KeyCode::Media(MediaKeyCode::TrackNext)
172 } else if s == "TrackPrevious" {
173 KeyCode::Media(MediaKeyCode::TrackPrevious)
174 } else if s == "Record" {
175 KeyCode::Media(MediaKeyCode::Record)
176 } else if s == "LowerVolume" {
177 KeyCode::Media(MediaKeyCode::LowerVolume)
178 } else if s == "RaiseVolume" {
179 KeyCode::Media(MediaKeyCode::RaiseVolume)
180 } else if s == "MuteVolume" {
181 KeyCode::Media(MediaKeyCode::MuteVolume)
182 } else {
183 KeyCode::Null
184 }
185}
186
187impl<'de> Deserialize<'de> for KeyBinding {
188 fn deserialize<D>(deserializer: D) -> Result<KeyBinding, D::Error>
189 where
190 D: Deserializer<'de>,
191 {
192 let mut key_bindings = KeyBinding {
193 code: KeyCode::Null,
194 modifiers: KeyModifiers::NONE,
195 };
196 let mut error = None;
197
198 <String as Deserialize>::deserialize(deserializer).map(|s| {
199 if s.contains('+') {
200 #[cfg(feature = "case_ignore")]
201 if s.starts_with_ignore_ascii_case("Shift") {
202 key_bindings.modifiers = KeyModifiers::SHIFT;
203 } else if s.starts_with_ignore_ascii_case("Control") || s.starts_with_ignore_ascii_case("Ctrl") {
204 key_bindings.modifiers = KeyModifiers::CONTROL;
205 } else if s.starts_with_ignore_ascii_case("Alternate") || s.starts_with_ignore_ascii_case("Alt") {
206 key_bindings.modifiers = KeyModifiers::ALT;
207 } else if s.starts_with_ignore_ascii_case("Super") {
208 key_bindings.modifiers = KeyModifiers::SUPER;
209 } else if s.starts_with_ignore_ascii_case("Hyper") {
210 key_bindings.modifiers = KeyModifiers::HYPER;
211 } else if s.starts_with_ignore_ascii_case("Meta") {
212 key_bindings.modifiers = KeyModifiers::META;
213 } else {
214 error = Some(de::Error::custom(
215 "Currently only support following KeyModifiers: Shift, Control, Alternate, Super, Hyper, Meta"
216 ));
217 }
218 #[cfg(not(feature = "case_ignore"))]
219 if s.starts_with("Shift") {
220 key_bindings.modifiers = KeyModifiers::SHIFT;
221 } else if s.starts_with("Control") || s.starts_with("Ctrl") {
222 key_bindings.modifiers = KeyModifiers::CONTROL;
223 } else if s.starts_with("Alternate") || s.starts_with("Alt") {
224 key_bindings.modifiers = KeyModifiers::ALT;
225 } else if s.starts_with("Super") {
226 key_bindings.modifiers = KeyModifiers::SUPER;
227 } else if s.starts_with("Hyper") {
228 key_bindings.modifiers = KeyModifiers::HYPER;
229 } else if s.starts_with("Meta") {
230 key_bindings.modifiers = KeyModifiers::META;
231 } else {
232 error = Some(de::Error::custom(
233 "Currently only support following KeyModifiers: Shift, Control, Alternate, Super, Hyper, Meta"
234 ));
235 }
236 let mut splitter = s.splitn(2, '+');
237 key_bindings.code = str_to_keycode(splitter.nth(1).unwrap());
238 } else {
239 key_bindings.code = str_to_keycode(&s);
240 }
241 })?;
242 if let Some(e) = error {
243 Err(e)
244 } else if key_bindings.code == KeyCode::Null {
245 Err(de::Error::custom(
246 r#"Can not load a KeyCode, please use a char or one of following KeyCodes:
247"Backspace", "Enter", "Left", "Right", "Up", "Down", "Home", "End", "PageUp", "PageDown", "Tab", "BackTab", "Delete",
248"Insert", "F1" ~ "F12", "Esc", "CapsLock", "ScrollLock", "NumLock", "PrintScreen", "Pause", "Menu", "KeypadBegin",
249"Play", "PlayPause", "Reverse", "Stop", "FastForward", "Rewind", "TrackNext", "TrackPrevious", "Record", "LowerVolume",
250"RaiseVolume", "MuteVolume""#,
251 ))
252 } else {
253 Ok(key_bindings)
254 }
255 }
256}
257
258impl fmt::Display for KeyBinding {
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 match self.modifiers {
264 KeyModifiers::SHIFT => write!(f, "\u{21e7}")?, KeyModifiers::CONTROL => write!(f, "^")?,
266 KeyModifiers::ALT => write!(f, "\u{2387}")?, KeyModifiers::SUPER => write!(f, "\u{2756}")?, KeyModifiers::HYPER => write!(f, "\u{2388}")?, KeyModifiers::META => write!(f, "\u{2318}")?, KeyModifiers::NONE => write!(f, "")?,
271 _ => write!(f, "?")?,
272 };
273 match self.code {
274 KeyCode::Char(c) => write!(f, "{}", c),
275 KeyCode::Backspace => write!(f, "\u{232b}"), KeyCode::Enter => write!(f, "\u{23ce}"), KeyCode::Left => write!(f, "\u{2190}"), KeyCode::Right => write!(f, "\u{2192}"), KeyCode::Up => write!(f, "\u{2191}"), KeyCode::Down => write!(f, "\u{2193}"), KeyCode::Home => write!(f, "\u{2912}"), KeyCode::End => write!(f, "\u{2913}"), KeyCode::PageUp => write!(f, "\u{21de}"), KeyCode::PageDown => write!(f, "\u{21df}"), KeyCode::Tab => write!(f, "\u{21e5}"), KeyCode::BackTab => write!(f, "\u{21e4}"), KeyCode::Delete => write!(f, "\u{2326}"), KeyCode::Insert => write!(f, "\u{2380}"), KeyCode::F(n) => write!(f, "F{}", n),
290 KeyCode::Esc => write!(f, "\u{238b}"), KeyCode::CapsLock => write!(f, "\u{1F130}"), KeyCode::ScrollLock => write!(f, "\u{1F4DC}"), KeyCode::NumLock => write!(f, "\u{2460}"), KeyCode::PrintScreen => write!(f, "\u{2399}"), KeyCode::Pause => write!(f, "\u{2389}"), KeyCode::Menu => write!(f, "\u{1F5C7}"), KeyCode::KeypadBegin => write!(f, "\u{1F5CA}"), KeyCode::Media(MediaKeyCode::Play) => write!(f, "\u{23F5}"), KeyCode::Media(MediaKeyCode::PlayPause) => write!(f, "\u{23EF}"), KeyCode::Media(MediaKeyCode::Reverse) => write!(f, "\u{2B6F}"), KeyCode::Media(MediaKeyCode::Stop) => write!(f, "\u{23F9}"), KeyCode::Media(MediaKeyCode::FastForward) => write!(f, "\u{23ED}"), KeyCode::Media(MediaKeyCode::Rewind) => write!(f, "\u{2B6E}"), KeyCode::Media(MediaKeyCode::TrackNext) => write!(f, "\u{29D0}"), KeyCode::Media(MediaKeyCode::TrackPrevious) => write!(f, "\u{29CF}"), KeyCode::Media(MediaKeyCode::Record) => write!(f, "\u{241E}"), KeyCode::Media(MediaKeyCode::LowerVolume) => write!(f, "\u{1F508}"), KeyCode::Media(MediaKeyCode::RaiseVolume) => write!(f, "\u{1F50A}"), KeyCode::Media(MediaKeyCode::MuteVolume) => write!(f, "\u{1F507}"), _ => write!(f, "?"),
311 }
312 }
313}
314
315impl fmt::Debug for KeyBinding {
316 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
317 write!(f,"\"")?;
318 match self.modifiers {
319 KeyModifiers::SHIFT => write!(f, "Shift+")?,
320 KeyModifiers::CONTROL => write!(f, "Control+")?,
321 KeyModifiers::ALT => write!(f, "Alternate+")?,
322 KeyModifiers::SUPER => write!(f, "Super+")?,
323 KeyModifiers::HYPER => write!(f, "Hyper+")?,
324 KeyModifiers::META => write!(f, "Meta+")?,
325 KeyModifiers::NONE => write!(f, "")?,
326 _ => write!(f, "UNKNOWN+")?,
327 };
328 match self.code {
329 KeyCode::Char(c) => write!(f, "{}", c)?,
330 KeyCode::Backspace => write!(f, "Backspace")?,
331 KeyCode::Enter => write!(f, "Enter")?,
332 KeyCode::Left => write!(f, "Left")?,
333 KeyCode::Right => write!(f, "Right")?,
334 KeyCode::Up => write!(f, "Up")?,
335 KeyCode::Down => write!(f, "Down")?,
336 KeyCode::Home => write!(f, "Home")?,
337 KeyCode::End => write!(f, "End")?,
338 KeyCode::PageUp => write!(f, "PageUp")?,
339 KeyCode::PageDown => write!(f, "PageDown")?,
340 KeyCode::Tab => write!(f, "Tab")?,
341 KeyCode::BackTab => write!(f, "BackTab")?,
342 KeyCode::Delete => write!(f, "Delete")?,
343 KeyCode::Insert => write!(f, "Insert")?,
344 KeyCode::F(n) => write!(f, "F{}", n)?,
345 KeyCode::Esc => write!(f, "Esc")?,
346 KeyCode::CapsLock => write!(f, "CapsLock")?,
347 KeyCode::ScrollLock => write!(f, "ScrollLock")?,
348 KeyCode::NumLock => write!(f, "NumLock")?,
349 KeyCode::PrintScreen => write!(f, "PrintScreen")?,
350 KeyCode::Pause => write!(f, "Pause")?,
351 KeyCode::Menu => write!(f, "Menu")?,
352 KeyCode::KeypadBegin => write!(f, "KeypadBegin")?,
353 KeyCode::Media(MediaKeyCode::Play) => write!(f, "Play")?,
354 KeyCode::Media(MediaKeyCode::PlayPause) => write!(f, "PlayPause")?,
355 KeyCode::Media(MediaKeyCode::Reverse) => write!(f, "Reverse")?,
356 KeyCode::Media(MediaKeyCode::Stop) => write!(f, "Stop")?,
357 KeyCode::Media(MediaKeyCode::FastForward) => write!(f, "FastForward")?,
358 KeyCode::Media(MediaKeyCode::Rewind) => write!(f, "Rewind")?,
359 KeyCode::Media(MediaKeyCode::TrackNext) => write!(f, "TrackNext")?,
360 KeyCode::Media(MediaKeyCode::TrackPrevious) => write!(f, "TrackPrevious")?,
361 KeyCode::Media(MediaKeyCode::Record) => write!(f, "Record")?,
362 KeyCode::Media(MediaKeyCode::LowerVolume) => write!(f, "LowerVolume")?,
363 KeyCode::Media(MediaKeyCode::RaiseVolume) => write!(f, "RaiseVolume")?,
364 KeyCode::Media(MediaKeyCode::MuteVolume) => write!(f, "MuteVolume")?,
365 _ => write!(f, "?")?,
366 }
367 write!(f,"\"")
368 }
369}
370
371impl KeyBinding {
372 pub fn display(&self, f: &DisplayFormat) -> String {
373 match f {
374 DisplayFormat::Symbols => format!("{}", self),
375 DisplayFormat::Debug => format!("{:?}", self),
376 DisplayFormat::Full | DisplayFormat::Abbreviation => {
377 let mut display = match (f, self.modifiers) {
378 (_, KeyModifiers::SHIFT) => "Shift+".to_string(),
379 (DisplayFormat::Full, KeyModifiers::CONTROL) => "Control+".to_string(),
380 (DisplayFormat::Abbreviation, KeyModifiers::CONTROL) => "Ctrl+".to_string(),
381 (DisplayFormat::Full, KeyModifiers::ALT) => "Alternate+".to_string(),
382 (DisplayFormat::Abbreviation, KeyModifiers::ALT) => "Alt+".to_string(),
383 (_, KeyModifiers::SUPER) => "Super+".to_string(),
384 (_, KeyModifiers::HYPER) => "Hyper+".to_string(),
385 (_, KeyModifiers::META) => "Meta+".to_string(),
386 (_, KeyModifiers::NONE) => String::new(),
387 (_, _) => "UNKNOWN+".to_string(),
388 };
389 match self.code {
390 KeyCode::Char(c) => display.push(c),
391 KeyCode::Backspace => display.push_str("Backspace"),
392 KeyCode::Enter => display.push_str("Enter"),
393 KeyCode::Left => display.push_str("Left"),
394 KeyCode::Right => display.push_str("Right"),
395 KeyCode::Up => display.push_str("Up"),
396 KeyCode::Down => display.push_str("Down"),
397 KeyCode::Home => display.push_str("Home"),
398 KeyCode::End => display.push_str("End"),
399 KeyCode::PageUp => display.push_str("PageUp"),
400 KeyCode::PageDown => display.push_str("PageDown"),
401 KeyCode::Tab => display.push_str("Tab"),
402 KeyCode::BackTab => display.push_str("BackTab"),
403 KeyCode::Delete => display.push_str("Delete"),
404 KeyCode::Insert => display.push_str("Insert"),
405 KeyCode::F(n) => display.push_str(&format!("F{}", n)),
406 KeyCode::Esc => display.push_str("Esc"),
407 KeyCode::CapsLock => display.push_str("CapsLock"),
408 KeyCode::ScrollLock => display.push_str("ScrollLock"),
409 KeyCode::NumLock => display.push_str("NumLock"),
410 KeyCode::PrintScreen => display.push_str("PrintScreen"),
411 KeyCode::Pause => display.push_str("Pause"),
412 KeyCode::Menu => display.push_str("Menu"),
413 KeyCode::KeypadBegin => display.push_str("KeypadBegin"),
414 KeyCode::Media(MediaKeyCode::Play) => display.push_str("Play"),
415 KeyCode::Media(MediaKeyCode::PlayPause) => display.push_str("PlayPause"),
416 KeyCode::Media(MediaKeyCode::Reverse) => display.push_str("Reverse"),
417 KeyCode::Media(MediaKeyCode::Stop) => display.push_str("Stop"),
418 KeyCode::Media(MediaKeyCode::FastForward) => display.push_str("FastForward"),
419 KeyCode::Media(MediaKeyCode::Rewind) => display.push_str("Rewind"),
420 KeyCode::Media(MediaKeyCode::TrackNext) => display.push_str("TrackNext"),
421 KeyCode::Media(MediaKeyCode::TrackPrevious) => display.push_str("TrackPrevious"),
422 KeyCode::Media(MediaKeyCode::Record) => display.push_str("Record"),
423 KeyCode::Media(MediaKeyCode::LowerVolume) => display.push_str("LowerVolume"),
424 KeyCode::Media(MediaKeyCode::RaiseVolume) => display.push_str("RaiseVolume"),
425 KeyCode::Media(MediaKeyCode::MuteVolume) => display.push_str("MuteVolume"),
426 _ => display.push('?'),
427 }
428 display
429 }
430 }
431 }
432}
433
434#[derive(Serialize, Deserialize, PartialEq)]
436pub struct KeyBindings(Vec<KeyBinding>);
437
438impl KeyBindings {
439 pub fn match_any(&self, key_event: &KeyEvent) -> bool {
441 for key_bind in self.0.iter() {
442 if key_bind.code == key_event.code && key_bind.modifiers == key_event.modifiers {
443 return true;
444 }
445 }
446 false
447 }
448}
449
450impl fmt::Display for KeyBindings {
451 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
452 for (i, kb) in self.0.iter().enumerate() {
453 if i > 0 {
454 write!(f, "|{}", kb)?; } else {
456 write!(f, "{}", kb)?;
457 }
458 }
459 Ok(())
460 }
461}
462
463impl fmt::Debug for KeyBindings {
464 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465 write!(f, "[")?;
466 for (i, kb) in self.0.iter().enumerate() {
467 if i > 0 {
468 write!(f, ", {:?}", kb)?;
469 } else {
470 write!(f, "{:?}", kb)?;
471 }
472 }
473 write!(f, "]")?;
474 Ok(())
475 }
476}
477impl KeyBindings {
478 pub fn display(&self, f: &DisplayFormat) -> String {
479 match f {
480 DisplayFormat::Symbols => format!("{}", self),
481 DisplayFormat::Debug => format!("{:?}", self),
482 _ => {
483 let mut display = String::new();
484 for (i, kb) in self.0.iter().enumerate() {
485 if i > 0 {
486 display.push_str(" | ");
487 display.push_str(&kb.display(f));
488 } else {
489 display.push_str(&kb.display(f));
490 }
491 }
492 display
493 }
494 }
495 }
496}
497
498#[cfg(test)]
499mod tests {
500 use super::*;
501
502 #[derive(Serialize, Deserialize)]
503 struct T {
504 kb: KeyBinding,
505 }
506 #[derive(Serialize, Deserialize)]
507 struct U {
508 kbs: KeyBindings,
509 }
510
511 #[test]
512 fn ser_keybinding_config() {
513 let (t_with_ctrl_modifier, t_with_alt_modifier,t, only_modifiers, t_with_esc) = keybinding_configs();
514
515 let serialized = toml::to_string(&t_with_ctrl_modifier).unwrap();
516 assert_eq!(serialized, "kb = \"Control+c\"\n");
517
518 let serialized = toml::to_string(&t_with_alt_modifier).unwrap();
519 assert_eq!(serialized, "kb = \"Alternate+c\"\n");
520
521 let serialized = toml::to_string(&t).unwrap();
522 assert_eq!(serialized, "kb = \"Q\"\n");
523
524 let serialized = toml::to_string(&only_modifiers);
525 assert_eq!(
526 serialized,
527 Err(ser::Error::custom("Unsupported KeyCode: Null"))
528 );
529
530 let serialized = toml::to_string(&t_with_esc).unwrap();
531 assert_eq!(serialized, "kb = \"Esc\"\n");
532 }
533
534 #[test]
535 #[cfg(feature = "case_ignore")]
536 fn deserialize_with_wrong_config() {
537 let desered_t: T = toml::from_str("kb = \"control+c\"\n").unwrap();
538 assert_eq!(desered_t.kb.modifiers, KeyModifiers::CONTROL);
539 }
540
541 #[test]
542 fn de_keybinding_config() {
543 let (t_with_ctrl_modifier, t_with_alt_modifier, t, _only_modifiers, t_with_esc) = keybinding_configs();
544
545 let serialized = toml::to_string(&t_with_ctrl_modifier).unwrap();
546 let desered_t: T = toml::from_str(serialized.as_str()).unwrap();
547 assert_eq!(desered_t.kb.code, t_with_ctrl_modifier.kb.code);
548 assert_eq!(desered_t.kb.modifiers, t_with_ctrl_modifier.kb.modifiers);
549
550 let serialized = toml::to_string(&t_with_alt_modifier).unwrap();
551 let desered_t: T = toml::from_str(serialized.as_str()).unwrap();
552 assert_eq!(desered_t.kb.code, t_with_alt_modifier.kb.code);
553 assert_eq!(desered_t.kb.modifiers, t_with_alt_modifier.kb.modifiers);
554
555 let serialized = toml::to_string(&t).unwrap();
556 let desered_t: T = toml::from_str(serialized.as_str()).unwrap();
557 assert_eq!(desered_t.kb.code, t.kb.code);
558 assert_eq!(desered_t.kb.modifiers, t.kb.modifiers);
559
560 let serialized = toml::to_string(&t_with_esc).unwrap();
561 let desered_t: T = toml::from_str(serialized.as_str()).unwrap();
562 assert_eq!(desered_t.kb.code, t_with_esc.kb.code);
563 assert_eq!(desered_t.kb.modifiers, t_with_esc.kb.modifiers);
564 }
565
566 #[test]
567 fn fmt_keybinding_config() {
568 let (t_with_modifiers, _t_with_alt, _t, _only_modifiers, t_with_esc) = keybinding_configs();
569
570 assert_eq!(format!("{}", t_with_modifiers.kb), "^c");
571 assert_eq!(format!("{}", t_with_esc.kb), "⎋");
572
573 assert_eq!(t_with_modifiers.kb.display(&DisplayFormat::Full), "Control+c");
574 assert_eq!(t_with_modifiers.kb.display(&DisplayFormat::Abbreviation), "Ctrl+c");
575 assert_eq!(t_with_esc.kb.display(&DisplayFormat::Full), "Esc");
576 }
577
578 #[test]
579 fn ser_keybindings_config() {
580 let config = keybindings_config();
581
582 let serialized = toml::to_string(&config).unwrap();
583 assert_eq!(serialized, "kbs = [\"Control+c\", \"Q\"]\n");
584 }
585
586 #[test]
587 fn fmt_keybindings_config() {
588 let config = keybindings_config();
589 assert_eq!(format!("{}", config.kbs), "^c|Q");
590 assert_eq!(config.kbs.display(&DisplayFormat::Full), "Control+c | Q");
591 assert_eq!(config.kbs.display(&DisplayFormat::Abbreviation), "Ctrl+c | Q");
592 }
593
594 fn keybinding_configs() -> (T, T, T, T, T) {
596 (
597 T {
598 kb: KeyBinding {
599 code: KeyCode::Char('c'),
600 modifiers: KeyModifiers::CONTROL,
601 },
602 },
603 T {
604 kb: KeyBinding {
605 code: KeyCode::Char('c'),
606 modifiers: KeyModifiers::ALT,
607 },
608 },
609 T {
610 kb: KeyBinding {
611 code: KeyCode::Char('Q'),
612 modifiers: KeyModifiers::NONE,
613 },
614 },
615 T {
616 kb: KeyBinding {
617 code: KeyCode::Null,
618 modifiers: KeyModifiers::ALT,
619 },
620 },
621 T {
622 kb: KeyBinding {
623 code: KeyCode::Esc,
624 modifiers: KeyModifiers::NONE,
625 },
626 },
627 )
628 }
629
630 fn keybindings_config() -> U {
632 U {
633 kbs: KeyBindings(vec![
634 KeyBinding {
635 code: KeyCode::Char('c'),
636 modifiers: KeyModifiers::CONTROL,
637 },
638 KeyBinding {
639 code: KeyCode::Char('Q'),
640 modifiers: KeyModifiers::NONE,
641 },
642 ]),
643 }
644 }
645}