diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 6626e1099..950ad2896 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -893,6 +893,13 @@ in A new module is available: 'programs.papis'. ''; } + + { + time = "2023-01-30T10:39:11+00:00"; + message = '' + A new module is available: 'programs.wlogout'. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index f831bcacf..b50564177 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -192,6 +192,7 @@ let ./programs/watson.nix ./programs/waybar.nix ./programs/wezterm.nix + ./programs/wlogout.nix ./programs/xmobar.nix ./programs/yt-dlp.nix ./programs/z-lua.nix diff --git a/modules/programs/wlogout.nix b/modules/programs/wlogout.nix new file mode 100644 index 000000000..49e59b078 --- /dev/null +++ b/modules/programs/wlogout.nix @@ -0,0 +1,151 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) all filterAttrs isStorePath literalExpression types; + inherit (lib.options) mkEnableOption mkPackageOption mkOption; + inherit (lib.modules) mkIf; + inherit (lib.strings) concatMapStrings; + inherit (builtins) toJSON; + + cfg = config.programs.wlogout; + + jsonFormat = pkgs.formats.json { }; + + wlogoutLayoutConfig = with types; + submodule { + freeformType = jsonFormat.type; + + options = { + label = mkOption { + type = str; + default = ""; + example = "shutdown"; + description = "CSS label of button."; + }; + + action = mkOption { + type = either path str; + default = ""; + example = "systemctl poweroff"; + description = "Command to execute when clicked."; + }; + + text = mkOption { + type = str; + default = ""; + example = "Shutdown"; + description = "Text displayed on button."; + }; + + keybind = mkOption { + type = str; + default = ""; + example = "s"; + description = "Keyboard character to trigger this action."; + }; + + height = mkOption { + type = nullOr (numbers.between 0 1); + default = null; + example = 0.5; + description = "Relative height of tile."; + }; + + width = mkOption { + type = nullOr (numbers.between 0 1); + default = null; + example = 0.5; + description = "Relative width of tile."; + }; + + circular = mkOption { + type = nullOr bool; + default = null; + example = true; + description = "Make button circular."; + }; + }; + }; +in { + meta.maintainers = [ lib.maintainers.Scrumplex ]; + + options.programs.wlogout = with lib.types; { + enable = mkEnableOption "wlogout"; + + package = mkPackageOption pkgs "wlogout" { }; + + layout = mkOption { + type = listOf wlogoutLayoutConfig; + default = [ ]; + description = '' + Layout configuration for wlogout, see + for supported values. + ''; + example = literalExpression '' + [ + { + label = "shutdown"; + action = "systemctl poweroff"; + text = "Shutdown"; + keybind = "s"; + } + ] + ''; + }; + + style = mkOption { + type = nullOr (either path str); + default = null; + description = '' + CSS style of the bar. + + + See + for the documentation. + + + If the value is set to a path literal, then the path will be used as the css file. + ''; + example = '' + window { + background: #16191C; + } + + button { + color: #AAB2BF; + } + ''; + }; + }; + + config = let + # Removes nulls because wlogout ignores them. + # This is not recursive. + removeTopLevelNulls = filterAttrs (_: v: v != null); + cleanJSON = foo: toJSON (removeTopLevelNulls foo); + + # wlogout doesn't want a JSON array, it just wants a list of JSON objects + layoutJsons = map cleanJSON cfg.layout; + layoutContent = concatMapStrings (l: l + "\n") layoutJsons; + + in mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "programs.wlogout" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."wlogout/layout" = mkIf (cfg.layout != [ ]) { + source = pkgs.writeText "wlogout/layout" layoutContent; + }; + + xdg.configFile."wlogout/style.css" = mkIf (cfg.style != null) { + source = if builtins.isPath cfg.style || isStorePath cfg.style then + cfg.style + else + pkgs.writeText "wlogout/style.css" cfg.style; + }; + }; +} diff --git a/tests/default.nix b/tests/default.nix index 9c60acead..57dedbb8b 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -163,6 +163,7 @@ import nmt { ./modules/programs/terminator ./modules/programs/thunderbird ./modules/programs/waybar + ./modules/programs/wlogout ./modules/programs/xmobar ./modules/programs/yt-dlp ./modules/services/barrier diff --git a/tests/modules/programs/wlogout/default.nix b/tests/modules/programs/wlogout/default.nix new file mode 100644 index 000000000..294772e74 --- /dev/null +++ b/tests/modules/programs/wlogout/default.nix @@ -0,0 +1,5 @@ +{ + wlogout-styling = ./styling.nix; + wlogout-layout-single = ./layout-single.nix; + wlogout-layout-multiple = ./layout-multiple.nix; +} diff --git a/tests/modules/programs/wlogout/layout-multiple-expected.json b/tests/modules/programs/wlogout/layout-multiple-expected.json new file mode 100644 index 000000000..9e69d4e93 --- /dev/null +++ b/tests/modules/programs/wlogout/layout-multiple-expected.json @@ -0,0 +1,6 @@ +{"action":"systemctl poweroff","keybind":"s","label":"shutdown","text":"Shutdown"} +{"action":"systemctl hibernate","height":0.5,"keybind":"h","label":"hibernate","text":"Hibernate","width":0.5} +{"action":"systemctl suspend","circular":true,"keybind":"u","label":"suspend","text":"Suspend"} +{"action":"swaymsg exit","keybind":"e","label":"exit","text":"Exit"} +{"action":"systemctl reboot","keybind":"r","label":"reboot","text":"Reboot"} +{"action":"gtklock","keybind":"l","label":"lock","text":"Lock"} diff --git a/tests/modules/programs/wlogout/layout-multiple.nix b/tests/modules/programs/wlogout/layout-multiple.nix new file mode 100644 index 000000000..108961aae --- /dev/null +++ b/tests/modules/programs/wlogout/layout-multiple.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "22.11"; + + programs.wlogout = { + package = config.lib.test.mkStubPackage { outPath = "@wlogout@"; }; + enable = true; + layout = [ + { + label = "shutdown"; + action = "systemctl poweroff"; + text = "Shutdown"; + keybind = "s"; + } + { + label = "hibernate"; + action = "systemctl hibernate"; + text = "Hibernate"; + keybind = "h"; + height = 0.5; + width = 0.5; + } + { + label = "suspend"; + action = "systemctl suspend"; + text = "Suspend"; + keybind = "u"; + circular = true; + } + { + label = "exit"; + action = "swaymsg exit"; + text = "Exit"; + keybind = "e"; + } + { + label = "reboot"; + action = "systemctl reboot"; + text = "Reboot"; + keybind = "r"; + } + { + label = "lock"; + action = "gtklock"; + text = "Lock"; + keybind = "l"; + } + ]; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/wlogout/style.css + assertFileContent \ + home-files/.config/wlogout/layout \ + ${./layout-multiple-expected.json} + ''; + }; +} diff --git a/tests/modules/programs/wlogout/layout-single-expected.json b/tests/modules/programs/wlogout/layout-single-expected.json new file mode 100644 index 000000000..d4d43dde3 --- /dev/null +++ b/tests/modules/programs/wlogout/layout-single-expected.json @@ -0,0 +1 @@ +{"action":"systemctl poweroff","keybind":"s","label":"shutdown","text":"Shutdown"} diff --git a/tests/modules/programs/wlogout/layout-single.nix b/tests/modules/programs/wlogout/layout-single.nix new file mode 100644 index 000000000..bbb5d61e6 --- /dev/null +++ b/tests/modules/programs/wlogout/layout-single.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "22.11"; + + programs.wlogout = { + package = config.lib.test.mkStubPackage { outPath = "@wlogout@"; }; + enable = true; + layout = [{ + label = "shutdown"; + action = "systemctl poweroff"; + text = "Shutdown"; + keybind = "s"; + }]; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/wlogout/style.css + assertFileContent \ + home-files/.config/wlogout/layout \ + ${./layout-single-expected.json} + ''; + }; +} diff --git a/tests/modules/programs/wlogout/styling-expected.css b/tests/modules/programs/wlogout/styling-expected.css new file mode 100644 index 000000000..49050beb4 --- /dev/null +++ b/tests/modules/programs/wlogout/styling-expected.css @@ -0,0 +1,16 @@ +* { + border: none; + border-radius: 0; + font-family: Source Code Pro; + font-weight: bold; + color: #abb2bf; + font-size: 18px; + min-height: 0px; +} +window { + background: #16191C; + color: #aab2bf; +} +#window { + padding: 0 0px; +} diff --git a/tests/modules/programs/wlogout/styling.nix b/tests/modules/programs/wlogout/styling.nix new file mode 100644 index 000000000..6df6290fd --- /dev/null +++ b/tests/modules/programs/wlogout/styling.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + config = { + home.stateVersion = "22.11"; + + programs.wlogout = { + package = config.lib.test.mkStubPackage { outPath = "@wlogout@"; }; + enable = true; + style = '' + * { + border: none; + border-radius: 0; + font-family: Source Code Pro; + font-weight: bold; + color: #abb2bf; + font-size: 18px; + min-height: 0px; + } + window { + background: #16191C; + color: #aab2bf; + } + #window { + padding: 0 0px; + } + ''; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/wlogout/layout + assertFileContent \ + home-files/.config/wlogout/style.css \ + ${./styling-expected.css} + ''; + }; +}