Keybindings
Keybinds
Buckle up, this chapter is going to be long, because me loves LOTS of keybinds.
First, let’s declare again we are using the default package stumpwm
:
(in-package :stumpwm)
This will avoid us always repeating stumpwm:define-key
or stumpwm:kbd
instead of simply define-key
and kbd
.
StumpWM behaves a bit like Emacs in terms of keybinds. You have keymaps, which are a collection of keybinds, which in turn call CLisp functions. However, unlike Emacs, you have to declare a lot of keymaps, because StumpWM cannot (yet) understand keybinds such as (kbd "C-x c l")
, so you end up creating a keybind to a keymap which contains other keybinds, which might contain a couple of keybinds to other keymaps. I hope this will get improved soon.
There are also two keymaps you need to be aware of:
*top-map*
: This is the keymap available literally everywhere. With this keymap, you can emulate most of your keybinds you have in other window managers. For instance, I cannot live withouts-RET
for creating new shells, so I’ll bind it to*top-map*
. But it’s good practice to avoid polluting*top-map*
with too many keybinds.*root-map*
: This keymap is the default keymap that is already somewhat populated. It is available after hitting the prefix key set withset-prefix-key
which we will see just below.
It is interesting to note that once you entered any keymap, except *top-map*
, if you hit ?
you will see the list of available keybinds. I’d like it if something similar to general
in Emacs too could be implemented: give any arbitrary name to the keybind you just declared which would be displayed instead of the actual function or keymap called by keybind. It would be nicer to see frames
rather than *my-frames-management-keymap*
.
Anyway, as mentioned above, *root-map*
is already pre-populated with some cool stuff for you, and you can access it with a prefix which is by default C-t
. But if this doesn’t suit you, you can always redefine it with set-prefix-key
. I personally like to have my space key as a leader key, but in order to not have it conflict with Emacs, I also need to press the super key too.
(set-prefix-key (my/kbd "s-SPC"))
Also, let’s enable which-key
:
(which-key-mode)
Lastly, before we get more into details, keep in mind that I use the bépo layout, as I often say in my different documents. This means the characters found in the numbers’ row when pressing shift are actually the numbers themselves. Also, some characters are not recognized as is by kbd
, so we need to use a special name (not fun…). Below are the following characters:
Number | Character |
---|---|
1 | " |
2 | « |
3 | » |
4 | ( |
5 | ) |
6 | @ |
7 | + |
8 | - |
9 | / |
0 | * |
So if you see any weird keybind involving these characters, this is because of my layout.
Something a bit annoying though is Lisp doesn’t know some characters by their actual name, rather by another one that I find too long and too bothersome to remember. So here’s a list, if you see any of the characters on the left column in my config, with the function described below, my actual config will use their name as specified in the right column.
Character | Name |
---|---|
« | guillemotleft |
» | guillemotright |
To convert these characters, I have my own macro which is a wrapper around the function kbd
.
(defun my/kbd (keys)
"Prepares KEYS for function `stumpwm:kbd'.
If a character declared in the car of a member of the variable char,
it is replaced with its cdr. This allows the user to input characters
such as « or » and have them replaced with their actual name when
`stumpwm:kbd' is called."
(kbd (let ((chars '(("«" . "guillemotleft") ("»" . "guillemotright"))))
(dolist (row chars keys)
(setf keys (cl-ppcre:regex-replace-all (car row) keys (cdr row)))))))
Applications
When I speak about applications, I speak about programs and scripts in general. With these keymaps, I can launch programs I have often use for, but I can also launch some scripts as well as take screenshots.
First, let’s create my rofi
scripts keymap.
Keychord | Function |
---|---|
a | exec awiki |
r | exec rofi -combi-modi drun,window -show combi |
s | exec rofi -show ssh |
p | exec rofi-pass -t |
P | exec rofi-pass |
e | exec rofi-emoji |
m | exec rofi-mount |
u | exec rofi-umount |
w | exec wacom-setup |
y | exec ytplay |
Y | exec rofi-ytdl |
Here’s the equivalent in Common Lisp.
(defvar *my-rofi-keymap*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "a") "exec awiki")
(define-key m (my/kbd "r") "exec rofi -combi-modi drun,window -show combi")
(define-key m (my/kbd "s") "exec rofi -show ssh")
(define-key m (my/kbd "p") "exec rofi-pass -t")
(define-key m (my/kbd "P") "exec rofi-pass")
(define-key m (my/kbd "e") "exec rofi-emoji")
(define-key m (my/kbd "m") "exec rofi-mount")
(define-key m (my/kbd "u") "exec rofi-umount")
(define-key m (my/kbd "w") "exec wacom-setup")
(define-key m (my/kbd "y") "exec ytplay")
(define-key m (my/kbd "Y") "exec rofi-ytdl")
m))
Let’s also create a keymap for screenshots.
Keychord | Function |
---|---|
d | exec flameshot gui -d 3000 |
s | exec flameshot full |
S | exec flameshot gui |
Here’s the equivalent in Common Lisp.
(defvar *my-screenshot-keymap*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "d") "exec flameshot gui -d 3000")
(define-key m (my/kbd "s") "exec flameshot full")
(define-key m (my/kbd "S") "exec flameshot gui")
m))
We can now define our applications keymap which will reference both the above keymaps.
Keychord | Function |
---|---|
b | firefox |
B | exec qutebrowser |
d | exec discord |
e | exec emacsclient -c |
g | exec gimp |
n | exec nemo |
r | '*my-rofi-keymap* |
s | '*my-screenshot-keymap* |
w | exec select-pape |
This translates to:
(defvar *my-applications-keymap*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "b") "firefox")
(define-key m (my/kbd "B") "exec qutebrowser")
(define-key m (my/kbd "d") "exec discord")
(define-key m (my/kbd "e") "exec emacsclient -c")
(define-key m (my/kbd "g") "exec gimp")
(define-key m (my/kbd "n") "exec nemo")
(define-key m (my/kbd "r") '*my-rofi-keymap*)
(define-key m (my/kbd "s") '*my-screenshot-keymap*)
(define-key m (my/kbd "w") "exec select-pape")
m))
The application keymap can now be bound to the root map like so:
(define-key *root-map* (my/kbd "a") '*my-applications-keymap*)
I will also bind to the top map s-RET
in order to open a new terminal window. The screenshot keymap is also bound to the ScreenPrint key, and the XF86Mail
key opens mu4e in Emacs.
(define-key *top-map* (my/kbd "s-RET") "term")
(define-key *top-map* (my/kbd "Print") '*my-screenshot-keymap*)
(define-key *top-map* (my/kbd "XF86Mail") "exec emacsclient -c -e \"(mu4e)\"")
End of Session, Powering Off, and the Likes
The module end-session
provides functions for gracefully ending the user session, powering off, restarting, and suspending the computer. It also provides a function that interactively asks what the user wishes to do.
Keychord | Function |
---|---|
q | end-session |
l | logout |
s | suspend-computer |
S | shutdown-computer |
r | loadrc |
R | restart-hard |
C-r | restart-computer |
This translates to:
(defvar *my-end-session-keymap*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "q") "end-session")
(define-key m (my/kbd "l") "logout")
(define-key m (my/kbd "s") "suspend-computer")
(define-key m (my/kbd "S") "shutdown-computer")
(define-key m (my/kbd "r") "loadrc")
(define-key m (my/kbd "R") "restart-hard")
(define-key m (my/kbd "C-r") "restart-computer")
m))
Which is bound in the root map to q
:
(define-key *root-map* (my/kbd "q") '*my-end-session-keymap*)
Groups
A basic keybind I need for groups is to be able to switch from one another. I’m very used to the ability of being able to jump between them with the keybind Super + number of the group, so let’s define this:
(define-key *top-map* (my/kbd "s-\"") "gselect 1")
(define-key *top-map* (my/kbd "s-«") "gselect 2")
(define-key *top-map* (my/kbd "s-»") "gselect 3")
(define-key *top-map* (my/kbd "s-(") "gselect 4")
(define-key *top-map* (my/kbd "s-)") "gselect 5")
Another batch of keybinds I use a lot is keybinds to send the currently active window to another group, using Super + Shift + number of the group. As mentioned before, due to my keyboard layout Shift + number is actually just number for me (e.g. Shift + "
results in 1
), so there’s no need to convert the group number to another character.
(define-key *top-map* (my/kbd "s-1") "gmove-and-follow 1")
(define-key *top-map* (my/kbd "s-2") "gmove-and-follow 2")
(define-key *top-map* (my/kbd "s-3") "gmove-and-follow 3")
(define-key *top-map* (my/kbd "s-4") "gmove-and-follow 4")
(define-key *top-map* (my/kbd "s-5") "gmove-and-follow 5")
If I want to send a window to another group without following it, I’ll use s-S-C-<group number>
, which gives us the following:
(define-key *top-map* (my/kbd "s-C-1") "gmove-and-follow 1")
(define-key *top-map* (my/kbd "s-C-2") "gmove-and-follow 2")
(define-key *top-map* (my/kbd "s-C-3") "gmove-and-follow 3")
(define-key *top-map* (my/kbd "s-C-4") "gmove-and-follow 4")
(define-key *top-map* (my/kbd "s-C-5") "gmove-and-follow 5")
And if I want to bring the windows of another group into the current group, I’ll use s-C-<group number>
:
(define-key *top-map* (my/kbd "s-C-\"") "gmove-and-follow 1")
(define-key *top-map* (my/kbd "s-C-«") "gmove-and-follow 2")
(define-key *top-map* (my/kbd "s-C-»") "gmove-and-follow 3")
(define-key *top-map* (my/kbd "s-C-(") "gmove-and-follow 4")
(define-key *top-map* (my/kbd "s-C-)") "gmove-and-follow 5")
StumpWM also has already a nice keymap for managing groups called *groups-map*
, so let’s bind it to *root-map*
too! (It’s actually already bound, but since I plan on erasing *root-map*
in the near future before binding stuff to it, I prefer to bind it already)
(define-key *root-map* (my/kbd "g") '*groups-map*)
And a binding to vgroups
is done on *groups-map*
in order to regroup similar keybinds.
(define-key *groups-map* (my/kbd "G") "vgroups")
I grew accustomed to s-ESC
bringing me to the previous group when using AwesomeWM, so let’s define that:
(define-key *top-map* (my/kbd "s-ESC") "gother")
Frames and Windows management
As you’ll see, I have loads of keybinds related to frames and windows management. They are all categorized in a specific keymap, called *my-frames-management-keymap*
. But before that, let’s define the keymap *my-frames-float-keymap*
, with keybinds dedicated to actions related with floating windows and frames.
Keychord | Function |
---|---|
f | float-this |
F | unfloat-this |
u | unfloat-this |
C-f | flatten-floats |
We can now pass onto *my-frames-management-keymap*
. My keybinds are organized this way:
Keychord | Function |
---|---|
c | move-focus left |
t | move-focus down |
s | move-focus up |
r | move-focus right |
C | move-window left |
T | move-window down |
S | move-window up |
R | move-window right |
C-c | exchange-direction left |
C-t | exchange-direction down |
C-s | exchange-direction up |
C-r | exchange-direction right |
/ | hsplit-and-focus |
- | vsplit-and-focus |
h | hsplit |
v | vsplit |
H | hsplit-equally |
V | vsplit-equally |
. | iresize |
+ | balance-frames |
d | remove-split |
D | only |
e | expose |
f | fullscreen |
F | '*my-frames-float-keymap* |
i | info |
I | show-window-properties |
m | meta |
s | sibling |
u | next-urgent |
U | unmaximize |
As you can see, with the binding to F
, we make use of the *my-frames-float-keymap*
keymap declared above, which means if we find ourselves in *my-frames-management-keymap*
, pressing F
will bring us in *my-frames-float-keymap*
.
(defvar *my-frames-float-keymap*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "f") "float-this")
(define-key m (my/kbd "F") "unfloat-this")
(define-key m (my/kbd "u") "unfloat-this")
(define-key m (my/kbd "C-f") "flatten-floats")
m))
(defvar *my-frames-management-keymap*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "c") "move-focus left")
(define-key m (my/kbd "t") "move-focus down")
(define-key m (my/kbd "s") "move-focus up")
(define-key m (my/kbd "r") "move-focus right")
(define-key m (my/kbd "C") "move-window left")
(define-key m (my/kbd "T") "move-window down")
(define-key m (my/kbd "S") "move-window up")
(define-key m (my/kbd "R") "move-window right")
(define-key m (my/kbd "C-c") "exchange-direction left")
(define-key m (my/kbd "C-t") "exchange-direction down")
(define-key m (my/kbd "C-s") "exchange-direction up")
(define-key m (my/kbd "C-r") "exchange-direction right")
(define-key m (my/kbd "/") "hsplit-and-focus")
(define-key m (my/kbd "-") "vsplit-and-focus")
(define-key m (my/kbd "h") "hsplit")
(define-key m (my/kbd "v") "vsplit")
(define-key m (my/kbd "H") "hsplit-equally")
(define-key m (my/kbd "V") "vsplit-equally")
(define-key m (my/kbd ".") "iresize")
(define-key m (my/kbd "+") "balance-frames")
(define-key m (my/kbd "d") "remove-split")
(define-key m (my/kbd "D") "only")
(define-key m (my/kbd "e") "expose")
(define-key m (my/kbd "f") "fullscreen")
(define-key m (my/kbd "F") '*my-frames-float-keymap*)
(define-key m (my/kbd "i") "info")
(define-key m (my/kbd "I") "show-window-properties")
(define-key m (my/kbd "m") "meta")
(define-key m (my/kbd "s") "sibling")
(define-key m (my/kbd "u") "next-urgent")
(define-key m (my/kbd "U") "unmaximize")
m))
Let’s bind *my-frames-management-keymap*
in *root-keymap*
:
(define-key *root-map* (my/kbd "w") '*my-frames-management-keymap*)
That way, if we want for instance to split our current frame vertically, we’ll be able to type s-SPC w -
and vsplit
will be called.
I also bound a couple of these functions to the top keymap for easier access:
Keychord | Function |
---|---|
s-c | move-focus left |
s-t | move-focus down |
s-s | move-focus up |
s-r | move-focus right |
s-C | move-window left |
s-T | move-window down |
s-S | move-window up |
s-R | move-window right |
s-M-c | exchange-direction left |
s-M-t | exchange-direction down |
s-M-s | exchange-direction up |
s-M-r | exchange-direction right |
This translates to:
(define-key *top-map* (my/kbd "s-c") "move-focus left")
(define-key *top-map* (my/kbd "s-t") "move-focus down")
(define-key *top-map* (my/kbd "s-s") "move-focus up")
(define-key *top-map* (my/kbd "s-r") "move-focus right")
(define-key *top-map* (my/kbd "s-C") "move-window left")
(define-key *top-map* (my/kbd "s-T") "move-window down")
(define-key *top-map* (my/kbd "s-S") "move-window up")
(define-key *top-map* (my/kbd "s-R") "move-window right")
(define-key *top-map* (my/kbd "s-M-c") "exchange-direction left")
(define-key *top-map* (my/kbd "s-M-t") "exchange-direction down")
(define-key *top-map* (my/kbd "s-M-s") "exchange-direction up")
(define-key *top-map* (my/kbd "s-M-r") "exchange-direction right")
Being a bépo layout user, the hjkl
keys don’t exactly fit me, as you might have noticed with my use of ctsr
which is its equivalent. Due to this, the interactive keymap for iresize
is not ideal for me, let me redefine it:
(define-interactive-keymap (iresize tile-group) (:on-enter #'setup-iresize
:on-exit #'resize-unhide
:abort-if #'abort-resize-p
:exit-on ((kbd "RET") (kbd "ESC")
(kbd "C-g") (kbd "q")))
((my/kbd "c") "resize-direction left")
((my/kbd "t") "resize-direction down")
((my/kbd "s") "resize-direction up")
((my/kbd "r") "resize-direction right"))
As with groups management, I grew used to s-TAB
in AwesomeWM bringing me back to the previously focused window, and I also grew used to s-o
doing the same thing.
(define-key *top-map* (my/kbd "s-TAB") "other-window")
(define-key *top-map* (my/kbd "s-o") "other-window")
Windows management
When it comes to windows management, I will treat them a bit like I do with Emacs’ buffers.
Keychord | Function |
---|---|
b | windowlist |
d | delete-window |
D | delete-window-and-frame |
k | kill-window |
n | next |
o | other-window |
p | prev |
(defvar *my-buffers-management-keymap*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "b") "windowlist")
(define-key m (my/kbd "d") "delete-window")
(define-key m (my/kbd "D") "delete-window-and-frame")
(define-key m (my/kbd "k") "kill-window")
(define-key m (my/kbd "n") "next")
(define-key m (my/kbd "o") "other-window")
(define-key m (my/kbd "p") "prev")
m))
(define-key *root-map* (my/kbd "b") '*my-buffers-management-keymap*)
Media and Media Control
My music is managed through MPD, and I often use playerctl
commands in order to interact with it without any GUI application. So, we’ll see a lot of its usage here, and numerous commands used here come from the mpd
minor mode loaded in the init file.
First, let’s declare an interactive keymap in order to easily change several times in a row either the current song playing or the volume of MPD.
Keychord | Function |
---|---|
c | mpd-prev |
t | mpd-volume-down |
s | mpd-volume-up |
r | mpd-next |
This can be translated in CommonLisp as:
(define-interactive-keymap mpc-interactive
(:exit-on ((kbd "RET") (kbd "ESC")
(kbd "C-g") (kbd "q")))
((my/kbd "c") "mpd-prev")
((my/kbd "t") "mpd-volume-down")
((my/kbd "s") "mpd-volume-up")
((my/kbd "r") "mpd-next"))
We need to indicate also how much the volume is affected by mpd-volume-down
and mpd-volume-up
.
(setf *mpd-volume-step* 2)
Another one will be defined for the general audio of my computer. And I know it isn’t technically media keybinds, but I’ll add in keybinds for my screen’s backlight.
Keys | Function |
---|---|
c | exec xbacklight -perceived -dec 2 |
t | exec amixer -q set Master 2%- unmute |
s | exec amixer -q set Master 2%+ unmute |
r | exec xbacklight -perceived -inc 2 |
m | exec amixer -q set Master 1+ toggle |
(define-interactive-keymap media-interactive
(:exit-on ((kbd "RET") (kbd "ESC")
(kbd "C-g") (kbd "q")))
((my/kbd "c") "exec xbacklight -perceived -dec 2")
((my/kbd "t") "exec amixer -q set Master 2%- unmute")
((my/kbd "s") "exec amixer -q set Master 2%+ unmute")
((my/kbd "r") "exec xbacklight -perceived -inc 2")
((my/kbd "m") "exec amixer -q set Master 1+ toggle"))
Then, let’s declare a keymap for our media controls.
Keychord | Function |
---|---|
a | mpd-search-and-add-artist |
A | mpd-search-and-add-album |
f | mpd-search-and-add-file |
F | mpd-add-file |
g | mpd-search-and-add-genre |
t | mpd-search-and-add-title |
Keychord | Function |
---|---|
a | mpd-browse-artists |
A | mpd-browse-albums |
g | mpd-browse-genres |
p | mpd-browse-playlist |
t | mpd-browse-tracks |
Keychord | Function |
---|---|
. | media-interactive |
« | exec playerctl previous |
» | exec playerctl next |
a | '*my-mpd-add-map* |
b | '*my-mpd-browse-map* |
c | mpd-clear |
m | mpc-interactive |
p | exec playerctl play-pause |
s | exec playerctl stop |
u | mpd-update |
n | exec kitty ncmpcpp -q |
v | exec kitty ncmpcpp -qs visualizer |
Let’s translate this table in CommonLisp:
(defvar *my-mpd-add-map*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "a") "mpd-search-and-add-artist")
(define-key m (my/kbd "A") "mpd-search-and-add-album")
(define-key m (my/kbd "f") "mpd-search-and-add-file")
(define-key m (my/kbd "F") "mpd-add-file")
(define-key m (my/kbd "g") "mpd-search-and-add-genre")
(define-key m (my/kbd "t") "mpd-search-and-add-title")
m))
(defvar *my-mpd-browse-map*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "a") "mpd-browse-artists")
(define-key m (my/kbd "A") "mpd-browse-albums")
(define-key m (my/kbd "g") "mpd-browse-genres")
(define-key m (my/kbd "p") "mpd-browse-playlist")
(define-key m (my/kbd "t") "mpd-browse-tracks")
m))
(defvar *my-media-keymap*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd ".") "media-interactive")
(define-key m (my/kbd "«") "exec playerctl previous")
(define-key m (my/kbd "»") "exec playerctl next")
(define-key m (my/kbd "a") '*my-mpd-add-map*)
(define-key m (my/kbd "b") '*my-mpd-browse-map*)
(define-key m (my/kbd "c") "mpd-clear")
(define-key m (my/kbd "m") "mpc-interactive")
(define-key m (my/kbd "p") "exec playerctl play-pause")
(define-key m (my/kbd "s") "exec playerctl stop")
(define-key m (my/kbd "u") "mpd-update")
(define-key m (my/kbd "n") "exec kitty ncmpcpp -q")
(define-key m (my/kbd "v") "exec kitty ncmpcpp -qs visualizer")
m))
(define-key *root-map* (my/kbd "m") '*my-media-keymap*)
I will also define on *top-map*
some basic volume management keybinds so that they are immediately accessible. Again, this isn’t technically media-related, but I’ll add keybinds for my screen’s backlight.
Keychord | Function |
---|---|
XF86AudioPlay | exec playerctl play-pause |
XF86AudioPause | exec playerctl pause |
XF86AudioStop | exec playerctl stop |
XF86AudioPrev | exec playerctl previous |
XF86AudioNext | exec playerctl next |
XF86AudioRewind | exec playerctl position -1 |
XF86AudioForward | exec playerctl position +1 |
XF86AudioRaiseVolume | exec pamixer -i 2 |
XF86AudioLowerVolume | exec pamixer -d 2 |
XF86AudioMute | exec pamixer -t |
XF86MonBrightnessDown | exec xbacklight -perceived -dec 2 |
XF86MonBrightnessUp | exec xbacklight -perceived -inc 2 |
(define-key *top-map* (my/kbd "XF86AudioPlay") "exec playerctl play-pause")
(define-key *top-map* (my/kbd "XF86AudioPause") "exec playerctl pause")
(define-key *top-map* (my/kbd "XF86AudioStop") "exec playerctl stop")
(define-key *top-map* (my/kbd "XF86AudioPrev") "exec playerctl previous")
(define-key *top-map* (my/kbd "XF86AudioNext") "exec playerctl next")
(define-key *top-map* (my/kbd "XF86AudioRewind") "exec playerctl position -1")
(define-key *top-map* (my/kbd "XF86AudioForward") "exec playerctl position +1")
(define-key *top-map* (my/kbd "XF86AudioRaiseVolume") "exec pamixer -i 2")
(define-key *top-map* (my/kbd "XF86AudioLowerVolume") "exec pamixer -d 2")
(define-key *top-map* (my/kbd "XF86AudioMute") "exec pamixer -t")
(define-key *top-map* (my/kbd "XF86MonBrightnessDown") "exec xbacklight -perceived -dec 2")
(define-key *top-map* (my/kbd "XF86MonBrightnessUp") "exec xbacklight -perceived -inc 2")
Misc
Finally, some misc keybinds on the root map which don’t really fit anywhere else:
Keychord | Function |
---|---|
SPC | colon |
B | beckon |
C-b | banish |
l | exec plock |
r | reload |
(define-key *root-map* (my/kbd "SPC") "colon")
(define-key *root-map* (my/kbd "B") "beckon")
(define-key *root-map* (my/kbd "C-b") "banish")
(define-key *root-map* (my/kbd "l") "exec plock")
(define-key *root-map* (my/kbd "r") "reload")
From time to time, I need to switch between different keyboard layouts, especially to the US QWERTY layout when I’m playing some games and the bépo layout most of the time. I’ll use the command switch-layout
defined above.
Keychord | Function |
---|---|
b | exec setxkbmap fr bepo_afnor |
u | exec setxkbmap us |
(defvar *my-keyboard-layout-keymap*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "b") "exec setxkbmap fr bepo_afnor")
(define-key m (my/kbd "u") "exec setxkbmap us")
m))
(define-key *root-map* (my/kbd "k") '*my-keyboard-layout-keymap*)
NetworkManager integration
It is possible to have some kind of integration between StumpWM and NetworkManager. To do so, we have to load the related module, then create the two keybinds described in 19.
Keychord | Command |
---|---|
W | nm-list-wireless-networks |
A call to (ql:quickload :dbus)
is necessary for this module. Installing the dbus
module in turn requires the library libfixposix
installed on the user’s machine. On Arch, you can install it like so using paru
:
paru -S libfixposix --noconfirm
(ql:quickload :dbus)
(load-module "stump-nm")
(define-key *root-map* (my/kbd "W") "nm-list-wireless-networks")
Binwarp
Binwarp allows the user to control their mouse from the keyboard, basically eliminating the need for a physical mouse in daily usage of the workstation (though a physical mouse stays useful for games and such).
(load-module "binwarp")
Next, I’ll define my keybinds for when using Binwarp for emulating mouse clicks as well as bépo-compatible mouse movements. This new Binwarp mode is now available from the keybind s-m
at top level.
(binwarp:define-binwarp-mode my-binwarp-mode "s-m" (:map *top-map*)
((my/kbd "SPC") "ratclick 1")
((my/kbd "RET") "ratclick 3")
((my/kbd "c") "binwarp left")
((my/kbd "t") "binwarp down")
((my/kbd "s") "binwarp up")
((my/kbd "r") "binwarp right")
((my/kbd "i") "init-binwarp")
((my/kbd "q") "exit-binwarp"))
Bluetooth
It’s all nice and all, but typing manually the commands with s-SPC ;
is a bit tiring, so let’s define our Bluetooth keymap which we will bind to s-SPC B
.
Keychord | Command |
---|---|
c | bluetooth-connect |
o | bluetooth-turn-on |
O | bluetooth-turn-off |
(defvar *my-bluetooth-keymap*
(let ((m (make-sparse-keymap)))
(define-key m (my/kbd "c") "bluetooth-connect")
(define-key m (my/kbd "o") "bluetooth-turn-on")
(define-key m (my/kbd "O") "bluetooth-turn-off")
m))
(define-key *root-map* (my/kbd "B") '*my-bluetooth-keymap*)