Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/src/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions modules/feh/hm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 }:
Expand Down
4 changes: 4 additions & 0 deletions modules/feh/nixos.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 }:
Expand Down
6 changes: 5 additions & 1 deletion modules/gnome/hm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down
8 changes: 5 additions & 3 deletions modules/hyprland/hm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 }:
Expand Down
8 changes: 5 additions & 3 deletions modules/qt/hm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ''
Expand Down
9 changes: 2 additions & 7 deletions modules/qt/nixos.nix
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
{
lib,
pkgs,
config,
...
}:
{ lib, config, ... }:

let

Expand All @@ -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.
Expand Down
22 changes: 13 additions & 9 deletions modules/swaylock/hm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
42 changes: 39 additions & 3 deletions stylix/mk-target.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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, ... }:
Expand Down Expand Up @@ -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 (
Expand Down
96 changes: 84 additions & 12 deletions stylix/target.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
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;
description = "Whether to set the wallpaper for ${humanName}.";
};

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
;
};
};
}