kll_compiler/
lib.rs

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(); // Should be set because this is an array
67                            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    /// Replaces any implied (KLL) state with explicit state
264    pub fn generate_state_scheduling(&mut self) {
265        // Generate explicit state for each Mapping
266        // Determine if we should use Result/Option for implied_state (probably option?)
267        // Build new keymap Vector with new keymapping
268        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; // No keys found
308        }
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
330// Holds owned version of all files
331// All other data structures are borrowed from this
332pub 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        //dbg!(&path);
344        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    /// Combines default and partialmaps as a list of layers (defaultmap being 0)
419    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}