Skip to content

Commit

Permalink
add combined action, add tests, fix a bug
Browse files Browse the repository at this point in the history
  • Loading branch information
jtroo committed Nov 12, 2024
1 parent 9ccd77a commit b0a4129
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 4 deletions.
2 changes: 2 additions & 0 deletions cfg_samples/kanata.kbd
Original file line number Diff line number Diff line change
Expand Up @@ -605,12 +605,14 @@ If you need help, please feel welcome to ask in the GitHub discussions.

rls (macro-release-cancel Digit1 500 bspc S-1 500 bspc S-2)
cop (macro-cancel-on-press Digit1 500 bspc S-1 500 bspc S-2)
rlpr (macro-release-cancel-and-cancel-on-press Digit1 500 bspc S-1 500 bspc S-2)

;; repeat variants will repeat while held, once ALL macros have ended,
;; including the held macro.
mr1 (macro-repeat mltp)
mr2 (macro-repeat-release-cancel mltp)
mr3 (macro-repeat-cancel-on-press mltp)
mr4 (macro-repeat-release-cancel-and-cancel-on-press mltp)

;; Kanata also supports dynamic macros. Dynamic macros can be nested, but
;; cannot recurse.
Expand Down
20 changes: 18 additions & 2 deletions docs/config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,7 @@ needs the delay of `5` to work correctly.
----

[[macro-release-cancel]]
==== `macro-release-cancel`
==== macro-release-cancel

The `macro-release-cancel` variant of the `+macro+` action
will cancel all active macros
Expand Down Expand Up @@ -1450,7 +1450,7 @@ and the rest of the macro does not run.
----

[[macro-cancel-on-press]]
==== `macro-cancel-on-press`
==== macro-cancel-on-press

The `macro-cancel-on-press` variant of the `macro action`
enables a cancellation trigger for all active macros including itself,
Expand All @@ -1465,6 +1465,21 @@ The trigger is enabled while the macro is in progress.
)
----

[[macro-release-cancel-and-cancel-on-press]]
==== macro-release-cancel-and-cancel-on-press

The `macro-release-cancel-and-cancel-on-press` variant
combines the cancel behaviours
of both the release-cancel and cancel-on-press.

[source]
----
(defalias
1 1
1!@ (macro-release-cancel-and-cancel-on-press @1 500 bspc S-1 500 bspc S-2)
)
----


[[macro-repeat]]
==== macro-repeat
Expand All @@ -1482,6 +1497,7 @@ only the most recently pressed macro will be repeated.
mr1 (macro-repeat mltp)
mr2 (macro-repeat-release-cancel mltp)
mr3 (macro-repeat-cancel-on-press mltp)
mr4 (macro-repeat-release-cancel-and-cancel-on-press mltp)
)
----

