Word selection QMK macro
Pascal Getreuer, 2021-11-12 (updated 2022-02-20)
Overview
This post describes a QMK macro for a button that selects the current
word, assuming conventional text editing hotkeys. Press it again to
extend the selection to the following word. The effect is similar to
word selection (W
) in the Kakoune editor.
Line selection: Similarly, press the button with shift to select the current line, and press it again to extend the selection to the following line.
Clearing the selection: During a selection, press Esc to make the macro tap right arrow → to deselect and leave the cursor at the end of the selection. Or press ← or → directly to deselect and choose which selection endpoint to jump the cursor to.
Add it to your keymap
If you are new to QMK macros, see my macro buttons post for an intro.
Step 1: In your keymap.c
, add a custom
keycode for activating the macro and use the new keycode somewhere in
your layout. I’ll name it SELWORD
, but you can call it
anything you like.
enum custom_keycodes {
= SAFE_RANGE,
SELWORD // Other custom keys...
};
Step 2: Handle the macro from your
process_record_user()
function by calling
process_select_word()
, passing your custom keycode as the
third argument:
#include "features/select_word.h"
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
if (!process_select_word(keycode, record, SELWORD)) { return false; }
// Your macros ...
return true;
}
Step 3: In your rules.mk
file, add
SRC += features/select_word.c
Step 4: In the directory containing your
keymap.c
, create a features
subdirectory and
copy select_word.h
and select_word.c
there. This is the meat of the implementation.
Note for Mac users: The implementation assumes
Windows/Linux editing hotkeys by default. Uncomment the
#define MAC_HOTKEYS
line in select_word.c
for
Mac hotkeys. The Mac implementation is untested, let me know if it has
problems.
Idle timeout
Optionally, Select Word may be configured to clear its internal state
if the keyboard is idle for some time. This is useful to improve
behavior when using Select Word and a mouse together. In your config.h,
define SELECT_WORD_TIMEOUT
with a time in milliseconds:
#define SELECT_WORD_TIMEOUT 2000 // When idle, clear state after 2 seconds.
and in your keymap.c, define (or add to)
matrix_scan_user()
as
void matrix_scan_user(void) {
();
select_word_task// Other tasks...
}
The default behavior (when SELECT_WORD_TIMEOUT
isn’t
set, or set to 0) is that Select Word never times out, and in this case
it isn’t necessary to call select_word_task()
.
Explanation
The macro checks for events involving sel_keycode
. For
word selection, the first press of the macro sends the keys
Ctrl+→, Ctrl+← to move the cursor to
the beginning of the word, then holds Ctrl+Shift+→ to
select to the end of the word. On subsequent presses,
Ctrl+Shift+→ is pressed again to extend the selection
to the next word.
For line selection, the macro sends Home, Shift+End on the first press, then ↓ on subsequent presses.
The state
variable keeps track of whether the macro has
done the initial press and whether it is making a word vs. line
selection.