A Programmer's Setup: How to Never Touch Your Arrow Keys Again

·

6 min read

As developers, we spend countless hours hunched over our keyboards, meticulously crafting lines of code, and navigating through sprawling codebases. Some of us spend exorbitant amounts to buy (or even build) custom keyboards. But, rarely does most of us think about the ergonomics of our daily tool.

Home Row Motion Keys

If you have used Vim before, you will attest to the fact that using Vim's motion keys (h, j, k, l) on the home row is much quicker and reduces the strain on your wrists. For those of you who haven't used Vim, let me introduce you to the pleasures of such a setup.

The setup I'm about to introduce uses the same Vim motions to control all the actions you would normally do with your arrow keys -- move left, move right, select one word, select the top line, or any arrow key action you can name. By the end of this article, you can pull the arrow keys out of your keyboard and throw them away!

For those of you new to touch-typing and Vim, allow me to give a quick introduction to the home row and Vim's motion keys. The home row is the center row on a keyboard. Your left-hand fingers rest on a, s, d, and f, while your right-hand fingers rest on j, k, l, and ; keys. In Vim, the motion keys replacing the arrow keys are as follows:

  • ← : h

  • ↓ : j

  • ↑ : k

  • → : l

The Setup

As you know, holding down on Ctrl key allows us to modify the behavior of other keys. For example, pressing the C key directly will type out the letter "c", whereas if you hold Ctrl and then press the C key will copy the selected area.

We can leverage our knowledge of such modifier keys and create our super-keyboard. Instead of relying only on the standard modifier keys (Ctrl, Alt, Super, Fn), we can create our own modifier keys!

f-mode

When you are resting your hand on the home row like a touch typist would, your left index finger should be resting on the F key. Why not use this key as a modifier key instead of its normal function of using it to type "f"? You might argue that the F key is very important to you as you cannot pay respects without it.

Fortunately, most key remappers allow us to map the same key to multiple functions depending on whether it is being held or tapped. For example, below is a keyd configuration that overloads the Capslock key to become Ctrl when held for more than 200ms, but remain as Capslock when just tapped:

capslock = overloadt(control, capslock, 200)

In this manner, we can overload the F key to act as a modifier called nav when being held and act as plain old F when being tapped.

f = overloadt(nav, f, 200)

Just like how the Ctrl modifier modifies the C key's behavior, our custom nav modifier can modify other keys to give our custom behavior. In this setup, I have made the nav modifier to modify as below:

  • H: left

  • J: down

  • K: up

  • L: right

  • Y: Home

  • O: End

[nav]

h = left
j = down
k = up
l = right
y = home
o = end

So, if you hold down your F key and then tap K, you will now mimic the up arrow action! We've replicated the arrow key motions from the comfort of our home row. No more stretching your wrist to access the arrow keys!us

d-mode

"Wait, I can move by holding down F and pressing one of the Vim motion keys (h, j, k, l). But how do I replicate the Shift+Arrow key functionality?" you ask.

If you haven't used the Shift+Arrow combination, here's what it does. In a text editor, if you press Shift + Left Arrow, you can select the character to the left of your cursor.

Here's how we replicate this in our setup. Just like how nav was a new modifier we created, we will also create another modifier called select_nav which will be activated by holding down the D key.

d = overloadt(select_nav, d, 200)

The same directional definitions in the f-mode are used here: (H = left, J = down, ..).

[select_nav]

h = S-left
k = S-up
j = S-down
l = S-right
y = S-home
o = S-end

a-mode and s-mode

If you want to take this even further, we also have the a-mode (word_nav) and s-mode (select_word_nav).

a-mode allows us to move directionally word-by-word instead of character-by-character.

a = overloadt(word_nav, a, 200)

[word_nav]

h = C-left
k = C-up
j = C-down
l = C-right
y = C-home
o = C-end

And s-mode allows us to select directionally word-by-word.

s = overloadt(select_word_nav, s, 200)

[select_word_nav]

h = C-S-left
k = C-S-up
j = C-S-down
l = C-S-right
y = C-S-home
o = C-S-end

Installation

As we will be remapping the keys, we will be installing a key-remapping solution. For Linux, my choice (after much experimentation) is keyd (the examples above are keyd configs).

Note: If anyone using Mac OS X is interested, please comment below as I do have a similar setup using Karabiner-Elements that I can share.

To use, follow the below steps:

  • Install keyd service using the following commands:
git clone https://github.com/rvaiya/keyd
cd keyd
make && sudo make install
sudo systemctl enable keyd && sudo systemctl start keyd

This installs the keyd service and enables it to activate on startup.

  • Now, we need to configure the key remappings. Paste the following in /etc/keyd/default.conf. You can also star this gist with the keyd.conf code.
[ids]

*

[global]

chord_timeout = 100

[main]

# Layer keys that act as themselves if not held for more than 200ms.
f = overloadt(nav, f, 200)
d = overloadt(select_nav, d, 200)
s = overloadt(select_word_nav, s, 200)
a = overloadt(word_nav, a, 200)

[nav]

h = left
k = up
j = down
l = right
y = home
o = end

[select_nav]

h = S-left
k = S-up
j = S-down
l = S-right
y = S-home
o = S-end

[select_word_nav]

h = C-S-left
k = C-S-up
j = C-S-down
l = C-S-right
y = C-S-home
o = C-S-end

[word_nav]

h = C-left
k = C-up
j = C-down
l = C-right
y = C-home
o = C-end

# Mapping the custom modifier keys to themselves to make those actions 
# instantaneous instead of waiting for the timeout
[shift]

f = F
d = D
s = S
a = A

[control]

f = C-f
d = C-d
s = C-s
a = C-a

[control+shift]

f = C-S-f
d = C-S-d
s = C-S-s
a = C-s-a
  • Run sudo keyd reload to reload the new config and voila! You can now pull out your arrow keys as promised!