From 5faa23d54ca1e3ab83097f2a07922f48800616e6 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Mon, 15 May 2023 22:27:37 +1000 Subject: Keymap introspection for combos. (#19670) --- docs/config_options.md | 2 -- docs/feature_combo.md | 33 +++++---------------------------- docs/ja/config_options.md | 2 -- docs/ja/feature_combo.md | 6 +++--- 4 files changed, 8 insertions(+), 35 deletions(-) (limited to 'docs') diff --git a/docs/config_options.md b/docs/config_options.md index 5ea71d993e..4698260118 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -186,8 +186,6 @@ If you define these options you will enable the associated feature, which may in * how long before oneshot times out * `#define ONESHOT_TAP_TOGGLE 2` * how many taps before oneshot toggle is triggered -* `#define COMBO_COUNT 2` - * Set this to the number of combos that you're using in the [Combo](feature_combo.md) feature. Or leave it undefined and programmatically set the count. * `#define COMBO_TERM 200` * how long for the Combo keys to be detected. Defaults to `TAPPING_TERM` if not defined. * `#define COMBO_MUST_HOLD_MODS` diff --git a/docs/feature_combo.md b/docs/feature_combo.md index 075fe252ae..fd241061fb 100644 --- a/docs/feature_combo.md +++ b/docs/feature_combo.md @@ -4,15 +4,12 @@ The Combo feature is a chording type solution for adding custom actions. It lets To enable this feature, you need to add `COMBO_ENABLE = yes` to your `rules.mk`. -Additionally, in your `config.h`, you'll need to specify the number of combos that you'll be using, by adding `#define COMBO_COUNT 1` (replacing 1 with the number that you're using). It is also possible to not define this and instead set the variable `COMBO_LEN` yourself. There's a trick where we don't need to think about this variable at all. More on this later. - - Then, in your `keymap.c` file, you'll need to define a sequence of keys, terminated with `COMBO_END`, and a structure to list the combination of keys, and its resulting action. ```c const uint16_t PROGMEM test_combo1[] = {KC_A, KC_B, COMBO_END}; const uint16_t PROGMEM test_combo2[] = {KC_C, KC_D, COMBO_END}; -combo_t key_combos[COMBO_COUNT] = { +combo_t key_combos[] = { COMBO(test_combo1, KC_ESC), COMBO(test_combo2, LCTL(KC_Z)), // keycodes with modifiers are possible too! }; @@ -33,7 +30,7 @@ It is possible to overlap combos. Before, with the example below both combos wou ```c const uint16_t PROGMEM test_combo1[] = {LSFT_T(KC_A), LT(1, KC_B), COMBO_END}; const uint16_t PROGMEM test_combo2[] = {LSFT_T(KC_A), LT(1, KC_B), KC_C, COMBO_END}; -combo_t key_combos[COMBO_COUNT] = { +combo_t key_combos[] = { COMBO(test_combo1, KC_ESC) COMBO(test_combo2, KC_TAB) }; @@ -41,17 +38,15 @@ combo_t key_combos[COMBO_COUNT] = { ## Examples -A long list of combos can be defined in an `enum` list that ends with `COMBO_LENGTH` and you can leave `COMBO_COUNT` undefined: +A long list of combos can be defined in an `enum` list: ```c enum combos { AB_ESC, JK_TAB, QW_SFT, - SD_LAYER, - COMBO_LENGTH + SD_LAYER }; -uint16_t COMBO_LEN = COMBO_LENGTH; // remove the COMBO_COUNT define and use this instead! const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END}; const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END}; @@ -72,9 +67,7 @@ For a more complicated implementation, you can use the `process_combo_event` fun enum combo_events { EM_EMAIL, BSPC_LSFT_CLEAR, - COMBO_LENGTH }; -uint16_t COMBO_LEN = COMBO_LENGTH; // remove the COMBO_COUNT define and use this instead! const uint16_t PROGMEM email_combo[] = {KC_E, KC_M, COMBO_END}; const uint16_t PROGMEM clear_line_combo[] = {KC_BSPC, KC_LSFT, COMBO_END}; @@ -259,18 +252,6 @@ bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode } ``` -### Variable Length Combos -If you leave `COMBO_COUNT` undefined in `config.h`, it allows you to programmatically declare the size of the Combo data structure and avoid updating `COMBO_COUNT`. Instead a variable called `COMBO_LEN` has to be set. It can be set with something similar to the following in `keymap.c`: `uint16_t COMBO_LEN = ARRAY_SIZE(key_combos);` or by adding `COMBO_LENGTH` as the *last* entry in the combo enum and then `uint16_t COMBO_LEN = COMBO_LENGTH;` as such: -```c -enum myCombos { - ..., - COMBO_LENGTH -}; -uint16_t COMBO_LEN = COMBO_LENGTH; -``` -Regardless of the method used to declare `COMBO_LEN`, this also requires to convert the `combo_t key_combos[COMBO_COUNT] = {...};` line to `combo_t key_combos[] = {...};`. - - ### Combo timer Normally, the timer is started on the first key press and then reset on every subsequent key press within the `COMBO_TERM`. @@ -300,10 +281,8 @@ Here's an example where a combo resolves to two modifiers, and on key releases t ```c enum combos { - AB_MODS, - COMBO_LENGTH + AB_MODS }; -uint16_t COMBO_LEN = COMBO_LENGTH; const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END}; @@ -415,6 +394,4 @@ SUBS(TH_THE, "the", KC_T, KC_H) // SUBS uses SEND_STRING to output the give ... ``` -Now, you can update only one place to add or alter combos. You don't even need to remember to update the `COMBO_COUNT` or the `COMBO_LEN` variables at all. Everything is taken care of. Magic! - For small to huge ready made dictionaries of combos, you can check out http://combos.gboards.ca/. diff --git a/docs/ja/config_options.md b/docs/ja/config_options.md index 4f9f1f2770..5e98da5eee 100644 --- a/docs/ja/config_options.md +++ b/docs/ja/config_options.md @@ -176,8 +176,6 @@ QMK での全ての利用可能な設定にはデフォルトがあります。 * ワンショットがタイムアウトするまでの時間 * `#define ONESHOT_TAP_TOGGLE 2` * ワンショットトグルが引き起こされるまでのタップ数 -* `#define COMBO_COUNT 2` - * [コンボ](ja/feature_combo.md)機能で使っているコンボの数にこれを設定します。 * `#define COMBO_TERM 200` * コンボキーが検出されるまでの時間。定義されていない場合は、デフォルトは `TAPPING_TERM` です。 * `#define TAP_CODE_DELAY 100` diff --git a/docs/ja/feature_combo.md b/docs/ja/feature_combo.md index bd46e88b7f..0c0591e5f7 100644 --- a/docs/ja/feature_combo.md +++ b/docs/ja/feature_combo.md @@ -18,7 +18,7 @@ ```c const uint16_t PROGMEM test_combo[] = {KC_A, KC_B, COMBO_END}; -combo_t key_combos[COMBO_COUNT] = {COMBO(test_combo, KC_ESC)}; +combo_t key_combos[] = {COMBO(test_combo, KC_ESC)}; ``` これは、A と B のキーを押した場合に、"Escape" を送信します。 @@ -38,7 +38,7 @@ enum combos { const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END}; const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END}; -combo_t key_combos[COMBO_COUNT] = { +combo_t key_combos[] = { [AB_ESC] = COMBO(ab_combo, KC_ESC), [JK_TAB] = COMBO(jk_combo, KC_TAB) }; @@ -55,7 +55,7 @@ enum combo_events { const uint16_t PROGMEM copy_combo[] = {KC_Z, KC_C, COMBO_END}; const uint16_t PROGMEM paste_combo[] = {KC_X, KC_V, COMBO_END}; -combo_t key_combos[COMBO_COUNT] = { +combo_t key_combos[] = { [ZC_COPY] = COMBO_ACTION(copy_combo), [XV_PASTE] = COMBO_ACTION(paste_combo), }; -- cgit v1.2.3