diff --git a/modules/programs/workstyle.nix b/modules/programs/workstyle.nix new file mode 100644 index 000000000..5ac6ec77e --- /dev/null +++ b/modules/programs/workstyle.nix @@ -0,0 +1,94 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + inherit (lib) literalExpression mkOption mkEnableOption; + inherit (lib.modules) mkIf; + + cfg = config.programs.workstyle; + + tomlFormat = pkgs.formats.toml { }; + + configFile = tomlFormat.generate "config.toml" cfg.settings; +in +{ + meta.maintainers = with lib.hm.maintainers; [ farberbrodsky ]; + + options.programs.workstyle = { + enable = mkEnableOption "Workstyle"; + + package = lib.mkPackageOption pkgs "workstyle" { }; + + systemd = { + enable = mkEnableOption "Workstyle systemd integration"; + + debug = mkEnableOption "Workstyle debug logs"; + + target = mkOption { + type = lib.types.str; + default = config.wayland.systemd.target; + defaultText = literalExpression "config.wayland.systemd.target"; + example = "sway-session.target"; + description = '' + The systemd target that will automatically start the Workstyle service. + + When setting this value to `"sway-session.target"`, + make sure to also enable {option}`wayland.windowManager.sway.systemd.enable`, + otherwise the service may never be started. + ''; + }; + }; + + settings = lib.mkOption { + inherit (tomlFormat) type; + default = { }; + description = "Configuration for workstyle"; + example = literalExpression '' + { + # Config for workstyle + # Format: "pattern" = "icon"; + # The pattern will be used to match against the application name, class_id or WM_CLASS. + # The icon will be used to represent that application. + # Note if multiple patterns are present in the same application name, + # precedence is given in order of apparition in this file. + kitty = "T"; + firefox = "B"; + other = { + fallback_icon = "F"; + deduplicate_icons = false; + separator = ": "; + }; + } + ''; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "programs.workstyle" pkgs lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + xdg.configFile."workstyle/config.toml" = mkIf (cfg.settings != { }) { source = configFile; }; + systemd.user.services.workstyle = mkIf cfg.systemd.enable { + Unit = { + Description = "workstyle autostart"; + BindsTo = [ cfg.systemd.target ]; + # This is not necessary: workstyle reloads the config file after every window event. + # It might become necessary in the future. + # X-Restart-Triggers = mkIf (cfg.settings != { }) [ "${configFile}" ]; + }; + Service = { + ExecStart = "${cfg.package}/bin/workstyle"; + Restart = "always"; + RestartSec = 3; + Environment = mkIf (cfg.systemd.debug) "RUST_LOG=debug"; + }; + Install.WantedBy = [ cfg.systemd.target ]; + }; + }; +} diff --git a/tests/modules/programs/workstyle/basic-configuration.nix b/tests/modules/programs/workstyle/basic-configuration.nix new file mode 100644 index 000000000..8752ef43a --- /dev/null +++ b/tests/modules/programs/workstyle/basic-configuration.nix @@ -0,0 +1,21 @@ +{ + config = { + programs.workstyle = { + enable = true; + settings = { + alice = "A"; + bob = "B"; + other = { + fallback_icon = "F"; + deduplicate_icons = false; + separator = ": "; + }; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/workstyle/config.toml + assertFileContent home-files/.config/workstyle/config.toml ${./basic-configuration.toml} + ''; + }; +} diff --git a/tests/modules/programs/workstyle/basic-configuration.toml b/tests/modules/programs/workstyle/basic-configuration.toml new file mode 100644 index 000000000..a20bb9b3c --- /dev/null +++ b/tests/modules/programs/workstyle/basic-configuration.toml @@ -0,0 +1,7 @@ +alice = "A" +bob = "B" + +[other] +deduplicate_icons = false +fallback_icon = "F" +separator = ": " diff --git a/tests/modules/programs/workstyle/default.nix b/tests/modules/programs/workstyle/default.nix new file mode 100644 index 000000000..4209c73fb --- /dev/null +++ b/tests/modules/programs/workstyle/default.nix @@ -0,0 +1,8 @@ +{ lib, pkgs, ... }: + +lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { + workstyle-basic-configuration = ./basic-configuration.nix; + workstyle-empty-configuration = ./empty-configuration.nix; + workstyle-systemd-user-service = ./systemd-user-service.nix; + workstyle-full-configuration = ./full-configuration.nix; +} diff --git a/tests/modules/programs/workstyle/empty-configuration.nix b/tests/modules/programs/workstyle/empty-configuration.nix new file mode 100644 index 000000000..f345c2350 --- /dev/null +++ b/tests/modules/programs/workstyle/empty-configuration.nix @@ -0,0 +1,11 @@ +{ + config = { + programs.workstyle = { + enable = true; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/workstyle/config.toml + ''; + }; +} diff --git a/tests/modules/programs/workstyle/full-configuration.nix b/tests/modules/programs/workstyle/full-configuration.nix new file mode 100644 index 000000000..3cc4e8271 --- /dev/null +++ b/tests/modules/programs/workstyle/full-configuration.nix @@ -0,0 +1,30 @@ +{ + config = { + programs.workstyle = { + enable = true; + settings = { + alice = "A"; + bob = "B"; + other = { + fallback_icon = "F"; + deduplicate_icons = false; + separator = ": "; + }; + }; + systemd = { + # Make sure to also enable {option}`wayland.windowManager.sway.systemd.enable` + enable = true; + target = "sway-session.target"; + }; + }; + + nmt.script = '' + assertFileExists home-files/.config/workstyle/config.toml + assertFileContent home-files/.config/workstyle/config.toml ${./basic-configuration.toml} + + assertFileContent \ + home-files/.config/systemd/user/workstyle.service \ + ${./systemd-user-service-expected-sway.service} + ''; + }; +} diff --git a/tests/modules/programs/workstyle/systemd-user-service-expected-debug.service b/tests/modules/programs/workstyle/systemd-user-service-expected-debug.service new file mode 100644 index 000000000..1b63780f7 --- /dev/null +++ b/tests/modules/programs/workstyle/systemd-user-service-expected-debug.service @@ -0,0 +1,12 @@ +[Install] +WantedBy=a.target + +[Service] +Environment=RUST_LOG=debug +ExecStart=@workstyle@/bin/workstyle +Restart=always +RestartSec=3 + +[Unit] +BindsTo=a.target +Description=workstyle autostart diff --git a/tests/modules/programs/workstyle/systemd-user-service-expected-sway.service b/tests/modules/programs/workstyle/systemd-user-service-expected-sway.service new file mode 100644 index 000000000..d041fc323 --- /dev/null +++ b/tests/modules/programs/workstyle/systemd-user-service-expected-sway.service @@ -0,0 +1,11 @@ +[Install] +WantedBy=sway-session.target + +[Service] +ExecStart=@workstyle@/bin/workstyle +Restart=always +RestartSec=3 + +[Unit] +BindsTo=sway-session.target +Description=workstyle autostart diff --git a/tests/modules/programs/workstyle/systemd-user-service.nix b/tests/modules/programs/workstyle/systemd-user-service.nix new file mode 100644 index 000000000..cb4871259 --- /dev/null +++ b/tests/modules/programs/workstyle/systemd-user-service.nix @@ -0,0 +1,20 @@ +{ + config = { + programs.workstyle = { + enable = true; + systemd = { + enable = true; + debug = true; + target = "a.target"; + }; + }; + + nmt.script = '' + assertPathNotExists home-files/.config/workstyle/config.toml + + assertFileContent \ + home-files/.config/systemd/user/workstyle.service \ + ${./systemd-user-service-expected-debug.service} + ''; + }; +}