CuteKey or KuteKey
An adorable key daemon
Features
All the simple features you could want from a key daemon!
The features we have :party:
- Remap combination of keys
<XX>to<YY>, with left/right modifier support - Remapping in stages
- Application-specific remaps (process-specific for console)
- Works on wayland, x11, and the console
- Importing other files using
@include
The features we don’t have :tear:
- Vim-style layers. That’s best left to a hotkey daemon
- Running shell commands on keystrokes. Also best for a hotkey daemon
- Keyboard-specific remaps. Considered for later
Methodology
Stages
To avoid recursive mappings while still allowing for “precedence” in mappings, we introduce a staging mechanism. This makes it clear what keycodes are coming in and going out
For example, if you want your capslock key to be indistinguishable from a
control key in all cases, map it at [Stage 0] with <capslock> = <C->. Then
if a mapping on [Stage 1] or higher maps control to something else, the
capslock will already appear as a control on that stage!
Stages are numbered 0 through 100. They do not have to be consecutive
App-specific remaps
Under each [Stage X] heading, a subheading [[ app_title ]] can be added.
These keys apply only when that app is focused. Multiple app titles, space
separated, can be included this way
If the first “title” is a !, the match is negated. These keys will apply to
all apps that aren’t listed in the heading. All matches are case-insensitive
[Stage 4] # App-specific sub-headings can be used under any stage
[[ Alacritty xTeRm kiTTy ]] # Applies to these 3 terminal apps
[[ ! Chromium firefox ]] # Any apps other than chromium and firefox
Including files
Sometimes it’s helpful to have slightly different configurations per-system or
per-keyboard, though with most mappings shared between the two. The @include
directive inserts a file by adding the current stage to all stages in that file
For example given file gimp_keys.tomlish
# This file is at ~/gimp_keys.tomlish
[Stage 0]
<e> = <a>
[Stage 4]
[[ Gimp ]]
<C-a> = <C-r>
When we include it in another file like
[Stage 2]
[[ Chromium ]]
@include ~/gimp_keys.tomlish
<C-v> = <C-S-v>
The other file effectively expands to
[Stage 2]
[[ Chromium ]]
<e> = <a>
<C-v> = <C-S-v>
[Stage 6]
[[ Chromium Gimp ]]
<C-a> = <C-r>
Notice how the @include inherits the app scope and the stage scope from where
it’s placed. This means placing an @include under [Stage 0] will import is
“as is”. I recommend not making too many stages in files that are @included.
Keep them atomic
Syntax
Configuration file is a TOML. Comments in TOML start with a #
Vim-ish syntax, see :h key-notation. Also supports fully qualified names from
libxkb. Names themselves are case-insensitive, though modifiers are preferred to
be capital
Modifiers:
rC # Right control
lC # Left control
# Using the (left/right) prefix is optional and applies to all modifiers
M # Meta/super/logo
A # Alt
S # Shift
Example
The configuration file is very similar to a TOML. Some differences include:
- Headings can include spaces
- All variables must start with
<and end with>on the left - Right side isn’t quoted
- The
@includedirective
[Stage 0]
<capslock> = <C-> # Globally remap capslock to ctrl
<lC-> = <esc> # Globally remap the bottom left control to escape
<esc> = <grave> # Notice, no conflict is present with the previous mapping
# The following mapping won't cause recursion. Note here that the side is
# preserved, so the right alt will be mapped to the right meta
<A-> = <M-> # Globally remap both Alts to the corresponding Meta
<M-> = <A-> # Globally remap both Metas to the corresponding Alt
[Stage 1]
# The ! negates the match. Here, this binding will apply to all apps except
# alacritty, xterm, and kitty
[[ ! Alacritty Xterm Kitty ]]
<C-backetleft> = <esc>
<C-p> = <up>
<C-n> = <down>
<C-j> = <left>
<C-f> = <right>
# In this example we're remapping to control modifier to itself
<C-w> = <C-right>
# The above is shorthand for the following:
# <lC-w> = <lC-right>
# <rC-w> = <rC-right>
# That is the "side" of the control is preserved
<C-b> = <C-left>
<C-a> = <home>
<C-e> = <end>
<C-i> = <S-end>
<C-u> = <C-S-left>
<C-h> = <backspace>
<C-d> = <delete>
[Stage 2]
# The following line inserts another config file at this stage. Note that stage
# 0 in the included file becomes stage 2. Stage 1 becomes stage 3 and so on...
# It's recommended to only have `[Stage 0]` in included files
@include /home/emiliko/.config/cutekey_nofn.toml
[[ Chromium Firefox ]] # This mapping applies to both firefox and chromium
<C-k> = <S-end>
<A-n> = <C-n>
<A-w> = <C-w>
<A-j> = <C-S-tab>
<A-k> = <C-tab>
<C-grave> = <grave> # Prevents accidental midnight discord calls
<A-f> = <C-f>
<A-l> = <C-l>
[[ Chromium ]]
<A-S-n> = <C-S-n>
[[ Firefox ]]
<A-S-n> = <C-S-p>