DEV Community

aldama
aldama

Posted on • Updated on

KMonad and the power of infinite leader keys

First of all that was a title clickbait.
Title clickbaits are still legal in Mexico (I think).

Jokes aside, I will show you how every key in your keyboard can be a leader key.

Since most of the Emacs community are keyboard driven freaks, I hope you will see the potential in your workflow.

What is KMonad?

It is a program that lets you remap the keys of your keyboard.

Install KMonad

Download the executable from https://github.com/kmonad/kmonad/releases.

Put it somewhere your PATH enviroment variable points.

In my case I like to put executables in $HOME/bin.
So I add this line export PATH="$HOME/bin:$PATH" in the .profile file.

Then run the following commands.

# Add self to the input and uinput groups
sudo usermod -aG input $USER
sudo groupadd uinput
sudo usermod -aG uinput $USER

echo 'KERNEL=="uinput", MODE="0660", GROUP="uinput", OPTIONS+="static_node=uinput"' | sudo tee /etc/udev/rules.d/90-uinput.rules

# This seems to be needed because uinput isn't compiled as a loadable module these days.
# See https://github.com/chrippa/ds4drv/issues/93#issuecomment-265300511
echo uinput | sudo tee /etc/modules-load.d/uinput.conf
Enter fullscreen mode Exit fullscreen mode

For more info check https://github.com/kmonad/kmonad/issues/160#issuecomment-766121884.

Create a KMonad configuration file

mkdir -p ~/.config/kmonad
touch ~/.config/kmonad/config.kbd
Enter fullscreen mode Exit fullscreen mode

Add system information

On the top of config.kbd add the next.

(defcfg
  input  (device-file "<path to your keyboard input>")
  output (uinput-sink "KMonad kbd"))
Enter fullscreen mode Exit fullscreen mode

Go to /dev/input/by-path/ or /dev/input/by-id/ and look for any file ending in kbd.

I think if your keyboard is plugable, it should appear in /dev/input/by-id/
and your build-in laptop keyboard should appear in /dev/input/by-path/.

In my case I am using my build-in laptop keyboard. This is what I added in the configuration file. Yours should be different, modify it with your information.

(defcfg
  input  (device-file "/dev/input/by-path/platform-i8042-serio-0-event-kbd")
  output (uinput-sink "KMonad kbd"))
Enter fullscreen mode Exit fullscreen mode

uinput-sink will be the name given to the virtual keyboard that KMonad creates.
You can write anything in there.

Keyboard blueprint

Now we need to create the blueprint of our keyboard. The layouts that will create later will base of this blueprint.

This is the blueprint of my keyboard. Modify it as you need.

(defsrc
  esc   f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11   f12    pause  prnt  ins  del
  `     1    2    3    4    5    6    7    8    9    0    -     =      bspc              home
  tab   q    w    e    r    t    y    u    i    o    p    [     ]      ret               pgup
  caps  a    s    d    f    g    h    j    k    l    ;    '     \                        pgdn
  lsft  z    x    c    v    b    n    m    ,    .    /    rsft         up                end
  lctl  lmet lalt      spc       ralt cmps rctl                 left   down   rght
  )
Enter fullscreen mode Exit fullscreen mode

Base layout (default)

KMonad takes the first layout as the default layout.
Let's create our first layout and named it base.
And let's also swap capslock and escape.

(deflayer base
  caps    f1    f2   f3   f4   f5   f6   f7   f8   f9   f10  f11   f12    pause  prnt  ins  del
  `       1     2    3    4    5    6    7    8    9    0    -     =      bspc              home
  tab     q     w    e    r    t    y    u    i    o    p    [     ]      ret               pgup
  esc     a     s    d    f    g    h    j    k    l    ;    '     \                        pgdn
  lsft    z     x    c    v    b    n    m    ,    .    /    rsft         up                end
  lctl    lmet  lalt      spc       ralt cmps rctl                 left   down   rght
  )
Enter fullscreen mode Exit fullscreen mode

Now if we run:

kmonad ~/.config/kmonad/config.kbd
Enter fullscreen mode Exit fullscreen mode

You will notice that capslock and escape have been swaped.

Create a second layout

Let's call the second layout syms, short for symbols.
First lets modify our base layout so when we hold a, it calls the syms
layout
.

(deflayer base
  caps    f1    f2   f3   f4   f5   f6   f7   f8   f9   f10  f11   f12    pause  prnt  ins  del
  `       1     2    3    4    5    6    7    8    9    0    -     =      bspc              home
  tab     q     w    e    r    t    y    u    i    o    p    [     ]      ret               pgup
  esc     (layer-toggle syms)  s    d    f    g    h    j    k    l    ;    '     \         pgdn
  lsft    z     x    c    v    b    n    m    ,    .    /    rsft         up                end
  lctl    lmet  lalt      spc       ralt cmps rctl                 left   down   rght
  )
Enter fullscreen mode Exit fullscreen mode

But that is too messy. Let's create an alias for that command.

(defalias
  sym (layer-toggle syms))
Enter fullscreen mode Exit fullscreen mode

And now we can modify out base layout like this:

(deflayer base
  caps    f1    f2   f3   f4   f5   f6   f7   f8   f9   f10  f11   f12    pause  prnt  ins  del
  `       1     2    3    4    5    6    7    8    9    0    -     =      bspc              home
  tab     q     w    e    r    t    y    u    i    o    p    [     ]      ret               pgup
  esc     @sym  s    d    f    g    h    j    k    l    ;    '     \                        pgdn
  lsft    z     x    c    v    b    n    m    ,    .    /    rsft         up                end
  lctl    lmet  lalt      spc       ralt cmps rctl                 left   down   rght
  )
