FOSS vs. Arthritis - alavi.me

alavi.me

13 min read Original article ↗

By Alireza Alavi13 minutes read


Table of Contents

Intro

here I want to focus on the software aspect of it (ergonomics). How I'm using FOSS software to enhance my computing ergonomics.

I have been working in software and programming for the last 7 years, and playing games and other things behind the computer before that. My fingers, wrists, elbows, shoulders and numerous other sore and aching parts of my body (all of them) can attest that. I don't have any serious physical condition like Arthritis, but if I don't look after myself, it's likely that I will develop some in a decade or two.

Considering the ~9 hours/day that I spend behind the computer, I find optimizing my setup for efficiency, ergonomics and joy a very rewarding investment.
Lately, after finding Kmonad, I feel like all the pieces of my setup puzzle have fit together, and I'm finally at a place where everything seems "good enough".
So I thought I might share it, hoping others who might want to stay healthier or already suffer from pain and physical complications might find it helpful.

There is an obvious hardware/physical aspect to optimizing your setups' ergonomics:

  • A good chair
  • Good monitor
  • Good keyboard
  • Good posture
  • Good typing technique
  • Good placement of chair, monitor, keyboard, mouse etc.

But here I want to focus on the software aspect of it: How I'm using FOSS software to enhance my computing ergonomics.

Outline (TL;DR)

