I have been needing a use for an extra keyboard I had sitting in the closet.

My desk

I like to latex all my assignments before turning them in, but I’ve started to notice that it is taking longer and longer to do so. I took a quantum computing course recently and the notation in that was abusive. Take for example this simple glyph:

\begin{equation} |\psi_1 \rangle \end{equation}

It is really a single character, but it is very complicated. I’d like to be able to only have to push one button. To type it, even with texstudio’s autocomplete took 12 key presses. This is for a single glyph! Only one of the symbols nested in that glyph are actually on my keyboard. I decided that if I made a new keyboard containing those symbols, I should be able to write math faster for latex. My goal was to be able to type at a speed fast enough that I could even be able to do some scratch work in math mode for latex.

I wanted this to be as customized to myself as possible. I am sure that many people use different symbols on a daily basis. I do mostly discrete math so it is rare that I work with integrals, or other symbols common to other people. I store all my latex assignments like .../School/Semester/Class/Assignment/hw1.tex. Knowing this I could get a regex to scan through every latex file I had written and sort by most popular. The regex ended up looking something like this:

grep -o -h -E "\\\\\\w+" ./*/*/*.tex | sort | uniq -c | sort -nr

This outputted a list like:

1556 \end
1556 \begin
667 \usepackage
614 \noindent
475 \in
435 \item
429 \frac
320 \alpha
252 \textbf
245 \mathbb
224 \ket
222 \bigskip
199 \implies

First thing to note is I used \begin exactly as many times as I used \end, so thats nice to know! Many were used only once. I really only needed to look at the most used ones. I also wanted my keyboard to be fully consistent. I use \ket way way more than I use \bra or \braket, but If I put \ket, I also wanted to be able to put \bra, and \braket. I came up with my list of symbols and the next challenge was to design a layout that would go on top of a keycap set. I first studied how dvorak was created. Dvorak tried to re-invent the qwerty layout to minimize errors and maximize speed. He studied hand movements and frequency of letters used in the English keyboard. The two main things I took away from his work was that, more common letter should be easier to reach, as well as that characters that have a similiar probability of being adjacent should be put on opposite hands. To explain better, if your characters don’t alternate as often as they could, it is effectly like you are typing with one hand as the second hand is really waiting for the queue of letters on the first to finish. You cannot type letters before the ones that come before them have been typed.

I tried to do the opposite of that in hoping it would have the same effect. Symbols that had no chance of being adjacent in a word, have a high chance of being adjacent on my layout. This worked well with the fact many symbols should just naturally be close to each other. If the \ket is not close to the \bra, it feels just kind of mentally wrong. When you want a \bra or a \ket, you should mentally think to the same area of the keyboard.

Another thing I did was try to group terminals and non terminals from how a context free grammar might form. I consider symbols that can stand on their own to be terminals, and everything else to be non terminals. For example operators, like +,- are non terminals, as well as \ket, \frac, \sum, \choose, all of these are dependent on following or previous terminals to form a glyph. Here is my layout:

Current Layout

I put my most common greek letters on the number keys, and on their shift layer, the capital versions of them. Alpha and Beta dont have capitals so I threw the terminals infinity and dagger (like, for hermitian operators) on those keys since I used them infrequently enough, but still wanted them on the keyboard and had no other room for them. I also use both variations of epsilon. I use varepsilion for empty strings, among other things and epsilon for analysis proofs.

I put the arrow keys right in the middle of the keyboard on hjkl, exactly how vim has it. I did this because I find that moving my hand to the arrow keys and then back to the rest position actually wastes quite a bit of time. I have to readjust and everything. The normal arrow keys still function perfectly fine if i want to lean back and scroll or something.

The only terminal I didn’t put on the number keys was the \emptyset, since there was no more room. I put it next to the other set nonterminals with \in.

I also wanted to use this opportunity to enforce better notation on my part. Sometimes when using modulo I use equal instead of congruence, which doesn’t really matter all that much, but if I put \cong on the keyboard, I might be encouraged to do the slightly more correct thing.

To configure the keyboard softwareside, we are going to use two programs. One is called xte, which is part of xautomation, and the other is called actkbd. To start we want to see a list of devices that we have.

cat /proc/bus/input/devices

This should list all inputs, even the power button. This is what an entry should look like

I: Bus=0003 Vendor=0f39 Product=1048 Version=0110
N: Name="Heng Yu Technology F-104"
P: Phys=usb-0000:00:12.1-1/input0
U: Uniq=
H: Handlers=sysrq kbd event7 leds 
B: EV=120013
B: KEY=e080ffdf01cfffff fffffffffffffffe
B: MSC=10
B: LED=1f

The keyboard i want is called the F-104, so this must be the entry for it. Notice that under handlers it says event7. This is important, and will probably change for you. Just remember this number. Now do

sudo actkbd -s -d /dev/input/event7

and start typing on the keyboard. It should tell you the keycodes for each key input. For example left shift should be 42. Now we need to write a config file for actkbd. It should be placed in /etc/actkbd.conf After a lot of trial and error, this is what mine partially looks like.


16:key:ungrabbed,grab:echo 'str \alpha ' | xte
16+42:key:grabbed:echo 'str \infty ' | xte

the entries go like, keycode, type, property, and then what is called to system. When we call echo 'str \alpha' | xte, xte simulates that string of keypresses. So what we are doing is physically inputting, then through the keyboard layer, interrupted by actkbd, to make a systemcall to go back to the keyboard layer to simulate the correct string. The grab command is there so that actkbd will stop the actual keyboard input as well so you don’t get “1\alpha”.

Finally to apply the configuration file you do:

sudo actkbd -d /dev/input/event7 -D

When testing around, its better to sudo kill -9 actkbd before reapplying an updated config. I have found not doing that while testing creates a ton of unexpected behavior regarding other inputs.

To make a pretty picture of the layout, I searched on the internet for a while. Eventually I found some inkscape files from the wasdkeyboards company for making and sending them custom layouts to create and purchase. I used latex and exported each symbol one by one as an svg. Then I imported them and spent a few hours arranging everything so it looks nice and even. I printed it out and taped the picture above my monitor so I can just glance if I don’t know where something is. If I update the layout I only need to print out a new picture.


From some testing, I would say it has decreased the time for me to type assignments to between a half and a third on average. To revisit the glyph from before, it took me twelve presses. Now it only takes me four. I also decided against either laser cutting or putting stickers on the keys to have them actually labelled. I want this to be a evolving and dynamic layout. I have already added two changes that I didn’t consider before to the comma key, and Im sure I will change more in the future as I get interested in different subjects.

Whats next? Foot pedals maybe? Programming them would be as easy as this, but I don’t think I could find a use for them. I feel like I have now hit peak automation, atleast as my input to the computer is concerned. If that will stay is to be seen.