diff --git a/doc/src/modules.md b/doc/src/modules.md index 0250dffc..d2b21d3a 100644 --- a/doc/src/modules.md +++ b/doc/src/modules.md @@ -106,6 +106,13 @@ the following applies: - There is no reliable way to detect whether the target is installed, *and* enabling it unconditionally would cause problems. +> [!CAUTION] +> The boolean value after `mkEnableTarget` should usually be a static `true` or +> `false` literal. +> +> Using a dynamic value requires you to document the dynamic expression using +> `mkEnableTargetWith`'s `autoEnableExpr` argument. + ### Overlays If your module is provided as an overlay it uses a special format, where config diff --git a/stylix/target.nix b/stylix/target.nix index 9f521efc..4ec78760 100644 --- a/stylix/target.nix +++ b/stylix/target.nix @@ -35,6 +35,42 @@ let cfg = config.stylix; self = config.lib.stylix; + + # Will wrap with (parentheses) if the expr contains operators with lower precedence than `&&` + wrapExprWith = + { + autoWrapExpr ? true, + trimExpr ? true, + indentMultilineExpr ? true, + }: + expr: + let + trimmed = if trimExpr then lib.trim expr else expr; + isWrapped = builtins.match ''[(].*[)]'' trimmed != null; + hasNewlines = lib.hasInfix "\n" trimmed; + needsWrapping = builtins.any (op: lib.hasInfix op trimmed) [ + # These operators have lower precedence than `&&` + # See https://nix.dev/manual/nix/2.28/language/operators + "||" + "->" + "|>" + "<|" + # These keywords would also need wrapping + "with " + "assert " + ]; + indented = + if indentMultilineExpr then + lib.pipe trimmed [ + (lib.strings.splitString "\n") + (map (line: if line == "" then "" else " " + line)) + (builtins.concatStringsSep "\n") + ] + else + trimmed; + wrapped = if hasNewlines then "(\n${indented}\n)" else "(${trimmed})"; + in + if autoWrapExpr && !isWrapped && needsWrapping then wrapped else trimmed; in { mkEnableTarget = @@ -45,13 +81,26 @@ { name, autoEnable ? true, - }: + autoEnableExpr ? null, + autoWrapExpr ? true, + example ? if args ? autoEnableExpr then true else !autoEnable, + }@args: + let + wrapExpr = wrapExprWith { + inherit autoWrapExpr; + }; + in self.mkEnableIf { - description = "Whether to enable theming for ${name}."; + description = "Whether to enable theming for ${name}"; default = cfg.autoEnable && autoEnable; - ${if autoEnable then "defaultText" else null} = - lib.literalExpression "stylix.autoEnable"; - example = !autoEnable; + defaultText = + if args ? autoEnableExpr then + lib.literalExpression "stylix.autoEnable && ${wrapExpr autoEnableExpr}" + else if autoEnable then + lib.literalExpression "stylix.autoEnable" + else + false; + inherit example; }; mkEnableWallpaper =