feat(docs): Improve parameterized macros docs
This commit is contained in:
parent
e65a7e3075
commit
d17c473d45
2 changed files with 122 additions and 65 deletions
|
@ -49,22 +49,6 @@ For use cases involving sending a single keycode with modifiers, for instance ct
|
|||
with [modifier functions](../codes/modifiers.mdx#modifier-functions) can be used instead of a macro.
|
||||
:::
|
||||
|
||||
### Parameterized Macros
|
||||
|
||||
Macros can also be "parameterized", allowing them to be bound in your keymap with unique values passed into them, e.g.:
|
||||
|
||||
```
|
||||
raise_layer {
|
||||
bindings = <&my_cool_macro A>
|
||||
};
|
||||
```
|
||||
|
||||
When defining a parameterized macro, a different `compatible` value will be used depending on how many parameters are passed into it:
|
||||
|
||||
- `zmk,behavior-macro` - a macro that takes no parameters.
|
||||
- `zmk,behavior-macro-one-param` - a macro that takes one parameter when used.
|
||||
- `zmk,behavior-macro-two-param` - a macro that takes two parameters when used.
|
||||
|
||||
### Bindings
|
||||
|
||||
Like [hold-taps](/docs/behaviors/hold-tap), macros are created by composing other behaviors, and any of those behaviors can
|
||||
|
@ -83,30 +67,6 @@ bindings
|
|||
There are a set of special macro controls that can be included in the `bindings` list to modify the
|
||||
way the macro is processed.
|
||||
|
||||
### Parameters
|
||||
|
||||
When creating a macro that takes parameter(s), there are macro controls that change when the parameters passed to the macro are used
|
||||
within the macro itself. All of the controls are "one shot" and will change how the passed in parameters are used for the very next non-macro control behavior in the `bindings` list of the macro.
|
||||
|
||||
For example, to pass the first parameter from the macro into a `&kp` used in the macro, you would use:
|
||||
|
||||
```
|
||||
bindings
|
||||
= <¯o_param_1to1>
|
||||
, <&kp MACRO_PLACEHOLDER>
|
||||
;
|
||||
```
|
||||
|
||||
Because `kp` takes one parameter, you can't simply make the second entry `<&kp>` in the `bindings` list. Whatever value you do pass in will be replaced when the macro is triggered, so you can put _any_ value there, e.g. `0`, `A` keycode, etc. To make it very obvious that the parameter there is not actually going to be used, you can use `MACRO_PLACEHOLDER` which is simply an alias for `0`.
|
||||
|
||||
The available parameter controls are:
|
||||
|
||||
- `¯o_param_1to1` - pass the first parameter of the macro into the first parameter of the next behavior in the `bindings` list.
|
||||
- `¯o_param_1to2` - pass the first parameter of the macro into the second parameter of the next behavior in the `bindings` list.
|
||||
|
||||
* `¯o_param_2to1` - pass the second parameter of the macro into the first parameter of the next behavior in the `bindings` list.
|
||||
* `¯o_param_2to2` - pass the second parameter of the macro into the second parameter of the next behavior in the `bindings` list.
|
||||
|
||||
### Binding Activation Mode
|
||||
|
||||
Bindings in a macro are activated differently, depending on the current "activation mode" of the macro.
|
||||
|
@ -185,6 +145,70 @@ Macros use an internal queue to invoke each behavior in the bindings list when t
|
|||
|
||||
To prevent issues with longer macros, you can change the size of this queue via the `CONFIG_ZMK_BEHAVIORS_QUEUE_SIZE` setting in your configuration, [typically through your `.conf` file](../config/index.md). For example, `CONFIG_ZMK_BEHAVIORS_QUEUE_SIZE=512` would allow your macro to type about 256 characters.
|
||||
|
||||
## Parameterized Macros
|
||||
|
||||
Macros can also be "parameterized", allowing them to be bound in your keymap with unique values passed into them, e.g.:
|
||||
|
||||
```
|
||||
raise_layer {
|
||||
bindings = <&my_one_param_macro A>
|
||||
};
|
||||
```
|
||||
|
||||
### Defining Parameterized Macros
|
||||
|
||||
Parameterized macros must be defined using specific values for the `compatible` and `#binding-cells` properties, depending on how many parameters they require (up to a maximum of two):
|
||||
|
||||
```dts
|
||||
/ {
|
||||
macros {
|
||||
// 0 params macro
|
||||
my_macro: my_macro {
|
||||
// ...
|
||||
compatible = "zmk,behavior-macro";
|
||||
#binding-cells = <0>; // Must be 0
|
||||
bindings = /* ... */;
|
||||
};
|
||||
|
||||
// 1 param macro
|
||||
my_one_param_macro: my_one_param_macro {
|
||||
// ...
|
||||
compatible = "zmk,behavior-macro-one-param";
|
||||
#binding-cells = <1>; // Must be 1
|
||||
bindings = /* ... */;
|
||||
};
|
||||
|
||||
// 2 params macro
|
||||
my_two_param_macro: my_two_param_macro {
|
||||
// ...
|
||||
compatible = "zmk,behavior-macro-two-param";
|
||||
#binding-cells = <2>; // Must be 2
|
||||
bindings = /* ... */;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### Parameters, Bindings and Controls
|
||||
|
||||
There are special macro controls which must be used in order to forward received parameters to the macro's `bindings`. These controls are "one shot" and will determine how received parameters are used on the very next (non-macro control) behavior in the macro's `bindings` list.
|
||||
|
||||
For example, to pass the first parameter received into a `&kp` binding, you would use:
|
||||
|
||||
```dts
|
||||
bindings = <¯o_param_1to1>, <&kp MACRO_PLACEHOLDER>;
|
||||
```
|
||||
|
||||
Because `kp` takes one parameter, you can't simply make the second entry `<&kp>` in the `bindings` list. Whatever value you do pass in will be replaced when the macro is triggered, so you can put _any_ value there, e.g. `0`, `A` keycode, etc. To make it very obvious that the parameter there is not actually going to be used, you can use `MACRO_PLACEHOLDER` which is simply an alias for `0`.
|
||||
|
||||
The available parameter controls are:
|
||||
|
||||
- `¯o_param_1to1` - pass the first parameter of the macro into the first parameter of the next behavior in the `bindings` list.
|
||||
- `¯o_param_1to2` - pass the first parameter of the macro into the second parameter of the next behavior in the `bindings` list.
|
||||
|
||||
* `¯o_param_2to1` - pass the second parameter of the macro into the first parameter of the next behavior in the `bindings` list.
|
||||
* `¯o_param_2to2` - pass the second parameter of the macro into the second parameter of the next behavior in the `bindings` list.
|
||||
|
||||
## Common Patterns
|
||||
|
||||
Below are some examples of how the macro behavior can be used for various useful functionality.
|
||||
|
@ -198,12 +222,36 @@ To achieve this, a combination of a 0ms wait time and splitting the press and re
|
|||
|
||||
#### Layer + Modifier
|
||||
|
||||
```
|
||||
wait-ms = <0>;
|
||||
bindings
|
||||
= <¯o_press &mo 1 &kp LSHFT>
|
||||
, <¯o_pause_for_release>
|
||||
, <¯o_release &mo 1 &kp LSHFT>;
|
||||
```dts
|
||||
/**
|
||||
* Temporarily switches to a layer (`&mo`) while a modifier is held.
|
||||
* Analogous to QMK's `LM()`, using a parameterized macro.
|
||||
*
|
||||
* Params:
|
||||
* 1. Layer to switch to
|
||||
* 2. Modifier to press while layer is active
|
||||
*
|
||||
* Example:
|
||||
* `&lm NUM_LAYER LSHIFT`
|
||||
*/
|
||||
lm: lm {
|
||||
label = "LAYER_MOD";
|
||||
compatible = "zmk,behavior-macro-two-param";
|
||||
wait-ms = <0>;
|
||||
tap-ms = <0>;
|
||||
#binding-cells = <2>;
|
||||
bindings
|
||||
= <¯o_param_1to1>
|
||||
, <¯o_press &mo MACRO_PLACEHOLDER>
|
||||
, <¯o_param_2to1>
|
||||
, <¯o_press &kp MACRO_PLACEHOLDER>
|
||||
, <¯o_pause_for_release>
|
||||
, <¯o_param_2to1>
|
||||
, <¯o_release &kp MACRO_PLACEHOLDER>
|
||||
, <¯o_param_1to1>
|
||||
, <¯o_release &mo MACRO_PLACEHOLDER>
|
||||
;
|
||||
};
|
||||
```
|
||||
|
||||
#### Layer + Underglow Color
|
||||
|
@ -252,20 +300,24 @@ bindings
|
|||
|
||||
## Convenience C Macro
|
||||
|
||||
To avoid repetition or possible typos when declaring a macro, a convenience _C_ macro, named `ZMK_MACRO(name, props)` can be used to simplify things:
|
||||
To avoid repetition or possible typos when declaring a **zero parameter macro**, a convenience _C_ macro, named `ZMK_MACRO(name, props)` can be used to simplify things:
|
||||
|
||||
```
|
||||
ZMK_MACRO(my_macro,
|
||||
ZMK_MACRO(my_zero_param_macro,
|
||||
wait-ms = <30>;
|
||||
tap-ms = <40>;
|
||||
bindings = <&kp Z &kp M &kp K>;
|
||||
)
|
||||
```
|
||||
|
||||
:::note
|
||||
`ZMK_MACRO()` **only supports declaring non-parameterized (zero parameter) macros**; parameterized declarations are not currently supported.
|
||||
:::
|
||||
|
||||
This can be used instead of a complete macro definition. During the firmware build process, the example above would produce the complete macro definition below:
|
||||
|
||||
```
|
||||
my_macro: my_macro {
|
||||
my_zero_param_macro: my_zero_param_macro {
|
||||
compatible = "zmk,behavior-macro";
|
||||
label = "ZM_my_macro";
|
||||
#binding-cells = <0>;
|
||||
|
|
|
@ -131,26 +131,31 @@ See the [macro behavior](../behaviors/macros.md) documentation for more details
|
|||
|
||||
Definition file: [zmk/app/dts/bindings/behaviors/zmk,behavior-macro.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/behaviors/zmk%2Cbehavior-macro.yaml)
|
||||
|
||||
Applies to: `compatible = "zmk,behavior-macro"`
|
||||
| Property | Type | Description | Default |
|
||||
| ---------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `compatible` | string | Macro type, **must be _one_ of**:<br/>• `"zmk,behavior-macro"`<br/>• `"zmk,behavior-macro-one-param"`<br/>• `"zmk,behavior-macro-two-param"` | |
|
||||
| `#binding-cells` | int | Number of params accepted (depends on `compatible` property), **must be _one_ of**:<br/>• `<0>`<br/>• `<1>`<br/>• `<2>` | |
|
||||
| `bindings` | phandle array | List of behaviors to trigger | |
|
||||
| `wait-ms` | int | The default time to wait (in milliseconds) before triggering the next behavior. | `CONFIG_ZMK_MACRO_DEFAULT_WAIT_MS` |
|
||||
| `tap-ms` | int | The default time to wait (in milliseconds) between the press and release events of a tapped behavior. | `CONFIG_ZMK_MACRO_DEFAULT_TAP_MS` |
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ---------------- | ------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `#binding-cells` | int | Must be `<0>` | |
|
||||
| `bindings` | phandle array | List of behaviors to trigger | |
|
||||
| `wait-ms` | int | The default time to wait (in milliseconds) before triggering the next behavior. | `CONFIG_ZMK_MACRO_DEFAULT_WAIT_MS` |
|
||||
| `tap-ms` | int | The default time to wait (in milliseconds) between the press and release events of a tapped behavior. | `CONFIG_ZMK_MACRO_DEFAULT_TAP_MS` |
|
||||
### Macro Control Behaviors
|
||||
|
||||
The following macro-specific behaviors can be added at any point in the `bindings` list to change how the macro triggers subsequent behaviors.
|
||||
|
||||
| Behavior | Description |
|
||||
| -------------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| `¯o_tap` | Switches to tap mode |
|
||||
| `¯o_press` | Switches to press mode |
|
||||
| `¯o_release` | Switches to release mode |
|
||||
| `¯o_pause_for_release` | Pauses the macro until the macro key itself is released |
|
||||
| `¯o_wait_time TIME` | Changes the time to wait (in milliseconds) before triggering the next behavior. |
|
||||
| `¯o_tap_time TIME` | Changes the time to wait (in milliseconds) between the press and release events of a tapped behavior. |
|
||||
| Behavior | Description |
|
||||
| -------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| `¯o_tap` | Switches to tap mode |
|
||||
| `¯o_press` | Switches to press mode |
|
||||
| `¯o_release` | Switches to release mode |
|
||||
| `¯o_pause_for_release` | Pauses the macro until the macro key itself is released |
|
||||
| `¯o_wait_time TIME` | Changes the time to wait (in milliseconds) before triggering the next behavior. |
|
||||
| `¯o_tap_time TIME` | Changes the time to wait (in milliseconds) between the press and release events of a tapped behavior. |
|
||||
| `¯o_param_1to1` | Forward the first parameter received by the macro to the first parameter of the next (non-macro control) behavior. |
|
||||
| `¯o_param_1to2` | Forward the first parameter received by the macro to the second parameter of the next (non-macro control) behavior. |
|
||||
| `¯o_param_2to1` | Forward the second parameter received by the macro to the first parameter of the next (non-macro control) behavior. |
|
||||
| `¯o_param_2to2` | Forward the second parameter received by the macro to the second parameter of the next (non-macro control) behavior. |
|
||||
|
||||
## Mod-Morph
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue