From 521a03d8bffe28745bcd4638bfdbc144a2e72065 Mon Sep 17 00:00:00 2001
From: polykernel <81340136+polykernel@users.noreply.github.com>
Date: Tue, 10 Aug 2021 00:21:03 -0400
Subject: [PATCH] fnott: add module
Fnott is a keyboard driven and lightweight Wayland notification daemon
for wlroots-based compositors.
There are four unit test to validate behavior for an empty
configuration, the default configuration, global properties and
systemd service file generation.
---
.github/CODEOWNERS | 3 +
modules/misc/news.nix | 8 ++
modules/modules.nix | 1 +
modules/services/fnott.nix | 130 ++++++++++++++++++
tests/default.nix | 1 +
tests/modules/services/fnott/default.nix | 6 +
.../modules/services/fnott/empty-settings.nix | 15 ++
.../fnott/example-settings-expected.ini | 6 +
.../services/fnott/example-settings.nix | 26 ++++
.../fnott/global-properties-expected.ini | 2 +
.../services/fnott/global-properties.nix | 24 ++++
.../systemd-user-service-expected.service | 10 ++
.../services/fnott/systemd-user-service.nix | 18 +++
13 files changed, 250 insertions(+)
create mode 100644 modules/services/fnott.nix
create mode 100644 tests/modules/services/fnott/default.nix
create mode 100644 tests/modules/services/fnott/empty-settings.nix
create mode 100644 tests/modules/services/fnott/example-settings-expected.ini
create mode 100644 tests/modules/services/fnott/example-settings.nix
create mode 100644 tests/modules/services/fnott/global-properties-expected.ini
create mode 100644 tests/modules/services/fnott/global-properties.nix
create mode 100644 tests/modules/services/fnott/systemd-user-service-expected.service
create mode 100644 tests/modules/services/fnott/systemd-user-service.nix
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 2d46797c..2720c7eb 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -238,6 +238,9 @@
/modules/services/fluidsynth.nix @Valodim
+/modules/services/fnott.nix @polykernel
+/tests/modules/services/fnott @polykernel
+
/modules/services/git-sync.nix @IvanMalison
/modules/services/gnome-keyring.nix @rycee
diff --git a/modules/misc/news.nix b/modules/misc/news.nix
index 183db447..69a18769 100644
--- a/modules/misc/news.nix
+++ b/modules/misc/news.nix
@@ -2180,6 +2180,14 @@ in
A new module is available: 'services.git-sync'.
'';
}
+
+ {
+ time = "2021-08-26T06:40:59+00:00";
+ condition = hostPlatform.isLinux;
+ message = ''
+ A new module is available: 'services.fnott'.
+ '';
+ }
];
};
}
diff --git a/modules/modules.nix b/modules/modules.nix
index ad311ac8..db6bdb29 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -162,6 +162,7 @@ let
./services/etesync-dav.nix
./services/flameshot.nix
./services/fluidsynth.nix
+ ./services/fnott.nix
./services/getmail.nix
./services/git-sync.nix
./services/gnome-keyring.nix
diff --git a/modules/services/fnott.nix b/modules/services/fnott.nix
new file mode 100644
index 00000000..a6a1aa69
--- /dev/null
+++ b/modules/services/fnott.nix
@@ -0,0 +1,130 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.fnott;
+
+ concatStringsSep' = sep: list:
+ concatStringsSep sep (filter (str: str != "") list);
+
+ mkKeyValue = generators.mkKeyValueDefault { } "=";
+ genINI = generators.toINI { };
+
+ iniFormatType = with types;
+ let
+ iniAtom = types.nullOr (types.oneOf [ bool int float str ]) // {
+ description = "INI atom (null, bool, int, float or string)";
+ };
+ in attrsOf (attrsOf iniAtom);
+in {
+ options = {
+ services.fnott = {
+ enable = mkEnableOption ''
+ fnott, a lightweight Wayland notification daemon for wlroots-based compositors
+ '';
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.fnott;
+ defaultText = literalExample "pkgs.fnott";
+ description = "Package providing fnott.";
+ };
+
+ configFile = mkOption {
+ type = types.either types.str types.path;
+ default = "${config.xdg.configHome}/fnott/fnott.ini";
+ defaultText = "$XDG_CONFIG_HOME/fnott/fnott.ini";
+ description = ''
+ Path to the configuration file read by fnott.
+
+ Note that environment variables in the path won't be properly expanded.
+
+ The configuration specified under
+ will be generated and
+ written to $XDG_CONFIG_HOME/fnott/fnott.ini
+ regardless of this option. This allows using a mutable configuration file
+ generated from the immutable one, useful in scenarios where live reloading is desired.
+ '';
+ };
+
+ extraFlags = mkOption {
+ type = types.listOf types.str;
+ default = [ ];
+ example = [ "-s" ];
+ description = ''
+ Extra arguments to use for executing fnott.
+ '';
+ };
+
+ settings = mkOption {
+ type = iniFormatType;
+ default = { };
+ description = ''
+ Configuration written to
+ $XDG_CONFIG_HOME/fnott/fnott.ini.
+
+ See
+
+ fnott.ini
+ 5
+ for a list of avaliable options and
+ for an example configuration.
+ '';
+ example = literalExample ''
+ {
+ main = {
+ notification-margin = 5;
+ };
+
+ low = {
+ timeout = 5;
+ title-font = "Dina:weight=bold:slant=italic";
+ title-color = "ffffff";
+ };
+ }
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ assertions =
+ [ (hm.assertions.assertPlatform "services.fnott" pkgs platforms.linux) ];
+
+ home.packages = [ cfg.package ];
+
+ systemd.user.services.fnott = {
+ Unit = {
+ Description = "Fnott notification daemon";
+ Documentation = "man:fnott(1)";
+ After = [ "graphical-session-pre.target" ];
+ PartOf = [ "graphical-session.target" ];
+ };
+
+ Service = {
+ Type = "dbus";
+ BusName = "org.freedesktop.Notifications";
+ ExecStart = concatStringsSep' " " [
+ "${cfg.package}/bin/fnott -c ${cfg.configFile}"
+ (escapeShellArgs cfg.extraFlags)
+ ];
+ };
+ };
+
+ # FIXME: Remove after next version release (https://codeberg.org/dnkl/fnott/pulls/24).
+ xdg.configFile."fnott/fnott.ini" = mkIf (cfg.settings != { }) (mkMerge [
+ { text = genINI cfg.settings; }
+ (mkIf (cfg.settings ? main) {
+ text = mkForce (concatStringsSep' "\n" [
+ ''
+ ${concatStringsSep "\n"
+ (mapAttrsToList mkKeyValue cfg.settings.main)}
+ ''
+ (genINI (removeAttrs cfg.settings [ "main" ]))
+ ]);
+ })
+ ]);
+ };
+}
diff --git a/tests/default.nix b/tests/default.nix
index b2b6be6b..161b4897 100644
--- a/tests/default.nix
+++ b/tests/default.nix
@@ -120,6 +120,7 @@ import nmt {
./modules/services/dropbox
./modules/services/emacs
./modules/services/fluidsynth
+ ./modules/services/fnott
./modules/services/git-sync
./modules/services/kanshi
./modules/services/lieer
diff --git a/tests/modules/services/fnott/default.nix b/tests/modules/services/fnott/default.nix
new file mode 100644
index 00000000..4ce849ff
--- /dev/null
+++ b/tests/modules/services/fnott/default.nix
@@ -0,0 +1,6 @@
+{
+ fnott-empty-settings = ./empty-settings.nix;
+ fnott-example-settings = ./example-settings.nix;
+ fnott-global-properties = ./global-properties.nix;
+ fnott-systemd-user-service = ./systemd-user-service.nix;
+}
diff --git a/tests/modules/services/fnott/empty-settings.nix b/tests/modules/services/fnott/empty-settings.nix
new file mode 100644
index 00000000..85d2c9d6
--- /dev/null
+++ b/tests/modules/services/fnott/empty-settings.nix
@@ -0,0 +1,15 @@
+{ config, lib, pkgs, ... }:
+
+{
+ config = {
+ services.fnott = {
+ enable = true;
+ package = pkgs.writeScriptBin "dummy-fnott" "";
+ settings = { };
+ };
+
+ nmt.script = ''
+ assertPathNotExists home-files/.config/fnott
+ '';
+ };
+}
diff --git a/tests/modules/services/fnott/example-settings-expected.ini b/tests/modules/services/fnott/example-settings-expected.ini
new file mode 100644
index 00000000..153e456c
--- /dev/null
+++ b/tests/modules/services/fnott/example-settings-expected.ini
@@ -0,0 +1,6 @@
+notification-margin=5
+
+[low]
+timeout=5
+title-color=ffffff
+title-font=Dina:weight=bold:slant=italic
diff --git a/tests/modules/services/fnott/example-settings.nix b/tests/modules/services/fnott/example-settings.nix
new file mode 100644
index 00000000..3685637d
--- /dev/null
+++ b/tests/modules/services/fnott/example-settings.nix
@@ -0,0 +1,26 @@
+{ config, lib, pkgs, ... }:
+
+{
+ config = {
+ services.fnott = {
+ enable = true;
+ package = pkgs.writeScriptBin "dummy-fnott" "";
+
+ settings = {
+ main = { notification-margin = 5; };
+
+ low = {
+ timeout = 5;
+ title-font = "Dina:weight=bold:slant=italic";
+ title-color = "ffffff";
+ };
+ };
+ };
+
+ nmt.script = ''
+ assertFileContent \
+ home-files/.config/fnott/fnott.ini \
+ ${./example-settings-expected.ini}
+ '';
+ };
+}
diff --git a/tests/modules/services/fnott/global-properties-expected.ini b/tests/modules/services/fnott/global-properties-expected.ini
new file mode 100644
index 00000000..a8264679
--- /dev/null
+++ b/tests/modules/services/fnott/global-properties-expected.ini
@@ -0,0 +1,2 @@
+max-icon-size=32
+notification-margin=5
diff --git a/tests/modules/services/fnott/global-properties.nix b/tests/modules/services/fnott/global-properties.nix
new file mode 100644
index 00000000..5a9d7e03
--- /dev/null
+++ b/tests/modules/services/fnott/global-properties.nix
@@ -0,0 +1,24 @@
+{ config, lib, pkgs, ... }:
+
+# FIXME: Deprecate on next version release of fnott (https://codeberg.org/dnkl/fnott/pulls/24).
+{
+ config = {
+ services.fnott = {
+ enable = true;
+ package = pkgs.writeScriptBin "dummy-fnott" "";
+
+ settings = {
+ main = {
+ max-icon-size = 32;
+ notification-margin = 5;
+ };
+ };
+ };
+
+ nmt.script = ''
+ assertFileContent \
+ home-files/.config/fnott/fnott.ini \
+ ${./global-properties-expected.ini}
+ '';
+ };
+}
diff --git a/tests/modules/services/fnott/systemd-user-service-expected.service b/tests/modules/services/fnott/systemd-user-service-expected.service
new file mode 100644
index 00000000..c39a7b19
--- /dev/null
+++ b/tests/modules/services/fnott/systemd-user-service-expected.service
@@ -0,0 +1,10 @@
+[Service]
+BusName=org.freedesktop.Notifications
+ExecStart=@fnott@/bin/fnott -c /home/hm-user/.config/fnott/fnott.ini
+Type=dbus
+
+[Unit]
+After=graphical-session-pre.target
+Description=Fnott notification daemon
+Documentation=man:fnott(1)
+PartOf=graphical-session.target
diff --git a/tests/modules/services/fnott/systemd-user-service.nix b/tests/modules/services/fnott/systemd-user-service.nix
new file mode 100644
index 00000000..a356f2ae
--- /dev/null
+++ b/tests/modules/services/fnott/systemd-user-service.nix
@@ -0,0 +1,18 @@
+{ config, lib, pkgs, ... }:
+
+{
+ config = {
+ services.fnott = {
+ enable = true;
+ package = pkgs.writeScriptBin "dummy-foot" "" // { outPath = "@fnott@"; };
+ };
+
+ nmt.script = ''
+ assertPathNotExists home-files/.config/fnott/fnott.ini
+
+ assertFileContent \
+ home-files/.config/systemd/user/fnott.service \
+ ${./systemd-user-service-expected.service}
+ '';
+ };
+}