repeat_key.md (17429B)
1 # Repeat Key 2 3 The Repeat Key performs the action of the last pressed key. Tapping the Repeat 4 Key after tapping the <kbd>Z</kbd> key types another "`z`." This is useful for 5 typing doubled letters, like the `z` in "`dazzle`": a double tap on <kbd>Z</kbd> 6 can instead be a roll from <kbd>Z</kbd> to <kbd>Repeat</kbd>, which is 7 potentially faster and more comfortable. The Repeat Key is also useful for 8 hotkeys, like repeating Ctrl + Shift + Right Arrow to select by word. 9 10 Repeat Key remembers mods that were active with the last key press. These mods 11 are combined with any additional mods while pressing the Repeat Key. If the last 12 press key was <kbd>Ctrl</kbd> + <kbd>Z</kbd>, then <kbd>Shift</kbd> + 13 <kbd>Repeat</kbd> performs Ctrl + Shift + `Z`. 14 15 ## How do I enable Repeat Key 16 17 In your `rules.mk`, add: 18 19 ```make 20 REPEAT_KEY_ENABLE = yes 21 ``` 22 23 Then pick a key in your keymap and assign it the keycode `QK_REPEAT_KEY` (short 24 alias `QK_REP`). Optionally, use the keycode `QK_ALT_REPEAT_KEY` (short alias 25 `QK_AREP`) on another key. 26 27 ## Keycodes 28 29 |Keycode |Aliases |Description | 30 |-----------------------|---------|-------------------------------------| 31 |`QK_REPEAT_KEY` |`QK_REP` |Repeat the last pressed key | 32 |`QK_ALT_REPEAT_KEY` |`QK_AREP`|Perform alternate of the last key | 33 34 ## Alternate Repeating 35 36 The Alternate Repeat Key performs the "alternate" action of the last pressed key 37 if it is defined. By default, Alternate Repeat is defined for navigation keys to 38 act in the reverse direction. When the last key is the common "select by word" 39 hotkey Ctrl + Shift + Right Arrow, the Alternate Repeat Key performs Ctrl + 40 Shift + Left Arrow, which together with the Repeat Key enables convenient 41 selection by words in either direction. 42 43 Alternate Repeat is enabled with the Repeat Key by default. Optionally, to 44 reduce firmware size, Alternate Repeat may be disabled by adding in config.h: 45 46 ```c 47 #define NO_ALT_REPEAT_KEY 48 ``` 49 50 The following alternate keys are defined by default. See 51 `get_alt_repeat_key_keycode_user()` below for how to change or add to these 52 definitions. Where it makes sense, these definitions also include combinations 53 with mods, like Ctrl + Left ↔ Ctrl + Right Arrow. 54 55 **Navigation** 56 57 |Keycodes |Description | 58 |-----------------------------------|-----------------------------------| 59 |`KC_LEFT` ↔ `KC_RGHT` | Left ↔ Right Arrow | 60 |`KC_UP` ↔ `KC_DOWN` | Up ↔ Down Arrow | 61 |`KC_HOME` ↔ `KC_END` | Home ↔ End | 62 |`KC_PGUP` ↔ `KC_PGDN` | Page Up ↔ Page Down | 63 |`MS_LEFT` ↔ `MS_RGHT` | Mouse Cursor Left ↔ Right | 64 |`MS_UP` ↔ `MS_DOWN` | Mouse Cursor Up ↔ Down | 65 |`MS_WHLL` ↔ `MS_WHLR` | Mouse Wheel Left ↔ Right | 66 |`MS_WHLU` ↔ `MS_WHLD` | Mouse Wheel Up ↔ Down | 67 68 **Misc** 69 70 |Keycodes |Description | 71 |-----------------------------------|-----------------------------------| 72 |`KC_BSPC` ↔ `KC_DEL` | Backspace ↔ Delete | 73 |`KC_LBRC` ↔ `KC_RBRC` | `[` ↔ `]` | 74 |`KC_LCBR` ↔ `KC_RCBR` | `{` ↔ `}` | 75 76 **Media** 77 78 |Keycodes |Description | 79 |-----------------------------------|-----------------------------------| 80 |`KC_WBAK` ↔ `KC_WFWD` | Browser Back ↔ Forward | 81 |`KC_MNXT` ↔ `KC_MPRV` | Next ↔ Previous Media Track | 82 |`KC_MFFD` ↔ `KC_MRWD` | Fast Forward ↔ Rewind Media | 83 |`KC_VOLU` ↔ `KC_VOLD` | Volume Up ↔ Down | 84 |`KC_BRIU` ↔ `KC_BRID` | Brightness Up ↔ Down | 85 86 **Hotkeys in Vim, Emacs, and other programs** 87 88 |Keycodes |Description | 89 |-----------------------------------|-----------------------------------| 90 |mod + `KC_F` ↔ mod + `KC_B` | Forward ↔ Backward | 91 |mod + `KC_D` ↔ mod + `KC_U` | Down ↔ Up | 92 |mod + `KC_N` ↔ mod + `KC_P` | Next ↔ Previous | 93 |mod + `KC_A` ↔ mod + `KC_E` | Home ↔ End | 94 |mod + `KC_O` ↔ mod + `KC_I` | Vim jump list Older ↔ Newer | 95 |`KC_J` ↔ `KC_K` | Down ↔ Up | 96 |`KC_H` ↔ `KC_L` | Left ↔ Right | 97 |`KC_W` ↔ `KC_B` | Forward ↔ Backward by Word | 98 99 (where above, "mod" is Ctrl, Alt, or GUI) 100 101 102 ## Defining alternate keys 103 104 Use the `get_alt_repeat_key_keycode_user()` callback to define the "alternate" 105 for additional keys or override the default definitions. For example, to define 106 Ctrl + Y as the alternate of Ctrl + Z, and vice versa, add the following in 107 keymap.c: 108 109 ```c 110 uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { 111 if ((mods & MOD_MASK_CTRL)) { // Was Ctrl held? 112 switch (keycode) { 113 case KC_Y: return C(KC_Z); // Ctrl + Y reverses to Ctrl + Z. 114 case KC_Z: return C(KC_Y); // Ctrl + Z reverses to Ctrl + Y. 115 } 116 } 117 118 return KC_TRNS; // Defer to default definitions. 119 } 120 ``` 121 122 The `keycode` and `mods` args are the keycode and mods that were active with the 123 last pressed key. The meaning of the return value from this function is: 124 125 * `KC_NO` – do nothing (any predefined alternate key is not used); 126 * `KC_TRNS` – use the default alternate key if it exists; 127 * anything else – use the specified keycode. Any keycode may be returned 128 as an alternate key, including custom keycodes. 129 130 Another example, defining Shift + Tab as the alternate of Tab, and vice versa: 131 132 ```c 133 uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { 134 bool shifted = (mods & MOD_MASK_SHIFT); // Was Shift held? 135 switch (keycode) { 136 case KC_TAB: 137 if (shifted) { // If the last key was Shift + Tab, 138 return KC_TAB; // ... the reverse is Tab. 139 } else { // Otherwise, the last key was Tab, 140 return S(KC_TAB); // ... and the reverse is Shift + Tab. 141 } 142 } 143 144 return KC_TRNS; 145 } 146 ``` 147 148 #### Eliminating SFBs 149 150 Alternate Repeat can be configured more generally to perform an action that 151 "complements" the last key. Alternate Repeat is not limited to reverse 152 repeating, and it need not be symmetric. You can use it to eliminate cases of 153 same-finger bigrams in your layout, that is, pairs of letters typed by the same 154 finger. The following addresses the top 5 same-finger bigrams in English on 155 QWERTY, so that for instance "`ed`" may be typed as <kbd>E</kbd>, <kbd>Alt 156 Repeat</kbd>. 157 158 ```c 159 uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { 160 switch (keycode) { 161 case KC_E: return KC_D; // For "ED" bigram. 162 case KC_D: return KC_E; // For "DE" bigram. 163 case KC_C: return KC_E; // For "CE" bigram. 164 case KC_L: return KC_O; // For "LO" bigram. 165 case KC_U: return KC_N; // For "UN" bigram. 166 } 167 168 return KC_TRNS; 169 } 170 ``` 171 172 #### Typing shortcuts 173 174 A useful possibility is having Alternate Repeat press [a 175 macro](../feature_macros). This way macros can be used without having to 176 dedicate keys to them. The following defines a couple shortcuts. 177 178 * Typing <kbd>K</kbd>, <kbd>Alt Repeat</kbd> produces "`keyboard`," with the 179 initial "`k`" typed as usual and the "`eybord`" produced by the macro. 180 * Typing <kbd>.</kbd>, <kbd>Alt Repeat</kbd> produces "`../`," handy for "up 181 directory" on the shell. Similarly, <kbd>.</kbd> types the initial "`.`" and 182 "`./`" is produced by the macro. 183 184 ```c 185 enum custom_keycodes { 186 M_KEYBOARD = SAFE_RANGE, 187 M_UPDIR, 188 // Other custom keys... 189 }; 190 191 uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { 192 switch (keycode) { 193 case KC_K: return M_KEYBOARD; 194 case KC_DOT: return M_UPDIR; 195 } 196 197 return KC_TRNS; 198 } 199 200 bool process_record_user(uint16_t keycode, keyrecord_t* record) { 201 switch (keycode) { 202 case M_KEYBOARD: SEND_STRING(/*k*/"eyboard"); break; 203 case M_UPDIR: SEND_STRING(/*.*/"./"); break; 204 } 205 return true; 206 } 207 ``` 208 209 ## Ignoring certain keys and mods 210 211 In tracking what is "the last key" to be repeated or alternate repeated, 212 modifier and layer switch keys are always ignored. This makes it possible to set 213 some mods and change layers between pressing a key and repeating it. By default, 214 all other (non-modifier, non-layer switch) keys are remembered so that they are 215 eligible for repeating. To configure additional keys to be ignored, define 216 `remember_last_key_user()` in your keymap.c. 217 218 #### Ignoring a key 219 220 The following ignores the Backspace key: 221 222 ```c 223 bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, 224 uint8_t* remembered_mods) { 225 switch (keycode) { 226 case KC_BSPC: 227 return false; // Ignore backspace. 228 } 229 230 return true; // Other keys can be repeated. 231 } 232 ``` 233 234 Then for instance, the Repeat key in <kbd>Left Arrow</kbd>, 235 <kbd>Backspace</kbd>, <kbd>Repeat</kbd> sends Left Arrow again instead of 236 repeating Backspace. 237 238 The `remember_last_key_user()` callback is called on every key press excluding 239 modifiers and layer switches. Returning true indicates the key is remembered, 240 while false means it is ignored. 241 242 #### Filtering remembered mods 243 244 The `remembered_mods` arg represents the mods that will be remembered with 245 this key. It can be modified to forget certain mods. This may be 246 useful to forget capitalization when repeating shifted letters, so that "Aaron" 247 does not becom "AAron": 248 249 ```c 250 bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, 251 uint8_t* remembered_mods) { 252 // Forget Shift on letter keys when Shift or AltGr are the only mods. 253 switch (keycode) { 254 case KC_A ... KC_Z: 255 if ((*remembered_mods & ~(MOD_MASK_SHIFT | MOD_BIT(KC_RALT))) == 0) { 256 *remembered_mods &= ~MOD_MASK_SHIFT; 257 } 258 break; 259 } 260 261 return true; 262 } 263 ``` 264 265 #### Further conditions 266 267 Besides checking the keycode, this callback could also make conditions based on 268 the current layer state (with `IS_LAYER_ON(layer)`) or mods (`get_mods()`). For 269 example, the following ignores keys on layer 2 as well as key combinations 270 involving GUI: 271 272 ```c 273 bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, 274 uint8_t* remembered_mods) { 275 if (IS_LAYER_ON(2) || (get_mods() & MOD_MASK_GUI)) { 276 return false; // Ignore layer 2 keys and GUI chords. 277 } 278 279 return true; // Other keys can be repeated. 280 } 281 ``` 282 283 ::: tip 284 See [Layer Functions](../feature_layers#functions) and [Checking Modifier State](../feature_advanced_keycodes#checking-modifier-state) for further details. 285 ::: 286 287 ## Handle how a key is repeated 288 289 By default, pressing the Repeat Key will simply behave as if the last key 290 were pressed again. This also works with macro keys with custom handlers, 291 invoking the macro again. In case fine-tuning is needed for sensible repetition, 292 you can handle how a key is repeated with `get_repeat_key_count()` within 293 `process_record_user()`. 294 295 The `get_repeat_key_count()` function returns a signed count of times the key 296 has been repeated or alternate repeated. When a key is pressed as usual, 297 `get_repeat_key_count()` is 0. On the first repeat, it is 1, then the second 298 repeat, 2, and so on. Negative counts are used similarly for alternate 299 repeating. For instance supposing `MY_MACRO` is a custom keycode used in the 300 layout: 301 302 ```c 303 bool process_record_user(uint16_t keycode, keyrecord_t* record) { 304 switch (keycode) { 305 case MY_MACRO: 306 if (get_repeat_key_count() > 0) { 307 // MY_MACRO is being repeated! 308 if (record->event.pressed) { 309 SEND_STRING("repeat!"); 310 } 311 } else { 312 // MY_MACRO is being used normally. 313 if (record->event.pressed) { 314 SEND_STRING("macro"); 315 } 316 } 317 return false; 318 319 // Other macros... 320 } 321 return true; 322 } 323 ``` 324 325 ## Handle how a key is alternate repeated 326 327 Pressing the Alternate Repeat Key behaves as if the "alternate" of the last 328 pressed key were pressed, if an alternate is defined. To define how a particular 329 key is alternate repeated, use the `get_alt_repeat_key_keycode_user()` callback 330 as described above to define which keycode to use as its alternate. Beyond this, 331 `get_repeat_key_count()` may be used in custom handlers to fine-tune behavior 332 when alternate repeating. 333 334 The following example defines `MY_MACRO` as its own alternate, and specially 335 handles repeating and alternate repeating: 336 337 ```c 338 uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { 339 switch (keycode) { 340 case MY_MACRO: return MY_MACRO; // MY_MACRO is its own alternate. 341 } 342 return KC_TRNS; 343 } 344 345 bool process_record_user(uint16_t keycode, keyrecord_t* record) { 346 switch (keycode) { 347 case MY_MACRO: 348 if (get_repeat_key_count() > 0) { // Repeating. 349 if (record->event.pressed) { 350 SEND_STRING("repeat!"); 351 } 352 } else if (get_repeat_key_count() < 0) { // Alternate repeating. 353 if (record->event.pressed) { 354 SEND_STRING("alt repeat!"); 355 } 356 } else { // Used normally. 357 if (record->event.pressed) { 358 SEND_STRING("macro"); 359 } 360 } 361 return false; 362 363 // Other macros... 364 } 365 return true; 366 } 367 ``` 368 369 370 ## Functions 371 372 | Function | Description | 373 |--------------------------------|------------------------------------------------------------------------| 374 | `get_last_keycode()` | The last key's keycode, the key to be repeated. | 375 | `get_last_mods()` | Mods to apply when repeating. | 376 | `set_last_keycode(kc)` | Set the keycode to be repeated. | 377 | `set_last_mods(mods)` | Set the mods to apply when repeating. | 378 | `get_repeat_key_count()` | Signed count of times the key has been repeated or alternate repeated. | 379 | `get_alt_repeat_key_keycode()` | Keycode to be used for alternate repeating. | 380 381 382 ## Additional "Alternate" keys 383 384 By leveraging `get_last_keycode()` in macros, it is possible to define 385 additional, distinct "Alternate Repeat"-like keys. The following defines two 386 keys `ALTREP2` and `ALTREP3` and implements ten shortcuts with them for common 387 English 5-gram letter patterns, taking inspiration from 388 [Stenotype](stenography): 389 390 391 | Typing | Produces | Typing | Produces | 392 |----------------------------------|----------|----------------------------------|----------| 393 | <kbd>A</kbd>, <kbd>ALTREP2</kbd> | `ation` | <kbd>A</kbd>, <kbd>ALTREP3</kbd> | `about` | 394 | <kbd>I</kbd>, <kbd>ALTREP2</kbd> | `ition` | <kbd>I</kbd>, <kbd>ALTREP3</kbd> | `inter` | 395 | <kbd>S</kbd>, <kbd>ALTREP2</kbd> | `ssion` | <kbd>S</kbd>, <kbd>ALTREP3</kbd> | `state` | 396 | <kbd>T</kbd>, <kbd>ALTREP2</kbd> | `their` | <kbd>T</kbd>, <kbd>ALTREP3</kbd> | `there` | 397 | <kbd>W</kbd>, <kbd>ALTREP2</kbd> | `which` | <kbd>W</kbd>, <kbd>ALTREP3</kbd> | `would` | 398 399 ```c 400 enum custom_keycodes { 401 ALTREP2 = SAFE_RANGE, 402 ALTREP3, 403 }; 404 405 // Use ALTREP2 and ALTREP3 in your layout... 406 407 bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, 408 uint8_t* remembered_mods) { 409 switch (keycode) { 410 case ALTREP2: 411 case ALTREP3: 412 return false; // Ignore ALTREP keys. 413 } 414 415 return true; // Other keys can be repeated. 416 } 417 418 static void process_altrep2(uint16_t keycode, uint8_t mods) { 419 switch (keycode) { 420 case KC_A: SEND_STRING(/*a*/"tion"); break; 421 case KC_I: SEND_STRING(/*i*/"tion"); break; 422 case KC_S: SEND_STRING(/*s*/"sion"); break; 423 case KC_T: SEND_STRING(/*t*/"heir"); break; 424 case KC_W: SEND_STRING(/*w*/"hich"); break; 425 } 426 } 427 428 static void process_altrep3(uint16_t keycode, uint8_t mods) { 429 switch (keycode) { 430 case KC_A: SEND_STRING(/*a*/"bout"); break; 431 case KC_I: SEND_STRING(/*i*/"nter"); break; 432 case KC_S: SEND_STRING(/*s*/"tate"); break; 433 case KC_T: SEND_STRING(/*t*/"here"); break; 434 case KC_W: SEND_STRING(/*w*/"ould"); break; 435 } 436 } 437 438 bool process_record_user(uint16_t keycode, keyrecord_t* record) { 439 switch (keycode) { 440 case ALTREP2: 441 if (record->event.pressed) { 442 process_altrep2(get_last_keycode(), get_last_mods()); 443 } 444 return false; 445 446 case ALTREP3: 447 if (record->event.pressed) { 448 process_altrep3(get_last_keycode(), get_last_mods()); 449 } 450 return false; 451 } 452 453 return true; 454 } 455 ``` 456