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

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](https://www.vim.org/) 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](https://en.wikipedia.org/wiki/Press_F_to_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:

```nix
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.

```nix
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`
    

```nix
[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.

```nix
d = overloadt(select_nav, d, 200)
```

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

```nix
[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.

```nix
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.

```nix
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](https://github.com/rvaiya/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**](https://karabiner-elements.pqrs.org/) that I can share.

To use, follow the below steps:

* Install **keyd** service using the following commands:
    

```bash
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](https://gist.github.com/jyuvaraj03/15fdf284bb97e9227fc50b5128072139) with the keyd.conf code.
    

```nix
[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!
