From d4e4d5cfa30455f50d034f24aa9bc0ab05388fcd Mon Sep 17 00:00:00 2001 From: PerchunPak Date: Fri, 2 Jan 2026 08:58:42 +0100 Subject: [PATCH] lib: make toHyprconf support strings and attrs in sections Adds support for section = [ "abc" { a = 123; } ]; Which gets generated to section=abc section { a=123 } This is very useful with the new windowrule syntax, where you can create anonymous window rules as strings and named rules as attribute sets. See . --- modules/lib/generators.nix | 32 ++++--- tests/lib/generators/default.nix | 1 + tests/lib/generators/tohyprconf-result.txt | 93 +++++++++++++++++++ tests/lib/generators/tohyprconf.nix | 70 ++++++++++++++ .../hyprland/multiple-devices-config.conf | 7 +- .../services/hyprland/simple-config.conf | 7 +- .../hyprland/sourceFirst-false-config.conf | 1 + .../services/hyprland/submaps-config.conf | 1 + .../modules/services/hyprpaper/hyprpaper.conf | 7 +- 9 files changed, 197 insertions(+), 22 deletions(-) create mode 100644 tests/lib/generators/tohyprconf-result.txt create mode 100644 tests/lib/generators/tohyprconf.nix diff --git a/modules/lib/generators.nix b/modules/lib/generators.nix index ee8461df5..d92114b90 100644 --- a/modules/lib/generators.nix +++ b/modules/lib/generators.nix @@ -21,6 +21,7 @@ isList mapAttrsToList replicate + attrNames ; initialIndent = concatStrings (replicate indentLevel " "); @@ -28,31 +29,36 @@ toHyprconf' = indent: attrs: let - sections = filterAttrs (n: v: isAttrs v || (isList v && all isAttrs v)) attrs; + isImportantField = + n: _: foldl (acc: prev: if hasPrefix prev n then true else acc) false importantPrefixes; + importantFields = filterAttrs isImportantField attrs; + withoutImportantFields = fields: removeAttrs fields (attrNames importantFields); + + allSections = filterAttrs (n: v: isAttrs v || isList v) attrs; + sections = withoutImportantFields allSections; mkSection = n: attrs: - if lib.isList attrs then - (concatMapStringsSep "\n" (a: mkSection n a) attrs) - else + if isList attrs then + let + separator = if all isAttrs attrs then "\n" else ""; + in + (concatMapStringsSep separator (a: mkSection n a) attrs) + else if isAttrs attrs then '' ${indent}${n} { ${toHyprconf' " ${indent}" attrs}${indent}} - ''; + '' + else + toHyprconf' indent { ${n} = attrs; }; mkFields = generators.toKeyValue { listsAsDuplicateKeys = true; inherit indent; }; - allFields = filterAttrs (n: v: !(isAttrs v || (isList v && all isAttrs v))) attrs; - - isImportantField = - n: _: foldl (acc: prev: if hasPrefix prev n then true else acc) false importantPrefixes; - - importantFields = filterAttrs isImportantField allFields; - - fields = builtins.removeAttrs allFields (mapAttrsToList (n: _: n) importantFields); + allFields = filterAttrs (n: v: !(isAttrs v || isList v)) attrs; + fields = withoutImportantFields allFields; in mkFields importantFields + concatStringsSep "\n" (mapAttrsToList mkSection sections) diff --git a/tests/lib/generators/default.nix b/tests/lib/generators/default.nix index da52640d1..4332907e1 100644 --- a/tests/lib/generators/default.nix +++ b/tests/lib/generators/default.nix @@ -1,4 +1,5 @@ { + generators-hyprconf = ./tohyprconf.nix; generators-tokdl = ./tokdl.nix; generators-toscfg-empty = ./toscfg-empty.nix; generators-toscfg-example = ./toscfg-example.nix; diff --git a/tests/lib/generators/tohyprconf-result.txt b/tests/lib/generators/tohyprconf-result.txt new file mode 100644 index 000000000..3c25b2549 --- /dev/null +++ b/tests/lib/generators/tohyprconf-result.txt @@ -0,0 +1,93 @@ +$important=123 +attrs-section { + bool=true + float=0.800000 + int=5 + null=null + string=abc +} + +combined-attrs-nested-section { + a { + a=123 + } + + a { + b=123 + } + + a { + c=123 + } + + b { + a=123 + } + + b { + b=123 + } + + b { + c=123 + } +} + +combined-list-nested-section { + b { + c { + abc=123 + } + } +} + +combined-list-nested-section { + bar { + baz { + aaa=111 + } + } +} + +list-section=foo +list-section=bar +list-section=baz + +list-with-strings-and-attrs=abc +list-with-strings-and-attrs { + a=123 +} +list-with-strings-and-attrs=foo +list-with-strings-and-attrs { + b=321 +} + +nested-attrs-section { + a { + b { + c { + abc=123 + } + } + } + + foo { + bar { + baz { + aaa=111 + } + } + } +} + +nested-list-section { + a=123 +} + +nested-list-section { + b=123 +} + +nested-list-section { + c=123 +} diff --git a/tests/lib/generators/tohyprconf.nix b/tests/lib/generators/tohyprconf.nix new file mode 100644 index 000000000..60953ae5d --- /dev/null +++ b/tests/lib/generators/tohyprconf.nix @@ -0,0 +1,70 @@ +{ lib, ... }: + +{ + home.file."tohyprconf-result.txt".text = lib.hm.generators.toHyprconf { + attrs = rec { + "$important" = 123; + + list-section = [ + "foo" + "bar" + "baz" + ]; + + attrs-section = { + string = "abc"; + int = 5; + float = 0.8; + bool = true; + null = null; + }; + + nested-attrs-section = { + a = { + b = { + c = { + abc = 123; + }; + }; + }; + + foo = { + bar = { + baz = { + aaa = 111; + }; + }; + }; + }; + + nested-list-section = [ + { a = 123; } + { b = 123; } + { c = 123; } + ]; + + combined-list-nested-section = [ + nested-attrs-section.a + nested-attrs-section.foo + ]; + + combined-attrs-nested-section = { + a = nested-list-section; + b = nested-list-section; + }; + + list-with-strings-and-attrs = [ + "abc" + { a = 123; } + "foo" + { b = 321; } + ]; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/tohyprconf-result.txt \ + ${./tohyprconf-result.txt} + ''; +} diff --git a/tests/modules/services/hyprland/multiple-devices-config.conf b/tests/modules/services/hyprland/multiple-devices-config.conf index 664421b6d..823ffa3b5 100644 --- a/tests/modules/services/hyprland/multiple-devices-config.conf +++ b/tests/modules/services/hyprland/multiple-devices-config.conf @@ -13,6 +13,10 @@ animations { enabled=true } +bindm=$mod, mouse:272, movewindow +bindm=$mod, mouse:273, resizewindow +bindm=$mod ALT, mouse:272, resizewindow + decoration { col.shadow=rgba(00000099) shadow_offset=0 5 @@ -45,9 +49,6 @@ plugin { dummy=plugin setting } } -bindm=$mod, mouse:272, movewindow -bindm=$mod, mouse:273, resizewindow -bindm=$mod ALT, mouse:272, resizewindow # window resize bind = $mod, S, submap, resize diff --git a/tests/modules/services/hyprland/simple-config.conf b/tests/modules/services/hyprland/simple-config.conf index 787455e20..1e0f240a6 100644 --- a/tests/modules/services/hyprland/simple-config.conf +++ b/tests/modules/services/hyprland/simple-config.conf @@ -13,6 +13,10 @@ animations { enabled=true } +bindm=$mod, mouse:272, movewindow +bindm=$mod, mouse:273, resizewindow +bindm=$mod ALT, mouse:272, resizewindow + decoration { col.shadow=rgba(00000099) shadow_offset=0 5 @@ -48,9 +52,6 @@ plugin { dummy=plugin setting } } -bindm=$mod, mouse:272, movewindow -bindm=$mod, mouse:273, resizewindow -bindm=$mod ALT, mouse:272, resizewindow # window resize bind = $mod, S, submap, resize diff --git a/tests/modules/services/hyprland/sourceFirst-false-config.conf b/tests/modules/services/hyprland/sourceFirst-false-config.conf index e3d54eff0..173ed83b9 100644 --- a/tests/modules/services/hyprland/sourceFirst-false-config.conf +++ b/tests/modules/services/hyprland/sourceFirst-false-config.conf @@ -10,4 +10,5 @@ input { follow_mouse=1 kb_layout=ro } + source=sourced.conf diff --git a/tests/modules/services/hyprland/submaps-config.conf b/tests/modules/services/hyprland/submaps-config.conf index 3caae3c9c..ec4329cf1 100644 --- a/tests/modules/services/hyprland/submaps-config.conf +++ b/tests/modules/services/hyprland/submaps-config.conf @@ -17,6 +17,7 @@ submap = reset submap = resize bind=, escape, submap, reset bind=, return, submap, reset + binde=, right, resizeactive, 10 0 binde=, left, resizeactive, -10 0 binde=, up, resizeactive, 0 -10 diff --git a/tests/modules/services/hyprpaper/hyprpaper.conf b/tests/modules/services/hyprpaper/hyprpaper.conf index d7b4ccb4f..1791dad9b 100644 --- a/tests/modules/services/hyprpaper/hyprpaper.conf +++ b/tests/modules/services/hyprpaper/hyprpaper.conf @@ -1,7 +1,8 @@ -ipc=on preload=/share/wallpapers/buttons.png preload=/share/wallpapers/cat_pacman.png -splash=false -splash_offset=2.000000 + wallpaper=DP-3,/share/wallpapers/buttons.png wallpaper=DP-1,/share/wallpapers/cat_pacman.png +ipc=on +splash=false +splash_offset=2.000000