-
Notifications
You must be signed in to change notification settings - Fork 563
Using Parameterized Macros in Keymap Editor
If you aren't already familiar with macros in the context of ZMK, they are a behavior type that allows you to define a sequence of bindings to be triggered wherever that macro is bound. Typically this is to a key in one of your keymap's layers, but it can also be a combo, a behavior, or another macro.
Not too long ago support for parameterized macros landed in ZMK, so in addition to enabling a quick way to trigger a number of behaviors you can supply parameters to specific bindings in that sequence for added flexibility and reuse.
In another post I detailed a combination of parameterized macros and hold tap to implement autoshift functionality without repetition in your bindings or resorting to preprocessor macros. Now I want to demonstrate the advanced support in Keymap Editor for resolving parameter types, even in the context of a macro.
In the ZMK macro docs there is an example Layer + Underglow Color macro. It uses the ¯o_press, ¯o_tap, ¯o_pause_for_release, and ¯o_release binding activation modes to:
- "hold" a
&mo(momentary layer) binding - "tap" a
&rgb_ug(colour change) binding - pause as long as the macro is held,
- "release" the initial
&mobinding - "tap" another
&rgb_ug(presumably default colour) binding
By turning this into a parameterized macro, the same behavior can be used for any layer without having to create a duplicate.
In Keymap Editor load your keymap and go to the Macros tab. Add a new macro called &rgblayer.

From here you can start adding control and key bindings to recreate the original macro:

Note: the macro sequence editor is drag-and-drop, so if you forget to add a binding in the correct spot you can always reorder them afterwards.
Now to make this generic, we'll include the appropriate control bindings to map macro parameters into the &mo and &rgb_ug bindings. Click the Add Control Binding and then change its behavior to ¯o_param_1to1.

Note that as soon as this new binding is added to the end of the sequence you'll get a warning that there's no binding following it to receive the parameter. Drag the binding above the first &mo 1 and you'll see the warning disappear as well as the layer value.
The editor knows that ¯o_param_1to1 will cause the next non-control binding to receive the first parameter passed to the macro, in this case that binding is &mo, so the given value is replaced with ?? (in the generated code this will become MACRO_PLACEHOLDER).
Now you can add the rest:
-
¯o_param_2to2before the first&rgb_ugbinding -
¯o_param_1to1before the second&mobinding

If you've loaded a keymap using the Clipboard integration, you can click the Keymap button and view macro source generated as something like the following:
rgblayer: rgb_layer {
compatible = "zmk,behavior-macro-two-param";
#binding-cells = <2>;
label = "MOMENTARY_LAYER_WITH_RGB_COLOR";
bindings
= <¯o_param_2to2 &rgb_ug RGB_COLOR_HSB_CMD MACRO_PLACEHOLDER ¯o_param_1to1>
, <¯o_press>
, <&mo MACRO_PLACEHOLDER>
, <¯o_pause_for_release>
, <¯o_release>
, <¯o_param_1to1 &mo MACRO_PLACEHOLDER>
, <¯o_tap>
, <&rgb_ug RGB_COLOR_HSB(0, 0, 0)>
;
};
There are a few things to note:
- The behavior type
zmk,behavior-macro-two-paramis selected for you, because you've indicated the use of two parameters. - The identifier
MACRO_PLACEHOLDERis injected for you -- it's value doesn't matter, but it helps to make it clear what the purpose is. - Although you may be used to
&rgb_ug RGB_COLOR_HSB(...)this is a preprocessor function that produces two values:RGB_COLOR_HSB_CMDandRGB_COLOR_HSB_VAL(...). The Keymap Editor recognizes the relationship here, and splits the binding up once it's identified as receiving a macro parameter.
Anywhere you might like to momentarily activate a layer you can change that binding's &mo behavior to &rgblayer. In the binding editor you'll see something like the following:

The parameter type resolution support built into Keymap Editor recognizes that:
- the macro accepts two parameters,
- the
&mobinding has a placeholder for its first parameter, a layer - the
rgb_ugbinding has a placeholder for its second parameter, and because its first parameter is already set asRGB_COLOR_HSB_CMDthe second must therefore beRGB_COLOR_HSB_VAL(...)which is already set up to use the colour picker helper.