The quest for a better keyboard layout

The Quest

Like most programmers, I type a lot – many hours a day, most days of the week. The keyboard is the primary conduit of my creative expression most of the time, whether I’m writing code or constructing elaborate stories to impress friends, clients, or co-workers (aka email/chat/this blog). For the last couple of years, I’ve been mildly obsessed with making that conduit more efficient. I’ve tried several different keyboards and entirely new keyboard layouts.

I stopped the keyboard search with the Kinesis Advantage – it works really well for me, and is the easiest keyboard for touch typing that I’ve ever used. But the keyboard layout search continued. The productivity hit during the learning period for Dvorak or Colemak was too great, and I quickly slid back to Qwerty.

I could type as fast as I wanted in Qwerty, so I tried to figure out what was really bugging me about my typing. I realized it was the shift key – I was frustrated with the high percentage of characters I typed that involved shift. I primarily code in Ruby, which uses ‘_’ much more often than ‘-’ (about 14 times more often), ‘:’ more than ‘;’ (about 78 times more often!), and ‘{}’ more than ‘[]‘ (or so I thought – more on that later).

I then decided to create a custom keyboard layout that would reduce the need for the shift key when coding. My goals were:

  • no remapping of the letter keys, since my muscle memory knows where they all are
  • remap commonly used symbols to be available without the shift key
  • be easy to learn, so no remapping characters to new keys

Using the Ukelele keyboard layout editing tool (for MacOS), I played around with some layout ideas before settling on the one I’ve been using since May 2009.

The Layout

Since I mostly code in Ruby, and mostly use symbols in code vs. email/chat/etc., I remapped the shifted symbols I used more often.

I ‘shift-swapped’ (meaning the symbol you get with or without the shift key depressed are reversed) the following character pairs:

  • { [
  • } ]
  • | \
  • ~ `
  • : ;
  • _ -

I assumed that I used most of the symbols on the top row number keys more than I used the numbers, so I shift-swapped the 1 – 0 number keys with the corresponding symbol. If caps-lock is on, number keys revert to normal, but all of the other symbol keys remain swapped (meaning when caps-lock is on, pressing the ’1′ key will give you a 1, but pressing the ‘[' key will give you a {). Since the Kinesis keyboard does not have a separate keypad, this makes entering number sequences easier.

The caps-lock key has been moved to the f1 key, and I use the original caps-lock as a control key (for Emacs). This mapping can't be done by Ukelele, since it cannot remap function or modifier keys, so I did this using the remapping functionality in the Kinesis keyboard itself.

Analysis

After six weeks or so of using the new layout, I decided to analyze a large ruby codebase to see what my shift pair ratios actually were (something I should have done before creating a new layout). Using this script, I got the following results:

Analyzed 457 files, 25060 lines
` ~     25     58  2.320
1 !   1161    713  0.614
2 @    564   2700  4.787
3 #    416   1914  4.601
4 $    264     55  0.208
5 %    359    303  0.844
6 ^    257     44  0.171
7 &    152    226  1.487
8 *    176    115  0.653
9 (    196   4479  22.852
0 )   1761   4485  2.547
- _   1559  21837  14.007
[ {   1385   1304  0.942
] }   1396   1306  0.936
\ |    144   1480  10.278
; :    108   8446  78.204
= +   5588    729  0.130
‘ "   5585   3909  0.700
, <   4737    791  0.167
. >  10257   2067  0.202
/ ?   1077   1054  0.979

Columns one and two are the shift pairs. Columns three and four are the occurrence counts for each character in the pair. The last column shows the ratio of the second character (normally shifted) to the first character (normally not shifted). So a higher number in that column indicates an advantage to swapping the shift pair.

I looked at the shift pairs I had swapped, along with the other symbol shift pairs that I did not swap (the last five lines above). There are some big wins here with my current remapping, along with some loses. The '[]'/'{}' swap was a small mistake - looks like I access elements of collections slightly more often than I define inline blocks or explicit hashes (which is kind of obvious in hindsight. In fact, on reflection I would think that collection access would happen considerably more often than inline block creation). And some of the number key remaps are big loses based on the ratios, but the lowest ratio pairs there have generally low volume. After this analysis, I didn't undo any of the remappings, though I should have reversed (and still should reverse) the bracket/brace swap.

Usage

The name of this layout is 'rubyist'. If you are interested in giving it a try, download the MacOS keylayout file here, and put it in ~/Library/Keyboard Layouts/.

I don't expect this layout to work well for everyone, or really anyone other than me. I do think all of us could benefit from evaluating the text we type the most, and seeing if some keyboard layout tweaks could make us more efficient. If you do want to give your own layout a try, check out these platform specific tools: