Tap Capslock for Escape, Hold for Control
About a month ago I picked up a Dygma raise1: a split, ergonomic keyboard with programable firmware. At some point I’d like to write more about my foray into mechanical, and more specifically split board keebs but for now the most important part is that the Raise has a programmable firmware. Beyond simple rebinds it also allows for dual function keys, layers, and QMK tap dance2 like contextually sensitive bindings.
This is Great! Love it! But every time I’m without my keyboard, and have to work on my laptop’s built-in keyboard I’m actively fighting against muscle memory.
The Past
As a brief detour, I’ve always had at least a few key rebindings.
If a penchant for legend-free key caps and track balls wasn’t enough to deter others from using my computer, keys not doing what you expect should be the cherry on top.
Due to my now complete reliance on Vi bindings - and (Neo)vim in general - I mash the escape button a lot.
To make this more ergonomic for my poor, strained, little, pinky finger I’ve always bound caps-lock to escape.
For the last several years I used a Leopold FC660M. Aside from the lovely tucked in arrow pad on the right corner, it provides a hardware toggle to swap caps-lock with escape.
Much like today I had the same issue of how to make my laptop keyboard more equitable.
A common way3 to accomplish this on this Linux, along with other simple key re-bindings, is to use xmodmap
or setxbmap
4.
If you’re on Gnome you can also just use the cli tool gsettings
, which maps to the keyboard options in Gnome Tweaks5 for simple things like swapping modifier keys.
As mentioned, only good for simple modifier key swaps, and as the name of the executables would imply, only good for XOrg.
Enlightenment
Using my laptop keyboard had become more and more frustrating after being exposed to QMK tap dance via the Ergodox EZ6. In short tap dance lets you define what a key does when tapped, when held, double tapped, tapped then held, etc. etc. Adding tap dance bindings to a key that’s in neutral position reduced my pinky strain and makes the once useless caps-lock a multi function powerhouse.
Both MacOSX, and Windows have decent solutions to arbitrary key rebindings in the form of Karabiner7, and Autohotkey8, respectively. One would expect Linux, in all it’s customizability and open-sourceness would surely have some similar options. Either they didn’t previously exist or I’ve been ignorant to them 9.
By chance I came across KMonad10. The project homepage made promises of being able to do all the things that I wanted, arbitrary key remapping, tap-dance like multi keys, layers. Even better is that I could make these configurations keyboard specific - very import for me as I wanted these to only apply to my ThinkPad’s builtin keyboard11
Surprisingly enough, it delivers on these promises!
KMonad
It’s been a while so let’s summarize what I’m actually trying to accomplish:
- Bind tap
CAPSLOCK
toESC
, as previously done in gnome settings / xmodmap. - Bind hold
CAPSLOCK
toCTRL
. - Bonus: Bind hold
ENTER
toCTRL
, so that the keyboard is symmetrical and both pinkies can benefit and prosper.
I won’t rehash the KMonad getting started docs, which you can find here.
After the initial install, I created my dot-kbd config file by copying one of the template kbd files. KMonad doesn’t automatically source your config file (more on that later) so I’m going to have it live near all my other XDG configs in ~/.config/kmonad/config.kbd.
As previously mentioned, this config is going to be keyboard specific.
For Linux specifically this means identifying the dev file that maps to the targeted keyboard.
I’d suggest using evtest
to test and identify your keyboard.
Hint: Your built-in keyboard is probably something like /dev/input/by-path/*-event-kbd
, so you can also just run find
and pick it out that way.
Having found our keyboard we can finally proceed. Taking this information we specify that this config maps to this input device and produces a virtual keyboard named “KMonad KBD”.
|
|
Next up: we define what the keyboard’s physical layout looks like. All of our subsequent layers will use this as a reference so that we can rebind keys in the same physical location. This is what it looks like for my 2021 ThinkPad X1.
|
|
With the boilerplate layout in place, we can define what we want our multi function keys to do.
We could write this in inline in the layout, but for the sake of legibility we use the kmonad defalias
function to define a new virtual key that we can bind to.
(defalias esc (tap-next-release esc lctl))
(defalias ret (tap-next-release ret rctl))
I’ll quote the kmonad docs to explain what the tap-next-release
function does in more detail, but the short version is it the first argument is the key to bind on tap (esc
), and the second is the key to bind on hold (lctl
), with some special stuff to make it work more predictably on frequently pushed keys.
The `tap-next-release` is like `tap-next`, except it decides whether to tap or hold based on the next release of a key that was not pressed before us. This also performs rollback like `tap-hold`. So, using the minilanguage and foo as: (tap-next-release x lsft) Then: Tesc Ta -> xa Pa Pesc Ra Resc -> ax (because ‘a’ was already pressed when we started, so foo decides it is tapping) Pesc Ta Resc -> A (because a was pressed and released after we started, so foo decides it is holding)
These increasingly stranger buttons are, I think, coming from the stubborn drive of some of my more eccentric (and I mean that in the most positive way) users to make typing with modifiers on the home-row more comfortable. Especially layouts that encourage a lot of rolling motions are nicer to use with the `release` style buttons.
All that’s left to do is to bind these aliases to their desired physical keys:
(deflayer base
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 home end ins del
grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ] \
@esc a s d f g h j k l ; ' @ret
lsft z x c v b n m , . / rsft
lctl lmet lalt spc ralt sys cmp pgup up pgdn
left down right
)
Et, VoilĂ ! All done.
- Bind tap
CAPSLOCK
toESC
- Bind hold
CAPSLOCK
toCTRL
- Bind hold
ENTER
toCTRL
Automatically applying the config on boot
As previously hinted at, KMonad is a daemon that has no preference where you store your config(s). It’s also up to you to start KMonad whenever you want the keyboard mappings to be applied.
There’s lots of way to auto start daemons. For me the easiest way - on Linux, in 2022 - is to create a Systemd user service.
|
|
All you have to do now is enable the service:
systemctl --user enable kmonad.service
https://vim.fandom.com/wiki/Map_caps_lock_to_escape_in_Windows ↩︎
https://superuser.com/questions/519994/how-to-swap-escape-and-caps-lock ↩︎
Gnome tweaks is a GUI application that’s part of the Gnome desktop manager https://wiki.gnome.org/Apps/Tweaks ↩︎
Note that I have used input mapper. I found it okay for keys that I didn’t press frequently, but found that there was a noticeable delay for anything I did a lot. ↩︎
I also have a Keychron K7, which is a lovely, wireless, mechanical keyboard featuring low profile hot swapable optical switches. It’s also pretty cheap, given the feature set, at $84 USD. I would say it’s a near perfect travel keyboard if not for it’s horrendous
INS
key placement, which is only accessible throughFN2+P
key chord, andgrave-tilde
is only accessible throughFN2+ESC
. I get that this sounds like a small gripe, but if it’s not already clear that I’m an insufferable Linux+Vim user, I useShift+INS
a lot in the terminal to paste from the one of Linux’s many clipboards.