Thomas Buß

28 Feb 2021

Using Capslock + hjkl as arrow keys on Linux

Why?

Since I adopted Vim keybindings in almost any application that lets me, I try to avoid the arrow keys as much as possible. However, there are situations where you can’t really get around it. For example, when you’re typing in IntelliJ or in Vim with an auto-pairing plugin, an opening parenthesis will automatically create a matching closing parenthesis behind the cursor. This happens dozens of time on a normal work day for any developer. The annoyance here is that to get behind the closing parenthesis you need to use the arrow keys (which means leaving the normal hand posture) or to leave Insert Mode, navigate behind the parenthesis and go to insert mode again. Both are not really attractive solutions to a situation that occurs so often on a normal day.

Let me first make one thing very clear: What is about to follow probably goes too far in the amount of keyboard customizing that is reasonable. However, it’s little annoyances like that that make you spend an evening tinkering with your system setup; not because the result is actually worth it, but because you always learn a little thing or two about how your system works. This is certainly true for keyboard input, which I didn’t care a lot for in the past. It just worked.

So here’s what I wanted to accomplish: Instead of leaving the Insert Mode, I wanted to reach the arrow keys without leaving the normal hand posture. I want to remain in Insert Mode, hold Capslock and press l to move the cursor on position to the right. Why Capslock? Well, the Capslock key has a very easy to reach position on the keyboard, but is rarely used (unless you’re a shitposter on YouTube or something). Why l? Cuz Vim.

I also wanted this solution to work in applications other than Vim or IntelliJ, so I did not try to make this work in Vim config. This also allows me to adopt the solution for other shortcuts with Capslock as well.

First step: Remap Capslock button

The first piece of this puzzle is to make Capslock a different modifier key, similar to Ctrl and Shift. The “key” we want to use is called Hyper. Is is not found on modern keyboards anyway, but sometimes exists as a combination of other modifier keys. To remap Capslock to this Hyper key, we can use a program called “Xmodmap”. You can read all about it on the Arch Wiki: https://wiki.archlinux.org/index.php/Xmodmap The config file to use is ~/.Xmodmap and here is it’s content:

1
2
3
4
clear Lock
keycode 66 = Hyper_L
remove mod4 = Hyper_L
add mod3 = Hyper_L

Thanks to this YouTube video, which shows how to do the remapping in this file. The key thing that might be missed when looking at other examples is the line with remove mod4 = ..., which is how the Hyper key is usually pressed by a combination of modifiers (called mod4). I must admit that I did not really dig into the internals of why this line is actually necessary. To apply the changes, run this command:

1
xmodmap ~/.Xmodmap

You should be able to see the results of this command very easily: Pressing Capslock no longer toggles the little indication LED for the Capslock key.

Second step: Add a keyboard shortcut for Capslock + { h, j, k, l }

You can remap individual keys with Xmodmap quite easily, but not arbitrary combinations of keys. For this setup, I’m using sxhkd, the Simple X Hot Key Daemon. It is the first solution for keyboard shortcuts I tried, it worked, so I sticked with it. Also, it is very minimal (being part of the bspwm window manager) and has a very easy to read configuration file, located at .config/sxhkd/sxhkdrc. It allows use to run arbitrary shell commands on key combinations. We’ll look at the individual commands in the next section.

1
2
3
4
5
6
7
8
hyper + h
    <command for arrow left>
hyper + j
    <command for arrow down>
hyper + k
    <command for arrow up>
hyper + l
    <command for arrow right>

Third step: Emulating the arrow keys with a command

The last piece of the puzzle is a command that sends keys to the currently focussed window. This can be accomplished with xdotool. To send the Down key, for example, you can use this command:

1
xdotool keyup j key --clearmodifiers Down

There are two parts to the command above:

  1. keyup j
  2. key --clearmodifiers Down

This sends just the Down key, not j + the Down key (which could be a different keyboard shortcut in the application). In place of Down, you can use a bunch of other keys. I found this useful list: https://www.tcl.tk/man/tcl/TkCmd/keysyms.htm. Note that the spelling is important.

With xdotool, we can complete our config file for sxhkd:

1
2
3
4
5
6
7
8
hyper + h
    xdotool keyup h key --clearmodifiers Left
hyper + j
    xdotool keyup j key --clearmodifiers Down
hyper + k
    xdotool keyup k key --clearmodifiers Up
hyper + l
    xdotool keyup l key --clearmodifiers Right

Save the changes and run the sxhkd command. You should now be able to hold the Capslock key and then use h, j, k, and l to send the arrow keys to any application.

To make the changes permanent, you need some way to start sxhkd at startup (or at least at login). I was lazy and just used Xfce4’s autostart menu, but you could do it the proper way with systemd or rund.

Conclusion

To summarize, we can use Xmodmap to remap the Capslock key to Hyper, and then use sxhkd create shortcuts with Hyper that call a xdotool command which then emulates the arrow keys. Feel free to leave a comment if you have a different approach to solve this.

comments powered by Disqus