[Keymap] csc027/macro-sync-keymap (#7873)

* Basic functionality to synchronize the strings and enums using C preprocessor macros.

* Updated all the custom convenience macros to work.

* Removed some duplicate update_tri_layer calls.

* Simplified the convenience accelerator macros for synchronizing enums and strings by removing the short enum names.

* Updated the CUSTOM_MACROS macro to use SS_LCTL instead of SS_LCTRL.

* Fixed a bug where the right side of the convenience layer in the Iris keymap was incorrectly listed twice.

* Removed the tenkey from the convenience layer.  Added Windows 10 virtual desktop shortcuts to the convenience layer.

* Fixed a bug where the macro range was not set correctly.

* Added sigil values for the keycode enum so that additions to the sync macros will not require changes to the process_record_user ranges.

* Hacked send_string_P to work with ChibiOS boards.

* Switched to using I2C for the Iris keyboard.

* Finished a comment.

* Updated comments to explain that for non-AVR MCUs, the PROGMEM macro doesn't do anything.

* Updated the synchronization macros to use the more descriptive "NAME" instead of "CALL".  Moved the Control-Alt-Delete chord macro to the  synchronization macro.

* Simplified the custom macros by consolidating the macros into a context change macro instead of using alt-tab and minimize macros.

* Fixed a formatting issue where several tabs were used instead of 4 spaces.

* Added more comments to explain the synchronization macros.

* Simplified the PARAMS macro, since any parameters could be passed with a space by the declarer instead.

* Consolidated the synchronization macros into a single list.  Simplified the synchronization mechanism.

* Removed the overloading macro, since it is no longer needed.

* Updated the convenience layer comments to reflect the changes made.

* Renamed the git_macros pointer table to custom_macros, since it no longer solely consists of git macros.

* Clarified that the send_string_P function's use of pgm_read_byte is different for AVR and non-AVR compilation targets.
This commit is contained in:
csc027 2020-01-13 17:41:13 +00:00 committed by Drashna Jaelre
parent 390a4fdc9d
commit 1b8cb95f2e
5 changed files with 141 additions and 118 deletions

View File

@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
// #define USE_I2C
#define USE_I2C
#define EE_HANDS
#undef RGBLED_NUM

View File

@ -45,10 +45,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_CN] = LAYOUT_wrapper(
___________________CONVENIENCE_L1__________________, ___________________CONVENIENCE_L1__________________,
___________________CONVENIENCE_L2__________________, ___________________CONVENIENCE_L2__________________,
___________________CONVENIENCE_L3__________________, ___________________CONVENIENCE_L3__________________,
___________________CONVENIENCE_L4__________________, _______, _______, ___________________CONVENIENCE_L4__________________,
___________________CONVENIENCE_L1__________________, ___________________CONVENIENCE_R1__________________,
___________________CONVENIENCE_L2__________________, ___________________CONVENIENCE_R2__________________,
___________________CONVENIENCE_L3__________________, ___________________CONVENIENCE_R3__________________,
___________________CONVENIENCE_L4__________________, _______, _______, ___________________CONVENIENCE_R4__________________,
_______, _______, _______, _______, _______, _______
),

View File

