livesplit_hotkey/
hotkey.rs1use core::{fmt, str::FromStr};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{KeyCode, Modifiers};
6
7#[derive(Eq, PartialEq, Hash, Copy, Clone)]
9pub struct Hotkey {
10 pub key_code: KeyCode,
12 pub modifiers: Modifiers,
14}
15
16impl fmt::Debug for Hotkey {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 fmt::Display::fmt(self, f)
19 }
20}
21
22impl fmt::Display for Hotkey {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 if self.modifiers.is_empty() {
25 f.write_str(self.key_code.name())
26 } else {
27 write!(f, "{} + {}", self.modifiers, self.key_code.name())
28 }
29 }
30}
31
32impl FromStr for Hotkey {
33 type Err = ();
34
35 fn from_str(s: &str) -> Result<Self, Self::Err> {
36 if let Some((modifiers, key_code)) = s.rsplit_once('+') {
37 let modifiers = modifiers.trim_end().parse()?;
38 let key_code = key_code.trim_start().parse()?;
39 Ok(Self {
40 key_code,
41 modifiers,
42 })
43 } else {
44 let key_code = s.parse()?;
45 Ok(Self {
46 key_code,
47 modifiers: Modifiers::empty(),
48 })
49 }
50 }
51}
52
53impl Serialize for Hotkey {
54 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55 where
56 S: serde::Serializer,
57 {
58 if self.modifiers.is_empty() {
59 self.key_code.serialize(serializer)
60 } else {
61 serializer.collect_str(self)
62 }
63 }
64}
65
66impl<'de> Deserialize<'de> for Hotkey {
67 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68 where
69 D: serde::Deserializer<'de>,
70 {
71 deserializer.deserialize_str(HotkeyVisitor)
72 }
73}
74
75struct HotkeyVisitor;
76
77impl serde::de::Visitor<'_> for HotkeyVisitor {
78 type Value = Hotkey;
79
80 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
81 formatter.write_str("a valid hotkey")
82 }
83
84 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
85 where
86 E: serde::de::Error,
87 {
88 Hotkey::from_str(v).map_err(|()| serde::de::Error::custom("invalid hotkey"))
89 }
90}
91
92impl From<KeyCode> for Hotkey {
93 fn from(key_code: KeyCode) -> Self {
94 Self {
95 key_code,
96 modifiers: Modifiers::empty(),
97 }
98 }
99}