Skip to content

Commit

Permalink
feat: add use-defsrc action (#1336)
Browse files Browse the repository at this point in the history
Potentially a breaking change in case someone has decided to use the
string `use-defsrc` within a `deflocalkeys` variant. I considered a
shorter name like `src` but that seemed like a higher risk of actually
being used within `deflocalkeys` due to its brevity. Thus the verbose
name `use-defsrc`.
  • Loading branch information
jtroo authored Nov 9, 2024
1 parent 84531cf commit 62b2269
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 20 deletions.
6 changes: 5 additions & 1 deletion cfg_samples/kanata.kbd
Original file line number Diff line number Diff line change
Expand Up @@ -771,8 +771,12 @@ If you need help, please feel welcome to ask in the GitHub discussions.

;; The underscore _ means transparent. The key on the base layer will be used
;; instead. XX means no-op. The key will do nothing.
;;
;; A similar concept to transparent, use-defsrc means the key will always
;; behave as the key as defined by defsrc.
(defalias src use-defsrc)
(deflayer numbers
_ _ _ _ _ _ nlk kp7 kp8 kp9 _ _ _ _
@src _ _ _ _ _ nlk kp7 kp8 kp9 _ _ _ _
_ _ _ _ _ XX _ kp4 kp5 kp6 - _ _ _
_ _ C-z _ _ XX _ kp1 kp2 kp3 + _ _
_ C-z C-x C-c C-v XX _ kp0 kp0 . / _
Expand Down
9 changes: 7 additions & 2 deletions docs/config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -641,15 +641,20 @@ default to the corresponding `defsrc` key. If `+_+` is pressed on the active
while-held layer, the base layer's behaviour will activate.
(alternatively you can use `+‗+` `+≝+`)

A similar concept to transparent key is the `+use-defsrc+` action.
When activated, the underlying `defsrc` key will be the output action.

.Example:
[source]
----
(defsrc
a b c d
)
(defalias
src use-defsrc
)
(deflayer remap-only-c-to-d
_ d
_ _ d @src
)
----

Expand Down
3 changes: 3 additions & 0 deletions keyberon/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,9 @@ where
/// The maximum number of actions that can activate the same time is governed by
/// `ACTION_QUEUE_LEN`.
Switch(&'a Switch<'a, T>),
/// Disregard the entire layer stack, i.e. the current base layer and any while-held layers,
/// and select the action from `Layout.src_keys`.
Src,
}

impl<'a, T> Action<'a, T> {
Expand Down
7 changes: 7 additions & 0 deletions keyberon/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,13 @@ impl<'a, const C: usize, const R: usize, T: 'a + Copy + std::fmt::Debug> Layout<
}
self.rpt_action = Some(action);
}
Src => {
let action = &self.src_keys[usize::from(coord.1)];
// Risk: infinite recursive resulting in stack overflow.
// In practice this is not expected to happen.
// The `src_keys` actions are all expected to be `KeyCode` or `NoOp` actions.
self.do_action(action, coord, delay, is_oneshot, &mut std::iter::empty());
}
Trans => {
// Transparent action should be resolved to non-transparent one near the top
// of `do_action`.
Expand Down
3 changes: 3 additions & 0 deletions parser/src/cfg/key_outputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ pub(crate) fn add_key_output_from_action_to_key_pos(
}
}
}
Action::Src => {
add_kc_output(osc_slot, osc_slot, outputs, overrides);
}
Action::NoOp
| Action::Trans
| Action::Repeat
Expand Down
23 changes: 8 additions & 15 deletions parser/src/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,9 @@ fn parse_action_atom(ac_span: &Spanned<String>, s: &ParserState) -> Result<&'sta
),
_ => return custom(CustomAction::ReverseReleaseOrder, &s.a),
},
"use-defsrc" => {
return Ok(s.a.sref(Action::Src));
}
_ => {}
};
if let Some(oscode) = str_to_oscode(ac) {
Expand Down Expand Up @@ -2729,6 +2732,7 @@ fn find_chords_coords(chord_groups: &mut [ChordGroup], coord: (u8, u16), action:
}
Action::NoOp
| Action::Trans
| Action::Src
| Action::Repeat
| Action::KeyCode(_)
| Action::MultipleKeyCodes(_)
Expand Down Expand Up @@ -2784,6 +2788,7 @@ fn fill_chords(
Action::NoOp
| Action::Trans
| Action::Repeat
| Action::Src
| Action::KeyCode(_)
| Action::MultipleKeyCodes(_)
| Action::Layer(_)
Expand Down Expand Up @@ -3151,21 +3156,9 @@ fn parse_layers(
let mut defsrc_anykey_used = false;
let mut unmapped_anykey_used = false;
let mut both_anykey_used = false;
for triplet in pairs.by_ref() {
let input = &triplet[0];
let action = &triplet[1];

// TODO: remove me some time after April 2024 to reduce code bloat somewhat.
const MAPSTRS: &[&str] = &[":", "->", ">>", "maps-to", "→", "🞂"];
const MAPSTR_ERR: &str = "Seems you are using a retired configuration style.\n\
You should remove all mapping strings from deflayermap;\n\
deflayermap now uses pairs instead of triples.";
if input.atom(s.vars()).is_some_and(|x| MAPSTRS.contains(&x)) {
bail_expr!(input, "{MAPSTR_ERR}");
}
if action.atom(s.vars()).is_some_and(|x| MAPSTRS.contains(&x)) {
bail_expr!(action, "{MAPSTR_ERR}");
}
for pair in pairs.by_ref() {
let input = &pair[0];
let action = &pair[1];

let action = parse_action(action, s)?;
if input.atom(s.vars()).is_some_and(|x| x == "_") {
Expand Down
2 changes: 0 additions & 2 deletions src/kanata/output_logic/zippychord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ use std::sync::MutexGuard;

// Maybe-todos:
// ---
// Feature-parity: smart spacing around words
// - fixup whitespace around punctuation?
// Feature-parity: suffixes - only active while disabled, to complete a word.
// Feature-parity: prefix vs. non-prefix. Assuming smart spacing is implemented and enabled,
// standard activations would output space one outputs space, but not prefixes.
Expand Down
1 change: 1 addition & 0 deletions src/tests/sim_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod seq_sim_tests;
mod switch_sim_tests;
mod unicode_sim_tests;
mod unmod_sim_tests;
mod use_defsrc_sim_tests;
mod zippychord_sim_tests;

fn simulate<S: AsRef<str>>(cfg: S, sim: S) -> String {
Expand Down
57 changes: 57 additions & 0 deletions src/tests/sim_tests/use_defsrc_sim_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use super::*;

#[test]
fn use_defsrc_deflayer() {
let result = simulate(
r##"
(defcfg)
(defsrc a b c d)
(deflayer base
1 2 3 (layer-while-held other)
)
(deflayer other
4 5 (layer-while-held src) XX
)
(deflayer src
use-defsrc use-defsrc XX XX
)
"##,
"d:d d:c d:b d:a t:100",
)
.to_ascii();
assert_eq!("t:2ms dn:B t:1ms dn:A", result);
}

#[test]
fn use_defsrc_deflayermap() {
const CFG: &str = "
(defcfg process-unmapped-keys yes)
(defsrc a b c d)
(deflayer base
1
(layer-while-held othermap1)
(layer-while-held othermap2)
(layer-while-held othermap3)
)
(deflayermap (othermap1)
a 5
___ use-defsrc
)
(deflayermap (othermap2)
a 6
__ use-defsrc
_ x
)
(deflayermap (othermap3)
a 7
_ use-defsrc
__ x
)
";
let result = simulate(CFG, "d:b d:a d:c d:e t:10").to_ascii();
assert_eq!("t:1ms dn:Kb5 t:1ms dn:C t:1ms dn:E", result);
let result = simulate(CFG, "d:c d:a d:c d:e t:10").to_ascii();
assert_eq!("t:1ms dn:Kb6 t:1ms dn:X t:1ms dn:E", result);
let result = simulate(CFG, "d:d d:a d:c d:e t:10").to_ascii();
assert_eq!("t:1ms dn:Kb7 t:1ms dn:C t:1ms dn:X", result);
}

0 comments on commit 62b2269

Please sign in to comment.