The Planck keyboard uses qmk_firmware and I have my keymap code In the ./configs/keyboard-firmware/planck/ folder. The following section describes my keyboard layout.
Alias | Meaning |
---|---|
C | Ctrl |
S | Shift |
SPC | Space |
RET | Return |
GUI | Win / Super key |
vert | pipe character |
===== | column spacer |
I use x/y
to denote a key that does x when tapped and y when held. For
example, RET/S
performs return when tapped and shift when held.
https://colemakmods.github.io/mod-dh/
I am using the ortho-linear variant of Colemak Mod-DH that switches the m
to the home row with the k
just below it. The reasoning is that m
is much
more frequently used in English and easier to reach.
In addition, I swapped the ,
and the y
. After typing a while on this
layout and getting my average speed close to where it was before switching, I
realize the thing I hate most about the layout is typing the words “you’re”,
“your”, and “you”. The word “you” et al. is one of the most common words in
English and is insanely hard to type in the standard Colemak positions.
You can enter this layout in the keyboard layout analyzer and see this is an
improvement in score on Colemak Mod-DH due to swapping the same-finger
bigrams e,
with the ey
which occurs about half as often. Typing the word
“you” et al. is still not amazing, but it’s much easier than before and with
a minimal change from Colemak Mod-DHm.
===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== |
---|---|---|---|---|---|---|---|---|---|---|---|
Tab | q | w | f | p | b | j | l | u | , | ; | Bksp |
Esc/C | a | r | s | t | g | m | n | e | i | o | ’ |
Shift | z | x | c | d | v | k | h | y | . | / | RET/S |
Ctrl | Num | Super | Alt | Lower | Hyper | SPC | Raise | Alt | GUI | Ctrl |
===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== |
---|---|---|---|---|---|---|---|---|---|---|---|
Tab | q | w | e | r | t | y | u | i | o | p | Bksp |
Esc/C | a | s | d | f | g | h | j | k | l | ; | ’ |
Shift | z | x | c | v | b | n | m | , | . | / | RET/S |
Ctrl | Num | Super | Alt | Lower | Hyper | SPC | Raise | Alt | GUI | Ctrl |
===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | ||
~ | ( | ! | = | ) | { | % | & | } | | | Del | |
< | > | ||||||||||
===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | ||
` | [ | + | - | ] | ^ | * | # | $ | \ | Del | |
< | > | _ | @ | ||||||||
===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | ||
F11 | Home | PgUp | PgDn | End | Left | Down | Up | Right | F12 | Del | |
F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | ||
After some trial and error I found that I like symbols on layers that I activate with my left hand because I often need to delimit them with spaces. I hit the space key with my right thumb, and it’s much easier to delimit things with spaces when that thumb is not having to alternate between holding a layer and inserting spaces.
Number keys are present on all three layers for easy access. Often symbols are accompanied by numbers and its annoying to have to switch layers to hit them. In addition, the raise layer also has numbers mainly for hitting with my left hand without having to hold the layer key down with the same hand.
I have changed most of the positions of symbols. The following explains why:
- Symbols on home row is great for programming and Vim/Evil
- Symbols often used together kept on the same layer to avoid layer alternating.
- Avoid covering
Esc/C
key so I have easy access to theCtrl
key. - Both raise and lower duplicate the
<
and>
keys for easy access since these are often used in combination with other symbols. I still have these available in the normal positions. - Positions motivated by Evil symbol keys:
I decided to mirror
h
,j
,k
,l
(Qwerty) style of Evil movement on the left hand with the same fingers since there are many things bound to symbols that have the notion of back/forward and up/down.Actually, the up and down positions on the left hand are mirrors of the right hand, but the left and right positions or spatially correct. It feels natural to me for the index finger to make things go down and the middle finger to make things go up. I used to hate these positions when I first started learning Vim because they weren’t as natural as the
w
,a
,s
,d
keys. However, horizontal movement usingh
andl
should be rare, if you’re doing it right, and with that in mind down and up on the index and middle finger makes a lot of sense.(
and)
which does back / forward a sentence in Evil bound to left / right positions on left hand.{
and}
which does back / forward a paragraph in Evil bound to left / right positions on right hand.[
and]
which does back / forward a section in Evil bound to left / right positions on left hand.^
and$
which does a soft beginning of line / end of line in Evil bound to left / right positions on left hand.+
and-
which are often associated with increasing and decreasing are bound to the up and down positions on the left hand.*
and#
which does a word search forward / back in Evil bound to down and up positions on the right hand. I used that location because I’m out of left and right positions to use and searching forward/back often jumps down/up, which is close enough mentally for me.!
and=
moved to home keys since their often used together and often used for negation.|
and\
moved over a column to put it on the home keys. This allowsDel
to be moved below backspace, which make key combinations involvingDel
easier to hit.~
and`
moved onto home keys. I mostly only used these with editing markdown and org files. The~
key toggles case in Evil, but I tend to useu
andU
to do that in visual state. The`
goes to a mark in Evil, but I rebind that to a better key.@
moved under right hand index finger. I often use this key along withq
because both are involved with using Evil macros, which I use a lot. I initially thought to leave it close toq
, but double tapping@
to replay the previous macro with my pinky finger would get old fast._
has functionality in Evil I’m aware of, but never use. I only use the key heavily when programming in Rust due to the typical snake case style. The primary reasoning behind it’s location is to being close to-
makes it easier to remember where it’s at since they are visually similar.%
jumps to a matching symbol such as a parenthesis or braces. I put it on the down position key despite it’s behavior not exactly matching that. However, it’s close enough for me.&
repeats a substitute command in Evil, but I never use it. I rebind this toevil-use-register
, which is typically on the quotation mark, because it’s quite annoying to hold shift to hit it and then a layer to hit a number.
I just bind the normal key code for numbers instead of the number pad variant of it because I only use it for entering numbers and I never want to deal with number lock.
===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== | ===== |
---|---|---|---|---|---|---|---|---|---|---|---|
7 | 8 | 9 | - | ||||||||
4 | 5 | 6 | + | ||||||||
1 | 2 | 3 | |||||||||
0 | . |
====== | ====== | ====== | ====== | ====== | ====== | ====== | ====== | ====== | ====== | ||
---|---|---|---|---|---|---|---|---|---|---|---|
MU_MOD | Aud on | Audoff | Qwerty | Colemk | |||||||
Mus on | Musoff | Debug | |||||||||
Reset |
Switching to Colemak keyboard layout has caused me to want to customize the
Evil/Vim key bindings from their defaults. The main motivator is the spread
out positions of h
, j
, k
, and l
keys.
Most people who use Vim/Evil with Colemak either get used to the new positions of things or use something like an extend layer to layer movement keys over the positions of said movement keys. The argument is that you shouldn’t be using those keys much anyways because there are better approaches to movement. In addition, using a keyboard layer makes these movement available to all applications outside of editors and IDEs that provide Evil emulation.
I find these arguments unsatisfactory. I already use most of the better
methods of movement, yet my usage of j
and k
remains quite high despite
using {
, }
, (
, )
, C-u
, C-d
, and avy quite a lot. The letters h
and l
for horizontal movement I use less frequently due to my usage of f/F
(find) and t/T
(till) along with w
, b
, and e
. In addition, we can both
rebind the motion keys and use a layer for Vim like arrow key movement in
other applications.
In my experience needing to go up or down short distances is a common task, and a lot of the time I’m just perusing with no specific target or editing goal in mind. In addition, these keys often provide the semantic equivalent of movement key bindings in various Emacs packages that are not concerned with editing text.
I haven’t actually measured this, but I suspect the frequency of my usage of
j
and k
is quite high. This is why I find the common solutions to Evil +
Colemak unsatisfactory. The same drive to optimize things (and perhaps shave
some Yaks) and learn Colemak is the same one that makes me want to fix this.
Personally, I see the main downside to customizing Evil is the need to replicate the custom keybindings in anything else where I want to use it’s Vim emulation. I think the Emacs package Tramp solves the issue with needing to ssh into a machine. And even without that, I typically have a user profile I could easily add a configuration file to.
So now the question is how far do I take the customization. Even doing the
minimal changes to get my Colemak Mod-DHm (ortho-linear version) keys (m
,
n
, e
, i
) swapped with h
, j
, k
, and l
will incur all the cons I
mentioned above, so why not go all the way? Learning curve might be one reason
to do a minimal fix. However, I personally don’t have a problem investing the
time to get over the learning curve for the sake of ergonomic bindings that
make more sense.
- The tables below heavily uses aliases for the sake of not having to scroll horizontally when viewing this in the browser (at least on my resolution screen).
- The left most column named
state
describes modified states (i.e. holding Shift, Ctrl etc.), keyboard layers, and Evil states. - I use
x/y
to denote a key that does x when tapped and y when held. For example,RET/S
performs return when tapped and shift when held.
Alias | Meaning |
---|---|
C | Ctrl |
GUI | Win / Super key |
M | Alt / Meta |
RET | Return |
S | Shift |
bol | beginning of line |
del | delete |
eof | end of file |
eol | end of line |
ln | line |
mk | mark |
para | paragraph |
rec | record |
rev | reverse |
rpl | replace |
scrn | screen |
sent | sentence |
subst | substitute |
tgl | toggle |
vis | visual |
The following table columns are numbered from high to low frequency of use where zero represents things I practically never use. This is my very rough estimation, which is not based on any gathered data at all.
7 | 6 | 5 | ||
---|---|---|---|---|
j down | p paste after | ; repeat t/T/f/F | ||
k up | P paste before | . repeat cmd | ||
i insert mode | f find | $ eol | ||
a append | t till | 0 hard bol | ||
Esc | F back find | h left | ||
u undo | T back till | l right | ||
C-r redo | w next word | I insert bol | ||
o open below | e end word | A append eol | ||
O open above | b prev word | |||
v vis mode | ||||
V vis lines | ||||
y yank | ||||
Y yank ln | ||||
4 | 3 | 2 | 1 | 0 |
* next id | / find | C-u scroll up | W next WORD | ~ tgl case |
n next | ? rev find | C-d scroll down | E end WORD | ! shell cmd |
N prev | { begin para | J join ln | B prev WORD | Q ex mode |
# prev id | } end para | , rev t/T/f/F | ( begin sent | | bol |
% goto match | > indent | H scrn top | ) end sent | z extra cmds |
G eof | < un-indent | M scrn mid | m set mk | Z quit |
g extra cmds | q rec macro | L scrn bot | ’ goto mk bol | R rpl mode |
d del | @ play macro | : ex cmd line | [ prev sect | s subst char |
r rpl char | ^ soft bol | ] next sect | S subst line | |
x del char | ” reg spec | ` goto mk | ||
c change | X Backspace | |||
D del to eol | ||||
C change to eol |
- I never use substitute and it’s on a home key. I don’t even think that’s a bad habit. I just think substitute is largely has its use-cases covered by more flexible commands.
- I hardly use marks, but that’s more of a bad habit that I can improve.
- I think my frequency of usage largely depends on what I’m doing. I read a lot more than I write so I do a lot of navigating.
- I use begin/end paragraph a lot more when looking at source code because it behaves more predictably than say in an org mode file where it might jump several pages past tables. Ideally I want to replace my usage of this with something more predictable.
- In practice, I think I hardly ever use the next/end/prev
WORD
motions. These motions are all about skipping over symbols to get somewhere faster. However, when I’m moving to a location horizontally with an intention I typically use find/till and;
to repeat.
One thing that seams really apparent to me after going over an iteration of binding custom keys for Colemak is that many of the positions of keys got worse. Vim key bindings are truly designed with Qwerty in mind. Let’s fix that.
The attributes (Attr column) shown in the table below:
Note that absence of an attribute indicates no change. Also note that I’m comparing how things were in Qwerty with defaults to how they are with my custom key map in Colemak-DHm based on my subjective opinion.
s
- A keybinding that remains in the same location for Colemak-DHm as it was in Qwerty. Note table only shows swapped keys so many other keys remain in the same location not shown below.
+
/-
- A keybinding moved to a better / worse location.
M
/m
- indicates a gain of motion synergy with positions of movement keys.
N
/n
- indicates a key moved to a more/less mnemonic position.
c
- indicates a key combined with another key of similar functionality.
P
/p
- indicates a key with a gain/loss in proximity to a key of similar functionality.
x
- indicates a key unbound because it’s not used and deemed not useful.
d
- indicates a key binding duplicated to another key and the old binding remains intact.
g m evil-middle-of-visual-line
function | before | after | new mnemonic | Attr | Commentary |
---|---|---|---|---|---|
substitute | s | x | I don’t use this and its on a home key | ||
subst line | S | x | related to substitute | ||
repeat subst | & | x | related to substitute | ||
rpt gbl subst | g & | x | related to substitute | ||
up | g k | x | Why does these even exist? | ||
down | g j | x | |||
next match | g n | x | Why not just press n? | ||
prev match | g N | x | Why not just press N? | ||
mid visual line | g m | x | can’t imagine I would ever want this | ||
window movements | C-w * | x | 48 C-w * bindings I don’t use | ||
open fold rec | z O | x | I don’t use these fold bindings | ||
toggle fold | z a | x | |||
close fold | z c | x | |||
close folds | z m | x | going to map something else to this key | ||
open fold | z o | x | |||
open folds | z r | x | |||
left | h | m | s | ||
down | j | n | s | ||
up | k | e | s | ||
right | l | i | s | ||
scroll col left | z h | z m | s | ||
scroll left | z H | z M | s | ||
scroll col right | z l | z i | s | ||
scroll right | z L | z I | s | ||
find file at pt | g f | g s | search file at pt | - | need to free up `g f’ |
find file.. w/ ln | g F | g S | search file.. etc | - | need to free up `g F’ |
end WORD | E | F | far WORD | s | foot/forward are other possible mnemonics |
end WORD | g E | g F | far WORD rev | s | foot/forward are other possible mnemonics |
end word | e | f | far word | s | |
end word | g e | g f | far word rev | s | |
find | f | s | search | P | right next to till :) |
rev find | F | S | rev search | P | |
eol | $ | I | +Md | ||
hard bol | 0 | M | +Md | ||
insert mode | i | l | ? | +n | looks like ‘i’ if you squint |
insert bol | I | L | +n | looks like ‘i’ if you squint harder | |
insert resume | g i | g l | +n | ||
visual mode | v | r | range | + | see note below |
visual lines | V | R | range lines | + | |
visual block | C-v | C-r | range block | + | |
visual restore | g v | g r | range restore | + | |
replace | r | v | revise | - | convert is another possible mnemonic |
replace mode | R | V | revise mode | - | |
next | n | h | ? | +n | easier to reach but not mnemonic |
prev | N | H | ? | +n | |
redo | C-r | U | +cn | makes much more sense and easier to do | |
scrn top | H | g e | +Mn | ||
scrn mid | M | g m | +M | ||
scrn low | L | g n | +Mn | ||
scroll down | C-d | C-S-n | -Mn | see note below for rationale | |
scroll up | C-u | C-S-e | -Mn | see note below for rationale | |
set mk | m | k | -n | mnemonic is still mark for me | |
join lines | J | C-j | - | ‘j’ is harder to reach on Colemak | |
goto mk | ` | j | jump | +Nc | easier to reach and now mnemonic |
goto mk ln | ’ | J | jump to line | -Nc | same key as j now, which makes sense to me |
repeat | ; | ’ | - | bring back down to home row due to high use | |
rev repeat | , | ” | -c | , can be used as another leader key | |
last change | g ; | g ’ | -c | ||
last change rev | g , | g ” | -c | ||
reg spec | ” | & | + | Easier for my personal keyboard layout |
I just couldn’t help but remap the visual mode key on to the home keys
because I use it all the time. I definitely use it more than I use the
replace functionality. In addition, notice the finger rolling action from
r
to s
/ t
(in Colemak) to visual/range select till some character.
If I left it where it was it would have been in a worse position compared
to Qwerty, but now it’s better.
I originally rebound scroll up/down keys to N
and E
. However, I instead
decided to bind those keys to a custom evil motion that’s equivalent to
prefixing normal n
and e
movements with 10. This gives me a way to move
up and down at a similar speed to forward/backward paragraph, but much more
reliably. I bind scroll up/down to C-S-e
and C-S-n
respectively because
it allows hold Control and Shift to move vertically quickly and release one
modifier key to reduce speed. The C-n
and C-e
keys are also options,
and are available.
This cheat sheet is an influence to these tables. However, this is not as easy to read since it’s text based and split in half. Note that many of the key are more nuanced than the description might lead one to believe. I also overlay the key-map for my Planck keyboard.
state | col 0 | col 1 | col 2 | col 3 | col 4 | col 5 |
---|---|---|---|---|---|---|
default | Tab | q rec macro | w next word | f far word | p paste after | b prev word |
shift | Q | W next WORD | F far WORD | P paste before | B prev WORD | |
======= | ===== | ============ | =========== | =============== | ============== | ============ |
default | Esc/C | a append | r range mode | s search | t till | g extra cmds |
shift | A append eol | R range lines | S rev search | T back till | G eof | |
lower | ~ tgl case | ( begin sent | ! shell cmd | = | ) end sent | |
raise | ` | [ prev sect | + | - | ] next sect | |
======= | ===== | ============ | =========== | =============== | ============== | ============ |
default | Shift | z extra cmds | x del char | c change | d del | v revise |
shift | Z quit | X Bksp | C change to eol | D del to eol | V revise mode |
state | col 6 | col 7 | col 8 | col 9 | col 10 | col 11 |
---|---|---|---|---|---|---|
default | j jump to mk | l insert mode | u undo | , | ; | Bksp |
shift | J jump mk ln | L insert bol | U redo | < un-indent | : ex cmd line | |
Ctrl | C-j join ln | |||||
======= | ========== | ============= | =========== | ========= | ============= | ===== |
default | m left | n down | e up | i right | o open below | ’ repeat |
shift | M hard bol | N 10 down | E 10 up | I eol | O open above | ” rev repeat |
Alt | n scrn bot | e scrn top | scrn mid | |||
C-S | n scroll down | e scroll up | ||||
lower | { begin para | % goto match | & reg spec | } end para | | goto col | Del |
raise | ^ soft bol | * next id | # prev id | $ eol | \ | Del |
======= | ========== | ============= | =========== | ========= | ============= | ===== |
default | k set mk | h next | y yank | . repeat cmd | / find | RET/S |
shift | K | H prev | Y yank ln | > indent | ? rev find | |
raise | @ play macro |
Here is something I threw together to pretty print and diff the keymaps:
(defun my/keymaps-to-temp-buffer (keymaps buffer-name)
(with-output-to-temp-buffer buffer-name
(mapc (lambda (m)
(princ (format "%s\n\n" m))
(princ (substitute-command-keys (format "\\{%s}" m))))
keymaps)
(with-current-buffer standard-output
(setq help-xref-stack-item (list #'my/keymaps-to-temp-buffer)))))
(setq my/evil-keymaps
'("evil-emacs-state-map"
"evil-insert-state-map"
"evil-motion-state-map"
"evil-normal-state-map"
"evil-operator-state-map"
"evil-replace-state-map"
"evil-visual-state-map"))
(my/keymaps-to-temp-buffer my/evil-keymaps "evil-keymaps-after.txt")
(ediff-buffers "evil-keymaps-before.txt" "evil-keymaps-after.txt")