diff --git a/wrapperModules/q/quickshell/check.nix b/wrapperModules/q/quickshell/check.nix index db07bb3b..19badd51 100644 --- a/wrapperModules/q/quickshell/check.nix +++ b/wrapperModules/q/quickshell/check.nix @@ -69,7 +69,10 @@ test { wrapper = "quickshell"; } { isShellPresent = wrapper: isFile "${wrapper}/${wrapper.passthru.configuration.binName}-config/shell.qml"; isBarPresent = - wrapper: isFile "${wrapper}/${wrapper.passthru.configuration.binName}-config/Bar.qml"; + wrapper: mod: + isFile "${wrapper}/${wrapper.passthru.configuration.binName}-config/${ + if mod != null then "${mod}/" else "" + }Bar.qml"; isCorrectConfig = wrapper: '' logs=$("${wrapper}/bin/quickshell" 2>&1) echo "$logs" | grep -q "Launching config: \"${wrapper}/${wrapper.passthru.configuration.binName}-config/shell.qml\"" @@ -85,7 +88,7 @@ test { wrapper = "quickshell"; } { in [ (isShellPresent wrapper) - (isBarPresent wrapper) + (isBarPresent wrapper null) (isCorrectConfig wrapper) ]; @@ -98,7 +101,20 @@ test { wrapper = "quickshell"; } { in [ (isShellPresent wrapper) - (isBarPresent wrapper) + (isBarPresent wrapper null) + (isCorrectConfig wrapper) + ]; + + "wrapper should keep correct hierachy with component modules" = + let + wrapper = baseWrapper.wrap { + configFile = "import qs.foo.boo\n" + shellContent; + components.foo.boo.bar = barContent; + }; + in + [ + (isShellPresent wrapper) + (isBarPresent wrapper "foo/boo") (isCorrectConfig wrapper) ]; }; diff --git a/wrapperModules/q/quickshell/module.nix b/wrapperModules/q/quickshell/module.nix index d3c6abd0..7fec7455 100644 --- a/wrapperModules/q/quickshell/module.nix +++ b/wrapperModules/q/quickshell/module.nix @@ -7,7 +7,8 @@ }: let inherit (lib) - mapAttrs' + isStringLike + mapAttrs mkDefault mkIf mkOption @@ -16,6 +17,16 @@ let isLinkable = wlib.types.linkable.check; makeForce = lib.mkOverride 0; + + componentType = types.submodule { + freeformType = types.lazyAttrsOf ( + types.oneOf [ + wlib.types.linkable + types.lines + (componentType // { description = "nested components"; }) + ] + ); + }; in { imports = [ wlib.modules.default ]; @@ -31,9 +42,30 @@ in ''; }; components = mkOption { - type = types.attrsOf (types.either wlib.types.linkable types.lines); + type = componentType; default = { }; description = "Quickshell components to include in the configuration"; + example = lib.literalExpression '' + { + some.path."Bar.qml" = ./some-widget.qml; + light.clock = ''' + Text { + text: "hello world" + } + '''; + dark.clock = "/etc/quickshell/Clock.qml"; + lockscreensDir = + let + repo = pkgs.fetchFromGitHub { + owner = "Darkkal44"; + repo = "qylock"; + rev = "cde4d11e9e3d385620becdc877a0521e40a55e47"; + hash = "sha256-17kRwrkdfe+hJdChMxove73zNCKcSi0nmSrO8Fh8hz0="; + }; + in + "''${repo}/quickshell-lockscreen"; + } + ''; }; generated.output = mkOption { type = types.str; @@ -56,24 +88,34 @@ in }/${config.binName}-config"; config.constructFiles = - mapAttrs' ( - name: val: - let - firstChar = builtins.substring 0 1 name; - rest = builtins.substring 1 (-1) name; - capitalizedName = (lib.toUpper firstChar) + rest; - linkable = isLinkable val; - in - { - name = "${name}Component"; - value = { - content = mkIf (!linkable) val; - builder = mkIf linkable ''ln -s ${val} "$2"''; - output = makeForce config.generated.output; - relPath = makeForce "${config.binName}-config/${capitalizedName}.qml"; - }; - } - ) config.components + let + getComponents' = + prefix: val: + if builtins.isAttrs val then + lib.foldlAttrs ( + acc: name: v: + let + value = if isStringLike v then builtins.toString v else v; + + # Auto capitalization for qml files or inlined text + attrIsFile = builtins.isString v || (isStringLike v && lib.hasSuffix ".qml" value); + + firstChar = builtins.substring 0 1 name; + restChars = builtins.substring 1 (-1) name; + finalName = if !attrIsFile then name else (lib.toUpper firstChar) + restChars + ".qml"; + in + acc // getComponents' (prefix + "/" + finalName) value + ) { } val + else + { ${prefix} = val; }; + getComponents = getComponents' ""; + in + (mapAttrs (name: value: { + content = mkIf (!isLinkable value) value; + builder = mkIf (isLinkable value) ''ln -s ${value} "$2"''; + output = makeForce config.generated.output; + relPath = makeForce "${config.binName}-config${name}"; + }) (getComponents config.components)) // { generatedConfig = { content = mkIf (!isLinkable config.configFile) config.configFile;