This ZMK firmware configuration was forked from urob's zmk-config and consists of a 42-keys layout designed for the Corne. It uses the Colemak keyboard layout, but can be toggled to a modified QWERTY layout for playing games with WASD movement. It is my daily driver for general typing, programming, navigation, and gaming.
The description below is a slight variation of urob's README, edited for my own personal use. Any use of first-person language is from urob's perspective and not my original work.
⌨️ Keymap Image Status: Up to date!
- "Timeless" homerow mods
- Combos replace symbol layer
- Smart numbers and mouse layers auto-toggle off
- Leader key template ready to be customized zmk-helpers
- Arrow-cluster doubles as home, end, begin/end of document on long-press
- More intuitive shift-actions: , ;, . : and ? !
- Gaming layer toggle that switches to a shifted QWERTY layout
- Noticeable delay when tapping HRMs: Increase
require-prior-idle-ms. As a rule of thumb, you want to set it to at least10500/xwherexis your (relaxed) WPM for English prose.1 - False negatives (same-hand): Reduce
tapping-term-ms(or disablehold-trigger-key-positions) - False negatives (cross-hand): Reduce
require-prior-idle-ms(or set flavor tohold-preferred-- to continue usinghold-trigger-on-release, you must also patch ZMK or use an already patched branch) - False positives (same-hand): Increase
tapping-term-ms - False positives (cross-hand): Increase
require-prior-idle-ms(or set flavor totap-preferred, which requires holding HRMs past tapping term to activate)
- The top vertical-combo row matches the symbols on a standard numbers row
(except
+and&being swapped) - The bottom vertical-combo row is symmetric to the top row (subscript
_aligns with superscript^; minus-aligns with+; division/aligns with multiplication*; logical-or|aligns with logical-and&) - Parenthesis, braces, brackets are set up symmetrically as horizontal combos
with
<,>,{and}being accessed from the Navigation layer (or when combined withShift) - Left-hand side combos for
tap,esc,enter,cut(on X + D),copyandpastethat go well with right-handed mouse usage - W + P activates the smart mouse layer
Inspired by Jonas Hietala's Numword for QMK, I implemented my own Auto-layer behavior for ZMK to set up Numword. It is triggered via a single tap on "Smart-Num". Numword continues to be activated as long as I type numbers, and deactivates automatically on any other keypress (holding it activates a non-sticky num layer).
After using Numword for more than a year now, I have been overall very happy with it. When typing single digits, it effectively is a sticky-layer but with the added advantage that I can also use it to type multiple digits.
The main downside is that if a sequence of numbers is immediately followed by
any of the letters on which my numpad is located (WFPRSTXCD), then the automatic
deactivation won't work. But this is rare -- most number sequences are
terminated by space, return or some form of punctuation/delimination. To
deal with the rare cases where they aren't, there is a CANCEL key that
deactivates Numword, Capsword and Smart-mouse. (It also toggles off when pressing
Numword again, but I find it cognitively easier to have a dedicated "off-switch"
than keeping track of which modes are currently active.)
Similarly to Numword, I have a smart-mouse layer (activated by comboing F + P), which adds scroll and mouse-movements, and replaces the right thumbs with mouse buttons. Pressing any other key automatically deactivates the layer.
My left thumb triggers three variations of shift: Tapping after any alpha key yields key-repeat (to reduce SFUs). Tapping after any other keycode yields sticky-shift (used to capitalize alphas). Holding activates a regular shift, and double-tapping (or equivalently shift + tap) activates ZMK's Caps-word behavior.
One minor technical detail: While it would be possible to implement the double-tap functionality as a tap-dance, this would add a delay when using single taps. To avoid the delays, I instead implemented the double-tap functionality as a mod-morph.
To economize on keys, I am using hold-taps on my navigation cluster, which yield
home, end, begin/end of document, and delete word forward/backward on
long-presses. The exact implementation is tweaked so that Ctrl is silently
absorbed in combination with home and end to avoid accidental document-wide
operations (which are accessible via the dedicated begin/end document keys.)
I am using Nick Conway's fantastic
tri-state behavior for a
one-handed Alt-Tab switcher (PWin and NWin).
I recently started using Nick Conway's Leader key implementation for ZMK. From my limited experience, I really like how it allows making less commonly used behaviors accessible without binding them to a dedicated key. For now I am using it for a variety of Unicode math symbols and international characters. I am planning to extend the use to various firmware interactions once I figure out the technical details.
NOTE: See zmk-helpers for instructions on how to set up unicode and international characters for the leader key. As of right now, the leader key has no sequences implemented.
Since I switched from QMK to ZMK I have been very impressed with how easy it is to set up relatively complex layouts in ZMK. For the most parts I don't miss any functionality (to the contrary, I found that ZMK supports many features natively that would require complex user-space implementations in QMK). Below are a few remaining issues:
- ZMK does not yet support "tap-only" combos (#544), requiring a brief pause when wanting to chord HRMs that overlap with combo positions. As a workaround, I implemented all homerow combos as homerow-mod-combos. This is good enough for day-to-day, but does not address all edge cases (eg changing active mods).
- Very minor:
&bootloaderdoesn't work with stm32 boards like the Planck (#1086)
Footnotes
-
E.g, if your WPM is 70 or larger, then the default of 150ms (=10500/70) should work well. The rule of thumb is based on an average character length of 4.7 for English words. Taking into account 1 extra tap for
space, this yields a minimumrequire-prior-idle-msof (60 _ 1000) / (5.7 _ x) ≈ 10500 / x milliseconds. The approximation errs on the safe side, as in practice home row taps tend to be faster than average. ↩