diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2033b1c24..d92482dab 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -464,6 +464,9 @@ Makefile @thiagokokada /modules/services/window-managers/i3-sway/swaynag.nix @polykernel +/modules/services/window-managers/spectrwm @loicreynier +/tests/modules/services/window-managers/spectrwm @loicreynier + /modules/services/wlsunset.nix @matrss /tests/modules/services/wlsunset @matrss diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 192860bcf..9f6bd72f1 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -616,6 +616,14 @@ in 'defaults -currentHost' command. ''; } + + { + time = "2022-07-25T11:29:14+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'xsession.windowManager.spectrwm'. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index 6a423f3c5..3be6a1867 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -269,6 +269,7 @@ let ./services/window-managers/i3-sway/i3.nix ./services/window-managers/i3-sway/sway.nix ./services/window-managers/i3-sway/swaynag.nix + ./services/window-managers/spectrwm.nix ./services/window-managers/xmonad.nix ./services/wlsunset.nix ./services/xcape.nix diff --git a/modules/services/window-managers/spectrwm.nix b/modules/services/window-managers/spectrwm.nix new file mode 100644 index 000000000..f2d7af4c0 --- /dev/null +++ b/modules/services/window-managers/spectrwm.nix @@ -0,0 +1,135 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xsession.windowManager.spectrwm; + + renderedValue = val: + if isBool val then if val then "1" else "0" else toString val; + + renderedSettings = settings: + mapAttrsToList (name: value: "${name} = ${renderedValue value}") settings; + + renderedBindings = bindings: + mapAttrsToList (name: value: "bind[${name}] = ${value}") bindings; + + renderedUnbindings = unbindings: map (value: "bind[] = ${value}") unbindings; + + renderedPrograms = programs: + mapAttrsToList (name: value: "program[${name}] = ${value}") programs; + + renderedQuirks = quirks: + mapAttrsToList (name: value: "quirk[${name}] = ${value}") quirks; + + settingType = types.oneOf [ types.bool types.int types.str ]; + +in { + meta.maintainers = [ hm.maintainers.loicreynier ]; + + options = { + xsession.windowManager.spectrwm = { + enable = mkEnableOption "Spectrwm window manager"; + + package = mkOption { + type = types.package; + default = pkgs.spectrwm; + defaultText = literalExpression "pkgs.spectrwm"; + description = '' + Package providing the spectrwm command. + ''; + }; + + settings = mkOption { + type = types.attrsOf settingType; + default = { }; + example = literalExpression '' + { + modkey = "Mod4"; + workspace_limit = 5; + focus_mode = "manual"; + focus_close = "next"; + } + ''; + description = "Spectrwm settings."; + }; + + bindings = mkOption { + type = types.attrsOf types.str; + default = { }; + example = literalExpression '' + { + term = "Mod+Return"; + restart = "Mod+Shift+r"; + quit = "Mod+Shift+q"; + } + ''; + description = "Spectrwm keybindings."; + }; + + unbindings = mkOption { + type = types.listOf types.str; + default = [ ]; + example = literalExpression '' + [ + "MOD+e" + "MOD+f" + "MOD+m" + "MOD+s" + "MOD+u" + "MOD+t" + ] + ''; + description = '' + List of keybindings to disable from default Spectrwm configuration. + ''; + }; + + programs = mkOption { + type = types.attrsOf types.str; + default = { }; + example = literalExpression '' + { + term = "alacritty"; + search = "dmenu -ip -p 'Window name/id:'; + } + ''; + description = "Spectrwm programs variables."; + }; + + quirks = mkOption { + type = types.attrsOf types.str; + default = { }; + example = literalExpression '' + { + Matplotlib = "FLOAT"; + Pavucontrol = "FLOAT"; + } + ''; + description = "Spectrwm quicks (custom window rules)."; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (hm.assertions.assertPlatform "xsession.windowManager.spectrwm" pkgs + platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xsession.windowManager.command = "${cfg.package}/bin/spectrwm"; + + xdg.configFile."spectrwm/spectrwm.conf".text = '' + # Generated by Home Manager + ${concatStringsSep "\n" ( # \ + renderedSettings cfg.settings # \ + ++ renderedPrograms cfg.programs # \ + ++ renderedQuirks cfg.quirks # \ + ++ renderedBindings cfg.bindings # \ + ++ renderedUnbindings cfg.unbindings)} + ''; + }; +} diff --git a/tests/default.nix b/tests/default.nix index 42a96579c..017e31176 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -181,6 +181,7 @@ import nmt { ./modules/services/window-managers/bspwm ./modules/services/window-managers/herbstluftwm ./modules/services/window-managers/i3 + ./modules/services/window-managers/spectrwm ./modules/services/window-managers/sway ./modules/services/wlsunset ./modules/services/xsettingsd diff --git a/tests/modules/services/window-managers/spectrwm/default.nix b/tests/modules/services/window-managers/spectrwm/default.nix new file mode 100644 index 000000000..be53aa1b6 --- /dev/null +++ b/tests/modules/services/window-managers/spectrwm/default.nix @@ -0,0 +1 @@ +{ spectrwm-simple-config = ./spectrwm-simple-config.nix; } diff --git a/tests/modules/services/window-managers/spectrwm/spectrwm-simple-config-expected-spectrwm.conf b/tests/modules/services/window-managers/spectrwm/spectrwm-simple-config-expected-spectrwm.conf new file mode 100644 index 000000000..54e55ad4a --- /dev/null +++ b/tests/modules/services/window-managers/spectrwm/spectrwm-simple-config-expected-spectrwm.conf @@ -0,0 +1,8 @@ +# Generated by Home Manager +bar_enabled = 1 +bar_format = +S [+R:+I] %a %b %d [%R] +bar_justify = center +modkey = Mod4 +program[term] = alacritty +bind[term] = MOD+Shift+Return +bind[] = MOD+Return diff --git a/tests/modules/services/window-managers/spectrwm/spectrwm-simple-config.nix b/tests/modules/services/window-managers/spectrwm/spectrwm-simple-config.nix new file mode 100644 index 000000000..3ba13b4d3 --- /dev/null +++ b/tests/modules/services/window-managers/spectrwm/spectrwm-simple-config.nix @@ -0,0 +1,25 @@ +{ ... }: + +{ + xsession.windowManager.spectrwm = { + enable = true; + settings = { + bar_enabled = true; + bar_format = "+S [+R:+I] %a %b %d [%R]"; + bar_justify = "center"; + modkey = "Mod4"; + }; + programs = { term = "alacritty"; }; + bindings = { term = "MOD+Shift+Return"; }; + unbindings = [ "MOD+Return" ]; + }; + + test.stubs.spectrwm = { }; + + nmt.script = '' + assertFileContent \ + home-files/.config/spectrwm/spectrwm.conf ${ + ./spectrwm-simple-config-expected-spectrwm.conf + } + ''; +}