Automatically add END to invocations of MACRO() and friends

Requiring end-users to terminate macros with END strikes me as
easy to mess up, and perhaps inelegant.  This commit removes the
requirement for end-users to terminate macros with END.

As a result of this commit, end-users (including other plugins) who
do use END will see a tiny amount of increased code size (1 byte per
declared macro I believe), but functionality remains intact.

Usage of END is hereby deprecated, and eventually #define END may
be removed in a future commit.

README.md has been modified with the new usage instructions, and
a note that usage of END is deprecated.
pull/365/head
Craig Disselkoen 7 years ago
parent 754647b6ca
commit ebd9f35d62

@ -48,8 +48,7 @@ const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) {
D(LeftShift), T(M), U(LeftShift), T(O), T(D), T(E), T(L), D(LeftShift), T(M), U(LeftShift), T(O), T(D), T(E), T(L),
T(Spacebar), T(Spacebar),
W(100), W(100),
T(0), T(1), T(0), T(1) );
END);
case MACRO_HELLO: case MACRO_HELLO:
if (key_toggled_on(keyState)) { if (key_toggled_on(keyState)) {
Macros.type(PSTR("Hello world!")); Macros.type(PSTR("Hello world!"));
@ -128,8 +127,10 @@ need to define them in a special way, using the `MACRO` helper (or its
> Defines a macro, that is built up from `steps` (explained below). The plugin > Defines a macro, that is built up from `steps` (explained below). The plugin
> will iterate through the sequence, and re-play the steps in order. > will iterate through the sequence, and re-play the steps in order.
> >
> The sequence must end with the `END` step, otherwise the playback will not be > Note: In older versions of the Macros plugin, the sequence of steps had to end
> able to stop, and will have unpredictable behaviour. > with a special step called END. This is no longer required. Existing macros
> that end with END will still work correctly, but new code should not use END;
> usage of END is deprecated.
### `MACRODOWN(steps...)` ### `MACRODOWN(steps...)`
@ -147,7 +148,7 @@ need to define them in a special way, using the `MACRO` helper (or its
## `MACRO` steps ## `MACRO` steps
Macro steps can be divided into three groups: Macro steps can be divided into two groups:
### Delays ### Delays
@ -162,20 +163,14 @@ Macro steps can be divided into three groups:
Key event steps have two variants: one that prefixes its argument with `Key_`, Key event steps have two variants: one that prefixes its argument with `Key_`,
and one that does not. The latter are the `Dr`, `Ur`, and `Tr` variants. In most and one that does not. The latter are the `Dr`, `Ur`, and `Tr` variants. In most
cases, one is likely to use normal keys for the steps, so the `D`, `U`, and `T` cases, one is likely to use normal keys for the steps, so the `D`, `U`, and `T`
steps apply the `Key_` prefix. This allows us to write `MACRO(T(X), END)` steps apply the `Key_` prefix. This allows us to write `MACRO(T(X))`
instead of `MACRO(Tr(Key_X), END)` - making the macro definition shorter, and instead of `MACRO(Tr(Key_X))` - making the macro definition shorter, and
more readable. more readable.
* `D(key)`, `Dr(key)`: Simulates a key being pressed (pushed down). * `D(key)`, `Dr(key)`: Simulates a key being pressed (pushed down).
* `U(key)`, `Ur(key)`: Simulates a key being released (going up). * `U(key)`, `Ur(key)`: Simulates a key being released (going up).
* `T(key)`, `Tr(key)`: Simulates a key being tapped (pressed first, then released). * `T(key)`, `Tr(key)`: Simulates a key being tapped (pressed first, then released).
### The End
* `END`: Signals the end of the macro. Anything past this step will be ignored.
But without this step, the plugin will continue trying to play the macro
further, and have unpredictable results.
## Overrideable methods ## Overrideable methods
### `macroAction(macroIndex, keyState)` ### `macroAction(macroIndex, keyState)`

@ -18,7 +18,7 @@ typedef enum {
typedef uint8_t macro_t; typedef uint8_t macro_t;
#define MACRO_NONE 0 #define MACRO_NONE 0
#define MACRO(...) ({static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; }) #define MACRO(...) ({static const macro_t __m[] PROGMEM = { __VA_ARGS__, MACRO_ACTION_END }; &__m[0]; })
#define MACRODOWN(...) (key_toggled_on(keyState) ? MACRO(__VA_ARGS__) : MACRO_NONE) #define MACRODOWN(...) (key_toggled_on(keyState) ? MACRO(__VA_ARGS__) : MACRO_NONE)
#define I(n) MACRO_ACTION_STEP_INTERVAL, n #define I(n) MACRO_ACTION_STEP_INTERVAL, n

Loading…
Cancel
Save