From 061baa1cf05fc396f7fe9d99e1f1499695c01ebc Mon Sep 17 00:00:00 2001 From: Zuckerberg Date: Tue, 24 Mar 2026 19:00:32 -0700 Subject: [PATCH] Add new remap rules: Ctrl+D, Ctrl(+Shift)+P with Xcode-specific bindings, Ctrl+Shift word selection, and Ctrl-as-Cmd for mouse clicks in Xcode/VSCode Co-Authored-By: Claude Opus 4.6 --- keymaps/custom/keymap.c | 81 ++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/keymaps/custom/keymap.c b/keymaps/custom/keymap.c index 72f1a49..914ff20 100644 --- a/keymaps/custom/keymap.c +++ b/keymaps/custom/keymap.c @@ -33,6 +33,9 @@ enum custom_keycodes { #define APP(a) (1 << (a)) #define APP_NOT(a) (APP_ANY & ~APP(a)) +// Rule flags +#define RULE_CANCEL_ON_KEYPRESS (1 << 0) // teardown rewrite if any other key is pressed + typedef struct { uint8_t os_mask; // bitmask of OS modes that match uint8_t app_mask; // bitmask of focused apps that match @@ -40,28 +43,50 @@ typedef struct { uint16_t key_from; // trigger keycode uint8_t mods_to; // replacement modifiers uint16_t key_to; // output keycode (0 = same as trigger key) + uint8_t flags; // RULE_* flags (0 for most rules via partial init) } remap_rule_t; static const remap_rule_t remap_rules[] = { - // --- Copy/paste (Mac) --- - // Ctrl+Shift+C/V -> Cmd+C/V (terminal copy/paste — Ctrl+Shift is the trigger in terminals) - { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_C, MOD_MASK_GUI, 0 }, - { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_V, MOD_MASK_GUI, 0 }, + // --- Ctrl -> Cmd for mouse clicks (Xcode/VSCode on Mac) --- + // Registers Cmd while Ctrl is held alone; any keyboard key cancels it. + // Enables Cmd+click (jump to symbol) via the Ctrl key. + { OS_MAC, APP(APP_XCODE) | APP(APP_VSCODE), 0, KC_LCTL, 0, KC_LGUI, RULE_CANCEL_ON_KEYPRESS }, + { OS_MAC, APP(APP_XCODE) | APP(APP_VSCODE), 0, KC_RCTL, 0, KC_LGUI, RULE_CANCEL_ON_KEYPRESS }, + + // --- Text editing (Mac) --- + // Ctrl+Shift+C/V -> copy/paste (Cmd on Mac, Ctrl on Linux/Windows) + { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_C, MOD_MASK_GUI, 0 }, + { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_V, MOD_MASK_GUI, 0 }, // Ctrl+C/V -> Cmd+C/V (not in terminal — let Ctrl+C = SIGINT through) { OS_MAC, APP_NOT(APP_TERMINAL), MOD_MASK_CTRL, KC_C, MOD_MASK_GUI, 0 }, { OS_MAC, APP_NOT(APP_TERMINAL), MOD_MASK_CTRL, KC_V, MOD_MASK_GUI, 0 }, - - // --- Common Ctrl -> Cmd shortcuts (Mac) --- { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_X, MOD_MASK_GUI, 0 }, // cut { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_A, MOD_MASK_GUI, 0 }, // select all - { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_S, MOD_MASK_GUI, 0 }, // save - { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_F, MOD_MASK_GUI, 0 }, // find + { OS_MAC, APP_NOT(APP_TERMINAL), MOD_MASK_CTRL, KC_D, MOD_MASK_GUI, 0 }, // bookmark / select next occurrence + { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_F, MOD_MASK_GUI, 0 }, // find { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_F, MOD_MASK_GUI | MOD_MASK_SHIFT, 0 }, // find in files + // Word navigation: Ctrl(+Shift)+Left/Right -> Alt(+Shift)+Left/Right + { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_LEFT, MOD_MASK_ALT | MOD_MASK_SHIFT, 0 }, // select word left + { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_RGHT, MOD_MASK_ALT | MOD_MASK_SHIFT, 0 }, // select word right + { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_LEFT, MOD_MASK_ALT, 0 }, // word left + { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_RGHT, MOD_MASK_ALT, 0 }, // word right + // Delete word: Ctrl+Backspace -> Alt+Backspace + { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_BSPC, MOD_MASK_ALT, 0 }, + // Home/End: terminal -> Ctrl+A/E, general -> Cmd+Left/Right + { OS_MAC, APP(APP_TERMINAL), 0, KC_HOME, MOD_MASK_CTRL, KC_A }, + { OS_MAC, APP(APP_TERMINAL), 0, KC_END, MOD_MASK_CTRL, KC_E }, + { OS_MAC, APP_ANY, 0, KC_HOME, MOD_MASK_GUI, KC_LEFT }, + { OS_MAC, APP_ANY, 0, KC_END, MOD_MASK_GUI, KC_RGHT }, + + // --- Common Ctrl -> Cmd shortcuts (Mac) --- + { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_S, MOD_MASK_GUI, 0 }, // save { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_W, MOD_MASK_GUI, 0 }, // close tab { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_L, MOD_MASK_GUI, 0 }, // address bar { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_R, MOD_MASK_GUI, 0 }, // reload - - // --- Undo/redo family: Ctrl -> Cmd, Ctrl+Shift -> Cmd+Shift (Mac) --- + { OS_MAC, APP(APP_XCODE), MOD_MASK_CTRL, KC_P, MOD_MASK_GUI | MOD_MASK_SHIFT, KC_O }, // Xcode: Open Quickly + { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_P, MOD_MASK_GUI, 0 }, // print / quick open + { OS_MAC, APP(APP_XCODE), MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_P, MOD_MASK_GUI | MOD_MASK_SHIFT, KC_A }, // Xcode: Quick Actions + { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_P, MOD_MASK_GUI | MOD_MASK_SHIFT, 0 }, // command palette { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_Z, MOD_MASK_GUI, 0 }, // undo { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_Z, MOD_MASK_GUI | MOD_MASK_SHIFT, 0 }, // redo { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_T, MOD_MASK_GUI, 0 }, // new tab @@ -69,22 +94,9 @@ static const remap_rule_t remap_rules[] = { { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_N, MOD_MASK_GUI, 0 }, // new window { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_SHIFT, KC_N, MOD_MASK_GUI | MOD_MASK_SHIFT, 0 }, // incognito - // --- Arrow key modifier rewrites (Mac) --- - { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_ALT, KC_LEFT, MOD_MASK_CTRL, 0 }, // switch workspace - { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_LEFT, MOD_MASK_ALT, 0 }, // word left - { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_ALT, KC_RGHT, MOD_MASK_CTRL, 0 }, // switch workspace - { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_RGHT, MOD_MASK_ALT, 0 }, // word right - - // --- Delete word (Mac) --- - { OS_MAC, APP_ANY, MOD_MASK_CTRL, KC_BSPC, MOD_MASK_ALT, 0 }, - - // --- Home/End (Mac) --- - // Terminal: Home -> Ctrl+A, End -> Ctrl+E (must be listed before the general rules) - { OS_MAC, APP(APP_TERMINAL), 0, KC_HOME, MOD_MASK_CTRL, KC_A }, - { OS_MAC, APP(APP_TERMINAL), 0, KC_END, MOD_MASK_CTRL, KC_E }, - // General: Home -> Cmd+Left, End -> Cmd+Right - { OS_MAC, APP_ANY, 0, KC_HOME, MOD_MASK_GUI, KC_LEFT }, - { OS_MAC, APP_ANY, 0, KC_END, MOD_MASK_GUI, KC_RGHT }, + // --- Workspace switching (Mac) --- + { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_ALT, KC_LEFT, MOD_MASK_CTRL, 0 }, // switch workspace left + { OS_MAC, APP_ANY, MOD_MASK_CTRL | MOD_MASK_ALT, KC_RGHT, MOD_MASK_CTRL, 0 }, // switch workspace right // --- Alt+F4 -> Cmd+Q (Mac) --- { OS_MAC, APP_ANY, MOD_MASK_ALT, KC_F4, MOD_MASK_GUI, KC_Q }, @@ -117,6 +129,7 @@ typedef struct { uint8_t to_mods; // normalized mods that were added uint8_t saved_mods; // exact get_mods() at press time, for restoration // updated as from-mods are released during hold + uint8_t flags; // propagated from remap_rule_t } active_rewrite_t; static active_rewrite_t active_rw = {0}; @@ -150,7 +163,7 @@ static bool process_rewrite_release(uint16_t keycode, keyrecord_t *record) { } // Apply a rewrite unconditionally (matching already done by caller). -static void apply_rewrite(uint16_t trigger_keycode, uint8_t mods_from, uint8_t mods_to, uint16_t key_out) { +static void apply_rewrite(uint16_t trigger_keycode, uint8_t mods_from, uint8_t mods_to, uint16_t key_out, uint8_t flags) { uint8_t mods = get_mods(); if (active_rw.trigger_keycode) teardown_active_rewrite(); active_rw = (active_rewrite_t){ @@ -159,6 +172,7 @@ static void apply_rewrite(uint16_t trigger_keycode, uint8_t mods_from, uint8_t m .from_mods = normalize_mods(mods_from), .to_mods = normalize_mods(mods_to), .saved_mods = mods, + .flags = flags, }; set_mods(active_rw.to_mods); register_code(key_out); @@ -173,7 +187,7 @@ static bool apply_remap_rules(uint16_t keycode) { if (!((1 << os_mode) & r->os_mask)) continue; if (!((1 << focused_app) & r->app_mask)) continue; if (norm != normalize_mods(r->mods_from)) continue; - apply_rewrite(keycode, r->mods_from, r->mods_to, r->key_to ? r->key_to : keycode); + apply_rewrite(keycode, r->mods_from, r->mods_to, r->key_to ? r->key_to : keycode, r->flags); return true; } return false; @@ -232,7 +246,7 @@ ________________________________________________________________________________ | x | | | | | | | | | | | | PGUP | |________________|________|________|________|________|________|________|________|________|________|________|____________|________|_________ | | | | | | | | | | | | | | - | x | | x | x | | | x | x | x | | HOME | PGDN | END | + | x | | x | x | | | x | x | NOREMAP | | HOME | PGDN | END | |____________|________|_______|________|_________________|_________________|________|________|_____________| |________|________|________| */ @@ -242,7 +256,7 @@ ________________________________________________________________________________ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, - KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_HOME, KC_PGDN, KC_END + KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, CK_NOREMAP, KC_HOME, KC_PGDN, KC_END ), [2] = LAYOUT( @@ -313,6 +327,13 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { // Handle release events for active modifier rewrites (key repeat support) if (!process_rewrite_release(keycode, record)) return false; + // Cancel modifier-only rewrites (e.g. Ctrl->Cmd) when any other key is pressed + if (record->event.pressed && active_rw.trigger_keycode && + (active_rw.flags & RULE_CANCEL_ON_KEYPRESS) && + keycode != active_rw.trigger_keycode) { + teardown_active_rewrite(); + } + // Any other key pressed while GUI held means it's being used as a modifier if (record->event.pressed && keycode != KC_LGUI) { super_tapped = false;