This is my QMK Kyria keymap, it has some nifty features and an interesting base layer.
The base alpha layer I use is a modified RSTHD, which has some interesting (perhaps dubious), choices. To understand my thought process you can read my Keymap Logs.
Caps word is a feature I came up with a while back that essentially acts as a caps lock key but only for the duration of a “word”.
This makes macros like CAPS_WORD
really easy to type, it feels a lot like using one shot shift, and it pairs very nicely with it.
What defines a “word” is sort of up for debate, I started out with a simple check to see if I had hit space or ESC but found that there were other things I wanted to exit on, like punctuation.
So now I detect whether space
, backspace
, -
, _
, or an alphanumeric is hit, if so we stay in caps word state, if not, it gets disabled. I also check for mod chording with these keys and if you are chording, it will also disable caps word (e.g. on Ctrl+S
).
The actual behavior of when to disable caps word can be tweaked using terminate_case_mode()
.
By default caps lock is used as the underlying capitalization method, however you can also choose to individually shift each keycode as the go out. This is useful for people who have changed the functionality of caps lock at the OS level. To do this simply add #define CAPSWORD_USE_SHIFT
in you config.h.
To use this feature enable_caps_word()
or toggle_caps_word()
can be called from a macro, combo, tap dance, or whatever else you can think of.
- Add capsword.c to your
SRCS
by calling addingSRC += capsword.c
to your rules.mk. - Add
process_case_modes()
to yourprocess_record_user()
, it can either go at the top or the bottom, it depends on how you want it to interact with your keycodes.If you process at the beginning it will look something like this, make sure that you return false when
process_case_modes
returns false.bool process_record_user(uint16_t keycode, keyrecord_t *record) { // Process case modes if (!process_caps_word(keycode, record)) { return false; } ...
- Add ways to enable the modes in your keymap.c, for example you could use custom keycodes (macros):
Remember to always start your custom keycodes at
SAFE_RANGE
.enum custom_keycodes { CAPSWORD = SAFE_RANGE, SNAKECASE, }; bool process_record_user(uint16_t keycode, keyrecord_t *record) { // Process case modes if (!process_caps_word(keycode, record)) { return false; } // Regular user keycode case statement switch (keycode) { case CAPSWORD: if (record->event.pressed) { enable_caps_word(); } return false; default: return true; } }
- (Optional) Change the mode termination conditions by creating a custom
terminate_case_mode()
function in your keymap.c:In the below example I’ve added the macros defined earlier to the terminate function as keycodes to ignore (ie not terminate on).
// Returns true if the case modes should terminate, false if they continue // Note that the keycodes given to this function will be stripped down to // basic keycodes if they are dual function keys. Meaning a modtap on 'a' // will pass KC_A rather than LSFT_T(KC_A). // Case delimiters will also not be passed into this function. bool terminate_case_modes(uint16_t keycode, const keyrecord_t *record) { switch (keycode) { // Keycodes to ignore (don't disable caps word) case KC_A ... KC_Z: case KC_1 ... KC_0: case KC_MINS: case KC_UNDS: case KC_BSPC: case CAPSWORD: case SNAKECASE: // If mod chording disable the mods if (record->event.pressed && (get_mods() != 0)) { return true; } break; default: if (record->event.pressed) { return true; } break; } return false; }
You can of course tweak this to get the exact functionality you want. Some people prefer to use a switch statement where they look for keys to end on, and default to keeping the mode enabled otherwise. I prefer the above method because I would rather exit the mode than stay in it.
- (Optional) Use shift rather than caps lock in caps word. To do this simply add
#define CAPSWORD_USE_SHIFT
in you config.h.