I'm using:

  • Neovim / Vim bindings
    • I use about 50/50 between Emacs and Neovim, But even on Emacs, I use "Evil mode" so it emulates vim bindings. Vim bindings are key. Use Vim bindings for everything you can.
      It helps you stay on the home row, and with itsits modal editing and layering, it reduces the need for reaching Ctrl, Alt constantly with your pinkie and strain your fingers to press multiple keys at once.
  • Vim mode on everything
    • I'll say it again, There are vim bindings for almost everything. Use them.
  • i3/sway window manager
    • It largely revolves around vim bindings (hjkl for movement)
    • I have optimized my keymaps over years to both be ergonomic enough and convenient.
  • Kmonad
    • You can create custom keymaps, layers different types of events. It's very powerful.
    • Important remaps
    • Caps lock tap-> Escape
    • Caps lock hold→ Ctrl
    • Space hold→ Meta
    • lShiftrShift tap→ ()
    • rCtrl double tap→ Menu
  • Bonus
    • Tmux/Wezterm/Zellij
    • I do most of my work in terminals. If you're like me, It's really important to be efficient in working with them and moving around in them. These tools plus vim-like bindings or other bindings that keep your fingers on the home row will really help our ergonomics.
    • I personally use Wezterm most because it supports RTL and BiDi text, and Tmux on servers
    • E-ink tablet as monitor for writing/reading
    • You can do this with an android E-ink tablet and VNC. I have explained it in this post
    • Mechvibes/Neptune for better feedback and pressing less
    • Emulates keyboard click so you can know when the click is actually registered, leading to pressing less.
    • A good keyboard (doesn't have to be expensive)
    • doesn't have to be an expensive ergonomic keyboard like Kinesis keyboards necessarily. You can go a long way with a normal, good, keyboard and switches. Even if you can't afford a mechanical keyboard, pick a membrane keyboard with some tactile feed back and low actuation force (you don't have to push hard to make the keys activate)
  • Huge honorable mention: The most important aspect of health is Regular, serious exercise and lifting weights (regarding skeletal health of muscles, tendons, joints etc.). Sleep and healthy diet are also extremely important.

Check out my dotfiles to see exactly how my setup works and replicate/modify it.

Neovim/Vim mode editors

We spend most of our time in our text editor/IDE, and most of that time navigating and editing code, and a small portion of it writing.

Vim bindings are arguably the most ergonomic and universal way of doing this. You can use Neovim/Vim themselves, or use Vim bindings in any editor that you prefer. Every single good editor/IDE has them.

There are many videos and resources on why Vim bindings are so good and efficient. Noboilerplate has a good video explaining it.

Vim bindings on anything you spend time in

There's also Vim bindings for almost all good software.

  • Browser? → Use qutebrowser or add-ons like "Vim raptor" for Firefox
  • IDE? → If not using Vim/Neovim, use Emacs evil mode, Use "Ideavim" for Jetbrains IDEs, so on...
  • Note-taking? → If not using Neovim or Emacs, there are vim bindings for Obsidian, Logseq, and most other tools

The list goes on and on.

i3/sway window manager

I love it when software become stable and invisible, meaning you don't notice it anymore. I have been using i3 exclusively for the past 3 years, and it's the definition of "stable" and "just works". The same goes for sway which is basically i3 for Wayland.

The main ergonomic benefit for these are again, Vim bindings and that they basically eliminate the need to use the mouse. They also make you incredibly efficient and organized in using your computer. While my friends are spamming Alt+Tab on Windows to find "that damn window", I just know that my terminal will be at Meta+1, Code/editor will be at Meta+2, Browsers at Meta+3 and so on.

This might also apply to other tiling window managers but I haven't tried anything besides i3 and sway because I haven't felt the need to.

Kmonad

After 5 years of using Linux, just this week I found the final, missing piece of my puzzle of ergonomics.

For years, I was yearning for an ergonomic keyboard like the Kinesis Advantage 360 and similar ones, because even though my setup was already pretty good, the excessive pinkie movements for using mod keys, especially Meta, Ctrl, Shift, was putting strain on my hands.

The thumb clusters on these ergonomic keyboards make you use your strongest finger, the old, beefy thumb more and your measly pinkie less (We can pretty much do this with Kmonad). The concave and tented structure of some of them also put your hands and wrists in a more natural position (We can't do this with Kmonad).

The problem with these keyboards is that they are expensive. I absolutely cannot afford one in anytime soon, since they are not available in my region and I also have to pay extra for bringing them in.

With Kmonad you can have 80%* of the benefits of ergonomic keyboards with 0% of the cost.

*Totally made-up number

Our approach to remaps

  1. Swap Caps Lock with Escape.
    The first and most important step that I was doing with setxkbmap even before kmonad.

    Escape is probably the most used key especially in vim bindings. And caps lock is basically useless. Now instead of reaching for the impossible top left corner of your keyboard, your pinkie just goes one column to the right from its place on the home row.

  2. Holding Caps Lock activates Ctrl
    The second-biggest pain point, the Ctrl key.
    Famous for various physical injuries such as the "Emacs pinkie" (because default Emacs bindings use Ctrl so much). The benefit of this is your pinkie doesn't have to do nearly any of those gymnastics for using Ctrl now. It's right there.

    Caps lock is one of our "mod keys". Keys that are almost exclusively used when held down, with combination of other keys. So binding it to activate only when held down makes perfect sense.

  3. Holding Space activates Meta
    Meta (the "windows" key as some may call it) is another of our most used keys. It's the activator for all i3/sway commands and top level workspace commands. So let's bind it to something that is both easy to use with both hands, and we can use our strong finger for it. Space is a great fit.

  4. Shift parenthesis
    Parenthesis are one of the most used symbols both in natural language and programming languages (and we lisp fans love our parens). So having to press Shift+9 or Shift+0 to type them is a real pain and un-ergonomic. So we bind left shift, and right shift to left and right parens, only when they are tapped. And when they are held, they are just shift keys.

  5. Double tap Ctrl activates Menu
    One of my old keyboards (from an Iranian company named "Farasoo". Great keyboard actually) has a "Menu" key which acted almost as "Right click" and was very handy. I miss this on all my keyboards.

  • Some people do home row mods, where the keys on the home row (asdf, jkl;) become mod keys (Ctrl Meta Alt Shift). The argument is valid from an efficiency and ergonomics standpoint.
    However, I haven't dipped my toes in that realm yet since I'm feeling pretty comfortable with my custom setup for now and home row mods are too different from normal keyboard usage, which I currently don't have the time to re-learn.
  • There are gazillion other things you can do which I'm sure are awesome (like "layering" for example, where you have different layers activated with a keymap). But I feel like this is the bare minimum that makes me feel comfortable.
    "80% results with 20% effort" type of thing.
    • My actual configs are more complicated, there's some layering for navigation keys (Up, down, left, right) and Backspace for example. You can find my actual configs in my dotfiles repository
  • You can switch the Ctrl and Meta remaps placement. See what suits you.

Kmonad implementation

For full tutorial and reference, read the official tutorial.kbd.

While the configuration is confusing at first, once you understand the overall structure it becomes pretty clear.

In case you're unfamiliar with lisp syntax, it's just your fortran style code (C, Java, JS etc.) but with the parenthesis on the outside.
foo(arg1, "b")(foo arg1 "b")

First create a file somewhere. I created it at ~/.config/kmonad/base.kbd

You can run kmonad with this config file kmonad ~/.config/kmonad/base.kbd

Let's write our base.kbd

defcfg is a mandatory function which inits and defines our configuration.

(defcfg
  input (device-file "/dev/input/by-id/<your-keyboard-dev>")
  ;;input  (device-file "/dev/input/by-id/usb-Sino_Wealth_USB_Keyboard-event-kbd")
  output (uinput-sink
           "kmonad")
           ;;"sleep 1 && ~/.config/scripts/input-conf.sh"
  cmp-seq ralt
  fallthrough true
  allow-cmd true)

To find your keyboard's ID, run ls /dev/input/by-id. It's usually one of the devices ending with -event-kbd.

Now we create a new block by calling the defalias function, which creates bindings for our keymap behaviors which we can later assign to keys.

(defalias
  ;; tap will emit rctl, double tap will emit menu(right click)
  ;; NOTE: 'compose' (evdev 127) maps to the real Menu keysym, not 'menu' (XF86MenuKB)
  rctl-menu (multi-tap 300 rctl compose)
  ;; tap will emit esc, if held, emits left Ctl
  esc-ctl (tap-hold-next-release 150 esc lctl)
  ;; tap will emit space, if held, emits left Meta
  ->met (tap-hold-next-release 150 space lmet)
  ;; Shift parantheses
  lpar->sft (tap-next \( lsft)
  rpar->sft (tap-next \) rsft))

I figured that using tap-hold-next-release is important here because if we use something like tap-next which immediately activates the hold state, it interferes with our typing (You want to press Space but Meta gets activated).

Now by calling defsrc we define the keys that we want to remap. Since lisp languages are not sensitive to extra whitespace and line breaks, we can organize them in their actual layout on the keyboard, or not.

(defsrc
  esc
  caps
  lsft        rsft
  _     space  rctl)

We can also write this like below, and it's exactly the same

(defsrc esc caps lsft rsft - space rctl)

We can define only the keys we want to remap thanks to fallthrough true in our defcfg

Now we define a layer, which in that layer, the keys in our defsrc are mapped to these new keys, based on their position as function arguments

(deflayer base
  caps
  @esc-ctl
  @lpar->sft                @rpar->sft
  _             @->met      @rctl-menu)

Notice how we can use the aliases we defined in defalias by prefixing them with @

Start Kmonad for all connected keyboards script

You can use this script and add it to your i3/sway startup or something else, so it runs on system startup

#!/usr/bin/env bash

# Setup kmonad base config for all connected keyboards

# All event files in /dev/input/by-id/ ending with -event-kbd

KMONAD_CFG="$HOME/.config/kmonad/base.kbd"

found=0

for kbd in /dev/input/by-id/*-event-kbd; do
  found=1

  export KBD_DEV="$kbd"

  cfg="$(envsubst < "$KMONAD_CFG")"
  printf 'Starting kmonad for %s\n' "$KBD_DEV" >&2
  notify-send -u low "⌨ Starting kmonad"
  kmonad <(echo "$cfg") &
done

if [ "$found" -eq 0 ]; then
  echo "No keyboards found in /dev/input/by-id/*-event-kbd" >&2
  exit 1
fi

exit

And modify your base.kbd's defcfg to read the input device from env variable

(defcfg
  input (device-file "$KBD_DEV")
  ;;input  (device-file "/dev/input/by-id/usb-Sino_Wealth_USB_Keyboard-event-kbd")
  output (uinput-sink
          "kmonad"
          "sleep 1 && ~/.config/scripts/input-conf.sh")
  cmp-seq ralt
  fallthrough true
  allow-cmd true)

We also added a input-conf.sh script to run other input configurations if needed (Setting input methods/languages with setxkbmap for example). You can remove it if you want.

Final Kmonad config

;; This is meant to run via a script that passes KBD_DEV
;; To run it straight from shell, you can do 
;; `kmonad --input "device-file \"/dev/input/by-id/usb-Sino_Wealth_USB_Keyboard-event-kbd\"" ~/.config/kmonad/base.kbd`

(defcfg
  input (device-file "$KBD_DEV")
  ;;input  (device-file "/dev/input/by-id/usb-Sino_Wealth_USB_Keyboard-event-kbd")
  output (uinput-sink
          "kmonad"
          "sleep 1 && ~/.config/scripts/input-conf.sh")
  cmp-seq ralt
  fallthrough true
  allow-cmd true)

(defalias
  ;; tap will emit rctl, double tap will emit menu(right click)
  ;; NOTE: 'compose' (evdev 127) maps to the real Menu keysym, not 'menu' (XF86MenuKB)
  rctl-menu (multi-tap 300 rctl compose)
  ;; tap will emit esc, if held, emits left Ctl
  esc-ctl (tap-hold-next-release 150 esc lctl)
  ;; tap will emit space, if held, emits left Meta
  ->met (tap-hold-next-release 150 space lmet)
  ;; Shift parentheses
  lpar->sft (tap-next \( lsft)
  rpar->sft (tap-next \) rsft))

(defsrc
  esc
  caps
  lsft         rsft
  _     space  rctl)

(deflayer base
  caps
  @esc-ctl
  @lpar->sft                @rpar->sft
  _             @->met      @rctl-menu)
  • Tip for multi-input (language) users: If you use multiple keyboard input methods (Persian + English for example), this setup fits very nice with using setxkbmap to switch input method with Caps lock which we have now on the physical Escape key. So your Escape key becomes a key to toggle input method. setxkbmap -layout 'us,ir' -option 'grp:caps_toggle

Nothing beats physical training

This isn't software related, but It's the most important aspect of longevity and health.
I have been doing sports and exercising for at least 17 years now, and it's the biggest thing that I attribute both my mental (others might disagree) and physical health to.

Most of us don't have much time. Don't worry, You don't need to spend 2 hours a day in the Gym. Just 2–3 sessions of 40–90 minutes a week will absolutely make you a house if you're consistent and keep the intensity high. The HIT (High Intensity Training) methodology popularized by Mike Mentzer and Dorian Yates is really great for tight schedules.

Do intense, soul crushing exercises. Be it running, cycling, or whatever. But I find bodybuilding and powerlifting the most concise, effective and fundamental ways of physical exercise.

Also, maintain and active lifestyle. Move around every 30–40 minutes, look outside, stretch out. 2-4 hours of heavy exercise in a 168 hour week isn't enough . You need to keep moving.

Endnotes

  • This is to help others enhance their physical longevity in working with computers, with a low cost. You might never need a $600 keyboard now. Hope it helps.
  • One can replicate almost all of this setup on all operating systems. Nvim/Vim, Emacs, Zellij, Wezterm, Kmonad are all cross-platform. For tiling window managers, there are options that emulate the behavior of i3 for Linux, Windows, Mac, and so on.
  • Another good alternative to Kmonad is Kanata
  • All my configuration and dotfiles are available online. I'm pretty sure you will find at least some interesting things there.

Discuss on Hacker News