<spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> KC_TRNS;</span><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Defer to default definitions.</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>The <code>keycode</code> and <code>mods</code> args are the keycode and mods that were active with the last pressed key. The meaning of the return value from this function is:</p><ul><li><code>KC_NO</code>– do nothing (any predefined alternate key is not used);</li><li><code>KC_TRNS</code>– use the default alternate key if it exists;</li><li>anything else – use the specified keycode. Any keycode may be returned as an alternate key, including custom keycodes.</li></ul><p>Another example, defining Shift + Tab as the alternate of Tab, and vice versa:</p><divclass="language-c vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">c</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><spanstyle="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> get_alt_repeat_key_keycode_user</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint8_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> mods</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
<spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (shifted) {</span><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // If the last key was Shift + Tab,</span></span>
<spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> KC_TAB;</span><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // ... the reverse is Tab.</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">else</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Otherwise, the last key was Tab,</span></span>
<spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><spanstyle="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> S</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(KC_TAB);</span><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // ... and the reverse is Shift + Tab.</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h4id="eliminating-sfbs"tabindex="-1">Eliminating SFBs <aclass="header-anchor"href="#eliminating-sfbs"aria-label="Permalink to "Eliminating SFBs""></a></h4><p>Alternate Repeat can be configured more generally to perform an action that "complements" the last key. Alternate Repeat is not limited to reverse repeating, and it need not be symmetric. You can use it to eliminate cases of same-finger bigrams in your layout, that is, pairs of letters typed by the same finger. The following addresses the top 5 same-finger bigrams in English on QWERTY, so that for instance "<code>ed</code>" may be typed as <kbd>E</kbd>, <kbd>Alt Repeat</kbd>.</p><divclass="language-c vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">c</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><spanstyle="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> get_alt_repeat_key_keycode_user</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint8_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> mods</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h4id="typing-shortcuts"tabindex="-1">Typing shortcuts <aclass="header-anchor"href="#typing-shortcuts"aria-label="Permalink to "Typing shortcuts""></a></h4><p>A useful possibility is having Alternate Repeat press <ahref="./../feature_macros">a macro</a>. This way macros can be used without having to dedicate keys to them. The following defines a couple shortcuts.</p><ul><li>Typing <kbd>K</kbd>, <kbd>Alt Repeat</kbd> produces "<code>keyboard</code>," with the initial "<code>k</code>" typed as usual and the "<code>eybord</code>" produced by the macro.</li><li>Typing <kbd>.</kbd>, <kbd>Alt Repeat</kbd> produces "<code>../</code>," handy for "up directory" on the shell. Similary, <kbd>.</kbd> types the initial "<code>.</code>" and "<code>./</code>" is produced by the macro.</li></ul><divclass="language-c vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">c</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">enum</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> custom_keycodes {</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h2id="ignoring-certain-keys-and-mods"tabindex="-1">Ignoring certain keys and mods <aclass="header-anchor"href="#ignoring-certain-keys-and-mods"aria-label="Permalink to "Ignoring certain keys and mods""></a></h2><p>In tracking what is "the last key" to be repeated or alternate repeated, modifier and layer switch keys are always ignored. This makes it possible to set some mods and change layers between pressing a key and repeating it. By default, all other (non-modifier, non-layer switch) keys are remembered so that they are eligible for repeating. To configure additional keys to be ignored, define <code>remember_last_key_user()</code> in your keymap.c.</p><h4id="ignoring-a-key"tabindex="-1">Ignoring a key <aclass="header-anchor"href="#ignoring-a-key"aria-label="Permalink to "Ignoring a key""></a></h4><p>The following ignores the Backspace key:</p><divclass="language-c vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">c</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><spanstyle="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> remember_last_key_user</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><spanstyle="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">keyrecord_t</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> record</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><spanstyle="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Other keys can be repeated.</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>Then for instance, the Repeat key in <kbd>Left Arrow</kbd>, <kbd>Backspace</kbd>, <kbd>Repeat</kbd> sends Left Arrow again instead of repeating Backspace.</p><p>The <code>remember_last_key_user()</code> callback is called on every key press excluding modifiers and layer switches. Returning true indicates the key is remembered, while false means it is ignored.</p><h4id="filtering-remembered-mods"tabindex="-1">Filtering remembered mods <aclass="header-anchor"href="#filtering-remembered-mods"aria-label="Permalink to "Filtering remembered mods""></a></h4><p>The <code>remembered_mods</code> arg represents the mods that will be remembered with this key. It can be modified to forget certain mods. This may be useful to forget capitalization when repeating shifted letters, so that "Aaron" does not becom "AAron":</p><divclass="language-c vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">c</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><spanstyle="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> remember_last_key_user</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><spanstyle="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">keyrecord_t</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> record</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<spanclass="line"><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Forget Shift on letter keys when Shift or AltGr are the only mods.</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h4id="further-conditions"tabindex="-1">Further conditions <aclass="header-anchor"href="#further-conditions"aria-label="Permalink to "Further conditions""></a></h4><p>Besides checking the keycode, this callback could also make conditions based on the current layer state (with <code>IS_LAYER_ON(layer)</code>) or mods (<code>get_mods()</code>). For example, the following ignores keys on layer 2 as well as key combinations involving GUI:</p><divclass="language-c vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">c</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><spanstyle="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> remember_last_key_user</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><spanstyle="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">keyrecord_t</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> record</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><spanstyle="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Other keys can be repeated.</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><divclass="tip custom-block"><pclass="custom-block-title">TIP</p><p>See <ahref="./../feature_layers#functions">Layer Functions</a> and <ahref="./../feature_advanced_keycodes#checking-modifier-state">Checking Modifier State</a> for further details.</p></div><h2id="handle-how-a-key-is-repeated"tabindex="-1">Handle how a key is repeated <aclass="header-anchor"href="#handle-how-a-key-is-repeated"aria-label="Permalink to "Handle how a key is repeated""></a></h2><p>By default, pressing the Repeat Key will simply behave as if the last key were pressed again. This also works with macro keys with custom handlers, invoking the macro again. In case fine-tuning is needed for sensible repetition, you can handle how a key is repeated with <code>get_repeat_key_count()</code> within <code>process_record_user()</code>.</p><p>The <code>get_repeat_key_count()</code> function returns a signed count of times the key has been repeated or alternate repeated. When a key is pressed as usual, <code>get_repeat_key_count()</code> is 0. On the first repeat, it is 1, then the second repeat, 2, and so on. Negative counts are used similarly for alternate repeating. For instance supposing <code>MY_MACRO</code> is a custom keycode used in the layout:</p><divclass="language-c vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">c</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">bool</span><spanstyle="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> process_record_user</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><spanstyle="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">keyrecord_t</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">*</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> record</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h2id="handle-how-a-key-is-alternate-repeated"tabindex="-1">Handle how a key is alternate repeated <aclass="header-anchor"href="#handle-how-a-key-is-alternate-repeated"aria-label="Permalink to "Handle how a key is alternate repeated""></a></h2><p>Pressing the Alternate Repeat Key behaves as if the "alternate" of the last pressed key were pressed, if an alternate is defined. To define how a particular key is alternate repeated, use the <code>get_alt_repeat_key_keycode_user()</code> callback as described above to define which keycode to use as its alternate. Beyond this, <code>get_repeat_key_count()</code> may be used in custom handlers to fine-tune behavior when alternate repeating.</p><p>The following example defines <code>MY_MACRO</code> as its own alternate, and specially handles repeating and alternate repeating:</p><divclass="language-c vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">c</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><spanstyle="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> get_alt_repeat_key_keycode_user</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint16_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> keycode</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint8_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> mods</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
<spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;"> case</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> MY_MACRO: </span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> MY_MACRO;</span><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // MY_MACRO is its own alternate.</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h2id="functions"tabindex="-1">Functions <aclass="header-anchor"href="#functions"aria-label="Permalink to "Functions""></a></h2><table><thead><tr><th>Function</th><th>Description</th></tr></thead><tbody><tr><td><code>get_last_keycode()</code></td><td>The last key's keycode, the key to be repeated.</td></tr><tr><td><code>get_last_mods()</code></td><td>Mods to apply when repeating.</td></tr><tr><td><code>set_last_keycode(kc)</code></td><td>Set the keycode to be repeated.</td></tr><tr><td><code>set_last_mods(mods)</code></td><td>Set the mods to apply when repeating.</td></tr><tr><td><code>get_repeat_key_count()</code></td><td>Signed count of times the key has been repeated or alternate repeated.</td></tr><tr><td><code>get_alt_repeat_key_keycode()</code></td><td>Keycode to be used for alternate repeating.</td></tr></tbody></table><h2id="additional-alternate-keys"tabindex="-1">Additional "Alternate" keys <aclass="header-anchor"href="#additional-alternate-keys"aria-label="Permalink to "Additional "Alternate" keys""></a></h2><p>By leveraging <code>get_last_keycode()</code> in macros, it is possible to define additional, distinct "Alternate Repeat"-like keys. The following defines two keys <code>ALTREP2</code> and <code>ALTREP3</code> and implements ten shortcuts with them for common English 5-gram letter patterns, taking inspiration from <ahref="./stenography">Stenotype</a>:</p><table><thead><tr><th>Typing</th><th>Produces</th><th>Typing</th><th>Produces</th></tr></thead><tbody><tr><td><kbd>A</kbd>, <kbd>ALTREP2</kbd></td><td><code>ation</code></td><td><kbd>A</kbd>, <kbd>ALTREP3</kbd></td><td><code>about</code></td></tr><tr><td><kbd>I</kbd>, <kbd>ALTREP2</kbd></td><td><code>ition</code></td><td><kbd>I</kbd>, <kbd>ALTREP3</kbd></td><td><code>inter</code></td></tr><tr><td><kbd>S</kbd>, <kbd>ALTREP2</kbd></td><td><code>ssion</code></td><td><kbd>S</kbd>, <kbd>ALTREP3</kbd></td><td><code>state</code></td></tr><tr><td><kbd>T</kbd>, <kbd>ALTREP2</kbd></td><td><code>their</code></td><td><kbd>T</kbd>, <kbd>ALTREP3</kbd></td><td><code>there</code></td></tr><tr><td><kbd>W</kbd>, <kbd>ALTREP2</kbd></td><td><code>which</code></td><td><kbd>W</kbd>, <kbd>ALTREP3</kbd></td><td><code>would</code></td></tr></tbody></table><divclass="language-c vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">c</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">enum</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> custom_keycodes {</span></span>
<spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><spanstyle="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Other keys can be repeated.</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div></div></div></main><footerclass="VPDocFooter"data-v-39a288b8data-v-09de1c0f><!--[--><!--]--><divclass="edit-info"data-v-09de1c0f><divclass="edit-link"data-v-09de1c0f><aclass="VPLink link vp-external-link-icon no-icon edit-link-button"href="https://github.com/qmk/qmk_firmware/edit/master/docs/features/repeat_key.md"target="_blank"rel="noreferrer"data-v-09de1c0f><!--[--><spanclass="vpi-square-pen edit-link-icon"data-v-09de1c0f></span> Edit this page<!--]--></a></div><!----></div><navclass="prev-next"data-v-09de1c0f><divclass="pager"data-v-09de1c0f><aclass="VPLink link pager-link prev"href="/features/programmable_button"data-v-09de1c0f><!--[--><spanclass="desc"data-v-09de1c0f>Previous page</span><spanclass="title"data-v-09de1c0f>Programmable Button</span><!--]--></a></div><divclass="pager"data-v-09de1c0f><aclass="VPLink link pager-link next"href="/features/space_cadet"data-v-09de1c0f><!--[--><spanclass="desc"data-v-09de1c0f>Next page</span><spanclass="title"data-v-09de1c0f>Space Cadet Shift</span><!--]--></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><!----><!--[--><!--]--></div></div>