Enter fullscreen mode Exit fullscreen mode

Let's create our syms layout.
We will start simple and just add two symbols to make everything more clear.

(deflayer syms
  _     _    _    _    _    _    _    _    _    _    _   _   _   _   _     _    _
  _     _    _    _    _    _    _    _    _    _    _   _   _   _              _
  _     _    _    _    _    _    _    _    _    _    _   _   _   _              _
  _     _    _    _    _    _    _    [    ]    _    _   _   _                  _
  _     _    _    _    _    _    _    _    _    _    _   _       _              _
  _     _    _         _         _    _    _                 _   _   _
  )
Enter fullscreen mode Exit fullscreen mode

Now if we if we run our configuration.

kmonad ~/.config/kmonad/config.kbd
Enter fullscreen mode Exit fullscreen mode

When we hold a and press j, we get [.
And when we hold a and press k, we get ].

The bad news is that we lost the ability to type the letter a.

Let's use a key a leader key

From our last example let's modify the alias we made for calling the syms layout.

(defalias
  sym (tap-next a (layer-toggle syms)))
Enter fullscreen mode Exit fullscreen mode

With this modification, if we just tap a, we get a.
But if we hold a and press j, we get [.
And also if we hold a and press k, we get ].

Let's create another leader key

(defcfg
  input  (device-file "<path to your keyboard input>")
  output (uinput-sink "KMonad kbd"))

(defalias
  sym (tap-next bspc (layer-toggle syms)))

(defsrc
  esc   f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11   f12    pause  prnt  ins  del
  `     1    2    3    4    5    6    7    8    9    0    -     =      bspc              home
  tab   q    w    e    r    t    y    u    i    o    p    [     ]      ret               pgup
  caps  a    s    d    f    g    h    j    k    l    ;    '     \                        pgdn
  lsft  z    x    c    v    b    n    m    ,    .    /    rsft         up                end
  lctl  lmet lalt      spc       ralt cmps rctl                 left   down   rght
  )

(deflayer base
  esc   f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11   f12    pause  prnt  ins  del
  `     1    2    3    4    5    6    7    8    9    0    -     =      bspc              home
  tab   q    w    e    r    t    y    u    i    o    p    [     ]      ret               pgup
  @sym  a    s    d    f    g    h    j    k    l    ;    '     \                        pgdn
  lsft  z    x    c    v    b    n    m    ,    .    /    rsft         up                end
  lctl  lmet lalt      spc       ralt cmps rctl                 left   down   rght
  )

(deflayer syms
  _     _    _    _    _    _    _    _    _    _    _   _   _   _   _     _    _
  _     _    _    _    _    _    _    _    _    _    _   _   _   _              _
  _     _    _    _    _    _    _    _    _    _    _   _   _   _              _
  _     _    _    _    _    _    _    [    ]    _    _   _   _                  _
  _     _    _    _    _    _    _    _    _    _    _   _       _              _
  _     _    _         _         _    _    _                 _   _   _
  )
Enter fullscreen mode Exit fullscreen mode

That is a full configuration.
In this configuration when we tap caplocks, get a backspace.
If we hold caplocks and press j, we get [.
If we hold caplocks and press k, we get ].
And the good news is that we got rid of caplocks previous life functionality.

Conclusion

There is much more you can do with KMonad.
I suggest you to read the official tutorial to learn more about KMonad.

Now you know how covert every key in a leader key.

One last thing. Since I use Linux Mint and Stumpwm.
I added this line kmonad $HOME/.config/kmonad/config.kbd & to my .profile file, so kmonad starts when I log in.

Extra

(defcfg
  input  (device-file "<path to your keyboard input>")
  output (uinput-sink "KMonad kbd"))

(defalias
  d  (tap-hold-next 150 d [)
  f  (tap-hold-next 150 f ]))

(defsrc
  esc   f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11   f12    pause  prnt  ins  del
  `     1    2    3    4    5    6    7    8    9    0    -     =      bspc              home
  tab   q    w    e    r    t    y    u    i    o    p    [     ]      ret               pgup
  caps  a    s    d    f    g    h    j    k    l    ;    '     \                        pgdn
  lsft  z    x    c    v    b    n    m    ,    .    /    rsft         up                end
  lctl  lmet lalt      spc       ralt cmps rctl                 left   down   rght
  )

(deflayer base
  esc   f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11   f12    pause  prnt  ins  del
  `     1    2    3    4    5    6    7    8    9    0    -     =      bspc              home
  tab   q    w    e    r    t    y    u    i    o    p    [     ]      ret               pgup
  caps  a    s    @d   @f   g    h    j    k    l    ;    '     \                        pgdn
  lsft  z    x    c    v    b    n    m    ,    .    /    rsft         up                end
  lctl  lmet lalt      spc       ralt cmps rctl                 left   down   rght
  )
Enter fullscreen mode Exit fullscreen mode

If you hold d more than 150 milliseconds, you will get [.
If you quickly tap d, you will get d.
If you hold f more than 150 milliseconds, you will get ].
If you quickly tap f, you will get f.

Discussion (0)