Define a StumpWM command that, when invoked, creates a named group, lays it out across two monitors per a chosen preset, and launches a set of applications, pulling each one into its assigned frame as it appears.
StumpWM. No external libraries.
Add to your init.lisp:
(add-to-load-path "~/.stumpwm.d/local-modules/layout-groups")
(load-module "layout-groups")(define-layout-group COMMAND-NAME "GROUP-NAME" PRESET
(SLOT CLASS-SUBSTRING LAUNCHER-STRING)
...)COMMAND-NAME– symbol; becomes a StumpWM command bindable by name.GROUP-NAME– string; the group’s displayed name.PRESET– keyword; chooses head/frame layout (see below).- Each app spec is
(slot class-substring launcher):slotis a keyword exposed by the chosen preset.class-substringis matched (case-insensitive substring) against each new window’sWM_CLASSto decide which spec it satisfies.launcheris the shell command to start the app.
Multiple specs may target the same slot; later arrivals cover earlier
ones in the frame and can be cycled with pull-hidden-next.
The defined command is idempotent: re-running it while the group exists
just switches to the group. To rebuild from scratch, kill the group
first (e.g. via your own gkill-windows-and-group binding) and re-run.
A “writing” group: editor on the left monitor, browser top-right, reference PDF bottom-right.
(define-layout-group writing "Writing" :tri-2-head-v-r
(:left "emacs" "emacsclient -c -a emacs ~/notes")
(:right-top "firefox" "firefox --no-remote -P writing")
(:right-bottom "zathura" "zathura ~/refs/handbook.pdf"))
(define-key *root-map* (kbd "W") "writing")Now C-t W (or whatever prefix you use) creates the Writing group,
splits the right monitor top/bottom, and launches the three apps into
their assigned frames.
All presets assume exactly 2 heads, sorted left-to-right by X.
| Preset | Left head | Right head | Slots |
|---|---|---|---|
:dual-2-heads | whole | whole | :left :right |
:tri-2-head-v-l | vsplit | whole | :left-top :left-bottom :right |
:tri-2-head-h-l | hsplit | whole | :left-left :left-right :right |
:tri-2-head-v-r | whole | vsplit | :left :right-top :right-bottom |
:tri-2-head-h-r | whole | hsplit | :left :right-left :right-right |
:quad-2-head-vv | vsplit | vsplit | :left-top :left-bottom :right-top :right-bottom |
:quad-2-head-hh | hsplit | hsplit | :left-left :left-right :right-left :right-right |
:quad-2-head-vh | vsplit | hsplit | :left-top :left-bottom :right-left :right-right |
:quad-2-head-hv | hsplit | vsplit | :left-left :left-right :right-top :right-bottom |
Naming: letters after 2-head- are read left-to-right as
“left head split / right head split”; v = top/bottom split,
h = left/right split.
The placer matches by case-insensitive substring against each window’s
WM_CLASS. To make matching reliable, give each app a distinct class:
alacritty --class my-class– setsWM_CLASSdirectly.firefox --no-remote -P profile– forces a separate process with a fresh window event. Without--no-remote, a second firefox invocation just opens a tab in an existing window and no new window event fires, so the placer never sees it.emacsclient -c -a emacs– emits classEmacs, matched by"emacs".
GNU GPL v3