Skip to content

Latest commit

 

History

History
556 lines (455 loc) · 34.3 KB

readme.org

File metadata and controls

556 lines (455 loc) · 34.3 KB

Keyboard Firmware - Planck layout

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.

Key aliases used below

AliasMeaning
CCtrl
SShift
SPCSpace
RETReturn
GUIWin / Super key
vertpipe 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.

Colemak Mod-DHm

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.

============================================================
Tabqwfpbjlu,;Bksp
Esc/Carstgmneio
Shiftzxcdvkhy./RET/S
CtrlNumSuperAltLowerHyperSPCRaiseAltGUICtrl

Qwerty

============================================================
TabqwertyuiopBksp
Esc/Casdfghjkl;
Shiftzxcvbnm,./RET/S
CtrlNumSuperAltLowerHyperSPCRaiseAltGUICtrl

Lower

============================================================
1234567890
~(!=){%&}|Del
<>

Hyper

============================================================
1234567890
`[+-]^*#$\Del
<>_@

Raise

============================================================
1234567890
F11HomePgUpPgDnEndLeftDownUpRightF12Del
F1F2F3F4F5F6F7F8F9F10

Lower, Hyper, and Raise Commentary

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 the Ctrl 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 using h and l 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 allows Del to be moved below backspace, which make key combinations involving Del 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 use u and U 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 with q because both are involved with using Evil macros, which I use a lot. I initially thought to leave it close to q, 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 to evil-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.

Num

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.

============================================================
789-
456+
123
0.

Adjust (Lower + Raise)

============================================================
MU_MODAud onAudoffQwertyColemk
Mus onMusoffDebug
Reset

Hacking Evil keybindings

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.

How to read the tables below:

  • 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.
AliasMeaning
CCtrl
GUIWin / Super key
MAlt / Meta
RETReturn
SShift
bolbeginning of line
deldelete
eofend of file
eolend of line
lnline
mkmark
paraparagraph
recrecord
revreverse
rplreplace
scrnscreen
sentsentence
substsubstitute
tgltoggle
visvisual

A rough estimation of frequency

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.

765
j downp paste after; repeat t/T/f/F
k upP paste before. repeat cmd
i insert modef find$ eol
a appendt till0 hard bol
EscF back findh left
u undoT back tilll right
C-r redow next wordI insert bol
o open belowe end wordA append eol
O open aboveb prev word
v vis mode
V vis lines
y yank
Y yank ln
43210
* next id/ findC-u scroll upW next WORD~ tgl case
n next? rev findC-d scroll downE end WORD! shell cmd
N prev{ begin paraJ join lnB prev WORDQ ex mode
# prev id} end para, rev t/T/f/F( begin sent| bol
% goto match> indentH scrn top) end sentz extra cmds
G eof< un-indentM scrn midm set mkZ quit
g extra cmdsq rec macroL scrn bot’ goto mk bolR rpl mode
d del@ play macro: ex cmd line[ prev sects subst char
r rpl char^ soft bol] next sectS subst line
x del char” reg spec` goto mk
c changeX Backspace
D del to eol
C change to eol

Things of note:

  • 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.

Custom Evil on ortho-linear Colemak-DHm

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.

Evil functionality keys before / after

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

functionbeforeafternew mnemonicAttrCommentary
substitutesxI don’t use this and its on a home key
subst lineSxrelated to substitute
repeat subst&xrelated to substitute
rpt gbl substg &xrelated to substitute
upg kxWhy does these even exist?
downg jx
next matchg nxWhy not just press n?
prev matchg NxWhy not just press N?
mid visual lineg mxcan’t imagine I would ever want this
window movementsC-w *x48 C-w * bindings I don’t use
open fold recz OxI don’t use these fold bindings
toggle foldz ax
close foldz cx
close foldsz mxgoing to map something else to this key
open foldz ox
open foldsz rx
lefthms
downjns
upkes
rightlis
scroll col leftz hz ms
scroll leftz Hz Ms
scroll col rightz lz is
scroll rightz Lz Is
find file at ptg fg ssearch file at pt-need to free up `g f’
find file.. w/ lng Fg Ssearch file.. etc-need to free up `g F’
end WORDEFfar WORDsfoot/forward are other possible mnemonics
end WORDg Eg Ffar WORD revsfoot/forward are other possible mnemonics
end wordeffar words
end wordg eg ffar word revs
findfssearchPright next to till :)
rev findFSrev searchP
eol$I+Md
hard bol0M+Md
insert modeil?+nlooks like ‘i’ if you squint
insert bolIL+nlooks like ‘i’ if you squint harder
insert resumeg ig l+n
visual modevrrange+see note below
visual linesVRrange lines+
visual blockC-vC-rrange block+
visual restoreg vg rrange restore+
replacervrevise-convert is another possible mnemonic
replace modeRVrevise mode-
nextnh?+neasier to reach but not mnemonic
prevNH?+n
redoC-rU+cnmakes much more sense and easier to do
scrn topHg e+Mn
scrn midMg m+M
scrn lowLg n+Mn
scroll downC-dC-S-n-Mnsee note below for rationale
scroll upC-uC-S-e-Mnsee note below for rationale
set mkmk-nmnemonic is still mark for me
join linesJC-j-‘j’ is harder to reach on Colemak
goto mk`jjump+Nceasier to reach and now mnemonic
goto mk lnJjump to line-Ncsame 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 changeg ;g ’-c
last change revg ,g ”-c
reg spec&+Easier for my personal keyboard layout

Visual Mode key remap

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.

Scroll up and down

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.

Left half

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.

statecol 0col 1col 2col 3col 4col 5
defaultTabq rec macrow next wordf far wordp paste afterb prev word
shiftQW next WORDF far WORDP paste beforeB prev WORD
============================================================================
defaultEsc/Ca appendr range modes searcht tillg extra cmds
shiftA append eolR range linesS rev searchT back tillG eof
lower~ tgl case( begin sent! shell cmd=) end sent
raise`[ prev sect+-] next sect
============================================================================
defaultShiftz extra cmdsx del charc changed delv revise
shiftZ quitX BkspC change to eolD del to eolV revise mode

Right half

statecol 6col 7col 8col 9col 10col 11
defaultj jump to mkl insert modeu undo,;Bksp
shiftJ jump mk lnL insert bolU redo< un-indent: ex cmd line
CtrlC-j join ln
====================================================================
defaultm leftn downe upi righto open below’ repeat
shiftM hard bolN 10 downE 10 upI eolO open above” rev repeat
Altn scrn bote scrn topscrn mid
C-Sn scroll downe scroll up
lower{ begin para% goto match& reg spec} end para| goto colDel
raise^ soft bol* next id# prev id$ eol\Del
====================================================================
defaultk set mkh nexty yank. repeat cmd/ findRET/S
shiftKH prevY yank ln> indent? rev find
raise@ play macro

Useful functions for rebinding

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")