1#![feature(if_let_guard)]
2#![feature(map_try_insert)]
3#![allow(incomplete_features)]
4
5pub mod emitters;
6pub mod parser;
7mod test;
8pub mod types;
9
10#[macro_use]
11extern crate derive_object_merge;
12
13use object_merge::Merge;
14pub use parser::parse_int;
15use parser::PestError;
16use std::collections::{HashMap, HashSet};
17use std::fs;
18use std::ops::Range;
19use std::path::{Path, PathBuf};
20pub use types::{
21 Action, Animation, AnimationResult, Capability, Key, KllFile, Mapping, PixelDef, Position,
22 ResultList, ResultType, Statement, Trigger, TriggerList, TriggerMode, TriggerType,
23};
24
25pub use layouts_rs::Layouts;
26
27#[derive(Debug, PartialEq, Eq, Hash, Clone)]
28pub enum Value<'a> {
29 List(Vec<&'a str>),
30 Single(&'a str),
31}
32
33#[derive(Debug, Default, Clone, Merge)]
34pub struct KllState<'a> {
35 #[combine]
36 pub defines: HashMap<&'a str, &'a str>,
37 #[combine]
38 pub variables: HashMap<&'a str, Value<'a>>,
39 #[combine]
40 pub capabilities: HashMap<&'a str, Capability<'a>>,
41 #[combine]
42 pub keymap: Vec<Mapping<'a>>,
43 #[combine]
44 pub positions: HashMap<usize, Position>,
45 #[combine]
46 pub pixelmap: HashMap<usize, PixelDef>,
47 #[combine]
48 pub animations: HashMap<&'a str, Animation<'a>>,
49}
50
51impl<'a> KllFile<'a> {
52 pub fn into_struct(self) -> KllState<'a> {
53 let mut kll = KllState::default();
54 for statement in self.statements {
55 match statement {
56 Statement::Define((name, val)) => {
57 kll.defines.insert(name, val);
58 }
59 Statement::Variable((name, index, val)) => {
60 let entry = kll.variables.entry(name).or_insert_with(|| match index {
61 Some(_) => Value::List(vec![]),
62 None => Value::Single(val),
63 });
64 match entry {
65 Value::List(vec) => {
66 let index = index.unwrap(); if index >= vec.len() {
68 vec.resize(index + 1, "");
69 }
70 vec[index] = val;
71 }
72 Value::Single(s) => {
73 *s = val;
74 }
75 };
76 }
77 Statement::Capability((name, cap)) => {
78 kll.capabilities.insert(name, cap);
79 }
80 Statement::Keymap(mapping) => {
81 kll.keymap.push(mapping);
82 }
83 Statement::Position((indices, pos)) => {
84 for range in indices {
85 for index in range {
86 kll.positions.insert(index, pos.clone());
87 }
88 }
89 }
90 Statement::Pixelmap((indices, map)) => {
91 for range in indices {
92 for index in range {
93 kll.pixelmap.insert(index, map.clone());
94 }
95 }
96 }
97 Statement::Animation((name, anim)) => {
98 kll.animations.insert(name, anim);
99 }
100 Statement::Frame((name, indices, frame)) => {
101 let animation = kll.animations.entry(name).or_default();
102 let frames = &mut animation.frames;
103 for range in indices {
104 for index in range {
105 if frames.len() <= index {
106 frames.resize(index + 1, vec![]);
107 }
108 frames[index] = frame.clone();
109 }
110 }
111 }
112 Statement::NOP => {}
113 };
114 }
115
116 kll
117 }
118}
119
120impl<'a> KllState<'a> {
121 pub fn triggers(&self) -> impl Iterator<Item = &Trigger> + '_ {
122 let groups = self
123 .keymap
124 .iter()
125 .map(|Mapping(trigger_groups, _, _)| trigger_groups);
126 let combos = groups.into_iter().map(|tl| tl.iter());
127 combos.into_iter().flatten()
128 }
129
130 pub fn trigger_lists(&self) -> impl Iterator<Item = &TriggerList> + '_ {
131 self.keymap
132 .iter()
133 .map(|Mapping(trigger_groups, _, _)| trigger_groups)
134 }
135
136 pub fn actions(&self) -> impl Iterator<Item = &Action> + '_ {
137 let groups = self
138 .keymap
139 .iter()
140 .map(|Mapping(_, _, result_groups)| result_groups);
141 let combos = groups.into_iter().map(|rl| rl.iter());
142 combos.into_iter().flatten()
143 }
144
145 pub fn result_lists(&self) -> impl Iterator<Item = &ResultList> + '_ {
146 self.keymap
147 .iter()
148 .map(|Mapping(_, _, result_groups)| result_groups)
149 }
150
151 pub fn trigger_result_lists(&self) -> impl Iterator<Item = (&TriggerList, &ResultList)> + '_ {
152 self.keymap
153 .iter()
154 .map(|Mapping(trigger_groups, _, result_groups)| (trigger_groups, result_groups))
155 }
156
157 pub fn scancode_map(&self) -> HashMap<&str, usize> {
158 self.keymap
159 .iter()
160 .filter_map(|Mapping(trigger_groups, _, result_groups)| match 1 {
161 _ if trigger_groups.iter().count() == 1 && result_groups.iter().count() == 1 => match 1 {
162 _ if let (TriggerType::Key(Key::Scancode(s)), ResultType::Output(Key::Usb(u))) = (&trigger_groups.iter().next().unwrap().trigger, &result_groups.iter().next().unwrap().result) => Some((*u, *s)),
163 _ => None,
164 },
165 _ => None
166 })
167 .collect::<HashMap<&str, usize>>()
168 }
169
170 pub fn scancodes(&self) -> Vec<usize> {
171 self.triggers()
172 .filter_map(|t| match &t.trigger {
173 TriggerType::Key(key) => Some(key),
174 _ => None,
175 })
176 .filter_map(|key| match key {
177 Key::Scancode(s) => Some(*s),
178 _ => None,
179 })
180 .collect()
181 }
182
183 pub fn animations(&self) -> impl Iterator<Item = &AnimationResult> + '_ {
184 self.actions().filter_map(|action| match &action.result {
185 ResultType::Animation(anim) => Some(anim),
186 _ => None,
187 })
188 }
189
190 pub fn unicode_strings(&self) -> HashSet<String> {
191 self.actions()
192 .filter_map(|action| match &action.result {
193 ResultType::UnicodeText(text) => Some(text.to_string()),
194 _ => None,
195 })
196 .collect()
197 }
198
199 pub fn reduce(&self, base: KllState<'a>) -> Vec<Mapping<'a>> {
200 let scancode_map = base.scancode_map();
201 let mut new_keymap: Vec<Mapping> = self
202 .keymap
203 .iter()
204 .map(|Mapping(trigger_groups, mode, result_groups)| {
205 let new_triggers = TriggerList(match mode {
206 TriggerMode::SoftReplace => trigger_groups.0.clone(),
207 _ => trigger_groups
208 .0
209 .iter()
210 .map(|combo| {
211 combo
212 .iter()
213 .map(|t| match &t.trigger {
214 TriggerType::Key(Key::Usb(u)) => {
215 let s = scancode_map.get(u).unwrap();
216 Trigger {
217 trigger: TriggerType::Key(Key::Scancode(*s)),
218 state: t.state.clone(),
219 }
220 }
221 _ => t.clone(),
222 })
223 .collect::<Vec<_>>()
224 })
225 .collect::<Vec<_>>(),
226 });
227 let new_results = ResultList(match mode {
228 TriggerMode::SoftReplace => result_groups.0.clone(),
229 _ => result_groups
230 .0
231 .iter()
232 .map(|combo| {
233 combo
234 .iter()
235 .map(|r| match &r.result {
236 ResultType::Output(Key::Usb(u)) => Action {
237 result: ResultType::Capability((
238 Capability::new("usbKeyOut", vec![u]),
239 None,
240 )),
241 state: r.state.clone(),
242 },
243 _ => r.clone(),
244 })
245 .collect::<Vec<_>>()
246 })
247 .collect::<Vec<_>>(),
248 });
249
250 Mapping(new_triggers, mode.clone(), new_results)
251 })
252 .collect::<Vec<_>>();
253
254 new_keymap.sort_by(|a, b| {
255 let a = format!("{}", a);
256 let b = format!("{}", b);
257 alphanumeric_sort::compare_path(a, b)
258 });
259
260 new_keymap
261 }
262
263 pub fn generate_state_scheduling(&mut self) {
265 let mut new_keymap = Vec::new();
269 for mapping in &self.keymap {
270 if let Some(mut mapping_vec) = mapping.implied_state() {
271 new_keymap.append(&mut mapping_vec);
272 } else {
273 new_keymap.push(mapping.clone());
274 }
275 }
276
277 self.keymap = new_keymap;
278 }
279}
280
281#[derive(Debug, Default, Clone)]
282pub struct KllDatastore<'a> {
283 pub scancode_range: Range<usize>,
284 pub unicode_strings: HashSet<String>,
285 pub unique_triggers: HashSet<Trigger<'a>>,
286 pub unique_results: HashSet<Action<'a>>,
287 pub unique_animations: HashSet<AnimationResult<'a>>,
288}
289
290impl<'a> KllDatastore<'a> {
291 pub fn get_scancode_range(state: &KllState) -> Range<usize> {
292 let mut range = Range {
293 start: 0xFFFF,
294 end: 0,
295 };
296
297 for scancode in state.scancodes() {
298 if scancode < range.start {
299 range.start = scancode;
300 }
301 if scancode > range.end {
302 range.end = scancode;
303 }
304 }
305
306 if range.start == 0xFFFF {
307 range.start = 0; }
309
310 assert!(range.start <= range.end);
311 range
312 }
313
314 pub fn new(state: &'a KllState<'a>) -> KllDatastore<'a> {
315 KllDatastore {
316 unicode_strings: state.unicode_strings(),
317 scancode_range: KllDatastore::get_scancode_range(state),
318 unique_triggers: state.triggers().cloned().collect(),
319 unique_results: state.actions().cloned().collect(),
320 unique_animations: state.animations().cloned().collect(),
321 }
322 }
323}
324
325#[allow(clippy::result_large_err)]
326pub fn parse(text: &str) -> Result<KllFile, PestError> {
327 KllFile::from_str(text)
328}
329
330pub struct Filestore {
333 files: HashMap<PathBuf, String>,
334}
335
336impl Filestore {
337 pub fn new() -> Self {
338 Filestore {
339 files: HashMap::new(),
340 }
341 }
342 pub fn load_file(&mut self, path: &Path) {
343 let raw_text = fs::read_to_string(path).expect("cannot read file");
345 self.files.insert(path.to_path_buf(), raw_text);
346 }
347
348 pub fn get_file<'a>(&'a self, path: &Path) -> KllState<'a> {
349 let raw_text = self.files.get(path).unwrap();
350 parse(raw_text).unwrap().into_struct()
351 }
352}
353
354impl Default for Filestore {
355 fn default() -> Self {
356 Self::new()
357 }
358}
359
360#[derive(Debug)]
361pub struct KllGroups<'a> {
362 config: Vec<KllState<'a>>,
363 base: Vec<KllState<'a>>,
364 default: Vec<KllState<'a>>,
365 partials: Vec<KllState<'a>>,
366}
367
368impl<'a> KllGroups<'a> {
369 pub fn new(
370 filestore: &'a Filestore,
371 config: &[PathBuf],
372 base: &[PathBuf],
373 default: &[PathBuf],
374 partials: &[PathBuf],
375 ) -> Self {
376 KllGroups {
377 config: config.iter().map(|p| filestore.get_file(p)).collect(),
378 base: base.iter().map(|p| filestore.get_file(p)).collect(),
379 default: default.iter().map(|p| filestore.get_file(p)).collect(),
380 partials: partials.iter().map(|p| filestore.get_file(p)).collect(),
381 }
382 }
383
384 pub fn config(&self) -> KllState<'a> {
385 let mut configs = self.config.iter();
386 let mut config = configs.next().unwrap().clone();
387 for c in configs {
388 config.merge(c);
389 }
390 config
391 }
392
393 pub fn basemap(&self) -> KllState<'a> {
394 let mut layouts = self.base.iter();
395 let mut layout = layouts.next().unwrap().clone();
396 for base in layouts {
397 layout.merge(base);
398 }
399 layout
400 }
401 pub fn defaultmap(&self) -> KllState<'a> {
402 let mut layout = self.basemap();
403 for default in &self.default {
404 layout.merge(default);
405 }
406 layout
407 }
408 pub fn partialmaps(&self) -> Vec<KllState<'a>> {
409 let mut partials: Vec<KllState> = vec![];
410 for partial in &self.partials {
411 let mut layout = self.basemap();
412 layout.merge(partial);
413 partials.push(layout);
414 }
415
416 partials
417 }
418 pub fn layers(&self) -> Vec<KllState<'a>> {
420 let mut layers: Vec<KllState> = vec![self.defaultmap()];
421 for layer in self.partialmaps() {
422 layers.push(layer);
423 }
424
425 layers
426 }
427}