qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

keycode_string.h (5132B)


      1 // Copyright 2024-2025 Google LLC
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #pragma once
     16 
     17 #include <stdint.h>
     18 
     19 #if KEYCODE_STRING_ENABLE
     20 
     21 /**
     22  * @brief Formats a QMK keycode as a human-readable string.
     23  *
     24  * Given a keycode, like `KC_A`, this function returns a formatted string, like
     25  * "KC_A". This is useful for debugging and diagnostics so that keys are more
     26  * easily identified than they would be by raw numerical codes.
     27  *
     28  * @note The returned char* string should be used right away. The string memory
     29  * is reused and will be overwritten by the next call to `keycode_string()`.
     30  *
     31  * Many common QMK keycodes are understood by this function, but not all.
     32  * Recognized keycodes include:
     33  *
     34  *  - Most basic keycodes, including letters `KC_A` - `KC_Z`, digits `KC_0` -
     35  *    `KC_9`, function keys `KC_F1` - `KC_F24`, and modifiers like `KC_LSFT`.
     36  *
     37  *  - Modified basic keycodes, like `S(KC_1)` (Shift + 1 = !).
     38  *
     39  *  - `MO`, `TO`, `TG`, `OSL`, `LM(layer,mod)`, `LT(layer,kc)` layer switches.
     40  *
     41  *  - One-shot mod `OSM(mod)` keycodes.
     42  *
     43  *  - Mod-tap `MT(mod, kc)` keycodes.
     44  *
     45  *  - Tap dance keycodes `TD(i)`.
     46  *
     47  *  - Swap hands keycodes `SH_T(kc)`, `SH_TOGG`, etc.
     48  *
     49  *  - Joystick keycodes `JS_n`.
     50  *
     51  *  - Programmable button keycodes `PB_n`.
     52  *
     53  *  - Unicode `UC(codepoint)` and Unicode Map `UM(i)` and `UP(i,j)` keycodes.
     54  *
     55  *  - Keyboard range keycodes `QK_KB_*`.
     56  *
     57  *  - User range (SAFE_RANGE) keycodes `QK_USER_*`.
     58  *
     59  * Keycodes involving mods like `OSM`, `LM`, `MT` are fully supported only where
     60  * a single mod is applied.
     61  *
     62  * Unrecognized keycodes are printed numerically as hex values like `0x1ABC`.
     63  *
     64  * Optionally, use `keycode_string_names_user` or `keycode_string_names_kb` to
     65  * define names for additional keycodes or override how any of the above are
     66  * formatted.
     67  *
     68  * @param keycode  QMK keycode.
     69  * @return         Stringified keycode.
     70  */
     71 const char* get_keycode_string(uint16_t keycode);
     72 
     73 /** Defines a human-readable name for a keycode. */
     74 typedef struct {
     75     uint16_t    keycode;
     76     const char* name;
     77 } keycode_string_name_t;
     78 
     79 // clang-format off
     80 /**
     81  * @brief Defines names for additional keycodes for `get_keycode_string()`.
     82  *
     83  * Define `KEYCODE_STRING_NAMES_USER` in your keymap.c to add names for
     84  * additional keycodes to `keycode_string()`. This table may also be used to
     85  * override how `keycode_string()` formats a keycode. For example, supposing
     86  * keymap.c defines `MYMACRO1` and `MYMACRO2` as custom keycodes:
     87  *
     88  *     KEYCODE_STRING_NAMES_USER(
     89  *         KEYCODE_STRING_NAME(MYMACRO1),
     90  *         KEYCODE_STRING_NAME(MYMACRO2),
     91  *         KEYCODE_STRING_NAME(KC_EXLM),
     92  *     );
     93  *
     94  * The above defines names for `MYMACRO1` and `MYMACRO2`, and overrides
     95  * `KC_EXLM` to format as "KC_EXLM" instead of the default "S(KC_1)".
     96  */
     97 #    define KEYCODE_STRING_NAMES_USER(...)                                          \
     98     static const keycode_string_name_t keycode_string_names_user[] = {__VA_ARGS__}; \
     99     uint16_t keycode_string_names_size_user =                                       \
    100         sizeof(keycode_string_names_user) / sizeof(keycode_string_name_t);          \
    101     const keycode_string_name_t* keycode_string_names_data_user =                   \
    102         keycode_string_names_user
    103 
    104 /** Same as above, but defines keycode string names at the keyboard level. */
    105 #    define KEYCODE_STRING_NAMES_KB(...)                                            \
    106     static const keycode_string_name_t keycode_string_names_kb[] = {__VA_ARGS__};   \
    107     uint16_t keycode_string_names_size_kb =                                         \
    108         sizeof(keycode_string_names_kb) / sizeof(keycode_string_name_t);            \
    109     const keycode_string_name_t* keycode_string_names_data_kb =                     \
    110         keycode_string_names_kb
    111 
    112 /** Helper to define a keycode_string_name_t. */
    113 #    define KEYCODE_STRING_NAME(kc) \
    114         { (kc), #kc }
    115 // clang-format on
    116 
    117 extern const keycode_string_name_t* keycode_string_names_data_user;
    118 extern uint16_t                     keycode_string_names_size_user;
    119 extern const keycode_string_name_t* keycode_string_names_data_kb;
    120 extern uint16_t                     keycode_string_names_size_kb;
    121 
    122 #else
    123 
    124 // When keycode_string is disabled, fall back to printing keycodes numerically
    125 // as decimal values, using get_u16_str() from quantum.c.
    126 #    define get_keycode_string(kc) get_u16_str(kc, ' ')
    127 
    128 const char* get_u16_str(uint16_t curr_num, char curr_pad);
    129 
    130 #    define KEYCODE_STRING_NAMES_USER(...)
    131 #    define KEYCODE_STRING_NAMES_KB(...)
    132 #    define KEYCODE_STRING_NAME(kc)
    133 
    134 #endif // KEYCODE_STRING_ENABLE