kanata_parser/cfg/
key_outputs.rs

1use super::*;
2
3// Note: this uses a Vec inside the HashMap instead of a HashSet because ordering matters, e.g. for
4// chords like `S-b`, we want to ensure that `b` is checked first because key repeat for `b` is
5// useful while it is not useful for shift. The outputs should be iterated over in reverse order.
6pub type KeyOutputs = Vec<HashMap<OsCode, Vec<OsCode>>>;
7
8/// Creates a `KeyOutputs` from `layers::LAYERS`.
9pub(crate) fn create_key_outputs(
10    layers: &KLayers,
11    overrides: &Overrides,
12    chords_v2: &Option<ChordsV2<'static, KanataCustom>>,
13) -> KeyOutputs {
14    let mut outs = KeyOutputs::new();
15    for (layer_idx, layer) in layers.iter().enumerate() {
16        let mut layer_outputs = HashMap::default();
17        for (i, action) in layer[0].iter().enumerate() {
18            let osc_slot = match i.try_into() {
19                Ok(i) => i,
20                Err(_) => continue,
21            };
22            add_key_output_from_action_to_key_pos(osc_slot, action, &mut layer_outputs, overrides);
23            add_chordsv2_output_for_key_pos(
24                osc_slot,
25                layer_idx,
26                chords_v2,
27                &mut layer_outputs,
28                overrides,
29            );
30        }
31        outs.push(layer_outputs);
32    }
33    for layer_outs in outs.iter_mut() {
34        for keys_out in layer_outs.values_mut() {
35            keys_out.shrink_to_fit();
36        }
37        layer_outs.shrink_to_fit();
38    }
39    outs.shrink_to_fit();
40    outs
41}
42
43pub(crate) fn add_chordsv2_output_for_key_pos(
44    osc_slot: OsCode,
45    layer_idx: usize,
46    chords_v2: &Option<ChordsV2<'static, KanataCustom>>,
47    outputs: &mut HashMap<OsCode, Vec<OsCode>>,
48    overrides: &Overrides,
49) {
50    assert!(layer_idx <= usize::from(u16::MAX));
51    let Some(chords_v2) = chords_v2.as_ref() else {
52        return;
53    };
54    let Some(chords_for_key) = chords_v2.chords().mapping.get(&u16::from(osc_slot)) else {
55        return;
56    };
57    for chord in chords_for_key.chords.iter() {
58        if !chord.disabled_layers.contains(&(layer_idx as u16)) {
59            add_key_output_from_action_to_key_pos(osc_slot, chord.action, outputs, overrides);
60        }
61    }
62}
63
64pub(crate) fn add_key_output_from_action_to_key_pos(
65    osc_slot: OsCode,
66    action: &KanataAction,
67    outputs: &mut HashMap<OsCode, Vec<OsCode>>,
68    overrides: &Overrides,
69) {
70    match action {
71        Action::KeyCode(kc) => {
72            add_kc_output(osc_slot, kc.into(), outputs, overrides);
73        }
74        Action::HoldTap(HoldTapAction {
75            tap,
76            hold,
77            timeout_action,
78            ..
79        }) => {
80            add_key_output_from_action_to_key_pos(osc_slot, tap, outputs, overrides);
81            add_key_output_from_action_to_key_pos(osc_slot, hold, outputs, overrides);
82            add_key_output_from_action_to_key_pos(osc_slot, timeout_action, outputs, overrides);
83        }
84        Action::OneShot(OneShot { action: ac, .. }) => {
85            add_key_output_from_action_to_key_pos(osc_slot, ac, outputs, overrides);
86        }
87        Action::MultipleKeyCodes(kcs) => {
88            for kc in kcs.iter() {
89                add_kc_output(osc_slot, kc.into(), outputs, overrides);
90            }
91        }
92        Action::MultipleActions(actions) => {
93            for ac in actions.iter() {
94                add_key_output_from_action_to_key_pos(osc_slot, ac, outputs, overrides);
95            }
96        }
97        Action::TapDance(TapDance { actions, .. }) => {
98            for ac in actions.iter() {
99                add_key_output_from_action_to_key_pos(osc_slot, ac, outputs, overrides);
100            }
101        }
102        Action::Fork(ForkConfig { left, right, .. }) => {
103            add_key_output_from_action_to_key_pos(osc_slot, left, outputs, overrides);
104            add_key_output_from_action_to_key_pos(osc_slot, right, outputs, overrides);
105        }
106        Action::Chords(ChordsGroup { chords, .. }) => {
107            for (_, ac) in chords.iter() {
108                add_key_output_from_action_to_key_pos(osc_slot, ac, outputs, overrides);
109            }
110        }
111        Action::Switch(Switch { cases }) => {
112            for case in cases.iter() {
113                add_key_output_from_action_to_key_pos(osc_slot, case.1, outputs, overrides);
114            }
115        }
116        Action::Custom(cacs) => {
117            for ac in cacs.iter() {
118                match ac {
119                    CustomAction::Unmodded { keys, .. } | CustomAction::Unshifted { keys } => {
120                        for k in keys.iter() {
121                            add_kc_output(osc_slot, k.into(), outputs, overrides);
122                        }
123                    }
124                    _ => {}
125                }
126            }
127        }
128        Action::Src => {
129            add_kc_output(osc_slot, osc_slot, outputs, overrides);
130        }
131        Action::NoOp
132        | Action::Trans
133        | Action::Repeat
134        | Action::Layer(_)
135        | Action::DefaultLayer(_)
136        | Action::Sequence { .. }
137        | Action::RepeatableSequence { .. }
138        | Action::CancelSequences
139        | Action::OneShotIgnoreEventsTicks(_)
140        | Action::ReleaseState(_) => {}
141    };
142}
143
144pub(crate) fn add_kc_output(
145    osc_slot: OsCode,
146    osc: OsCode,
147    outs: &mut HashMap<OsCode, Vec<OsCode>>,
148    overrides: &Overrides,
149) {
150    let outputs = match outs.entry(osc_slot) {
151        Entry::Occupied(o) => o.into_mut(),
152        Entry::Vacant(v) => v.insert(vec![]),
153    };
154    if !outputs.contains(&osc) {
155        outputs.push(osc);
156    }
157    for ov_osc in overrides
158        .output_non_mods_for_input_non_mod(osc)
159        .iter()
160        .copied()
161    {
162        if !outputs.contains(&ov_osc) {
163            outputs.push(ov_osc);
164        }
165    }
166}