Jeromy Anglim's Blog: Psychology and Statistics


Friday, July 30, 2010

How to Edit Text Faster on Windows by Updating Key Bindings

The following post sets out one way of binding the navigation keys to convenient keys on the keyboard on Windows. The approach means that I don't have to move my hands from the home keys position (i.e., JKL;) when switching between entering text and moving the cursor.

Overview

I spend a lot of time on a computer. Much of this time is spent doing tasks like typing LaTeX, typing R code, and typing HTML. Regardless of what I'm doing I often need to switch between typing text and navigating the cursor. I long ago realised that moving the hands between the home keys (i.e., JKL;) and the mouse was slower than moving the hands between the home keys and the navigation keys (e.g., left, right, Home, etc.). However, I wanted something quicker. Moving the hands between the home keys and the cursor keys takes time and it is also slightly disruptive to attention. I was aware of some of the key bindings used in text editors such as Emacs and Vi that allowed typing and navigation to occur without moving the hands away from the home key position. However, I wanted to have a standard set of keys that would work across all program on Windows.

This led me to use AutoHotKey to bind the navigation keys to more accessible keys. This post sets out the key bindings that I chose. It also sets out the AutoHotKey script in case you wanted to implement it.

The new bindings took about a week to be useful, a month to feel natural, and about three months to feel completely automatic. The bindings are more efficient than my old strategy of moving between the cursor keys and the home keys.

Choosing Keys to Bind

The choice of keys to bind was a critical one. I used the following principles for bindings:
  • Bindings should not override important existing bindings
  • Bindings should require minimal effort
  • Bindings should facilitate transfer from skills with traditional layout
  • Bindings should integrate with important key combinations such as Ctrl+Left, Ctrl+Shift+Left
I chose the Windows Key as the modifier to activate navigation mode. I chose the following bindings for the navigation keys.
J - Down
K - Up
L - Left
; - Right
H - Home
N - End
U - Del
I - Page Down
O - Page Up
Thus, for example, if I want to move the cursor to the left, I press WindowsKey+L; if I want to move the cursor one word to the left, I press WindowsKey+Ctrl+L; if I want to highlight one word to the right, I press WindowsKey+Ctrl+Shift+;.

Issues

There were a couple of initial implementation issues which I resolved.

1. Windows Key and the Start Menu

One issue with using the Windows Key as a modifier key is that it often triggers the Start Menu.

To solve this problem, I added the following commands to my AutoHotKey script (see below).
~LWin Up:: return
~RWin Up:: return
If I need to actually use the Start Menu from the keyboard I just press Ctrl+Esc.

2. Problems with binding

On my old laptop (5 years old), the key bindings sometimes failed to work. For example, the letter L would be printed when I intended to navigate left.

I have not had this issue since updating my laptop.

3. Combining with modifier keys

When first adopting the keys, I wasn't sure which fingers to use for the modifier keys.

After some experimentation I adopted the following. In general I use my left ring finger to press the Windows Key. When I need to select text, I use the left little finger for the Control Key, left ring finger for the Shift Key, and the left thumb for the Windows Key.

Implementing in AutoHotKey

The following procedure sets out how to set up the key bindings using AutoHotKey.

1. Download and Install AutoHotKey

AutoHotKey is a free download and is available here.

2. Disable Windows + L

If you are running Windows 7, Windows+L logs you off the computer. To disable this feature, see the following post on HowToGeek. In summary to disable this feature:
1. Start regedit: e.g., press Windows+R and type "regedit"

2. Navigate to the following folder HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System

3. Then "On the right-hand side, create a new DWORD 32-bit value named DisableLockWorkstation and give it one of these values: 1 – Disable Lock Workstation 0 – Enable Lock Workstation" (i.e., 1 to disable)

3. Set up the AutoHotKey Script

Copy the following code into a text file and give it a name like "newkeybindings.ahk". Double click on the file to check that it works. If you want the key bindings to be made permanently, add a shortcut to the file to your Startup folder (i.e., Start Menu - Programs - Startup).
#space::
SendInput {Space}
return

~LWin Up:: return
~RWin Up:: return


#l::
SendInput {Left}
return

#j::
SendInput {Down}
return

#;::
SendInput {Right}
return

#k::
SendInput {Up}
return

#u::
SendInput {Delete}
return

#h::
SendInput {Home}
return

#n::
SendInput {End}
return


#o::
SendInput {PgUp}
return

#i::
SendInput {PgDn}
return


#+l::
SendInput +{Left}
return

#+j::
SendInput +{Down}
return

#+;::
SendInput +{Right}
return

#+k::
SendInput +{Up}
return

#+u::
SendInput +{Delete}
return

#+h::
SendInput +{Home}
return

#+n::
SendInput +{End}
return

#^+h::
SendInput ^+{Home}
return

#^+n::
SendInput ^+{End}
return

#+o::
SendInput +{PgUp}
return

#+i::
SendInput +{PgDn}
return


#^l::
SendInput ^{Left}
return

#^j::
SendInput ^{Down}
return

#^;::
SendInput ^{Right}
return

#^k::
SendInput ^{Up}
return

#^u::
SendInput ^{Delete}
return

#^h::
SendInput ^{Home}
return

#^n::
SendInput ^{End}
return

#^o::
SendInput ^{PgUp}
return

#^i::
SendInput ^{PgDn}
return


#+^l::
SendInput +^{Left}
return

#+^j::
SendInput +^{Down}
return

#+^;::
SendInput +^{Right}
return

#+^k::
SendInput +^{Up}
return

#+^u::
SendInput +^{Delete}
return



#!l::
SendInput !{Left}
return

#!j::
SendInput !{Down}
return

#!;::
SendInput !{Right}
return

#!k::
SendInput !{Up}
return



#+!l::
SendInput +!{Left}
return

#+!j::
SendInput +!{Down}
return

#+!;::
SendInput +!{Right}
return

#+!k::
SendInput +!{Up}
return



#^!l::
SendInput ^!{Left}
return

#^!j::
SendInput ^!{Down}
return

#^!;::
SendInput ^!{Right}
return

#^!k::
SendInput ^!{Up}
return



#+^!l::
SendInput +^!{Left}
return

#+^!j::
SendInput +^!{Down}
return

#+^!;::
SendInput +^!{Right}
return

#+^!k::
SendInput +^!{Up}
return