diff --git a/UPGRADING.md b/UPGRADING.md index ccd1d1618d..af69f8cade 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -71,6 +71,17 @@ The API version will remain the same, even if we introduce breaking changes - until a stable release is made from the v2 branch. From that point onwards, the API version will change with further breaking changes. +### New source code layout + +The sources were rearranged so that most of them live under `src/kaleidoscope`, +with only the main header, `Kaleidoscope.h` out in `src/`. Some select headers +that were used by plugins in the wild also remained in `src/`, but now emit a +warning. If you were including anything other than `Kaleidoscope.h` which was +not namespaced, please update the include, and either add the namespace prefix, +or consider removing the include altogether. Most - if not all - parts of +Kaleidoscope are included via `Kaleidoscope.h` by design, so there should not be +a need for any extra includes. + Deprecated APIs and their replacements -------------------------------------- @@ -83,6 +94,17 @@ If any of this does not make sense to you, or you have trouble updating your .ino sketch, do not hesitate to write us at help@keyboard.io, we can help you fix it. +### To be removed by 2019-01-14 + +Any headers provided by the firmware other than `Kaleidoscope.h` (currently +`layers.h`, `key_defs_keymaps.h` and `macro_helpers.h`) are obsolete, and will +be removed. + +One should not need to use `key_defs_keymaps.h` and `layers.h`, as +`Kaleidoscope.h` includes them anyway, and the same goes for `macro_helpers.h`. +If one absolutely must, use `kaleidoscope/key_defs_keymaps.h` and +`kaleidoscope/macro_helpers.h` instead. + Deprecated and removed APIs --------------------------- diff --git a/src/Kaleidoscope.h b/src/Kaleidoscope.h index b8e295c466..be7e344fac 100644 --- a/src/Kaleidoscope.h +++ b/src/Kaleidoscope.h @@ -16,138 +16,4 @@ #pragma once -#include - -//end of add your includes here -#ifdef __cplusplus -extern "C" { -#endif -void loop(); -void setup(); -#ifdef __cplusplus -} // extern "C" -#endif - -//add your function definitions for the project KeyboardIO here - -#define TS(X) //Serial.print(micros() );Serial.print("\t");Serial.println(X); - -#include -#include -#include - -#include KALEIDOSCOPE_HARDWARE_H -#include "key_events.h" -#include "kaleidoscope/hid.h" -#include "layers.h" -#include "macro_map.h" -#include "kaleidoscope_internal/event_dispatch.h" -#include "macro_helpers.h" -#include "plugin.h" - -#define HOOK_MAX 64 - -extern HARDWARE_IMPLEMENTATION KeyboardHardware; - -#ifndef VERSION -#define VERSION "locally-built" -#endif - -/** Kaleidoscope API (major) version. - * - * The API is guaranteed to be backwards compatible for the entire duration of a - * major version. However, breaking changes may come, and result in a major - * version bump. To help migration, the `KALEIDOSCOPE_API_VERSION` macro can be - * used to check the major version provided by the Kaleidoscope we are compiling - * against. This can be used to error out with a helpful message, or change how - * the API is used - it is entirely up to the plugin or sketch author. The point - * of this macro is to let them easily check the version. - */ -#define KALEIDOSCOPE_API_VERSION 2 - -/** Required Kaleidoscope major version. - * - * For the sake of convenience, defining `KALEIDOSCOPE_REQUIRED_API_VERSION` - * before including `Kaleidoscope.h` itself will result in comparing its value - * to `KALEIDOSCOPE_API_VERSION`. If they differ, a helpful error message is - * printed. - * - * Done so that a new API version would result in a helpful error message, - * instead of cryptic compile errors. - */ -#if defined(KALEIDOSCOPE_REQUIRED_API_VERSION) && (KALEIDOSCOPE_REQUIRED_API_VERSION != KALEIDOSCOPE_API_VERSION) -#define xstr(a) str(a) -#define str(a) #a -static_assert(KALEIDOSCOPE_REQUIRED_API_VERSION == KALEIDOSCOPE_API_VERSION, - "Kaleidoscope API version mismatch! We have version " xstr(KALEIDOSCOPE_API_VERSION) - " available, but version " xstr(KALEIDOSCOPE_REQUIRED_API_VERSION) " is required."); -#endif - -namespace kaleidoscope { - -class Kaleidoscope_ { - public: - Kaleidoscope_(void); - - void setup(void); - void loop(void); - - /** Detaching from / attaching to the host. - * - * These two functions wrap the hardware plugin's similarly named functions. - * We wrap them, because we'd like plugins and user-code not having to use - * `KeyboardHardware` directly. - * - * The methods themselves implement detaching from / attaching to the host, - * without rebooting the device, and remaining powered in between. - * - * Intended to be used in cases where we want to change some settings between - * detach and attach. - */ - void detachFromHost() { - KeyboardHardware.detachFromHost(); - } - void attachToHost() { - KeyboardHardware.attachToHost(); - } - - /** Returns the timer as it was at the start of the cycle. - * The goal of this method is two-fold: - * - To reduce the amount of calls to millis(), providing something cheaper. - * - To have a consistent timer value for the whole duration of a cycle. - * - * This cached value is updated at the start of each cycle as the name - * implies. It is recommended to use this in plugins over millis() unless - * there is good reason not to. - */ - static uint32_t millisAtCycleStart() { - return millis_at_cycle_start_; - } - - EventHandlerResult onFocusEvent(const char *command) { - return kaleidoscope::Hooks::onFocusEvent(command); - } - - private: - static uint32_t millis_at_cycle_start_; -}; - -extern kaleidoscope::Kaleidoscope_ Kaleidoscope; - -} // namespace kaleidoscope - -// For compatibility reasons we enable class Kaleidoscope_ also to be available -// in global namespace. -// -typedef kaleidoscope::Kaleidoscope_ Kaleidoscope_; - -// For compatibility reasons we enable the global variable Kaleidoscope -// in global namespace. -// -using kaleidoscope::Kaleidoscope; - -// Use this function macro to register plugins with Kaleidoscope's -// hooking system. The macro accepts a list of plugin instances that -// must have been instantiated at global scope. -// -#define KALEIDOSCOPE_INIT_PLUGINS(...) _KALEIDOSCOPE_INIT_PLUGINS(__VA_ARGS__) +#include "kaleidoscope/Kaleidoscope.h" diff --git a/src/HIDTables.h b/src/kaleidoscope/HIDTables.h similarity index 100% rename from src/HIDTables.h rename to src/kaleidoscope/HIDTables.h diff --git a/src/Kaleidoscope.cpp b/src/kaleidoscope/Kaleidoscope.cpp similarity index 98% rename from src/Kaleidoscope.cpp rename to src/kaleidoscope/Kaleidoscope.cpp index 0b4fdacd48..4aa602ec9e 100644 --- a/src/Kaleidoscope.cpp +++ b/src/kaleidoscope/Kaleidoscope.cpp @@ -14,7 +14,7 @@ * this program. If not, see . */ -#include "Kaleidoscope.h" +#include "kaleidoscope/Kaleidoscope.h" #include namespace kaleidoscope { diff --git a/src/kaleidoscope/Kaleidoscope.h b/src/kaleidoscope/Kaleidoscope.h new file mode 100644 index 0000000000..b8659eef57 --- /dev/null +++ b/src/kaleidoscope/Kaleidoscope.h @@ -0,0 +1,153 @@ +/* Kaleidoscope - Firmware for computer input devices + * Copyright (C) 2013-2018 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include + +//end of add your includes here +#ifdef __cplusplus +extern "C" { +#endif +void loop(); +void setup(); +#ifdef __cplusplus +} // extern "C" +#endif + +//add your function definitions for the project KeyboardIO here + +#define TS(X) //Serial.print(micros() );Serial.print("\t");Serial.println(X); + +#include +#include +#include + +#include KALEIDOSCOPE_HARDWARE_H +#include "kaleidoscope/key_events.h" +#include "kaleidoscope/hid.h" +#include "kaleidoscope/layers.h" +#include "kaleidoscope/macro_map.h" +#include "kaleidoscope_internal/event_dispatch.h" +#include "kaleidoscope/macro_helpers.h" +#include "kaleidoscope/plugin.h" + +#define HOOK_MAX 64 + +extern HARDWARE_IMPLEMENTATION KeyboardHardware; + +#ifndef VERSION +#define VERSION "locally-built" +#endif + +/** Kaleidoscope API (major) version. + * + * The API is guaranteed to be backwards compatible for the entire duration of a + * major version. However, breaking changes may come, and result in a major + * version bump. To help migration, the `KALEIDOSCOPE_API_VERSION` macro can be + * used to check the major version provided by the Kaleidoscope we are compiling + * against. This can be used to error out with a helpful message, or change how + * the API is used - it is entirely up to the plugin or sketch author. The point + * of this macro is to let them easily check the version. + */ +#define KALEIDOSCOPE_API_VERSION 2 + +/** Required Kaleidoscope major version. + * + * For the sake of convenience, defining `KALEIDOSCOPE_REQUIRED_API_VERSION` + * before including `Kaleidoscope.h` itself will result in comparing its value + * to `KALEIDOSCOPE_API_VERSION`. If they differ, a helpful error message is + * printed. + * + * Done so that a new API version would result in a helpful error message, + * instead of cryptic compile errors. + */ +#if defined(KALEIDOSCOPE_REQUIRED_API_VERSION) && (KALEIDOSCOPE_REQUIRED_API_VERSION != KALEIDOSCOPE_API_VERSION) +#define xstr(a) str(a) +#define str(a) #a +static_assert(KALEIDOSCOPE_REQUIRED_API_VERSION == KALEIDOSCOPE_API_VERSION, + "Kaleidoscope API version mismatch! We have version " xstr(KALEIDOSCOPE_API_VERSION) + " available, but version " xstr(KALEIDOSCOPE_REQUIRED_API_VERSION) " is required."); +#endif + +namespace kaleidoscope { + +class Kaleidoscope_ { + public: + Kaleidoscope_(void); + + void setup(void); + void loop(void); + + /** Detaching from / attaching to the host. + * + * These two functions wrap the hardware plugin's similarly named functions. + * We wrap them, because we'd like plugins and user-code not having to use + * `KeyboardHardware` directly. + * + * The methods themselves implement detaching from / attaching to the host, + * without rebooting the device, and remaining powered in between. + * + * Intended to be used in cases where we want to change some settings between + * detach and attach. + */ + void detachFromHost() { + KeyboardHardware.detachFromHost(); + } + void attachToHost() { + KeyboardHardware.attachToHost(); + } + + /** Returns the timer as it was at the start of the cycle. + * The goal of this method is two-fold: + * - To reduce the amount of calls to millis(), providing something cheaper. + * - To have a consistent timer value for the whole duration of a cycle. + * + * This cached value is updated at the start of each cycle as the name + * implies. It is recommended to use this in plugins over millis() unless + * there is good reason not to. + */ + static uint32_t millisAtCycleStart() { + return millis_at_cycle_start_; + } + + EventHandlerResult onFocusEvent(const char *command) { + return kaleidoscope::Hooks::onFocusEvent(command); + } + + private: + static uint32_t millis_at_cycle_start_; +}; + +extern kaleidoscope::Kaleidoscope_ Kaleidoscope; + +} // namespace kaleidoscope + +// For compatibility reasons we enable class Kaleidoscope_ also to be available +// in global namespace. +// +typedef kaleidoscope::Kaleidoscope_ Kaleidoscope_; + +// For compatibility reasons we enable the global variable Kaleidoscope +// in global namespace. +// +using kaleidoscope::Kaleidoscope; + +// Use this function macro to register plugins with Kaleidoscope's +// hooking system. The macro accepts a list of plugin instances that +// must have been instantiated at global scope. +// +#define KALEIDOSCOPE_INIT_PLUGINS(...) _KALEIDOSCOPE_INIT_PLUGINS(__VA_ARGS__) diff --git a/src/event_handlers.h b/src/kaleidoscope/event_handlers.h similarity index 100% rename from src/event_handlers.h rename to src/kaleidoscope/event_handlers.h diff --git a/src/kaleidoscope/hid.h b/src/kaleidoscope/hid.h index a9fe8e3762..32aed22594 100644 --- a/src/kaleidoscope/hid.h +++ b/src/kaleidoscope/hid.h @@ -16,7 +16,7 @@ #pragma once #include -#include "key_defs.h" +#include "kaleidoscope/key_defs.h" namespace kaleidoscope { namespace hid { diff --git a/src/kaleidoscope/hooks.h b/src/kaleidoscope/hooks.h index 50e832aa8e..d83bb29307 100644 --- a/src/kaleidoscope/hooks.h +++ b/src/kaleidoscope/hooks.h @@ -22,8 +22,8 @@ namespace kaleidoscope { union Key; } -#include "plugin.h" -#include "event_handlers.h" +#include "kaleidoscope/plugin.h" +#include "kaleidoscope/event_handlers.h" // Forward declaration required to enable friend declarations // in class Hooks. diff --git a/src/key_defs.h b/src/kaleidoscope/key_defs.h similarity index 94% rename from src/key_defs.h rename to src/kaleidoscope/key_defs.h index 7ae490cd4f..8ae7fa36f4 100644 --- a/src/key_defs.h +++ b/src/kaleidoscope/key_defs.h @@ -17,14 +17,14 @@ #pragma once -#include "HIDTables.h" +#include "kaleidoscope/HIDTables.h" -#include "key_defs_keyboard.h" -#include "key_defs_sysctl.h" -#include "key_defs_consumerctl.h" -#include "key_defs_keymaps.h" +#include "kaleidoscope/key_defs_keyboard.h" +#include "kaleidoscope/key_defs_sysctl.h" +#include "kaleidoscope/key_defs_consumerctl.h" +#include "kaleidoscope/key_defs_keymaps.h" -#include "key_defs_aliases.h" +#include "kaleidoscope/key_defs_aliases.h" #ifdef ARDUINO_VIRTUAL #include "VirtualHID/VirtualHID.h" diff --git a/src/key_defs_aliases.h b/src/kaleidoscope/key_defs_aliases.h similarity index 100% rename from src/key_defs_aliases.h rename to src/kaleidoscope/key_defs_aliases.h diff --git a/src/key_defs_consumerctl.h b/src/kaleidoscope/key_defs_consumerctl.h similarity index 100% rename from src/key_defs_consumerctl.h rename to src/kaleidoscope/key_defs_consumerctl.h diff --git a/src/key_defs_keyboard.h b/src/kaleidoscope/key_defs_keyboard.h similarity index 100% rename from src/key_defs_keyboard.h rename to src/kaleidoscope/key_defs_keyboard.h diff --git a/src/kaleidoscope/key_defs_keymaps.h b/src/kaleidoscope/key_defs_keymaps.h new file mode 100644 index 0000000000..541f11bff1 --- /dev/null +++ b/src/kaleidoscope/key_defs_keymaps.h @@ -0,0 +1,68 @@ +/* Kaleidoscope - Firmware for computer input devices + * Copyright (C) 2013-2018 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include "kaleidoscope_internal/deprecations.h" + +static const uint8_t LAYER_SHIFT_OFFSET = 42; + +#define KEYMAP_0 0 +#define KEYMAP_1 1 +#define KEYMAP_2 2 +#define KEYMAP_3 3 +#define KEYMAP_4 4 +#define KEYMAP_5 5 +#define KEYMAP_6 6 +#define KEYMAP_7 7 + + +#define KEYMAP_PREVIOUS 33 +#define KEYMAP_NEXT 34 + + +#define Key_Keymap0 (Key) { KEYMAP_0, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap1 (Key) { KEYMAP_1, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap2 (Key) { KEYMAP_2, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap3 (Key) { KEYMAP_3, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap4 (Key) { KEYMAP_4, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap5 (Key) { KEYMAP_5, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap0_Momentary (Key){ KEYMAP_0 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap1_Momentary (Key){ KEYMAP_1 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap2_Momentary (Key){ KEYMAP_2 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap3_Momentary (Key){ KEYMAP_3 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap4_Momentary (Key){ KEYMAP_4 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_Keymap5_Momentary (Key){ KEYMAP_5 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } + +#define Key_KeymapNext_Momentary (Key) { KEYMAP_NEXT + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define Key_KeymapPrevious_Momentary (Key) { KEYMAP_PREVIOUS + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } + + +/** Lock/Unlock layer `n`. + * + * When locking a layer, it will remain active until unlocked explicitly. `n` + * can be a number, or an enum value declared previously. + */ +#define LockLayer(n) (Key){ n, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#define UnlockLayer(n) LockLayer(n) + +/** Temporarily shift to layer `n`. + * + * Shifts to layer `n` for as long as the key is held. When the key is + * released, the layer shifts back too. `n` can be a number, or an enum + * value declared previously. + */ +#define ShiftToLayer(n) (Key){ n + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } diff --git a/src/key_defs_sysctl.h b/src/kaleidoscope/key_defs_sysctl.h similarity index 100% rename from src/key_defs_sysctl.h rename to src/kaleidoscope/key_defs_sysctl.h diff --git a/src/key_events.cpp b/src/kaleidoscope/key_events.cpp similarity index 98% rename from src/key_events.cpp rename to src/kaleidoscope/key_events.cpp index 06b57b4676..72aba01a6e 100644 --- a/src/key_events.cpp +++ b/src/kaleidoscope/key_events.cpp @@ -14,9 +14,9 @@ * this program. If not, see . */ -#include "Kaleidoscope.h" +#include "kaleidoscope/Kaleidoscope.h" #include "kaleidoscope/hooks.h" -#include "plugin.h" +#include "kaleidoscope/plugin.h" static bool handleSyntheticKeyswitchEvent(Key mappedKey, uint8_t keyState) { if (mappedKey.flags & RESERVED) diff --git a/src/key_events.h b/src/kaleidoscope/key_events.h similarity index 97% rename from src/key_events.h rename to src/kaleidoscope/key_events.h index 2f2e825734..b346d2f798 100644 --- a/src/key_events.h +++ b/src/kaleidoscope/key_events.h @@ -18,8 +18,8 @@ #include #include KALEIDOSCOPE_HARDWARE_H -#include "key_defs.h" -#include "keyswitch_state.h" +#include "kaleidoscope/key_defs.h" +#include "kaleidoscope/keyswitch_state.h" extern const Key keymaps[][ROWS][COLS]; diff --git a/src/keyswitch_state.h b/src/kaleidoscope/keyswitch_state.h similarity index 100% rename from src/keyswitch_state.h rename to src/kaleidoscope/keyswitch_state.h diff --git a/src/layers.cpp b/src/kaleidoscope/layers.cpp similarity index 88% rename from src/layers.cpp rename to src/kaleidoscope/layers.cpp index 0dcf4c893b..72e4a7e3b3 100644 --- a/src/layers.cpp +++ b/src/kaleidoscope/layers.cpp @@ -14,43 +14,43 @@ * this program. If not, see . */ -#include "Kaleidoscope.h" - -static uint8_t DefaultLayer; -static uint32_t LayerState; +#include "kaleidoscope/Kaleidoscope.h" // The maximum number of layers allowed. `LayerState`, which stores // the on/off status of the layers in a bitfield has only 32 bits, and // that should be enough for almost any layout. -#define MAX_LAYERS sizeof(LayerState) * 8; - -uint8_t Layer_::highestLayer; -Key Layer_::liveCompositeKeymap[ROWS][COLS]; -uint8_t Layer_::activeLayers[ROWS][COLS]; -Key(*Layer_::getKey)(uint8_t layer, byte row, byte col) = Layer.getKeyFromPROGMEM; +#define MAX_LAYERS sizeof(uint32_t) * 8; // The total number of defined layers in the firmware sketch keymaps[] // array. If the keymap wasn't defined using KEYMAPS(), set it to the // highest possible number of layers. uint8_t layer_count __attribute__((weak)) = MAX_LAYERS; -static void handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) { +namespace kaleidoscope { +uint8_t Layer_::DefaultLayer; +uint32_t Layer_::LayerState; +uint8_t Layer_::highestLayer; +Key Layer_::liveCompositeKeymap[ROWS][COLS]; +uint8_t Layer_::activeLayers[ROWS][COLS]; +Key(*Layer_::getKey)(uint8_t layer, byte row, byte col) = Layer.getKeyFromPROGMEM; + +void Layer_::handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) { if (keymapEntry.keyCode >= LAYER_SHIFT_OFFSET) { uint8_t target = keymapEntry.keyCode - LAYER_SHIFT_OFFSET; switch (target) { case KEYMAP_NEXT: if (keyToggledOn(keyState)) - Layer.next(); + next(); else if (keyToggledOff(keyState)) - Layer.previous(); + previous(); break; case KEYMAP_PREVIOUS: if (keyToggledOn(keyState)) - Layer.previous(); + previous(); else if (keyToggledOff(keyState)) - Layer.next(); + next(); break; default: @@ -70,23 +70,22 @@ static void handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState) { */ if (keyIsPressed(keyState)) { if (!Layer.isOn(target)) - Layer.on(target); + on(target); } else if (keyToggledOff(keyState)) { - Layer.off(target); + off(target); } break; } } else if (keyToggledOn(keyState)) { // switch keymap and stay there if (Layer.isOn(keymapEntry.keyCode) && keymapEntry.keyCode) - Layer.off(keymapEntry.keyCode); + off(keymapEntry.keyCode); else - Layer.on(keymapEntry.keyCode); + on(keymapEntry.keyCode); } } -Key -Layer_::eventHandler(Key mappedKey, byte row, byte col, uint8_t keyState) { +Key Layer_::eventHandler(Key mappedKey, byte row, byte col, uint8_t keyState) { if (mappedKey.flags != (SYNTHETIC | SWITCH_TO_KEYMAP)) return mappedKey; @@ -94,12 +93,7 @@ Layer_::eventHandler(Key mappedKey, byte row, byte col, uint8_t keyState) { return Key_NoKey; } -Layer_::Layer_(void) { - defaultLayer(0); -} - -Key -Layer_::getKeyFromPROGMEM(uint8_t layer, byte row, byte col) { +Key Layer_::getKeyFromPROGMEM(uint8_t layer, byte row, byte col) { Key key; key.raw = pgm_read_word(&(keymaps[layer][row][col])); @@ -107,14 +101,12 @@ Layer_::getKeyFromPROGMEM(uint8_t layer, byte row, byte col) { return key; } -void -Layer_::updateLiveCompositeKeymap(byte row, byte col) { +void Layer_::updateLiveCompositeKeymap(byte row, byte col) { int8_t layer = activeLayers[row][col]; liveCompositeKeymap[row][col] = (*getKey)(layer, row, col); } -void -Layer_::updateActiveLayers(void) { +void Layer_::updateActiveLayers(void) { memset(activeLayers, DefaultLayer, ROWS * COLS); for (byte row = 0; row < ROWS; row++) { for (byte col = 0; col < COLS; col++) { @@ -222,4 +214,6 @@ uint32_t Layer_::getLayerState(void) { return LayerState; } -Layer_ Layer; +} + +kaleidoscope::Layer_ Layer; diff --git a/src/kaleidoscope/layers.h b/src/kaleidoscope/layers.h new file mode 100644 index 0000000000..dad31cb42d --- /dev/null +++ b/src/kaleidoscope/layers.h @@ -0,0 +1,115 @@ +/* Kaleidoscope - Firmware for computer input devices + * Copyright (C) 2013-2018 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include +#include "kaleidoscope/key_defs.h" +#include KALEIDOSCOPE_HARDWARE_H + +// Macro for defining the keymap. This should be used in the sketch +// file (*.ino) to define the keymap[] array that holds the user's +// layers. It also computes the number of layers in that keymap. +#define KEYMAPS(layers...) \ + const Key keymaps[][ROWS][COLS] PROGMEM = { layers }; \ + uint8_t layer_count = sizeof(keymaps) / sizeof(*keymaps); + +extern uint8_t layer_count; + +namespace kaleidoscope { +class Layer_ { + public: + Layer_() {} + + /* There are two lookup functions, because we have two caches, and different + * parts of the firmware will want to use either this or that (or perhaps + * both, in rare cases). + * + * First of all, we use caches because looking up a key through all the layers + * is costy, and the cost increases dramatically the more layers we have. + * + * Then, we have the `liveCompositeKeymap`, because to have layer behaviours + * we want, that is, if you hold a key on a layer, release the layer key but + * continue holding the other, we want for the layered keycode to continue + * repeating. + * + * At the same time, we want other keys to not be affected by the + * now-turned-off layer. So we update the keycode in the cache on-demand, when + * the key is pressed. (see the top of `handleKeyswitchEvent`). + * + * On the other hand, we also have plugins that scan the whole keymap, and do + * things based on that information, such as highlighting keys that changed + * between layers. These need to be able to look at a state of where the + * keymap *should* be, not necessarily where it is. The `liveCompositeKeymap` + * is not useful here. So we use `activeLayers` which we update whenever + * layers change (see `Layer.on` and `Layer.off`), and it updates the cache to + * show how the keymap should look, without the `liveCompositeKeymap`-induced + * behaviour. + * + * Thus, if we are curious about what a given key will do, use `lookup`. If we + * are curious what the active layer state describes the key as, use + * `lookupOnActiveLayer`. + */ + static Key lookup(byte row, byte col) { + return liveCompositeKeymap[row][col]; + } + static Key lookupOnActiveLayer(byte row, byte col) { + uint8_t layer = activeLayers[row][col]; + return (*getKey)(layer, row, col); + } + static uint8_t lookupActiveLayer(byte row, byte col) { + return activeLayers[row][col]; + } + static void on(uint8_t layer); + static void off(uint8_t layer); + static void move(uint8_t layer); + + static uint8_t top(void) { + return highestLayer; + } + static void next(void); + static void previous(void); + + static boolean isOn(uint8_t layer); + + static void defaultLayer(uint8_t layer); + static uint8_t defaultLayer(void); + + static uint32_t getLayerState(void); + + static Key eventHandler(Key mappedKey, byte row, byte col, uint8_t keyState); + + static Key(*getKey)(uint8_t layer, byte row, byte col); + + static Key getKeyFromPROGMEM(uint8_t layer, byte row, byte col); + + static void updateLiveCompositeKeymap(byte row, byte col); + static void updateActiveLayers(void); + + private: + static void updateHighestLayer(void); + + static uint8_t DefaultLayer; + static uint32_t LayerState; + static uint8_t highestLayer; + static Key liveCompositeKeymap[ROWS][COLS]; + static uint8_t activeLayers[ROWS][COLS]; + + static void handleKeymapKeyswitchEvent(Key keymapEntry, uint8_t keyState); +}; +} + +extern kaleidoscope::Layer_ Layer; diff --git a/src/kaleidoscope/macro_helpers.h b/src/kaleidoscope/macro_helpers.h new file mode 100644 index 0000000000..7bccb1db90 --- /dev/null +++ b/src/kaleidoscope/macro_helpers.h @@ -0,0 +1,137 @@ +/* Kaleidoscope - Firmware for computer input devices + * Copyright (C) 2013-2018 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +// Code generated by muli-line pre-processor macros is hard to read after +// pre-processing. +// +// When you want to check pre-processed code, e.g. for debugging or +// to understand what's going on, do the following: +// +// 1) Add the compiler command line definition +// -DKALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION +// This prevents the __NL__ macro being defined below. +// 2) Generate the preprocessed code (it will contain a lot of __NL__ definitions). +// 3) Open the pre-processed code in your favorite editor. +// 3.1) Replace all __NL__ with newline characters. +// In vim the command would be ':%s/__NL__/\r/g'. +// 3.2) Autocorrect code-indenting to improve readability. This is necessary +// as pre-processor macros remove all whitespaces at the beginning of lines. +// With vim, the command gg=G helps (just type the characters one after +// the other). +// 4) Don't forget to remove the +// -DKALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION +// from your compiler command line. Else the code won't compile. + +#ifndef KALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION +#define __NL__ +#endif + +#define __NN__ + +// Some auxiliary macros +// +#define __STRINGIZE(S) #S +#define STRINGIZE(S) __STRINGIZE(S) + +// Allow for the creation of verbose messages in static_asserts +// +#define VERBOSE_STATIC_ASSERT_HEADER \ + "\n" __NL__ \ + "\n***************************************************************" __NL__ \ + "\n******************** READ THIS CAREFULLY! *********************" __NL__ \ + "\n***************************************************************" __NL__ \ + "\n" + +#define VERBOSE_STATIC_ASSERT_FOOTER \ + "\n" __NL__ \ + "\n***************************************************************" __NL__ \ + "\n***************************************************************" __NL__ \ + "\n***************************************************************" __NL__ \ + "\n" + +#define VERBOSE_FILE_INFO \ + "\nFile: " __FILE__ __NL__ + +#define VERBOSE_LINE_INFO \ + "\nLine: " STRINGIZE(__LINE__) __NL__ + +// The macro function RESTRICT_ARGS_COUNT can be used to generate more +// verbose error messages when users supply an insuitable number of arguments +// to a macro. +// +// For a macro it is used wherever one of the arguments A, B, C might +// be used, e.g. +// +#if 0 // This is just so that A_MACRO is not actually defined +#define A_MACRO(A, B, C, ...) \ + (void)RESTRICT_ARGS_COUNT(0, 3, A_MACRO, ##__VA_ARGS__); \ + int a = A; \ + int b = B; \ + int c = C; +#endif +// +// Note that RESTRICT_ARGS_COUNT can also be invoked wherever one of the macro +// arguments is used, e.g. +// +#if 0 // This is just so that B_MACRO is not actually defined +#define B_MACRO(A, B, C, ...) +int array[] = { A, B, RESTRICT_ARGS_COUNT(C, 3, B_MACRO, ##__VA_ARGS__) }; +#endif +// +#define RESTRICT_ARGS_COUNT(B, \ + NUM_EXPECTED_ARGS, \ + ORIGINAL_MACRO, \ + ...) \ + ((struct { __NL__ \ + /* Here we are in the body of a dummy lambda function. */ __NL__ \ + /* []{} is, BTW, the shortest way to write a lambda. */ __NL__ \ + /* It is only used to hold the static_assert that cannot be */ __NL__ \ + /* defined directly in the keymap initializer list. By using the */ __NL__ \ + /* comma operator ((A, B) always evaluates to b), we ensure */ __NL__ \ + /* that not the lambda but B is what ASSERT_ARGS_COUNT */ __NL__ \ + /* finally evaluates to. */ __NL__ \ + /* Please not that passing B through this macro is a must */ __NL__ \ + /* as we need it for the comma operator to work. */ __NL__ \ + static_assert(sizeof(const char) == sizeof(#__VA_ARGS__ ), __NL__ \ + /* sizeof(const char) == sizeof(#__VA_ARGS__ ) checks the quoted */ __NL__ \ + /* list of additional arguments. If there are none, then the */ __NL__ \ + /* length of #__VA_ARGS__ is a single char as it contains '\0'. */ __NL__ \ + /* This check is not able to find the corner case of a single */ __NL__ \ + /* superfluous comma at the end of the macro arguments as this */ __NL__ \ + /* causes #__VA_ARGS__ being empty (only '\0'). */ __NL__ \ + VERBOSE_STATIC_ASSERT_HEADER __NL__ \ + __NL__ \ + VERBOSE_FILE_INFO __NL__ \ + VERBOSE_LINE_INFO __NL__ \ + "\n" __NL__ \ + "\nStrange arguments found in invocation of " #ORIGINAL_MACRO "." __NL__ \ + "\n" __NL__ \ + "\nPlease make sure to pass exactly " #NUM_EXPECTED_ARGS __NL__ \ + " macro arguments to" __NL__ \ + "\n" #ORIGINAL_MACRO ". Also make sure that there are no dangling" __NL__ \ + "\ncommas at the end of the argument list." __NL__ \ + "\n" __NL__ \ + "\nThis is the superfluous part at the end of the macro" __NL__ \ + "\narguments list: \'" #__VA_ARGS__ "\'" __NL__ \ + __NL__ \ + VERBOSE_STATIC_ASSERT_FOOTER __NL__ \ + ); __NL__ \ + __NL__ \ + }){}, /* End of dummy lambda, the comma operator's A operand. */ __NL__ \ + B /* The overall ASSERT_ARGS_COUNT evaluates to B. */ __NL__ \ + ) diff --git a/src/macro_map.h b/src/kaleidoscope/macro_map.h similarity index 100% rename from src/macro_map.h rename to src/kaleidoscope/macro_map.h diff --git a/src/plugin.h b/src/kaleidoscope/plugin.h similarity index 97% rename from src/plugin.h rename to src/kaleidoscope/plugin.h index d161574504..0a7c62acfa 100644 --- a/src/plugin.h +++ b/src/kaleidoscope/plugin.h @@ -18,7 +18,7 @@ #include "kaleidoscope/event_handler_result.h" #include "kaleidoscope_internal/event_dispatch.h" -#include "event_handlers.h" +#include "kaleidoscope/event_handlers.h" #if KALEIDOSCOPE_ENABLE_V1_PLUGIN_API #error The V1 plugin API has been removed, please see UPGRADING.md. diff --git a/src/kaleidoscope_internal/event_dispatch.h b/src/kaleidoscope_internal/event_dispatch.h index 89e860a739..43db3165ce 100644 --- a/src/kaleidoscope_internal/event_dispatch.h +++ b/src/kaleidoscope_internal/event_dispatch.h @@ -33,11 +33,11 @@ #pragma once -#include "macro_helpers.h" -#include "plugin.h" +#include "kaleidoscope/macro_helpers.h" +#include "kaleidoscope/plugin.h" #include "kaleidoscope/hooks.h" -#include "eventhandler_signature_check.h" -#include "event_handlers.h" +#include "kaleidoscope_internal/eventhandler_signature_check.h" +#include "kaleidoscope/event_handlers.h" // Some words about the design of hook routing: // diff --git a/src/kaleidoscope_internal/eventhandler_signature_check.h b/src/kaleidoscope_internal/eventhandler_signature_check.h index 193ee47129..661e2c9fa1 100644 --- a/src/kaleidoscope_internal/eventhandler_signature_check.h +++ b/src/kaleidoscope_internal/eventhandler_signature_check.h @@ -16,8 +16,8 @@ #pragma once -#include "macro_helpers.h" -#include "plugin.h" +#include "kaleidoscope/macro_helpers.h" +#include "kaleidoscope/plugin.h" // ************************************************************************* diff --git a/src/key_defs_keymaps.h b/src/key_defs_keymaps.h index 541f11bff1..a8386eaea7 100644 --- a/src/key_defs_keymaps.h +++ b/src/key_defs_keymaps.h @@ -16,53 +16,6 @@ #pragma once -#include "kaleidoscope_internal/deprecations.h" +#warning Please migrate to including "kaleidoscope/key_defs_keymaps.h" instead of "key_defs_keymaps.h", or even consider dropping the include, because will pull the right header in anyway. -static const uint8_t LAYER_SHIFT_OFFSET = 42; - -#define KEYMAP_0 0 -#define KEYMAP_1 1 -#define KEYMAP_2 2 -#define KEYMAP_3 3 -#define KEYMAP_4 4 -#define KEYMAP_5 5 -#define KEYMAP_6 6 -#define KEYMAP_7 7 - - -#define KEYMAP_PREVIOUS 33 -#define KEYMAP_NEXT 34 - - -#define Key_Keymap0 (Key) { KEYMAP_0, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap1 (Key) { KEYMAP_1, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap2 (Key) { KEYMAP_2, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap3 (Key) { KEYMAP_3, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap4 (Key) { KEYMAP_4, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap5 (Key) { KEYMAP_5, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap0_Momentary (Key){ KEYMAP_0 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap1_Momentary (Key){ KEYMAP_1 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap2_Momentary (Key){ KEYMAP_2 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap3_Momentary (Key){ KEYMAP_3 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap4_Momentary (Key){ KEYMAP_4 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_Keymap5_Momentary (Key){ KEYMAP_5 + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } - -#define Key_KeymapNext_Momentary (Key) { KEYMAP_NEXT + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define Key_KeymapPrevious_Momentary (Key) { KEYMAP_PREVIOUS + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } - - -/** Lock/Unlock layer `n`. - * - * When locking a layer, it will remain active until unlocked explicitly. `n` - * can be a number, or an enum value declared previously. - */ -#define LockLayer(n) (Key){ n, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } -#define UnlockLayer(n) LockLayer(n) - -/** Temporarily shift to layer `n`. - * - * Shifts to layer `n` for as long as the key is held. When the key is - * released, the layer shifts back too. `n` can be a number, or an enum - * value declared previously. - */ -#define ShiftToLayer(n) (Key){ n + LAYER_SHIFT_OFFSET, KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP } +#include "kaleidoscope/key_defs_keymaps.h" diff --git a/src/layers.h b/src/layers.h index 288790c163..032c367327 100644 --- a/src/layers.h +++ b/src/layers.h @@ -16,94 +16,6 @@ #pragma once -#include -#include "key_defs.h" -#include KALEIDOSCOPE_HARDWARE_H +#warning Please migrate to including "kaleidoscope/layers.h" instead of "layers.h", or even consider dropping the include, because will pull the right header in anyway. -// Macro for defining the keymap. This should be used in the sketch -// file (*.ino) to define the keymap[] array that holds the user's -// layers. It also computes the number of layers in that keymap. -#define KEYMAPS(layers...) \ - const Key keymaps[][ROWS][COLS] PROGMEM = { layers }; \ - uint8_t layer_count = sizeof(keymaps) / sizeof(*keymaps); - -extern uint8_t layer_count; - -class Layer_ { - public: - Layer_(void); - - /* There are two lookup functions, because we have two caches, and different - * parts of the firmware will want to use either this or that (or perhaps - * both, in rare cases). - * - * First of all, we use caches because looking up a key through all the layers - * is costy, and the cost increases dramatically the more layers we have. - * - * Then, we have the `liveCompositeKeymap`, because to have layer behaviours - * we want, that is, if you hold a key on a layer, release the layer key but - * continue holding the other, we want for the layered keycode to continue - * repeating. - * - * At the same time, we want other keys to not be affected by the - * now-turned-off layer. So we update the keycode in the cache on-demand, when - * the key is pressed. (see the top of `handleKeyswitchEvent`). - * - * On the other hand, we also have plugins that scan the whole keymap, and do - * things based on that information, such as highlighting keys that changed - * between layers. These need to be able to look at a state of where the - * keymap *should* be, not necessarily where it is. The `liveCompositeKeymap` - * is not useful here. So we use `activeLayers` which we update whenever - * layers change (see `Layer.on` and `Layer.off`), and it updates the cache to - * show how the keymap should look, without the `liveCompositeKeymap`-induced - * behaviour. - * - * Thus, if we are curious about what a given key will do, use `lookup`. If we - * are curious what the active layer state describes the key as, use - * `lookupOnActiveLayer`. - */ - static Key lookup(byte row, byte col) { - return liveCompositeKeymap[row][col]; - } - static Key lookupOnActiveLayer(byte row, byte col) { - uint8_t layer = activeLayers[row][col]; - return (*getKey)(layer, row, col); - } - static uint8_t lookupActiveLayer(byte row, byte col) { - return activeLayers[row][col]; - } - static void on(uint8_t layer); - static void off(uint8_t layer); - static void move(uint8_t layer); - - static uint8_t top(void) { - return highestLayer; - } - static void next(void); - static void previous(void); - - static boolean isOn(uint8_t layer); - - static void defaultLayer(uint8_t layer); - static uint8_t defaultLayer(void); - - static uint32_t getLayerState(void); - - static Key eventHandler(Key mappedKey, byte row, byte col, uint8_t keyState); - - static Key(*getKey)(uint8_t layer, byte row, byte col); - - static Key getKeyFromPROGMEM(uint8_t layer, byte row, byte col); - - static void updateLiveCompositeKeymap(byte row, byte col); - static void updateActiveLayers(void); - - private: - static void updateHighestLayer(void); - - static uint8_t highestLayer; - static Key liveCompositeKeymap[ROWS][COLS]; - static uint8_t activeLayers[ROWS][COLS]; -}; - -extern Layer_ Layer; +#include "kaleidoscope/layers.h" diff --git a/src/macro_helpers.h b/src/macro_helpers.h index 7bccb1db90..58042886af 100644 --- a/src/macro_helpers.h +++ b/src/macro_helpers.h @@ -16,122 +16,6 @@ #pragma once -// Code generated by muli-line pre-processor macros is hard to read after -// pre-processing. -// -// When you want to check pre-processed code, e.g. for debugging or -// to understand what's going on, do the following: -// -// 1) Add the compiler command line definition -// -DKALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION -// This prevents the __NL__ macro being defined below. -// 2) Generate the preprocessed code (it will contain a lot of __NL__ definitions). -// 3) Open the pre-processed code in your favorite editor. -// 3.1) Replace all __NL__ with newline characters. -// In vim the command would be ':%s/__NL__/\r/g'. -// 3.2) Autocorrect code-indenting to improve readability. This is necessary -// as pre-processor macros remove all whitespaces at the beginning of lines. -// With vim, the command gg=G helps (just type the characters one after -// the other). -// 4) Don't forget to remove the -// -DKALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION -// from your compiler command line. Else the code won't compile. +#warning Please migrate to including "kaleidoscope/macro_helpers.h" instead of "macro_helpers.h"! -#ifndef KALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION -#define __NL__ -#endif - -#define __NN__ - -// Some auxiliary macros -// -#define __STRINGIZE(S) #S -#define STRINGIZE(S) __STRINGIZE(S) - -// Allow for the creation of verbose messages in static_asserts -// -#define VERBOSE_STATIC_ASSERT_HEADER \ - "\n" __NL__ \ - "\n***************************************************************" __NL__ \ - "\n******************** READ THIS CAREFULLY! *********************" __NL__ \ - "\n***************************************************************" __NL__ \ - "\n" - -#define VERBOSE_STATIC_ASSERT_FOOTER \ - "\n" __NL__ \ - "\n***************************************************************" __NL__ \ - "\n***************************************************************" __NL__ \ - "\n***************************************************************" __NL__ \ - "\n" - -#define VERBOSE_FILE_INFO \ - "\nFile: " __FILE__ __NL__ - -#define VERBOSE_LINE_INFO \ - "\nLine: " STRINGIZE(__LINE__) __NL__ - -// The macro function RESTRICT_ARGS_COUNT can be used to generate more -// verbose error messages when users supply an insuitable number of arguments -// to a macro. -// -// For a macro it is used wherever one of the arguments A, B, C might -// be used, e.g. -// -#if 0 // This is just so that A_MACRO is not actually defined -#define A_MACRO(A, B, C, ...) \ - (void)RESTRICT_ARGS_COUNT(0, 3, A_MACRO, ##__VA_ARGS__); \ - int a = A; \ - int b = B; \ - int c = C; -#endif -// -// Note that RESTRICT_ARGS_COUNT can also be invoked wherever one of the macro -// arguments is used, e.g. -// -#if 0 // This is just so that B_MACRO is not actually defined -#define B_MACRO(A, B, C, ...) -int array[] = { A, B, RESTRICT_ARGS_COUNT(C, 3, B_MACRO, ##__VA_ARGS__) }; -#endif -// -#define RESTRICT_ARGS_COUNT(B, \ - NUM_EXPECTED_ARGS, \ - ORIGINAL_MACRO, \ - ...) \ - ((struct { __NL__ \ - /* Here we are in the body of a dummy lambda function. */ __NL__ \ - /* []{} is, BTW, the shortest way to write a lambda. */ __NL__ \ - /* It is only used to hold the static_assert that cannot be */ __NL__ \ - /* defined directly in the keymap initializer list. By using the */ __NL__ \ - /* comma operator ((A, B) always evaluates to b), we ensure */ __NL__ \ - /* that not the lambda but B is what ASSERT_ARGS_COUNT */ __NL__ \ - /* finally evaluates to. */ __NL__ \ - /* Please not that passing B through this macro is a must */ __NL__ \ - /* as we need it for the comma operator to work. */ __NL__ \ - static_assert(sizeof(const char) == sizeof(#__VA_ARGS__ ), __NL__ \ - /* sizeof(const char) == sizeof(#__VA_ARGS__ ) checks the quoted */ __NL__ \ - /* list of additional arguments. If there are none, then the */ __NL__ \ - /* length of #__VA_ARGS__ is a single char as it contains '\0'. */ __NL__ \ - /* This check is not able to find the corner case of a single */ __NL__ \ - /* superfluous comma at the end of the macro arguments as this */ __NL__ \ - /* causes #__VA_ARGS__ being empty (only '\0'). */ __NL__ \ - VERBOSE_STATIC_ASSERT_HEADER __NL__ \ - __NL__ \ - VERBOSE_FILE_INFO __NL__ \ - VERBOSE_LINE_INFO __NL__ \ - "\n" __NL__ \ - "\nStrange arguments found in invocation of " #ORIGINAL_MACRO "." __NL__ \ - "\n" __NL__ \ - "\nPlease make sure to pass exactly " #NUM_EXPECTED_ARGS __NL__ \ - " macro arguments to" __NL__ \ - "\n" #ORIGINAL_MACRO ". Also make sure that there are no dangling" __NL__ \ - "\ncommas at the end of the argument list." __NL__ \ - "\n" __NL__ \ - "\nThis is the superfluous part at the end of the macro" __NL__ \ - "\narguments list: \'" #__VA_ARGS__ "\'" __NL__ \ - __NL__ \ - VERBOSE_STATIC_ASSERT_FOOTER __NL__ \ - ); __NL__ \ - __NL__ \ - }){}, /* End of dummy lambda, the comma operator's A operand. */ __NL__ \ - B /* The overall ASSERT_ARGS_COUNT evaluates to B. */ __NL__ \ - ) +#include "kaleidoscope/macro_helpers.h"