Skip to content

Commit 4b2fdfd

Browse files
Seeker04Seeker04
authored andcommitted
Configuration overhaul (#30)
- Settings are no longer compiled in, only loaded during runtime - Settings can be changed dynamically (with set/2 and add/2) - Any setting can be omitted, because everything has a default value - Default settings are installed to /etc/plwm/config.pl - reload_config/0 re-reads config file - dump_settings/1 dumps current setting values to a file - Config files must NOT use module declarations (settings are in the global namespace) - bar_class/2 became bar_classes/1 taking a list (all settings must have arity 1 and be deterministic)
1 parent 9facf36 commit 4b2fdfd

File tree

17 files changed

+1444
-556
lines changed

17 files changed

+1444
-556
lines changed

Dockerfile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ ENV DEBIAN_FRONTEND=noninteractive
99
# Use UTF-8 encoding, otherwise swipl throws "Illegal multibyte Sequence" errors
1010
ENV LANG=en_US.UTF-8
1111

12-
# Set user config directory
13-
ENV XDG_CONFIG_HOME=/home/testuser/.config
14-
1512
# Update package list and install required packages
1613
RUN apt-get update && \
1714
apt-get install -y \

Makefile

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,11 @@ LDFLAGS = -shared -lX11 -lXft -lXrandr
1414
SWIFLAGS = -p foreign=$(INSTALLDIR_LIB) \
1515
--goal=main --toplevel=halt --stand_alone=true -O -o plwm -c src/plwm.pl
1616

17-
INSTALLDIR = /usr/local/bin
17+
INSTALLDIR_BIN = /usr/local/bin
1818
INSTALLDIR_LIB = /usr/local/lib
19+
INSTALLDIR_CNF = /etc/plwm
1920
INSTALLDIR_MAN = /usr/local/share/man/man1
2021

21-
ifdef XDG_CONFIG_HOME
22-
CONFIG_PATH = $(XDG_CONFIG_HOME)/plwm
23-
else
24-
CONFIG_PATH = $(HOME)/.config/plwm
25-
endif
26-
2722
#================================== Build =====================================
2823

2924
plwm: plx.so src/*.pl
@@ -67,18 +62,16 @@ test:
6762
VERSION = ${shell sed -n 's/^version(\([0-9.]\+\))\.$$/\1/p' src/plwm.pl}
6863

6964
install: plwm
70-
install -D --mode=755 plwm $(INSTALLDIR)/plwm
65+
install -D --mode=755 plwm $(INSTALLDIR_BIN)/plwm
7166
install -D --mode=755 plx.so $(INSTALLDIR_LIB)/plx.so
67+
install -D --mode=644 -C --backup=numbered config/config.pl $(INSTALLDIR_CNF)/config.pl
7268
mkdir -p $(INSTALLDIR_MAN)
7369
sed 's/VERSION/$(VERSION)/' < docs/plwm.1 > $(INSTALLDIR_MAN)/plwm.1
7470
chmod 644 $(INSTALLDIR_MAN)/plwm.1
7571

7672
uninstall:
77-
rm -f $(INSTALLDIR)/plwm \
73+
rm -f $(INSTALLDIR_BIN)/plwm \
7874
$(INSTALLDIR_LIB)/plx.so \
7975
$(INSTALLDIR_MAN)/plwm.1
80-
81-
mkconfig:
82-
install -D src/config.pl $(CONFIG_PATH)/config.pl
83-
sed -i 's/module(config/module(runtime_config/' $(CONFIG_PATH)/config.pl
76+
[ -d $(INSTALLDIR_CNF) ] && echo "Note: $(INSTALLDIR_CNF) is kept" || true
8477

README.md

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -181,24 +181,16 @@ then you'll have a triple stack layout where your windows will be evenly spread
181181

182182
## Configuration
183183

184-
Configuration is done by modifying [config.pl](src/config.pl) then recompiling with `make && sudo make install`.
184+
`sudo make install` installs the [default configuration](config/config.pl) to `/etc/plwm/config.pl`. This file can be copied to user config directories.
185185

186-
plwm will also attempt reading configuration when it starts from the first file among
186+
plwm attempts reading configuration when it starts from the first file among
187187
- `$XDG_CONFIG_HOME/plwm/config.pl`
188188
- `$HOME/.config/plwm/config.pl`
189189
- `/etc/plwm/config.pl`
190190

191-
if any exists, so users don't have to recompile each time if they don't wish to. Any values read from the runtime config will override the compiled in settings.
192-
193191
A custom path can be specified with the `-c` flag.
194192

195-
**Attention:** the module name in the runtime config must be `runtime_config`!
196-
197-
You can run:
198-
199-
`$ make mkconfig`
200-
201-
which takes `src/config.pl` and generates the runtime config from it. Then keep modifying the latter while leaving the former in the default state. Or you can use the source one as a stable config and the runtime one for experimental overrides...
193+
**Note:** a reinstall will overwrite `/etc/plwm/config.pl`, however a backup is always created if there is any difference.
202194

203195
While cooking your config, you can use the `-C` flag to quickly and easily check its validity.
204196

@@ -223,7 +215,7 @@ While cooking your config, you can use the `-C` flag to quickly and easily check
223215
| `ws_format` | string with a \~w **or**<br/>string with a \~d followed by a \~w<br>**Default:** "\~w" | Format of empty workspaces on bars (~d = index, ~w = name) |
224216
| `ws_format_occupied` | string with a \~w **or**<br/>string with a \~d followed by a \~w<br>**Default:** "▘\~w" | Format of occupied workspaces on bars |
225217
| `layout_default_overrides` | list of (Monitor, Workspace -> Nmaster, Mfact, Layout)<br>**Default:** [] | Overrides of the 3 values to specific monitors and/or workspaces (explained [here](#layout-overrides)) |
226-
| `bar_class` | the two strings from bar's WM_CLASS,<br/>query with [xprop(1)](https://linux.die.net/man/1/xprop)<br>**Default:** "polybar", "Polybar" | Space will be reserved for matching windows and they cannot be focused, resized, etc. |
218+
| `bar_classes` | list of string pairs from bar's WM_CLASS,<br/>query with [xprop(1)](https://linux.die.net/man/1/xprop)<br>**Default:** ["polybar"-"Polybar"] | Space will be reserved for matching windows and they cannot be focused, resized, etc. |
227219
| `bar_placement` | follow_focus, static<br>**Default:** follow_focus | Determines placement of external bars (explained [here](#layout-overrides)) |
228220
| `fifo_enabled` | true or false<br>**Default:** false | Whether to spawn a command FIFO<br>(explained [here](#scriptability)) |
229221
| `fifo_path` | string<br>**Default:** "/tmp/plwm_fifo" | Path of command FIFO |
@@ -238,13 +230,31 @@ While cooking your config, you can use the `-C` flag to quickly and easily check
238230
| `rules` | list of (Name, Class, Title -> Monitor, Workspace, Mode)<br>**Default:** [] | Auto place and configure matching windows (explained [here](#rules)) |
239231
| `hooks` | list of (Event -> Action)<br>**Default:** `[start -> writeln("plwm starting"), quit -> writeln("plwm quitting")]` | Run custom logic on certain events (explained [here](#hooks)) |
240232

241-
**Notes**
233+
**Tips**
242234

243-
In `keymaps/1`, the callback predicates can be arbitrary shell commands using `shellcmd/1`, even whole commandlines (some examples are included in the [default config](src/config.pl)).
235+
* You can safely remove any setting from your config file, plwm will use the default value for those.
236+
* In `keymaps/1`, the callback predicates can be arbitrary shell commands using `shellcmd/1`, even whole commandlines (some examples are included in the [default config](config/config.pl)).
237+
* If you wish to stick to default keymaps mostly, with only a few changes and feel redundant to list the whole table in your config, you can simply omit the `keymaps/1` setting and add your changes as a `start` hook like this:
238+
239+
```Prolog
240+
hooks([
241+
start -> (
242+
add(keymaps, super + g -> shellcmd("gcolor2")), % add new
243+
add(keymaps, super + l -> switch_workspace(next)), % overwrite existing
244+
add(keymaps, super + f -> none) % remove existing
245+
)
246+
]).
247+
```
248+
249+
**Changing settings during runtime**
250+
251+
* `set/2` and `add/2` can be used to overwrite or append to existing settings, respectively. You can invoke them via a keymap, the [command fifo](#scriptability) or the [command menu](#menus).
252+
* The whole configuration file can be reloaded by calling `reload_config/0`.
253+
* You can use `dump_settings/1` to dump all current settings to a file.
244254

245255
## External bars
246256

247-
First, you must specify `bar_class/2` based on the WM_CLASS properties of your bars, which you can find out using [xprop(1)](https://linux.die.net/man/1/xprop). Then you can both:
257+
First, you must specify `bar_classes/1` based on the WM_CLASS properties of your bars, which you can find out using [xprop(1)](https://linux.die.net/man/1/xprop). Then you can both:
248258
* manually start/close bars while plwm is already running
249259
* automatically start bars using `hooks/1` and its `start` event in the config
250260

@@ -275,7 +285,7 @@ alt + b -> shellcmd("pkill -fx 'polybar top' || polybar top"),
275285
alt + shift + b -> shellcmd("pkill -fx 'polybar bot' || polybar bot")
276286
```
277287

278-
**Note:** if you are using polybar, **do not enable** its `override-redirect = true` setting (it can even crash plwm in some cases)! Reasoning: plwm itself handles all bars (anything that matches `bar_class`, not just polybar) the intended way: bars cannot be focused, grabbed, moved or resized; tiling windows will never cover them (but you can drag floating windows above them); fullscreen windows will always cover them.
288+
**Note:** if you are using polybar, **do not enable** its `override-redirect = true` setting (it can even crash plwm in some cases)! Reasoning: plwm itself handles all bars (anything that matches `bar_classes`, not just polybar) the intended way: bars cannot be focused, grabbed, moved or resized; tiling windows will never cover them (but you can drag floating windows above them); fullscreen windows will always cover them.
279289

280290
## Multi-monitor
281291

@@ -538,9 +548,9 @@ For known problems, see [the Issues with bug labels](https://github.com/Seeker04
538548

539549
First and foremost, if you find any bugs, please [create a GitHub issue](https://github.com/Seeker04/plwm/issues/new), preferably, with all details you can provide. (First, please check if it's not reported already).
540550

541-
If you have a feature request, please do the same.
551+
If you have a feature request or questions, feel free to [open discussions](https://github.com/Seeker04/plwm/discussions).
542552

543-
Any code contribution is also welcome. Especially if it solves some known issue. For brand new ideas, I recommend creating an issue first, so we can discuss it.
553+
Any code contribution is also welcome. Especially if it solves some known issue. For brand new ideas, I recommend creating a discussion first.
544554

545555
Please read the [Development Guide](docs/development_guide.md).
546556

@@ -570,15 +580,17 @@ export _JAVA_AWT_WM_NONREPARENTING=1
570580
```
571581
to your `.xinitrc` should solve this problem.
572582

573-
**plwm doesn't start! What's going on?**
583+
**My configuration doesn't work!**
574584

575-
Most likely your configuration is faulty. Run `plwm --check`, then you should see the problem.
585+
Run `plwm --check`, then you should see the problem. Consult the [table here](#configuration) to see the proper type for each setting. E.g. make sure you use double quotes for _strings_ and single quotes for _atoms_.
576586

577-
If you don't see a config error, then please report it as an issue. Preferably by attaching any message plwm dumps to stderr or to its logfile with `-l`.
587+
If you don't see any error, then please report it as an issue by attaching your config and any message plwm dumps to stderr or to its logfile with `-l`.
578588

579589
**Something is missing...**
580590

581-
plwm is minimal in the sense that it doesn't try to solve problems outside of a window manager's domain, especially if they are easily served by other programs (see [here](https://en.wikipedia.org/wiki/Unix_philosophy)):
591+
tl;dr plwm is a window manager, not a full-fledged desktop environment.
592+
593+
plwm is minimal in the sense that it doesn't try to solve problems outside of a wm's domain, especially if they are easily served by other programs (see [here](https://en.wikipedia.org/wiki/Unix_philosophy)):
582594

583595
* Don't want a status bar? You're set. Want one (or more)? Here are a few: [polybar](https://polybar.github.io/), [lemonbar](https://github.com/LemonBoy/bar), [xmobar](https://codeberg.org/xmobar/xmobar)
584596
* Want transparent windows or other effects? Use a compositor like [picom](https://wiki.archlinux.org/title/Picom)

src/config.pl renamed to config/config.pl

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
% MIT License, Copyright (c) 2023-2025 Barnabás Zahorán, see LICENSE
22
%
3+
% This is plwm's default configuration installed under /etc
4+
%
5+
% You can revert this file by reinstalling plwm (if it differs, a backup will be kept)
6+
%
7+
% Users can create their own configs under
8+
% $XDG_CONFIG_HOME/plwm/config.pl
9+
% or
10+
% $HOME/.config/plwm/config.pl
11+
% to overrule this file
12+
%
313
% Note: there is extensive commenting in this file, as well as arbitrary examples
414
% for easier understanding. Feel free to remove them once you're familiar with the settings
515

6-
:- module(config, []).
7-
816
%********************************* Layout ***********************************
917

1018
default_nmaster(1). % initial number of master windows for master-stack layouts
@@ -79,10 +87,9 @@
7987
%********************************** Bars ************************************
8088

8189
% Use xprop(1) or a similar tool to find out the WM_CLASS property of your bar
82-
% You may specify only the name: ("name", _) or only the class: (_, "class")
83-
% List multiple bar_class lines below if you use multiple different bars
84-
% You can delete the line, if you don't use any bar
85-
bar_class("polybar", "Polybar").
90+
% You may specify only the name: "name"-_ or only the class: _-"class"
91+
% List multiple bar_classes if you use multiple different bars
92+
bar_classes(["polybar"-"Polybar"]).
8693

8794
% Possible values:
8895
% follow_focus: space will be reserved for bars on all monitors and bars will
@@ -243,22 +250,22 @@
243250

244251
%%%%% Custom mapping examples %%%%%
245252

253+
% Launch applications
254+
ctrl + shift + space -> shellcmd("alacritty") ,
255+
alt + a -> shellcmd("dmenu_run -l 20 -p run")
256+
246257
% Toggle status bar
247-
alt + b -> shellcmd("pkill polybar || polybar top") ,
258+
%alt + b -> shellcmd("pkill polybar || polybar top") ,
248259
%alt + b -> shellcmd("pkill polybar || (polybar top & polybar bot)") ,
249260
%alt + b -> shellcmd("pkill -fx 'polybar top' || polybar top") ,
250261
%alt + shift + b -> shellcmd("pkill -fx 'polybar bot' || polybar bot") ,
251262

252-
% Launch applications
253-
ctrl + shift + space -> shellcmd("alacritty") ,
254-
alt + a -> shellcmd("dmenu_run -c -l 20") ,
255-
256263
% Special keys (see xf86names.pl for all such keys)
257-
"AudioRaiseVolume" -> shellcmd("pulseaudio-ctl up") ,
258-
"AudioLowerVolume" -> shellcmd("pulseaudio-ctl down") ,
259-
"AudioMute" -> shellcmd("pulseaudio-ctl mute") ,
260-
"MonBrightnessUp" -> shellcmd("xbacklight -inc 1") ,
261-
"MonBrightnessDown" -> shellcmd("xbacklight -dec 1")
264+
%"AudioRaiseVolume" -> shellcmd("pulseaudio-ctl up") ,
265+
%"AudioLowerVolume" -> shellcmd("pulseaudio-ctl down") ,
266+
%"AudioMute" -> shellcmd("pulseaudio-ctl mute") ,
267+
%"MonBrightnessUp" -> shellcmd("xbacklight -inc 1") ,
268+
%"MonBrightnessDown" -> shellcmd("xbacklight -dec 1")
262269
]).
263270

264271

@@ -288,9 +295,9 @@
288295

289296
rules([
290297
% name class title monitor wspace mode
291-
(_ , _ , exact("gcolor2") -> _ , _ , [center, center, 1/3, 1/3]),
292-
(_ , _ , "Firefox" -> "eDP-1" , 'www' , fullscreen ),
293-
("Bar" , "Baz" , _ -> "HDMI-1" , '1' , [700, 250, _, _] )
298+
% ( _ , _ , exact("gcolor2") -> _ , _ , [center, center, 1/3, 1/3] ),
299+
% ( _ , _ , "Firefox" -> "eDP-1" , 'www' , fullscreen ),
300+
% ( "Bar" , "Baz" , _ -> "HDMI-1" , '1' , [700, 250, _, _] )
294301
]).
295302

296303
% You can find out the name, class and title values of windows using xprop(1):

docs/development_guide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ User interaction is possible by three methods:
5151
| ----------------------------------- | ----------------------------------------- |
5252
| [plwm.pl](../src/plwm.pl) | entry point, event loop and wm logic |
5353
| [animation.pl](../src/animation.pl) | window animations |
54-
| [config.pl](../src/config.pl) | default configuration |
5554
| [fifo.pl](../src/fifo.pl) | command fifo implementation |
5655
| [layout.pl](../src/layout.pl) | layout definitions |
5756
| [menu.pl](../src/menu.pl) | menu commands |
57+
| [setting.pl](../src/setting.pl) | settings related predicates |
5858
| [utils.pl](../src/utils.pl) | common utilities used by multiple modules |
5959
| [xf86names.pl](../src/xf86names.pl) | definitions for special keys |
6060
| [plx.c](../src/plx.c) | libX11 bindings |

src/fifo.pl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44

55
%! setup_fifo() is det
66
%
7-
% If config:fifo_enabled/1 and config:fifo_path/1 are set, attempts to create
7+
% If fifo_enabled/1 and fifo_path/1 are set, attempts to create
88
% a named pipe with mkfifo(1).
99
% If the fifo is created, its path is passed to fifo:process_fifo/1 on a detached thread.
1010
setup_fifo() :-
11-
optcnf_then(fifo_enabled(true), optcnf_then(fifo_path(FifoPath), (
11+
(fifo_enabled(true), fifo_path(FifoPath) ->
1212
catch(delete_file(FifoPath), _, true), % cleanup from previous execution
1313
string_concat("mkfifo ", FifoPath, MkFifoCmd), % no swipl predicate for this
1414
shell(MkFifoCmd, ExitCode),
1515
(ExitCode == 0 ->
1616
thread_create(fifo:process_fifo(FifoPath), _, [detached(true)])
1717
; writeln(user_error, "Could not spawn command fifo!"))
18-
)))
18+
; true)
1919
.
2020

2121
%! process_fifo(++FifoPath:string) is det

0 commit comments

Comments
 (0)