Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add use-defsrc action #1336

Merged
merged 3 commits into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
Loading