Expand Down
6 changes: 6 additions & 0 deletions parser/src/cfg/list_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ pub const MACRO_REPEAT_RELEASE_CANCEL: &str = "macro-repeat-release-cancel";
pub const MACRO_REPEAT_RELEASE_CANCEL_A: &str = "macro⟳↑⤫";
pub const MACRO_CANCEL_ON_NEXT_PRESS: &str = "macro-cancel-on-press";
pub const MACRO_REPEAT_CANCEL_ON_NEXT_PRESS: &str = "macro-repeat-cancel-on-press";
pub const MACRO_CANCEL_ON_NEXT_PRESS_CANCEL_ON_RELEASE: &str =
"macro-release-cancel-and-cancel-on-press";
pub const MACRO_REPEAT_CANCEL_ON_NEXT_PRESS_CANCEL_ON_RELEASE: &str =
"macro-repeat-release-cancel-and-cancel-on-press";
pub const UNICODE: &str = "unicode";
pub const SYM: &str = "🔣";
pub const ONE_SHOT: &str = "one-shot";
Expand Down Expand Up @@ -225,6 +229,8 @@ pub fn is_list_action(ac: &str) -> bool {
ON_IDLE,
MACRO_CANCEL_ON_NEXT_PRESS,
MACRO_REPEAT_CANCEL_ON_NEXT_PRESS,
MACRO_CANCEL_ON_NEXT_PRESS_CANCEL_ON_RELEASE,
MACRO_REPEAT_CANCEL_ON_NEXT_PRESS_CANCEL_ON_RELEASE,
];
LIST_ACTIONS.contains(&ac)
}
27 changes: 27 additions & 0 deletions parser/src/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1750,6 +1750,12 @@ fn parse_action_list(ac: &[SExpr], s: &ParserState) -> Result<&'static KanataAct
MACRO_REPEAT_CANCEL_ON_NEXT_PRESS => {
parse_macro_cancel_on_next_press(&ac[1..], s, RepeatMacro::Yes)
}
MACRO_CANCEL_ON_NEXT_PRESS_CANCEL_ON_RELEASE => {
parse_macro_cancel_on_next_press_cancel_on_release(&ac[1..], s, RepeatMacro::No)
}
MACRO_REPEAT_CANCEL_ON_NEXT_PRESS_CANCEL_ON_RELEASE => {
parse_macro_cancel_on_next_press_cancel_on_release(&ac[1..], s, RepeatMacro::Yes)
}
UNICODE | SYM => parse_unicode(&ac[1..], s),
ONE_SHOT | ONE_SHOT_PRESS | ONE_SHOT_PRESS_A => {
parse_one_shot(&ac[1..], s, OneShotEndConfig::EndOnFirstPress)
Expand Down Expand Up @@ -2156,6 +2162,27 @@ fn parse_macro_cancel_on_next_press(
])))))
}

fn parse_macro_cancel_on_next_press_cancel_on_release(
ac_params: &[SExpr],
s: &ParserState,
repeat: RepeatMacro,
) -> Result<&'static KanataAction> {
let macro_action = parse_macro(ac_params, s, repeat)?;
let macro_duration = match macro_action {
Action::RepeatableSequence { events } | Action::Sequence { events } => {
macro_sequence_event_total_duration(events)
}
_ => unreachable!("parse_macro should return sequence action"),
};
Ok(s.a.sref(Action::MultipleActions(s.a.sref(s.a.sref_vec(vec![
*macro_action,
Action::Custom(
s.a.sref(s.a.sref_slice(CustomAction::CancelMacroOnNextPress(macro_duration))),
),
Action::Custom(s.a.sref(s.a.sref_slice(CustomAction::CancelMacroOnRelease))),
])))))
}

fn macro_sequence_event_total_duration<T>(events: &[SequenceEvent<T>]) -> u32 {
events.iter().fold(0, |duration, event| {
duration.saturating_add(match event {
Expand Down
4 changes: 2 additions & 2 deletions src/kanata/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ impl Kanata {
layout.active_sequences.clear();
layout
.states
.retain(|s| !matches!(s, State::FakeKey { .. }));
.retain(|s| !matches!(s, State::FakeKey { .. } | State::RepeatingSequence { .. }));
}
Event::Press(0, evc)
}
Expand Down Expand Up @@ -1653,7 +1653,7 @@ impl Kanata {
self.macro_on_press_cancel_duration = 0;
layout
.states
.retain(|s| !matches!(s, State::FakeKey { .. }));
.retain(|s| !matches!(s, State::FakeKey { .. } | State::RepeatingSequence { .. }));
pbtn
}
CustomAction::SendArbitraryCode(code) => {
Expand Down
7 changes: 7 additions & 0 deletions src/tests/sim_tests/macro_sim_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ fn macro_cancel_on_press() {
let cfg = "\
(defsrc a b c)
(deflayer base (macro-cancel-on-press z 100 y) (macro x 100 w) c)";
test_on_press(cfg);
let cfg = "\
(defsrc a b c)
(deflayer base (macro-repeat-cancel-on-press z 100 y 100) (macro x 100 w) c)";
test_on_press(cfg);
}

fn test_on_press(cfg: &str) {
// Cancellation should happen.
let result = simulate(cfg, "d:a t:50 d:c t:100").to_ascii();
assert_eq!("t:1ms dn:Z t:1ms up:Z t:48ms dn:C", result);
Expand Down

0 comments on commit b0a4129

Please sign in to comment.