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.
|
||||
|
||||
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
|
||||
const keycode_string_name_t *keycode_string_names_user =
|
||||
(keycode_string_name_t []){
|
||||
#define KEYCODE_STRING_NAMES_USER
|
||||
```
|
||||
|
||||
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(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}
|
||||
|
||||
|
@ -17,8 +17,10 @@
|
||||
#include <string.h>
|
||||
#include "bitwise.h"
|
||||
#include "keycode.h"
|
||||
#include "keymap_introspection.h"
|
||||
#include "progmem.h"
|
||||
#include "quantum_keycodes.h"
|
||||
#include "util.h"
|
||||
|
||||
typedef int_fast8_t index_t;
|
||||
|
||||
@ -89,16 +91,16 @@ static const keycode_string_name_t keycode_names[] = {
|
||||
KEYCODE_STRING_NAME(QK_LLCK),
|
||||
#endif // LAYER_LOCK_ENABLE
|
||||
KEYCODE_STRING_NAME(DB_TOGG),
|
||||
KEYCODE_STRING_NAMES_END
|
||||
};
|
||||
// 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. */
|
||||
static const char* mod_names[4] = {PSTR("CTL"), PSTR("SFT"), PSTR("ALT"), PSTR("GUI")};
|
||||
/** Internal buffer for holding a stringified keycode. */
|
||||
@ -107,17 +109,21 @@ static char buffer[32];
|
||||
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.
|
||||
*/
|
||||
static const char* find_keycode_name(const keycode_string_name_t* table, uint16_t keycode) {
|
||||
for (; table->keycode; ++table) {
|
||||
if (table->keycode == keycode) {
|
||||
return table->name;
|
||||
static const char* find_keycode_name(const keycode_string_name_t* (*table_get)(uint16_t), uint16_t keycode) {
|
||||
for (uint16_t i = 0;; ++i) {
|
||||
const keycode_string_name_t* entry = table_get(i);
|
||||
if (entry == NULL) {
|
||||
break;
|
||||
} else if (entry->keycode == keycode) {
|
||||
return entry->name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@ -206,19 +212,24 @@ static void append_unary_keycode(const char* name, const char* param) {
|
||||
|
||||
/** Stringifies `keycode` and appends it to `buffer`. */
|
||||
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`
|
||||
// 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) {
|
||||
append_P(keycode_name);
|
||||
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) {
|
||||
append_P(keycode_name);
|
||||
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) {
|
||||
append_P(keycode_name);
|
||||
return;
|
||||
|
@ -65,10 +65,11 @@
|
||||
const char* get_keycode_string(uint16_t keycode);
|
||||
|
||||
/** Defines a human-readable name for a keycode. */
|
||||
typedef struct {
|
||||
typedef struct keycode_string_name_t {
|
||||
uint16_t keycode;
|
||||
const char* name;
|
||||
} keycode_string_name_t;
|
||||
// typedef struct keycode_string_name_t keycode_string_name_t;
|
||||
|
||||
/**
|
||||
* @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
|
||||
* `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. */
|
||||
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. */
|
||||
# define KEYCODE_STRING_NAME(kc) \
|
||||
{ (kc), PSTR(#kc) }
|
||||
# define KEYCODE_STRING_NAME(kc) {(kc), PSTR(#kc)}
|
||||
/** Makes end-of-table sentinel for a table of keycode_string_name_t. */
|
||||
# define KEYCODE_STRING_NAMES_END \
|
||||
{ 0, NULL }
|
||||
# define KEYCODE_STRING_NAMES_END {0, NULL}
|
||||
|
||||
#else
|
||||
|
||||
|
@ -171,3 +171,36 @@ __attribute__((weak)) const key_override_t* key_override_get(uint16_t key_overri
|
||||
}
|
||||
|
||||
#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);
|
||||
|
||||
#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
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
#define KEYCODE_STRING_NAMES_USER
|
||||
#define KEYCODE_STRING_NAMES_KB
|
||||
|
||||
|
@ -15,3 +15,4 @@
|
||||
KEYCODE_STRING_ENABLE = yes
|
||||
EXTRAKEY_ENABLE = yes
|
||||
MOUSEKEY_ENABLE = yes
|
||||
INTROSPECTION_KEYMAP_C = test_keymap.c
|
||||
|
@ -15,23 +15,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "test_common.hpp"
|
||||
|
||||
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
|
||||
#include "test_keymap.h"
|
||||
|
||||
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