Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kanshi: Better configuration options #5388

Merged
merged 1 commit into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
177 changes: 141 additions & 36 deletions modules/services/kanshi.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,48 @@ let

cfg = config.services.kanshi;

directivesTag = types.attrTag {
profile = mkOption {
type = profileModule;
description = ''
profile attribute set.
'';
};
output = mkOption {
type = outputModule;
description = ''
output attribute set.
'';
};
include = mkOption {
type = types.str;
description = ''
Include as another file from _path_.
Expands shell syntax (see *wordexp*(3) for details).
'';
};
};

tagToStr = x:
if x ? profile then
profileStr x.profile
else if x ? output then
outputStr x.output
else if x ? include then
''include "${x.include}"''
else
throw "Unknown tags ${attrNames x}";

directivesStr = ''
${concatStringsSep "\n" (map tagToStr cfg.settings)}
'';

oldDirectivesStr = ''
${concatStringsSep "\n"
(mapAttrsToList (n: v: profileStr (v // { name = n; })) cfg.profiles)}
${cfg.extraConfig}
'';

outputModule = types.submodule {
options = {

Expand Down Expand Up @@ -113,6 +155,14 @@ let
'';
};

name = mkOption {
type = types.str;
default = "";
description = ''
Profile name
'';
};

exec = mkOption {
type = with types; coercedTo str singleton (listOf str);
default = [ ];
Expand All @@ -127,15 +177,14 @@ let
};
};

profileStr = name:
{ outputs, exec, ... }: ''
profile ${name} {
${
concatStringsSep "\n "
(map outputStr outputs ++ map (cmd: "exec ${cmd}") exec)
}
profileStr = { outputs, exec, ... }@args: ''
profile ${args.name or ""} {
${
concatStringsSep "\n "
(map outputStr outputs ++ map (cmd: "exec ${cmd}") exec)
}
'';
}
'';
in {

meta.maintainers = [ hm.maintainers.nurelin ];
Expand All @@ -157,7 +206,7 @@ in {
type = types.attrsOf profileModule;
default = { };
description = ''
List of profiles.
Attribute set of profiles.
'';
example = literalExpression ''
undocked = {
Expand Down Expand Up @@ -190,6 +239,39 @@ in {
'';
};

settings = mkOption {
type = types.listOf directivesTag;
default = [ ];
description = ''
Ordered list of directives.
See kanshi(5) for informations.
'';
example = literalExpression ''
{ include = "path/to/included/files"; }
{ output.criteria = "eDP-1";
output.scale = 2;
}
{ profile.name = "undocked";
profile.outputs = [
{
criteria = "eDP-1";
}
];
}
{ profile.name = "docked";
profile.outputs = [
{
criteria = "eDP-1";
}
{
criteria = "Some Company ASDF 4242";
transform = "90";
}
];
}
'';
};

systemdTarget = mkOption {
type = types.str;
default = "sway-session.target";
Expand All @@ -199,33 +281,56 @@ in {
};
};

config = mkIf cfg.enable {
assertions = [
(lib.hm.assertions.assertPlatform "services.kanshi" pkgs
lib.platforms.linux)
];

xdg.configFile."kanshi/config".text = ''
${concatStringsSep "\n" (mapAttrsToList profileStr cfg.profiles)}
${cfg.extraConfig}
'';

systemd.user.services.kanshi = {
Unit = {
Description = "Dynamic output configuration";
Documentation = "man:kanshi(1)";
PartOf = cfg.systemdTarget;
Requires = cfg.systemdTarget;
After = cfg.systemdTarget;
};
config = mkIf cfg.enable (mkMerge [
{
assertions = [
(lib.hm.assertions.assertPlatform "services.kanshi" pkgs
lib.platforms.linux)
{
assertion = (cfg.profiles == { } && cfg.extraConfig == "")
|| (length cfg.settings) == 0;
message =
"Cannot mix kanshi.settings with kanshi.profiles or kanshi.extraConfig";
}
];
}

Service = {
Type = "simple";
ExecStart = "${cfg.package}/bin/kanshi";
Restart = "always";
};
(mkIf (cfg.profiles != { }) {
warnings = [
"kanshi.profiles option is deprecated. Use kanshi.settings instead."
];
})

Install = { WantedBy = [ cfg.systemdTarget ]; };
};
};
(mkIf (cfg.extraConfig != "") {
warnings = [
"kanshi.extraConfig option is deprecated. Use kanshi.settings instead."
];
})

{
xdg.configFile."kanshi/config".text =
if cfg.profiles == { } && cfg.extraConfig == "" then
directivesStr
else
oldDirectivesStr;

systemd.user.services.kanshi = {
Unit = {
Description = "Dynamic output configuration";
Documentation = "man:kanshi(1)";
PartOf = cfg.systemdTarget;
Requires = cfg.systemdTarget;
After = cfg.systemdTarget;
};

Service = {
Type = "simple";
ExecStart = "${cfg.package}/bin/kanshi";
Restart = "always";
};

Install = { WantedBy = [ cfg.systemdTarget ]; };
};
}
]);
}
5 changes: 5 additions & 0 deletions tests/modules/services/kanshi/basic-configuration.nix
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
'';
};

test.asserts.warnings.expected = [
"kanshi.profiles option is deprecated. Use kanshi.settings instead."
"kanshi.extraConfig option is deprecated. Use kanshi.settings instead."
];

nmt.script = ''
serviceFile=home-files/.config/systemd/user/kanshi.service
assertFileExists $serviceFile
Expand Down
5 changes: 4 additions & 1 deletion tests/modules/services/kanshi/default.nix
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
{ kanshi-basic-configuration = ./basic-configuration.nix; }
{
kanshi-basic-configuration = ./basic-configuration.nix;
kanshi-new-configuration = ./new-configuration.nix;
}
19 changes: 19 additions & 0 deletions tests/modules/services/kanshi/new-configuration.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
include "path/to/included/file"
output "*" enable
profile nomad {
output "eDP-1" enable
}

profile desktop {
output "eDP-1" disable
output "Iiyama North America PLE2483H-DP" enable position 0,0
output "Iiyama North America PLE2483H-DP 1158765348486" enable mode 1920x1080 position 1920,0 scale 2.100000 transform flipped-270
exec echo "1 two 3"
exec echo "4 five 6"
}

profile {
output "LVDS-1" enable
exec echo "7 eight 9"
}

63 changes: 63 additions & 0 deletions tests/modules/services/kanshi/new-configuration.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{ config, pkgs, ... }: {
config = {
services.kanshi = {
enable = true;
package = config.lib.test.mkStubPackage { };
settings = [
{ include = "path/to/included/file"; }
{
output = {
criteria = "*";
status = "enable";
};
}
{
profile.name = "nomad";
profile.outputs = [{
criteria = "eDP-1";
status = "enable";
}];
}
{
profile.name = "desktop";
profile.exec = [ ''echo "1 two 3"'' ''echo "4 five 6"'' ];
profile.outputs = [
{
criteria = "eDP-1";
status = "disable";
}
{
criteria = "Iiyama North America PLE2483H-DP";
status = "enable";
position = "0,0";
}
{
criteria = "Iiyama North America PLE2483H-DP 1158765348486";
status = "enable";
position = "1920,0";
scale = 2.1;
mode = "1920x1080";
transform = "flipped-270";
}
];
}
{
profile.outputs = [{
criteria = "LVDS-1";
status = "enable";
}];
profile.exec = ''echo "7 eight 9"'';
}
];
};

nmt.script = ''
serviceFile=home-files/.config/systemd/user/kanshi.service
assertFileExists $serviceFile

assertFileExists home-files/.config/kanshi/config
assertFileContent home-files/.config/kanshi/config \
${./new-configuration.conf}
'';
};
}