@ -1,32 +1,11 @@
#include "csc027.h"
static const char* git_macros[] = {
// Make sure that the macro strings match the order they are declared
// in the custom_keycodes enum.
"git add ",
"git branch ",
"git checkout ",
"git cherry-pick ",
"git commit -m \"\""SS_TAP(X_LEFT),
"git diff ",
"git fetch ",
"git grep ",
"git log --decorate --oneline --graph ",
"git init ",
"git mv ",
"git merge ",
"git push ",
"git pull ",
"git rebase ",
"git remote ",
"git reset ",
"git show ",
"git stash ",
"git status ",
"git tag ",
SS_LCTL(SS_LALT(SS_TAP(X_HOME)))"\t ",
SS_LCTL(SS_LALT(SS_TAP(X_HOME)))"\t\t\t ",
SS_LCTL(SS_LALT(SS_TAP(X_HOME)))SS_LALT("\t")
// Declare the strings in PROGMEM using the convenience macro
CUSTOM_MACROS(CUSTOM_DEF, CUSTOM_MACRO_STRING, SEMI_DELIM);
static const char* const custom_macros[] PROGMEM = {
// Declare the pointer to the strings in PROGMEM
CUSTOM_MACROS(CUSTOM_VAR, DROP, COMMA_DELIM)
};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
@ -34,26 +13,37 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
case LOWER:
if(record->event.pressed) {
layer_on(_LW);
update_tri_layer(_LW, _RS, _MS);
} else {
layer_off(_LW);
update_tri_layer(_LW, _RS, _MS);
}
update_tri_layer(_LW, _RS, _MS);
return false;
case RAISE:
if(record->event.pressed) {
layer_on(_RS);
update_tri_layer(_LW, _RS, _MS);
} else {
layer_off(_RS);
update_tri_layer(_LW, _RS, _MS);
}
update_tri_layer(_LW, _RS, _MS);
return false;
case GIT_ADD...MC_ATRD:
case (MC_first + 1)...(MC_last - 1):
if(record->event.pressed) {
// The calculation here is to make sure that the custom keycode
// aligns with the git_macros array.
send_string(git_macros[keycode - GIT_ADD]);
send_string_P(
#if defined(__AVR__)
// The accessor here first reads from the pointer array that is located
// in PROGMEM. The pointer is taken and passed to the send_string_P
// function, which is aware of the difference between RAM and PROGMEM
// pointers.
(char*)pgm_read_word(&custom_macros[keycode - MC_first - 1])
#else
// For non-AVR MCUs, the PROGMEM macro is defined as nothing. So, the strings are
// declared in RAM instead of flash. The send_string_P function, when compiled for
// non-AVR targets, uses a different definition of pgm_read_byte internally. This
// definition uses RAM pointers instead. This is why the raw pointer is passed for
// non-AVR MCUs.
custom_macros[keycode - MC_first - 1]
#endif
);
return true;
}
return false;

View File

@ -8,33 +8,13 @@ enum custom_keycodes {
LOWER = SAFE_RANGE,
RAISE,
// Git Keycodes
GIT_ADD, // Add
GIT_BRC, // Branch
GIT_CHK, // Checkout
GIT_CHR, // Cherry-Pick
GIT_CMT, // Commit
GIT_DIF, // Diff
GIT_FTC, // Fetch
GIT_GRP, // Grep
GIT_LOG, // Log
GIT_INT, // Init
GIT_MRG, // Merge
GIT_MOV, // Move (mv)
GIT_PSH, // Push
GIT_PUL, // Pull
GIT_RBS, // Rebase
GIT_RMT, // Remote
GIT_RST, // Reset
GIT_SHW, // Show
GIT_STH, // Stash
GIT_STS, // Status
GIT_TAG, // Tag
// Remote Desktop
MC_MRD7, // Minimize Remote Desktop on Windows 7
MC_MRD8, // Minimize Remote Desktop on Windows 8+
MC_ATRD // Switch windows on local machine from Remote Desktop on Windows
MC_first,
// Macro Keycodes
CUSTOM_MACROS(CUSTOM_ENUM, DROP, COMMA_DELIM),
MC_last
};
enum custom_layers {

View File

@ -1,7 +1,6 @@
#pragma once
#include "csc027.h"
#define MC_LCAD LCA(KC_DEL) // Control-Alt-Delete
#define MC_RSFE RSFT_T(KC_ENT) // Right Shift on hold, Enter on tap
#define MC_LSEC LSFT_T(KC_ESC) // Left Shift on hold, Escape on tap
@ -85,15 +84,15 @@
* `-----------------------------------' `-----------------------------------'
*/
#define ______________________RAISE_L1_____________________ KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC
#define ______________________RAISE_L2_____________________ _______, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_CAPS
#define ______________________RAISE_L3_____________________ _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5
#define ______________________RAISE_L4_____________________ _______, _______, _______, _______, _______, _______
#define ______________________RAISE_L1_____________________ KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC
#define ______________________RAISE_L2_____________________ _______, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_CAPS
#define ______________________RAISE_L3_____________________ _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5
#define ______________________RAISE_L4_____________________ _______, _______, _______, _______, _______, _______
#define ______________________RAISE_R1_____________________ KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DELT
#define ______________________RAISE_R2_____________________ KC_HOME, KC_PGDN, KC_PGUP, KC_END, XXXXXXX, XXXXXXX
#define ______________________RAISE_R3_____________________ KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, _______
#define ______________________RAISE_R4_____________________ _______, _______, _______, _______, XXXXXXX, XXXXXXX
#define ______________________RAISE_R1_____________________ KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DELT
#define ______________________RAISE_R2_____________________ KC_HOME, KC_PGDN, KC_PGUP, KC_END, XXXXXXX, XXXXXXX
#define ______________________RAISE_R3_____________________ KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, _______
#define ______________________RAISE_R4_____________________ _______, _______, _______, _______, XXXXXXX, XXXXXXX
/* Lower Layer
*
@ -118,15 +117,15 @@
* `-----------------------------------' `-----------------------------------'
*/
#define ______________________LOWER_L1_____________________ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5
#define ______________________LOWER_L2_____________________ _______, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, XXXXXXX
#define ______________________LOWER_L3_____________________ _______, KC_F11, KC_F12, XXXXXXX, XXXXXXX, XXXXXXX
#define ______________________LOWER_L4_____________________ _______, _______, _______, _______, _______, _______
#define ______________________LOWER_L1_____________________ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5
#define ______________________LOWER_L2_____________________ _______, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, XXXXXXX
#define ______________________LOWER_L3_____________________ _______, KC_F11, KC_F12, XXXXXXX, XXXXXXX, XXXXXXX
#define ______________________LOWER_L4_____________________ _______, _______, _______, _______, _______, _______
#define ______________________LOWER_R1_____________________ KC_6, KC_7, KC_8, KC_9, KC_0, KC_DELT
#define ______________________LOWER_R2_____________________ KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, XXXXXXX, XXXXXXX
#define ______________________LOWER_R3_____________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______
#define ______________________LOWER_R4_____________________ _______, _______, _______, _______, XXXXXXX, XXXXXXX
#define ______________________LOWER_R1_____________________ KC_6, KC_7, KC_8, KC_9, KC_0, KC_DELT
#define ______________________LOWER_R2_____________________ KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, XXXXXXX, XXXXXXX
#define ______________________LOWER_R3_____________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______
#define ______________________LOWER_R4_____________________ _______, _______, _______, _______, XXXXXXX, XXXXXXX
/* MIT Layout (Mouse)
@ -144,15 +143,15 @@
* `-----------------------------------' `-----------------------------------'
*/
#define ______________________MOUSE_L1_____________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
#define ______________________MOUSE_L2_____________________ _______, XXXXXXX, XXXXXXX, KC_BTN1, KC_BTN2, XXXXXXX
#define ______________________MOUSE_L3_____________________ _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
#define ______________________MOUSE_L4_____________________ _______, _______, _______, _______, _______, _______
#define ______________________MOUSE_L1_____________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
#define ______________________MOUSE_L2_____________________ _______, XXXXXXX, XXXXXXX, KC_BTN1, KC_BTN2, XXXXXXX
#define ______________________MOUSE_L3_____________________ _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
#define ______________________MOUSE_L4_____________________ _______, _______, _______, _______, _______, _______
#define ______________________MOUSE_R1_____________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
#define ______________________MOUSE_R2_____________________ KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, XXXXXXX, XXXXXXX
#define ______________________MOUSE_R3_____________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______
#define ______________________MOUSE_R4_____________________ _______, _______, _______, _______, XXXXXXX, XXXXXXX
#define ______________________MOUSE_R1_____________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
#define ______________________MOUSE_R2_____________________ KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, XXXXXXX, XXXXXXX
#define ______________________MOUSE_R3_____________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______
#define ______________________MOUSE_R4_____________________ _______, _______, _______, _______, XXXXXXX, XXXXXXX
/* MIT Layout (Git)
*
@ -169,49 +168,103 @@
* `-----------------------------------' `-----------------------------------'
*/
#define _______________________GIT_L1______________________ XXXXXXX, GIT_CHR, GIT_SHW, GIT_RBS, GIT_RST, GIT_TAG
#define _______________________GIT_L2______________________ _______, GIT_ADD, GIT_STS, GIT_DIF, GIT_FTC, GIT_GRP
#define _______________________GIT_L3______________________ _______, XXXXXXX, XXXXXXX, GIT_CMT, GIT_MOV, GIT_BRC
#define _______________________GIT_L4______________________ _______, _______, _______, _______, _______, _______
#define _______________________GIT_L1______________________ XXXXXXX, MC_cherrypick, MC_show, MC_rebase, MC_reset, MC_tag
#define _______________________GIT_L2______________________ _______, MC_add, MC_status, MC_diff, MC_fetch, MC_grep
#define _______________________GIT_L3______________________ _______, XXXXXXX, XXXXXXX, MC_commit, MC_mv, MC_branch
#define _______________________GIT_L4______________________ _______, _______, _______, _______, _______, _______
#define _______________________GIT_R1______________________ XXXXXXX, GIT_PUL, GIT_INT, GIT_RMT, GIT_PSH, XXXXXXX
#define _______________________GIT_R2______________________ GIT_STH, XXXXXXX, GIT_CHK, GIT_LOG, XXXXXXX, XXXXXXX
#define _______________________GIT_R3______________________ XXXXXXX, GIT_MRG, XXXXXXX, XXXXXXX, XXXXXXX, _______
#define _______________________GIT_R4______________________ _______, _______, _______, _______, XXXXXXX, XXXXXXX
#define _______________________GIT_R1______________________ XXXXXXX, MC_pull, MC_init, MC_remote, MC_push, XXXXXXX
#define _______________________GIT_R2______________________ MC_stash, XXXXXXX, MC_checkout, MC_log, XXXXXXX, XXXXXXX
#define _______________________GIT_R3______________________ XXXXXXX, MC_merge, XXXXXXX, XXXXXXX, XXXXXXX, _______
#define _______________________GIT_R4______________________ _______, _______, _______, _______, XXXXXXX, XXXXXXX
/* MIT Layout (Convenience)
*
* The Convenience layer adds a tenkey and miscellaneous chords to the keyboard.
* The lack of a fifth row means that some of the tenkey's functions need to be
* moved to the left of tenkey from the top.
* The Convenience layer adds miscellaneous chords to the keyboard.
*
* - The Number Lock key is physically in the same spot as the Caps Lock key
* in the raise layer.
* - There is also a Backspace Key for convenience.
* - There is a convenience macro to type the Control-Alt-Delete login chord for Windows.
* - There is a convenience macro to Minimize Remote Desktop within Remote Desktop
* in Windows.
* - There is a convenience macro to cycle through programs in Windows.
* - There is a convenience macro to go to the previous program in Windows.
* - There is a convenience macro to switch context from the Remote Desktop to the local
* machine in Windows.
* - There are convenience macros to switch between virtual desktops in Windows.
* - There are convenience macros to create and delete virtual desktops in Windows.
*
* ,-----------------------------------. ,-----------------------------------.
* | | |Insrt|ScrLk|PrtSc| | | * | 7 | 8 | 9 | - |BkSpc|
* | | |Insrt|ScrLk|PrtSc| | | | | | | |BkSpc|
* |-----------------------------------| |-----------------------------------|
* | | | App | LCAD|MRDP7|NmLck| | / | 4 | 5 | 6 | + | |
* | | | App | LCAD|MRDCC|NmLck| |MVTDL|MVTDC|MVTDN|MVTDR| | |
* |-----------------------------------| |-----------------------------------|
* | | | | ATRD|MRDP8| | | | 1 | 2 | 3 |Enter| |
* | | | | | | | | | | | | | |
* |-----------------------------------| |-----------------------------------|
* | | | | | | | | | 0 | 0 | . | | |
* | | | | | | | | | | | | | |
* `-----------------------------------' `-----------------------------------'
*/
#define ___________________CONVENIENCE_L1__________________ XXXXXXX, XXXXXXX, KC_INS, KC_SLCK, KC_PSCR, XXXXXXX
#define ___________________CONVENIENCE_L2__________________ _______, XXXXXXX, KC_APP, MC_LCAD, MC_MRD7, KC_NLCK
#define ___________________CONVENIENCE_L3__________________ _______, XXXXXXX, XXXXXXX, MC_ATRD, MC_MRD8, XXXXXXX
#define ___________________CONVENIENCE_L4__________________ _______, _______, _______, _______, _______, _______
#define ___________________CONVENIENCE_L1__________________ XXXXXXX, XXXXXXX, KC_INS, KC_SLCK, KC_PSCR, XXXXXXX
#define ___________________CONVENIENCE_L2__________________ _______, XXXXXXX, KC_APP, MC_lcad, MC_rdcc, KC_NLCK
#define ___________________CONVENIENCE_L3__________________ _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
#define ___________________CONVENIENCE_L4__________________ _______, _______, _______, _______, _______, _______
#define ___________________CONVENIENCE_R1__________________ KC_PAST, KC_P7, KC_P8, KC_P9, KC_PMNS, KC_BSPC
#define ___________________CONVENIENCE_R2__________________ KC_PSLS, KC_P4, KC_P5, KC_P6, KC_PPLS, XXXXXXX
#define ___________________CONVENIENCE_R3__________________ XXXXXXX, KC_P1, KC_P2, KC_P3, KC_PENT, _______
#define ___________________CONVENIENCE_R4__________________ _______, KC_P0, KC_P0, KC_PDOT, XXXXXXX, XXXXXXX
#define ___________________CONVENIENCE_R1__________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_BSPC
#define ___________________CONVENIENCE_R2__________________ MC_vtdl, MC_vtdc, MC_vtdn, MC_vtdr, XXXXXXX, XXXXXXX
#define ___________________CONVENIENCE_R3__________________ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______
#define ___________________CONVENIENCE_R4__________________ _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
/* Convenience macros
*
* These are accelerator macros for simplifying declaration of PROGMEM strings
*/
// Declare variable name
#define CUSTOM_VAR(VAR) mc_##VAR
// Declare PROGMEM string using the variable name
#define CUSTOM_DEF(VAR) const char CUSTOM_VAR(VAR)[] PROGMEM =
// Declare enum name
#define CUSTOM_ENUM(VAR) MC_##VAR
#define CUSTOM_MACRO_STRING(X) X
#define COMMA_DELIM(...) ,
#define SEMI_DELIM(...) ;
#define DROP(...)
/* Keycode synchronization macros
*
* These macros help synchronize the keycodes between the string declaration, string pointer declaration, and enum order.
*/
#define CUSTOM_MACROS(CUSTOM_NAME, CUSTOM_STRING, CUSTOM_DELIM) \
CUSTOM_NAME(add) CUSTOM_STRING("git add ") CUSTOM_DELIM() \
CUSTOM_NAME(branch) CUSTOM_STRING("git branch ") CUSTOM_DELIM() \
CUSTOM_NAME(checkout) CUSTOM_STRING("git checkout ") CUSTOM_DELIM() \
CUSTOM_NAME(cherrypick) CUSTOM_STRING("git cherry-pick ") CUSTOM_DELIM() \
CUSTOM_NAME(commit) CUSTOM_STRING("git commit -m \"\""SS_TAP(X_LEFT)) CUSTOM_DELIM() \
CUSTOM_NAME(diff) CUSTOM_STRING("git diff ") CUSTOM_DELIM() \
CUSTOM_NAME(fetch) CUSTOM_STRING("git fetch ") CUSTOM_DELIM() \
CUSTOM_NAME(grep) CUSTOM_STRING("git grep ") CUSTOM_DELIM() \
CUSTOM_NAME(log) CUSTOM_STRING("git log --decorate --oneline --graph ") CUSTOM_DELIM() \
CUSTOM_NAME(init) CUSTOM_STRING("git init ") CUSTOM_DELIM() \
CUSTOM_NAME(mv) CUSTOM_STRING("git mv ") CUSTOM_DELIM() \
CUSTOM_NAME(merge) CUSTOM_STRING("git merge ") CUSTOM_DELIM() \
CUSTOM_NAME(push) CUSTOM_STRING("git push ") CUSTOM_DELIM() \
CUSTOM_NAME(pull) CUSTOM_STRING("git pull ") CUSTOM_DELIM() \
CUSTOM_NAME(rebase) CUSTOM_STRING("git rebase ") CUSTOM_DELIM() \
CUSTOM_NAME(remote) CUSTOM_STRING("git remote ") CUSTOM_DELIM() \
CUSTOM_NAME(reset) CUSTOM_STRING("git reset ") CUSTOM_DELIM() \
CUSTOM_NAME(show) CUSTOM_STRING("git show ") CUSTOM_DELIM() \
CUSTOM_NAME(stash) CUSTOM_STRING("git stash ") CUSTOM_DELIM() \
CUSTOM_NAME(status) CUSTOM_STRING("git status ") CUSTOM_DELIM() \
CUSTOM_NAME(tag) CUSTOM_STRING("git tag ") CUSTOM_DELIM() \
CUSTOM_NAME(rdcc) CUSTOM_STRING(SS_LCTL(SS_LALT(SS_TAP(X_HOME)))) CUSTOM_DELIM() \
CUSTOM_NAME(lcad) CUSTOM_STRING(SS_LCTL(SS_LALT(SS_TAP(X_DELETE)))) CUSTOM_DELIM() \
CUSTOM_NAME(vtdl) CUSTOM_STRING(SS_LCTL(SS_LGUI(SS_TAP(X_LEFT)))) CUSTOM_DELIM() \
CUSTOM_NAME(vtdc) CUSTOM_STRING(SS_LCTL(SS_LGUI(SS_TAP(X_F4)))) CUSTOM_DELIM() \
CUSTOM_NAME(vtdn) CUSTOM_STRING(SS_LCTL(SS_LGUI("d"))) CUSTOM_DELIM() \
CUSTOM_NAME(vtdr) CUSTOM_STRING(SS_LCTL(SS_LGUI(SS_TAP(X_RIGHT))))