1#[derive(PartialEq, Debug, Clone)]
6pub struct LetterKey {
7 pub(crate) lower: &'static str,
8 pub(crate) upper: &'static str,
9 pub(crate) alt: &'static str,
10 #[allow(unused)]
11 pub(crate) is_alt_accent: bool,
12}
13
14#[derive(PartialEq, Debug, Clone)]
15pub enum SpecialKey {
16 ALT,
17 DEL,
18 ENTER,
19 SHIFT,
20 SPACE,
21}
22
23#[derive(PartialEq, Debug, Clone)]
24pub enum Key {
25 Letter(LetterKey),
26 Special(SpecialKey, &'static str),
27}
28
29const DEFAULT_KEY: LetterKey = LetterKey { lower: "", upper: "", alt: "", is_alt_accent: false };
30
31const KEY_A: Key = Key::Letter(LetterKey { lower: "a", upper: "A", alt: "æ", ..DEFAULT_KEY });
32const KEY_B: Key = Key::Letter(LetterKey { lower: "b", upper: "B", ..DEFAULT_KEY });
33const KEY_C: Key = Key::Letter(LetterKey { lower: "c", upper: "C", alt: "ç", ..DEFAULT_KEY });
34const KEY_D: Key = Key::Letter(LetterKey { lower: "d", upper: "D", alt: "∂", ..DEFAULT_KEY });
35const KEY_E: Key =
36 Key::Letter(LetterKey {
37 lower: "e", upper: "E", alt: "´", is_alt_accent: true, ..DEFAULT_KEY
38 });
39const KEY_F: Key = Key::Letter(LetterKey { lower: "f", upper: "F", alt: "ƒ", ..DEFAULT_KEY });
40const KEY_G: Key = Key::Letter(LetterKey { lower: "g", upper: "G", alt: "©", ..DEFAULT_KEY });
41const KEY_H: Key = Key::Letter(LetterKey { lower: "h", upper: "H", ..DEFAULT_KEY });
42const KEY_I: Key =
43 Key::Letter(LetterKey {
44 lower: "i", upper: "I", alt: "ˆ", is_alt_accent: true, ..DEFAULT_KEY
45 });
46const KEY_J: Key = Key::Letter(LetterKey { lower: "j", upper: "J", ..DEFAULT_KEY });
47const KEY_K: Key =
48 Key::Letter(LetterKey {
49 lower: "k", upper: "K", alt: "˚", is_alt_accent: true, ..DEFAULT_KEY
50 });
51const KEY_L: Key = Key::Letter(LetterKey { lower: "l", upper: "L", ..DEFAULT_KEY });
52const KEY_M: Key = Key::Letter(LetterKey { lower: "m", upper: "M", ..DEFAULT_KEY });
53const KEY_N: Key =
54 Key::Letter(LetterKey {
55 lower: "n", upper: "N", alt: "˜", is_alt_accent: true, ..DEFAULT_KEY
56 });
57const KEY_O: Key = Key::Letter(LetterKey { lower: "o", upper: "O", alt: "ø", ..DEFAULT_KEY });
58const KEY_P: Key = Key::Letter(LetterKey { lower: "p", upper: "P", alt: "Ø", ..DEFAULT_KEY });
59const KEY_Q: Key = Key::Letter(LetterKey { lower: "q", upper: "Q", alt: "œ", ..DEFAULT_KEY });
60const KEY_R: Key = Key::Letter(LetterKey { lower: "r", upper: "R", alt: "®", ..DEFAULT_KEY });
61const KEY_S: Key = Key::Letter(LetterKey { lower: "s", upper: "S", alt: "ß", ..DEFAULT_KEY });
62const KEY_T: Key = Key::Letter(LetterKey { lower: "t", upper: "T", ..DEFAULT_KEY });
63const KEY_U: Key =
64 Key::Letter(LetterKey {
65 lower: "u", upper: "U", alt: "¨", is_alt_accent: true, ..DEFAULT_KEY
66 });
67const KEY_V: Key = Key::Letter(LetterKey { lower: "v", upper: "V", ..DEFAULT_KEY });
68const KEY_W: Key = Key::Letter(LetterKey { lower: "w", upper: "W", alt: "Œ", ..DEFAULT_KEY });
69const KEY_X: Key = Key::Letter(LetterKey { lower: "x", upper: "X", alt: "Ç", ..DEFAULT_KEY });
70const KEY_Y: Key = Key::Letter(LetterKey { lower: "y", upper: "Y", alt: "¥", ..DEFAULT_KEY });
71const KEY_Z: Key = Key::Letter(LetterKey { lower: "z", upper: "Z", alt: "Æ", ..DEFAULT_KEY });
72const KEY_0: Key = Key::Letter(LetterKey { lower: "0", upper: ")", alt: "º", ..DEFAULT_KEY });
73const KEY_1: Key = Key::Letter(LetterKey { lower: "1", upper: "!", alt: "¡", ..DEFAULT_KEY });
74const KEY_2: Key = Key::Letter(LetterKey { lower: "2", upper: "@", alt: "€", ..DEFAULT_KEY });
75const KEY_3: Key = Key::Letter(LetterKey { lower: "3", upper: "#", alt: "£", ..DEFAULT_KEY });
76const KEY_4: Key = Key::Letter(LetterKey { lower: "4", upper: "$", alt: "¢", ..DEFAULT_KEY });
77const KEY_5: Key = Key::Letter(LetterKey { lower: "5", upper: "%", alt: "∞", ..DEFAULT_KEY });
78const KEY_6: Key = Key::Letter(LetterKey { lower: "6", upper: "^", alt: "§", ..DEFAULT_KEY });
79const KEY_7: Key = Key::Letter(LetterKey { lower: "7", upper: "&", alt: "¶", ..DEFAULT_KEY });
80const KEY_8: Key = Key::Letter(LetterKey { lower: "8", upper: "*", alt: "•", ..DEFAULT_KEY });
81const KEY_9: Key = Key::Letter(LetterKey { lower: "9", upper: "(", alt: "ª", ..DEFAULT_KEY });
82const KEY_BACK_TICK: Key =
83 Key::Letter(LetterKey { lower: "`", upper: "~", alt: "`", is_alt_accent: true, ..DEFAULT_KEY });
84const KEY_HYPHEN: Key = Key::Letter(LetterKey { lower: "-", upper: "_", alt: "±", ..DEFAULT_KEY });
85const KEY_EQUALS: Key =
86 Key::Letter(LetterKey { lower: "=", upper: "+", alt: "≠", ..DEFAULT_KEY });
87const KEY_L_BRACKET: Key = Key::Letter(LetterKey { lower: "[", upper: "{", ..DEFAULT_KEY });
88const KEY_R_BRACKET: Key = Key::Letter(LetterKey { lower: "]", upper: "}", ..DEFAULT_KEY });
89const KEY_BACKSLASH: Key = Key::Letter(LetterKey { lower: "\\", upper: "|", ..DEFAULT_KEY });
90const KEY_SEMICOLON: Key = Key::Letter(LetterKey { lower: ";", upper: ":", ..DEFAULT_KEY });
91const KEY_QUOTE: Key = Key::Letter(LetterKey { lower: "'", upper: "\"", ..DEFAULT_KEY });
92const KEY_COMMA: Key = Key::Letter(LetterKey { lower: ",", upper: "<", ..DEFAULT_KEY });
93const KEY_FULL_STOP: Key = Key::Letter(LetterKey { lower: ".", upper: ">", ..DEFAULT_KEY });
94const KEY_SLASH: Key = Key::Letter(LetterKey { lower: "/", upper: "?", ..DEFAULT_KEY });
95
96const KEY_ALT: Key = Key::Special(SpecialKey::ALT, "alt");
97const KEY_DEL: Key = Key::Special(SpecialKey::DEL, "del");
98const KEY_ENTER: Key = Key::Special(SpecialKey::ENTER, "enter");
99const KEY_SHIFT: Key = Key::Special(SpecialKey::SHIFT, "shift");
100const KEY_SPACE: Key = Key::Special(SpecialKey::SPACE, "space");
101
102pub(crate) const ROW0: &'static [&Key] = &[
103 &KEY_BACK_TICK,
104 &KEY_1,
105 &KEY_2,
106 &KEY_3,
107 &KEY_4,
108 &KEY_5,
109 &KEY_6,
110 &KEY_7,
111 &KEY_8,
112 &KEY_9,
113 &KEY_0,
114 &KEY_HYPHEN,
115 &KEY_EQUALS,
116];
117
118pub(crate) const ROW1: &'static [&Key] = &[
119 &KEY_Q,
120 &KEY_W,
121 &KEY_E,
122 &KEY_R,
123 &KEY_T,
124 &KEY_Y,
125 &KEY_U,
126 &KEY_I,
127 &KEY_O,
128 &KEY_P,
129 &KEY_L_BRACKET,
130 &KEY_R_BRACKET,
131 &KEY_BACKSLASH,
132];
133
134const ROW2: &'static [&Key] = &[
135 &KEY_A,
136 &KEY_S,
137 &KEY_D,
138 &KEY_F,
139 &KEY_G,
140 &KEY_H,
141 &KEY_J,
142 &KEY_K,
143 &KEY_L,
144 &KEY_SEMICOLON,
145 &KEY_QUOTE,
146];
147
148const ROW3: &'static [&Key] = &[
149 &KEY_Z,
150 &KEY_X,
151 &KEY_C,
152 &KEY_V,
153 &KEY_B,
154 &KEY_N,
155 &KEY_M,
156 &KEY_COMMA,
157 &KEY_FULL_STOP,
158 &KEY_SLASH,
159];
160const SPECIAL_ROW: &'static [&Key] = &[&KEY_SHIFT, &KEY_ALT, &KEY_SPACE, &KEY_DEL, &KEY_ENTER];
161
162pub const KEYBOARD: &'static [&'static [&Key]] = &[ROW0, ROW1, ROW2, ROW3, SPECIAL_ROW];
163
164#[derive(Debug, PartialEq)]
165pub struct Accent {
166 accent: &'static Key,
167 pub(crate) lower: &'static str,
168 pub(crate) upper: &'static str,
169}
170
171#[derive(Debug, PartialEq)]
172pub struct AccentKey {
173 pub alt_key: &'static Key,
174 accents: &'static [&'static Accent],
175}
176
177const ACCENT_GRAVE: AccentKey = AccentKey {
178 alt_key: &KEY_BACK_TICK,
179 accents: &[
180 &Accent { accent: &KEY_A, lower: "à", upper: "À" },
181 &Accent { accent: &KEY_E, lower: "è", upper: "È" },
182 &Accent { accent: &KEY_I, lower: "ì", upper: "Ì" },
183 &Accent { accent: &KEY_O, lower: "ò", upper: "Ò" },
184 &Accent { accent: &KEY_U, lower: "ù", upper: "Ù" },
185 ],
186};
187
188const ACCENT_ACUTE: AccentKey = AccentKey {
189 alt_key: &KEY_E,
190 accents: &[
191 &Accent { accent: &KEY_A, lower: "á", upper: "Á" },
192 &Accent { accent: &KEY_E, lower: "é", upper: "É" },
193 &Accent { accent: &KEY_I, lower: "í", upper: "Í" },
194 &Accent { accent: &KEY_O, lower: "ó", upper: "Ó" },
195 &Accent { accent: &KEY_U, lower: "ú", upper: "Ú" },
196 ],
197};
198
199const ACCENT_RING: AccentKey =
200 AccentKey { alt_key: &KEY_K, accents: &[&Accent { accent: &KEY_A, lower: "å", upper: "Å" }] };
201
202const ACCENT_UMLAUT: AccentKey = AccentKey {
203 alt_key: &KEY_U,
204 accents: &[
205 &Accent { accent: &KEY_A, lower: "ä", upper: "Ä" },
206 &Accent { accent: &KEY_E, lower: "ë", upper: "Ë" },
207 &Accent { accent: &KEY_I, lower: "ï", upper: "Ï" },
208 &Accent { accent: &KEY_O, lower: "ö", upper: "Ö" },
209 &Accent { accent: &KEY_U, lower: "ü", upper: "ü" },
210 ],
211};
212
213const ACCENT_CIRCUMFLEX: AccentKey = AccentKey {
214 alt_key: &KEY_I,
215 accents: &[
216 &Accent { accent: &KEY_A, lower: "â", upper: "Â" },
217 &Accent { accent: &KEY_E, lower: "ê", upper: "Ê" },
218 &Accent { accent: &KEY_I, lower: "î", upper: "Î" },
219 &Accent { accent: &KEY_O, lower: "ô", upper: "Ô" },
220 &Accent { accent: &KEY_U, lower: "û", upper: "Û" },
221 ],
222};
223
224const ACCENT_TILDE: AccentKey = AccentKey {
225 alt_key: &KEY_N,
226 accents: &[
227 &Accent { accent: &KEY_A, lower: "ã", upper: "Ã" },
228 &Accent { accent: &KEY_N, lower: "ñ", upper: "Ñ" },
229 &Accent { accent: &KEY_O, lower: "õ", upper: "Õ " },
230 ],
231};
232
233pub const ACCENTS: &'static [AccentKey] =
234 &[ACCENT_GRAVE, ACCENT_CIRCUMFLEX, ACCENT_ACUTE, ACCENT_RING, ACCENT_UMLAUT, ACCENT_TILDE];
235
236pub fn get_accent(alt_key: &Key, pressed_key: &Key) -> Option<&'static &'static Accent> {
237 if let Some(accent_key) = ACCENTS.iter().find(|ak| ak.alt_key == alt_key) {
238 return accent_key.accents.iter().find(|a| a.accent == pressed_key);
239 };
240 None
241}
242
243#[cfg(test)]
244mod test {
245
246 use crate::keys::*;
247
248 #[test]
249 fn get_accent() {
250 assert_eq!(
251 super::get_accent(&KEY_E, &KEY_E),
252 Some(&&Accent { accent: &KEY_E, lower: "é", upper: "É" })
253 );
254 }
255
256 #[test]
257 fn get_non_accent() {
258 assert_eq!(super::get_accent(&KEY_P, &KEY_E), None);
259 }
260}