diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 00000000..f0db1c28 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,112 @@ +Breaking changes in `MagicCombo` +================================ + +To make `MagicCombo` more portable, and easier to use, we had to break the API +previously provided, there was no way to maintain backwards compatibility. This +document is an attempt at guiding you through the process of migrating from the +earlier API to the current one. + +Migration should be a straightforward process, but if you get stuck, please feel +free to [open an issue][gh:issues], or start a thread on the [forums][forums], +and we'll help you with it. + + [gh:issues]: https://github.com/keyboardio/Kaleidoscope-MagicCombo/issues + [forums]: https://community.keyboard.io/ + +## The old API + +```c++ +void magicComboActions(uint8_t combo_index, uint32_t left_hand, uint32_t right_hand) { + switch (combo_index) { + case 0: + Macros.type(PSTR("It's a kind of magic!")); + break; + } +} + +static const kaleidoscope::MagicCombo::combo_t magic_combos[] PROGMEM = { + { + R3C6, // left palm key + R3C9 // right palm key + }, + {0, 0} +}; + +void setup() { + Kaleidoscope.setup(); + + MagicCombo.magic_combos = magic_combos; +} +``` + +Previsouly, we used a global, overrideable function (`magicComboActions`) to run +the actions of all magic combos, similar to how macros are set up to work. +Unlike macros, magic combos can't be defined in the keymap, due to technical +reasons, so we had to use a separate list - `magic_combos` in our example. We +also needed to tell `MagicCombo` to use this list, which is what we've done in +`setup()`. + +## The new API + +```c++ +void kindOfMagic(uint8_t combo_index) { + Macros.type(PSTR("It's a kind of magic!")); +} + +USE_MAGIC_COMBOS({ + .action = kindOfMagic, + .keys = {R3C6, R3C9} // Left Fn + Right Fn +}); +``` + +The new API is much shorter, and is inspired by the way the [Leader][leader] +plugin works: instead of having a list, and a dispatching function like +`magicComboActions`, we include the action method in the list too! + + [leader]: https://github.com/keyboardio/Kaleidoscope-Leader + +We also don't make a difference between left- and right-hand anymore, you can +just list keys for either in the same list. This will be very handy for +non-split keyboards. + +## Migration + +First of all, we'll need to split up `magicComboActions` into separate +functions. Each function should have a unique name, but their shape is always +the same: + +```c++ +void someFunction(uint8_t combo_index) { + // Do some action here +} +``` + +Copy the body of each `case` statement of `magicComboActions`, and copy them one +by one into appropriately named functions of the above shape. You can name your +functions anything you want, the only constraint is that they need to be valid +C++ function names. The plugin itself does nothing with the name, we'll +reference them later in the `USE_MAGIC_COMBOS` helper macro. + +Once `magicComboActions` is split up, we need to migrate the `magic_combos` list +to the new format. That list had to be terminated by a `{0, 0}` entry, the new +method does not require such a sentinel at the end. + +For each entry in `magic_combos`, add an entry to `USE_MAGIC_COMBOS`, with the +following structure: + +```c++ +{.action = theActionFunction, + .keys = { /* list of keys */ }} +``` + +The list of keys are the same `RxCy` constants you used for `magic_combos`, with +the left- and right hands combined. The action, `theActionFunction`, is the +function you extracted the magic combo action to. It's the function that has the +same body as the `case` statement in `magicComboActions` had. + +And this is all there is to it. + +If your actions made use of the `left_hand` or `right_hand` arguments of +`magicComboActions`, the same information is still available. But that's a bit +more involved to get to, out of scope for this simple migration guide. Please +open an issue, or ask for help on the forums, and we'll help you. diff --git a/examples/MagicCombo/MagicCombo.ino b/examples/MagicCombo/MagicCombo.ino index 9d16b455..d09a11b2 100644 --- a/examples/MagicCombo/MagicCombo.ino +++ b/examples/MagicCombo/MagicCombo.ino @@ -30,6 +30,22 @@ void kindOfMagic(uint8_t combo_index) { USE_MAGIC_COMBOS([KIND_OF_MAGIC] = {.action = kindOfMagic, .keys = {R3C6, R3C9}}); +void magicComboActions(uint8_t combo_index, uint32_t left_hand, uint32_t right_hand) { + switch (combo_index) { + case 0: + Macros.type(PSTR("It's a kind of magic!")); + break; + } +} + +static const kaleidoscope::MagicCombo::combo_t magic_combos[] PROGMEM = { + { + R3C6, // left palm key + R3C9 // right palm key + }, + {0, 0} +}; + // *INDENT-OFF* const Key keymaps[][ROWS][COLS] PROGMEM = { [0] = KEYMAP_STACKED @@ -56,6 +72,8 @@ KALEIDOSCOPE_INIT_PLUGINS(MagicCombo, Macros); void setup() { Kaleidoscope.setup(); + + MagicCombo.magic_combos = magic_combos; } void loop() { diff --git a/src/Kaleidoscope/MagicCombo.h b/src/Kaleidoscope/MagicCombo.h index be3419dc..902fe84e 100644 --- a/src/Kaleidoscope/MagicCombo.h +++ b/src/Kaleidoscope/MagicCombo.h @@ -31,6 +31,13 @@ } \ } +#define _MAGICCOMBO_API_CHANGE \ + "The MagicCombo API changed in an incompatible way, you will need to\n" \ + "upgrade.\n" \ + "\n" \ + "Please see the `UPGRADING.md` document shipped with the source:\n" \ + " https://github.com/keyboardio/Kaleidoscope-MagicCombo/blob/master/UPGRADING.md" + namespace kaleidoscope { class MagicCombo : public kaleidoscope::Plugin { @@ -40,9 +47,18 @@ class MagicCombo : public kaleidoscope::Plugin { ComboAction action; int8_t keys[MAX_COMBO_LENGTH + 1]; } Combo; + typedef struct combo_t { + uint32_t left_hand, right_hand; + + combo_t& operator=(combo_t &) { + static_assert(false, _DEPRECATE(_MAGICCOMBO_API_CHANGE)); + return *this; + } + } combo_t; MagicCombo(void) {} + static const combo_t *magic_combos; static uint16_t min_interval; EventHandlerResult beforeReportingState();