Skip to content

Commit

Permalink
Add parsing for macro which translates to Action::Sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
jtroo committed Apr 24, 2022
1 parent fa81945 commit cd7323f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
12 changes: 7 additions & 5 deletions cfg_samples/jtroo.kbd
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,13 @@
)

(defalias
;; Note - keys are pressed for the whole sequence which is likely
;; undesirable, particularly for modifiers like shift. This could be
;; improved in the future by using the code in:
;; https://github.com/TeXitoi/keyberon/pull/30
;; Note - for multi, keys are pressed for the whole sequence which is likely
;; undesirable, particularly for modifiers like shift. You probably want to
;; use macro instead.
alp (multi a b c d e f g h i j k l m n o p q r s t u v w x y z)

;; macro accepts keys, chords, and numbers (a delay in ms).
lch (macro h t t p @: / / 100 l o c a l h o s t)
)

(deflayer dvorak
Expand Down Expand Up @@ -127,7 +129,7 @@

(deflayer chords
_ _ _ _ _ _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ @csc _ _ _ _ _
_ _ _ _ _ _ _ _ @csc _ @lch _ _ _
_ @alp _ _ _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ _ @csv _ _
_ _ _ _ _ _ _
Expand Down
42 changes: 42 additions & 0 deletions src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ fn parse_action_list(
"layer-toggle" => parse_layer_toggle(&ac[1..], layers),
"tap-hold" => parse_tap_hold(&ac[1..], aliases, layers),
"multi" => parse_multi(&ac[1..], aliases, layers),
"macro" => parse_macro(&ac[1..], aliases, layers),
_ => bail!(
"Unknown action type: {}. Valid types: layer-switch, layer-toggle, tap-hold, multi",
ac_type
Expand Down Expand Up @@ -599,6 +600,47 @@ fn parse_multi(
Ok(sref(Action::MultipleActions(sref(actions))))
}

fn parse_macro(
ac_params: &[SExpr],
aliases: &Aliases,
layers: &LayerIndexes,
) -> Result<&'static Action> {
if ac_params.is_empty() {
bail!("macro expects at least one atom after it")
}
let mut events = Vec::new();
for expr in ac_params {
if let Ok(delay) = parse_timeout(expr) {
events.push(SequenceEvent::Delay { duration: delay.into() });
continue;
}
match parse_action(expr, aliases, layers)? {
Action::KeyCode(kc) => {
// Should note that I tried `SequenceEvent::Tap` initially but it seems to be buggy
// so I changed the code to use individual press and release. The SequenceEvent
// code is from a PR that (at the time of this writing) hasn't yet been merged into
// keyberon master and doesn't have tests written for it yet. This seems to work as
// expected right now though.
events.push(SequenceEvent::Press(*kc));
events.push(SequenceEvent::Release(*kc));
}
Action::MultipleKeyCodes(kcs) => {
// chord - press in order then release in the reverse order
for kc in kcs.iter() {
events.push(SequenceEvent::Press(*kc));
}
for kc in kcs.iter().rev() {
events.push(SequenceEvent::Release(*kc));
}
},
_ => {
bail!("Action \"macro\" only accepts delays, keys, and chords. Invalid value {:?}", expr)
}
}
}
Ok(sref(Action::Sequence{ events: sref(events)} ))
}

/// Mutates `layers::LAYERS` using the inputs.
fn parse_layers(
layers: &[&Vec<SExpr>],
Expand Down

0 comments on commit cd7323f

Please sign in to comment.