mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-05-20 08:10:38 +00:00
Attempt at simplifying interface.
This commit is contained in:
parent
45f573f335
commit
8eaf67de76
@ -75,18 +75,22 @@ Use the result of `get_keycode_string()` immediately. Subsequent invocations reu
|
|||||||
|
|
||||||
Many common QMK keycodes are recognized by `get_keycode_string()`, but not all. These include some common basic keycodes, layer switch keycodes, mod-taps, one-shot keycodes, tap dance keycodes, and Unicode keycodes. As a fallback, an unrecognized keycode is written as a hex number.
|
Many common QMK keycodes are recognized by `get_keycode_string()`, but not all. These include some common basic keycodes, layer switch keycodes, mod-taps, one-shot keycodes, tap dance keycodes, and Unicode keycodes. As a fallback, an unrecognized keycode is written as a hex number.
|
||||||
|
|
||||||
Optionally, `keycode_string_names_user` may be defined to add names for additional keycodes. For example, supposing keymap.c defines `MYMACRO1` and `MYMACRO2` as custom keycodes, the following adds their names:
|
Optionally, names for additional keycodes may be defined. To do this, define `KEYCODE_STRING_NAMES_USER` in config.h:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
const keycode_string_name_t *keycode_string_names_user =
|
#define KEYCODE_STRING_NAMES_USER
|
||||||
(keycode_string_name_t []){
|
```
|
||||||
|
|
||||||
|
Then define `keycode_string_names_user` with the names for the additional keycodes. For example, supposing keymap.c defines `MYMACRO1` and `MYMACRO2` as custom keycodes, the following adds their names:
|
||||||
|
|
||||||
|
```c
|
||||||
|
const keycode_string_name_t keycode_string_names_user[] = {
|
||||||
KEYCODE_STRING_NAME(MYMACRO1),
|
KEYCODE_STRING_NAME(MYMACRO1),
|
||||||
KEYCODE_STRING_NAME(MYMACRO2),
|
KEYCODE_STRING_NAME(MYMACRO2),
|
||||||
KEYCODE_STRING_NAMES_END // End of table sentinel.
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Similarly, `keycode_string_names_kb` may be defined to add names at the keyboard level.
|
Similarly at the keyboard level, names for additional keycodes may be added by defining `KEYCODE_STRING_NAMES_KB` in config.h and defining keycode names in `keycode_string_names_kb`.
|
||||||
|
|
||||||
# Tracing Variables {#tracing-variables}
|
# Tracing Variables {#tracing-variables}
|
||||||
|
|
||||||
|
@ -17,8 +17,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "bitwise.h"
|
#include "bitwise.h"
|
||||||
#include "keycode.h"
|
#include "keycode.h"
|
||||||
|
#include "keymap_introspection.h"
|
||||||
#include "progmem.h"
|
#include "progmem.h"
|
||||||
#include "quantum_keycodes.h"
|
#include "quantum_keycodes.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
typedef int_fast8_t index_t;
|
typedef int_fast8_t index_t;
|
||||||
|
|
||||||
@ -89,16 +91,16 @@ static const keycode_string_name_t keycode_names[] = {
|
|||||||
KEYCODE_STRING_NAME(QK_LLCK),
|
KEYCODE_STRING_NAME(QK_LLCK),
|
||||||
#endif // LAYER_LOCK_ENABLE
|
#endif // LAYER_LOCK_ENABLE
|
||||||
KEYCODE_STRING_NAME(DB_TOGG),
|
KEYCODE_STRING_NAME(DB_TOGG),
|
||||||
KEYCODE_STRING_NAMES_END
|
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
__attribute__((weak)) const keycode_string_name_t empty_table[] = {KEYCODE_STRING_NAMES_END};
|
static const keycode_string_name_t* keycode_names_get(uint16_t i) {
|
||||||
|
if (i >= ARRAY_SIZE(keycode_names)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &keycode_names[i];
|
||||||
|
}
|
||||||
|
|
||||||
/** Users can override this to define names of additional keycodes. */
|
|
||||||
__attribute__((weak)) const keycode_string_name_t* keycode_string_names_user = empty_table;
|
|
||||||
/** Keyboard vendors can override this to define names of additional keycodes. */
|
|
||||||
__attribute__((weak)) const keycode_string_name_t* keycode_string_names_kb = empty_table;
|
|
||||||
/** Names of the 4 mods on each hand. */
|
/** Names of the 4 mods on each hand. */
|
||||||
static const char* mod_names[4] = {PSTR("CTL"), PSTR("SFT"), PSTR("ALT"), PSTR("GUI")};
|
static const char* mod_names[4] = {PSTR("CTL"), PSTR("SFT"), PSTR("ALT"), PSTR("GUI")};
|
||||||
/** Internal buffer for holding a stringified keycode. */
|
/** Internal buffer for holding a stringified keycode. */
|
||||||
@ -107,17 +109,21 @@ static char buffer[32];
|
|||||||
static index_t buffer_len;
|
static index_t buffer_len;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Finds the name of a keycode in `table` or returns NULL.
|
* @brief Finds the name of a keycode in table or returns NULL.
|
||||||
*
|
*
|
||||||
* The last entry of the table must be `KEYCODE_STRING_NAMES_END`.
|
* The function arg `table_get(i)` is called as `table_get(0)`, `table_get(1)`,
|
||||||
|
* `table_get(2)`, etc., until it returns NULL or once the keycode is found.
|
||||||
*
|
*
|
||||||
* @param table A table of keycode_string_name_t to be searched.
|
* @param table_get Function to get the table entries.
|
||||||
* @return Name string for the keycode, or NULL if not found.
|
* @return Name string for the keycode, or NULL if not found.
|
||||||
*/
|
*/
|
||||||
static const char* find_keycode_name(const keycode_string_name_t* table, uint16_t keycode) {
|
static const char* find_keycode_name(const keycode_string_name_t* (*table_get)(uint16_t), uint16_t keycode) {
|
||||||
for (; table->keycode; ++table) {
|
for (uint16_t i = 0;; ++i) {
|
||||||
if (table->keycode == keycode) {
|
const keycode_string_name_t* entry = table_get(i);
|
||||||
return table->name;
|
if (entry == NULL) {
|
||||||
|
break;
|
||||||
|
} else if (entry->keycode == keycode) {
|
||||||
|
return entry->name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -206,19 +212,24 @@ static void append_unary_keycode(const char* name, const char* param) {
|
|||||||
|
|
||||||
/** Stringifies `keycode` and appends it to `buffer`. */
|
/** Stringifies `keycode` and appends it to `buffer`. */
|
||||||
static void append_keycode(uint16_t keycode) {
|
static void append_keycode(uint16_t keycode) {
|
||||||
|
const char* keycode_name;
|
||||||
|
#ifdef KEYCODE_STRING_NAMES_USER
|
||||||
// In case there is overlap among tables, search `keycode_string_names_user`
|
// In case there is overlap among tables, search `keycode_string_names_user`
|
||||||
// first so that it takes precedence.
|
// first so that it takes precedence.
|
||||||
const char* keycode_name = find_keycode_name(keycode_string_names_user, keycode);
|
keycode_name = find_keycode_name(keycode_string_names_user_get, keycode);
|
||||||
if (keycode_name) {
|
if (keycode_name) {
|
||||||
append_P(keycode_name);
|
append_P(keycode_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keycode_name = find_keycode_name(keycode_string_names_kb, keycode);
|
#endif // KEYCODE_STRING_NAMES_USER
|
||||||
|
#ifdef KEYCODE_STRING_NAMES_KB
|
||||||
|
keycode_name = find_keycode_name(keycode_string_names_kb_get, keycode);
|
||||||
if (keycode_name) {
|
if (keycode_name) {
|
||||||
append_P(keycode_name);
|
append_P(keycode_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keycode_name = find_keycode_name(keycode_names, keycode);
|
#endif // KEYCODE_STRING_NAMES_KB
|
||||||
|
keycode_name = find_keycode_name(keycode_names_get, keycode);
|
||||||
if (keycode_name) {
|
if (keycode_name) {
|
||||||
append_P(keycode_name);
|
append_P(keycode_name);
|
||||||
return;
|
return;
|
||||||
|
@ -65,10 +65,11 @@
|
|||||||
const char* get_keycode_string(uint16_t keycode);
|
const char* get_keycode_string(uint16_t keycode);
|
||||||
|
|
||||||
/** Defines a human-readable name for a keycode. */
|
/** Defines a human-readable name for a keycode. */
|
||||||
typedef struct {
|
typedef struct keycode_string_name_t {
|
||||||
uint16_t keycode;
|
uint16_t keycode;
|
||||||
const char* name;
|
const char* name;
|
||||||
} keycode_string_name_t;
|
} keycode_string_name_t;
|
||||||
|
// typedef struct keycode_string_name_t keycode_string_name_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Names for additional keycodes for `get_keycode_string()`.
|
* @brief Names for additional keycodes for `get_keycode_string()`.
|
||||||
@ -90,16 +91,14 @@ typedef struct {
|
|||||||
* The above defines names for `MYMACRO1` and `MYMACRO2`, and overrides
|
* The above defines names for `MYMACRO1` and `MYMACRO2`, and overrides
|
||||||
* `KC_EXLM` to format as "KC_EXLM" instead of the default "S(KC_1)".
|
* `KC_EXLM` to format as "KC_EXLM" instead of the default "S(KC_1)".
|
||||||
*/
|
*/
|
||||||
extern const keycode_string_name_t* keycode_string_names_user;
|
// extern const keycode_string_name_t* keycode_string_names_user;
|
||||||
/** Same as `keycode_string_names_user`, but for use at the keyboard level. */
|
/** Same as `keycode_string_names_user`, but for use at the keyboard level. */
|
||||||
extern const keycode_string_name_t* keycode_string_names_kb;
|
// extern const keycode_string_name_t* keycode_string_names_kb;
|
||||||
|
|
||||||
/** Helper to define a keycode_string_name_t. */
|
/** Helper to define a keycode_string_name_t. */
|
||||||
# define KEYCODE_STRING_NAME(kc) \
|
# define KEYCODE_STRING_NAME(kc) {(kc), PSTR(#kc)}
|
||||||
{ (kc), PSTR(#kc) }
|
|
||||||
/** Makes end-of-table sentinel for a table of keycode_string_name_t. */
|
/** Makes end-of-table sentinel for a table of keycode_string_name_t. */
|
||||||
# define KEYCODE_STRING_NAMES_END \
|
# define KEYCODE_STRING_NAMES_END {0, NULL}
|
||||||
{ 0, NULL }
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -171,3 +171,36 @@ __attribute__((weak)) const key_override_t* key_override_get(uint16_t key_overri
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // defined(KEY_OVERRIDE_ENABLE)
|
#endif // defined(KEY_OVERRIDE_ENABLE)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Keycode String
|
||||||
|
|
||||||
|
#if defined(KEYCODE_STRING_ENABLE)
|
||||||
|
|
||||||
|
# if defined(KEYCODE_STRING_NAMES_USER)
|
||||||
|
const keycode_string_name_t* keycode_string_names_user_get_raw(uint16_t i) {
|
||||||
|
if (i >= ARRAY_SIZE(keycode_string_names_user)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return (const keycode_string_name_t*)&keycode_string_names_user[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) const keycode_string_name_t* keycode_string_names_user_get(uint16_t i) {
|
||||||
|
return keycode_string_names_user_get_raw(i);
|
||||||
|
}
|
||||||
|
# endif // defined(KEYCODE_STRING_NAMES_USER)
|
||||||
|
|
||||||
|
# if defined(KEYCODE_STRING_NAMES_KB)
|
||||||
|
const keycode_string_name_t* keycode_string_names_kb_get_raw(uint16_t i) {
|
||||||
|
if (i >= ARRAY_SIZE(keycode_string_names_kb)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return (const keycode_string_name_t*)&keycode_string_names_kb[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) const keycode_string_name_t* keycode_string_names_kb_get(uint16_t i) {
|
||||||
|
return keycode_string_names_kb_get_raw(i);
|
||||||
|
}
|
||||||
|
# endif // defined(KEYCODE_STRING_NAMES_KB)
|
||||||
|
|
||||||
|
#endif // defined(KEYCODE_STRING_ENABLE)
|
||||||
|
@ -109,3 +109,27 @@ const key_override_t* key_override_get_raw(uint16_t key_override_idx);
|
|||||||
const key_override_t* key_override_get(uint16_t key_override_idx);
|
const key_override_t* key_override_get(uint16_t key_override_idx);
|
||||||
|
|
||||||
#endif // defined(KEY_OVERRIDE_ENABLE)
|
#endif // defined(KEY_OVERRIDE_ENABLE)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Keycode String
|
||||||
|
|
||||||
|
#if defined(KEYCODE_STRING_ENABLE)
|
||||||
|
|
||||||
|
struct keycode_string_name_t;
|
||||||
|
typedef struct keycode_string_name_t keycode_string_name_t;
|
||||||
|
|
||||||
|
# if defined(KEYCODE_STRING_NAMES_USER)
|
||||||
|
// Get the user-level keycode names, stored in firmware.
|
||||||
|
const keycode_string_name_t* keycode_string_names_user_get_raw(uint16_t i);
|
||||||
|
// Get the user-level keycode names, potentially stored dynamically.
|
||||||
|
const keycode_string_name_t* keycode_string_names_user_get(uint16_t i);
|
||||||
|
# endif // defined(KEYCODE_STRING_NAMES_USER)
|
||||||
|
|
||||||
|
# if defined(KEYCODE_STRING_NAMES_KB)
|
||||||
|
// Get the kb-level keycode names, stored in firmware.
|
||||||
|
const keycode_string_name_t* keycode_string_names_kb_get_raw(uint16_t i);
|
||||||
|
// Get the kb-level keycode names, potentially stored dynamically.
|
||||||
|
const keycode_string_name_t* keycode_string_names_kb_get(uint16_t i);
|
||||||
|
# endif // defined(KEYCODE_STRING_NAMES_KB)
|
||||||
|
|
||||||
|
#endif // defined(KEYCODE_STRING_ENABLE)
|
||||||
|
@ -17,3 +17,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "test_common.h"
|
#include "test_common.h"
|
||||||
|
|
||||||
|
#define KEYCODE_STRING_NAMES_USER
|
||||||
|
#define KEYCODE_STRING_NAMES_KB
|
||||||
|
|
||||||
|
@ -15,3 +15,4 @@
|
|||||||
KEYCODE_STRING_ENABLE = yes
|
KEYCODE_STRING_ENABLE = yes
|
||||||
EXTRAKEY_ENABLE = yes
|
EXTRAKEY_ENABLE = yes
|
||||||
MOUSEKEY_ENABLE = yes
|
MOUSEKEY_ENABLE = yes
|
||||||
|
INTROSPECTION_KEYMAP_C = test_keymap.c
|
||||||
|
@ -15,23 +15,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "test_common.hpp"
|
#include "test_common.hpp"
|
||||||
|
#include "test_keymap.h"
|
||||||
enum {
|
|
||||||
MYMACRO1 = SAFE_RANGE,
|
|
||||||
MYMACRO2,
|
|
||||||
};
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
extern "C" const keycode_string_name_t *keycode_string_names_kb = (keycode_string_name_t []){
|
|
||||||
KEYCODE_STRING_NAME(MYMACRO1),
|
|
||||||
KEYCODE_STRING_NAMES_END // End of table sentinel.
|
|
||||||
};
|
|
||||||
extern "C" const keycode_string_name_t *keycode_string_names_user = (keycode_string_name_t []){
|
|
||||||
KEYCODE_STRING_NAME(MYMACRO2),
|
|
||||||
KEYCODE_STRING_NAME(KC_EXLM),
|
|
||||||
KEYCODE_STRING_NAMES_END // End of table sentinel.
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
class KeycodeStringTest : public TestFixture {};
|
class KeycodeStringTest : public TestFixture {};
|
||||||
|
|
||||||
|
27
tests/keycode_string/test_keymap.c
Normal file
27
tests/keycode_string/test_keymap.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2025 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "test_keymap.h"
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
const keycode_string_name_t keycode_string_names_kb[] = {
|
||||||
|
KEYCODE_STRING_NAME(MYMACRO1),
|
||||||
|
};
|
||||||
|
|
||||||
|
const keycode_string_name_t keycode_string_names_user[] = {
|
||||||
|
KEYCODE_STRING_NAME(MYMACRO2),
|
||||||
|
KEYCODE_STRING_NAME(KC_EXLM),
|
||||||
|
};
|
||||||
|
// clang-format on
|
20
tests/keycode_string/test_keymap.h
Normal file
20
tests/keycode_string/test_keymap.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2025 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MYMACRO1 = SAFE_RANGE,
|
||||||
|
MYMACRO2,
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user