treewide: use mkEnableTargetWith for dynamic autoEnable conditions (#1244)
Use the new `mkEnableTargetWith` function for dynamic `autoEnable`
conditions to prevent the evaluation of dynamic conditions during
documentation rendering.
The "same as `stylix.autoEnable`" `defaultText` is replaced with
`stylix.autoEnable` or `stylix.autoEnable && ${autoEnableExpr}`,
depending on whether `autoEnableExpr` is provided. For readability,
`autoEnable` expressions containing Nix operators of lower precedence
than `&&` are automatically wrapped in parentheses, unless
`autoWrapExpr` is disabled.
Closes: https://github.com/nix-community/stylix/issues/98
Link: https://github.com/nix-community/stylix/pull/1244
Reviewed-by: awwpotato <awwpotato@voidq.com>
Reviewed-by: NAHO <90870942+trueNAHO@users.noreply.github.com>
Reviewed-by: Daniel Thwaites <danth@danth.me>
This commit is contained in:
commit
d73d8f6a48
10 changed files with 173 additions and 39 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -15,6 +15,14 @@ mkTarget {
|
|||
|| i3.enable
|
||||
|| spectrwm.enable
|
||||
|| xmonad.enable;
|
||||
autoEnableExpr = ''
|
||||
with config.xsession.windowManager;
|
||||
bspwm.enable
|
||||
|| herbstluftwm.enable
|
||||
|| i3.enable
|
||||
|| spectrwm.enable
|
||||
|| xmonad.enable
|
||||
'';
|
||||
|
||||
configElements =
|
||||
{ imageScalingMode, image }:
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ mkTarget {
|
|||
autoEnable =
|
||||
with config.services.xserver.windowManager;
|
||||
xmonad.enable || i3.enable;
|
||||
autoEnableExpr = ''
|
||||
with services.xserver.windowManager;
|
||||
xmonad.enable || i3.enable
|
||||
'';
|
||||
|
||||
configElements =
|
||||
{ image, imageScalingMode }:
|
||||
|
|
|
|||
|
|
@ -44,7 +44,11 @@ let
|
|||
in
|
||||
{
|
||||
options.stylix.targets.gnome = {
|
||||
enable = config.lib.stylix.mkEnableTarget "GNOME" pkgs.stdenv.hostPlatform.isLinux;
|
||||
enable = config.lib.stylix.mkEnableTargetWith {
|
||||
name = "GNOME";
|
||||
autoEnable = pkgs.stdenv.hostPlatform.isLinux;
|
||||
autoEnableExpr = "pkgs.stdenv.hostPlatform.isLinux";
|
||||
};
|
||||
useWallpaper = config.lib.stylix.mkEnableWallpaper "GNOME" true;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@
|
|||
mkTarget {
|
||||
name = "hyprland";
|
||||
humanName = "Hyprland";
|
||||
extraOptions.hyprpaper.enable = config.lib.stylix.mkEnableTarget "Hyprpaper" (
|
||||
config.stylix.image != null
|
||||
);
|
||||
extraOptions.hyprpaper.enable = config.lib.stylix.mkEnableTargetWith {
|
||||
name = "Hyprpaper";
|
||||
autoEnable = config.stylix.image != null;
|
||||
autoEnableExpr = "stylix.image != null";
|
||||
};
|
||||
configElements = [
|
||||
(
|
||||
{ colors }:
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@
|
|||
#
|
||||
# [1]: https://github.com/nix-community/stylix/issues/933
|
||||
# [2]: https://github.com/nix-community/home-manager/issues/6565
|
||||
enable = config.lib.stylix.mkEnableTarget "QT" (
|
||||
pkgs.stdenv.hostPlatform.isLinux && osConfig != null
|
||||
);
|
||||
enable = config.lib.stylix.mkEnableTargetWith {
|
||||
name = "QT";
|
||||
autoEnable = pkgs.stdenv.hostPlatform.isLinux && osConfig != null;
|
||||
autoEnableExpr = "pkgs.stdenv.hostPlatform.isLinux && osConfig != null";
|
||||
};
|
||||
|
||||
platform = lib.mkOption {
|
||||
description = ''
|
||||
|
|
|
|||
|
|
@ -1,9 +1,4 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{ lib, config, ... }:
|
||||
|
||||
let
|
||||
|
||||
|
|
@ -16,7 +11,7 @@ let
|
|||
in
|
||||
{
|
||||
options.stylix.targets.qt = {
|
||||
enable = config.lib.stylix.mkEnableTarget "QT" pkgs.stdenv.hostPlatform.isLinux;
|
||||
enable = config.lib.stylix.mkEnableTarget "QT" true;
|
||||
platform = lib.mkOption {
|
||||
description = ''
|
||||
Selects the platform theme to use for Qt applications.
|
||||
|
|
|
|||
|
|
@ -26,15 +26,19 @@ in
|
|||
})
|
||||
];
|
||||
options.stylix.targets.swaylock = {
|
||||
enable =
|
||||
config.lib.stylix.mkEnableTarget "Swaylock"
|
||||
# When the state version is older than 23.05, Swaylock enables itself
|
||||
# automatically if `settings != {}` [1]. Therefore, Swaylock theming
|
||||
# shouldn't be enabled by default for such state versions, to avoid
|
||||
# inadvertently installing Swaylock when it's not desired.
|
||||
#
|
||||
# [1]: https://github.com/nix-community/home-manager/blob/5cfbf5cc37a3bd1da07ae84eea1b828909c4456b/modules/programs/swaylock.nix#L12-L17
|
||||
(lib.versionAtLeast config.home.stateVersion "23.05");
|
||||
enable = config.lib.stylix.mkEnableTargetWith {
|
||||
name = "Swaylock";
|
||||
# When the state version is older than 23.05, Swaylock enables itself
|
||||
# automatically if `settings != {}` [1]. Therefore, Swaylock theming
|
||||
# shouldn't be enabled by default for such state versions, to avoid
|
||||
# inadvertently installing Swaylock when it's not desired.
|
||||
#
|
||||
# [1]: https://github.com/nix-community/home-manager/blob/5cfbf5cc37a3bd1da07ae84eea1b828909c4456b/modules/programs/swaylock.nix#L12-L17
|
||||
autoEnable = lib.versionAtLeast config.home.stateVersion "23.05";
|
||||
autoEnableExpr = ''
|
||||
lib.versionAtLeast home.stateVersion "23.05"
|
||||
'';
|
||||
};
|
||||
|
||||
useWallpaper = config.lib.stylix.mkEnableWallpaper "Swaylock" true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -66,6 +66,27 @@
|
|||
This should be disabled if manual setup is required or if auto-enabling
|
||||
causes issues.
|
||||
|
||||
The default (`true`) is inherited from `mkEnableTargetWith`.
|
||||
|
||||
`autoEnableExpr` (String)
|
||||
: A string representation of `autoEnable`, for use in documentation.
|
||||
|
||||
Not required if `autoEnable` is a literal `true` or `false`, but **must**
|
||||
be used when `autoEnable` is a dynamic expression.
|
||||
|
||||
E.g. `"pkgs.stdenv.hostPlatform.isLinux"`.
|
||||
|
||||
`autoWrapEnableExpr` (Boolean)
|
||||
: Whether to automatically wrap `autoEnableExpr` with parenthesis, when it
|
||||
contains a potentially problematic infix.
|
||||
|
||||
The default (`true`) is inherited from `mkEnableTargetWith`.
|
||||
|
||||
`enableExample` (Boolean or literal expression)
|
||||
: An example to include on the enable option. The default is calculated
|
||||
automatically by `mkEnableTargetWith` and depends on `autoEnable` and
|
||||
whether an `autoEnableExpr` is used.
|
||||
|
||||
`extraOptions` (Attribute set)
|
||||
: Additional options to be added in the `stylix.targets.${name}` namespace
|
||||
along the `stylix.targets.${name}.enable` option.
|
||||
|
|
@ -152,12 +173,15 @@
|
|||
{
|
||||
name,
|
||||
humanName,
|
||||
autoEnable ? true,
|
||||
autoEnable ? null,
|
||||
autoEnableExpr ? null,
|
||||
autoWrapEnableExpr ? null,
|
||||
enableExample ? null,
|
||||
extraOptions ? { },
|
||||
configElements ? [ ],
|
||||
generalConfig ? null,
|
||||
imports ? [ ],
|
||||
}:
|
||||
}@args:
|
||||
let
|
||||
module =
|
||||
{ config, lib, ... }:
|
||||
|
|
@ -212,7 +236,19 @@ let
|
|||
inherit imports;
|
||||
|
||||
options.stylix.targets.${name}.enable =
|
||||
config.lib.stylix.mkEnableTarget humanName autoEnable;
|
||||
let
|
||||
enableArgs =
|
||||
{
|
||||
name = humanName;
|
||||
}
|
||||
// lib.optionalAttrs (args ? autoEnable) { inherit autoEnable; }
|
||||
// lib.optionalAttrs (args ? autoEnableExpr) { inherit autoEnableExpr; }
|
||||
// lib.optionalAttrs (args ? autoWrapEnableExpr) {
|
||||
autoWrapExpr = autoWrapEnableExpr;
|
||||
}
|
||||
// lib.optionalAttrs (args ? enableExample) { example = enableExample; };
|
||||
in
|
||||
config.lib.stylix.mkEnableTargetWith enableArgs;
|
||||
|
||||
config = lib.mkIf (config.stylix.enable && cfg.enable) (
|
||||
lib.mkMerge (
|
||||
|
|
|
|||
|
|
@ -34,28 +34,100 @@
|
|||
config.lib.stylix =
|
||||
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 =
|
||||
humanName: autoEnable:
|
||||
lib.mkEnableOption "theming for ${humanName}"
|
||||
// {
|
||||
name: autoEnable:
|
||||
config.lib.stylix.mkEnableTargetWith { inherit name autoEnable; };
|
||||
|
||||
mkEnableTargetWith =
|
||||
{
|
||||
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}";
|
||||
default = cfg.autoEnable && autoEnable;
|
||||
example = !autoEnable;
|
||||
}
|
||||
// lib.optionalAttrs autoEnable {
|
||||
defaultText = lib.literalMD "same as `stylix.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 =
|
||||
humanName: autoEnable:
|
||||
lib.mkOption {
|
||||
default = config.stylix.image != null && autoEnable;
|
||||
example = config.stylix.image == null;
|
||||
self.mkEnableIf {
|
||||
description = "Whether to set the wallpaper for ${humanName}.";
|
||||
default = config.stylix.image != null && autoEnable;
|
||||
defaultText =
|
||||
if autoEnable then lib.literalExpression "stylix.image != null" else false;
|
||||
example = config.stylix.image == null;
|
||||
};
|
||||
|
||||
mkEnableIf =
|
||||
{
|
||||
description,
|
||||
default,
|
||||
defaultText ? null,
|
||||
example ? if args ? defaultText then true else !default,
|
||||
}@args:
|
||||
lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
}
|
||||
// lib.optionalAttrs autoEnable {
|
||||
defaultText = lib.literalMD "`stylix.image != null`";
|
||||
defaultText = if args ? defaultText then defaultText else default;
|
||||
inherit
|
||||
default
|
||||
description
|
||||
example
|
||||
;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue