diff --git a/lib/types.nix b/lib/types.nix index 3f990382c..e949727bf 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -43,8 +43,10 @@ in mergeModules [ name = "static"; description = "static wallpaper"; descriptionClass = "noun"; + check = value: builtins.attrNames value == [ "colors" "image" ]; + constructor = { image, polarity ? "either" }: { @@ -57,8 +59,10 @@ in mergeModules [ name = "slideshow"; description = "slideshow wallpaper"; descriptionClass = "noun"; + check = value: builtins.attrNames value == [ "colors" "delay" "image" "images" ]; + constructor = { images, delay ? 300, polarity ? "either" }: rec { @@ -72,8 +76,10 @@ in mergeModules [ name = "animation"; description = "animated wallpaper"; descriptionClass = "noun"; + check = value: builtins.attrNames value == [ "animation" "colors" "image" ]; + constructor = { animation, polarity ? "either" }: rec { @@ -87,8 +93,10 @@ in mergeModules [ name = "video"; description = "video wallpaper"; descriptionClass = "noun"; + check = value: builtins.attrNames value == [ "colors" "image" "video" ]; + constructor = { video, polarity ? "either" }: rec { @@ -104,74 +112,60 @@ in mergeModules [ types.oneOf [ static slideshow animation video ]; } - (typeModule { - name = "scheme"; - description = "base16 scheme"; - descriptionClass = "noun"; - check = value: - let - bases = [ - "base00" "base01" "base02" "base03" - "base04" "base05" "base06" "base07" - "base08" "base09" "base0A" "base0B" - "base0C" "base0D" "base0E" "base0F" - ]; - meta = [ - "scheme" "author" "description" "slug" - ]; - requiredAttrs = bases; - allowedAttrs = bases ++ meta; - in - types.path.check value || - (builtins.isAttrs value - && all (a: elem a allowedAttrs) (builtins.attrNames value) - && all (a: elem a (builtins.attrNames value)) requiredAttrs - ); - }) + (let + bases = [ + "base00" "base01" "base02" "base03" + "base04" "base05" "base06" "base07" + "base08" "base09" "base0A" "base0B" + "base0C" "base0D" "base0E" "base0F" + ]; + meta = [ + "scheme" "author" "description" "slug" + ]; - (typeModule { - name = "override"; - description = "override for base16 scheme"; - descriptionClass = "noun"; - emptyValue.value = { }; - check = value: - let allowedAttrs = [ - "base00" "base01" "base02" "base03" - "base04" "base05" "base06" "base07" - "base08" "base09" "base0A" "base0B" - "base0C" "base0D" "base0E" "base0F" - "scheme" "author" "description" "slug" - ]; - in builtins.isAttrs value - && all (a: elem a allowedAttrs) (builtins.attrNames value); - }) + hasOnlyPermittedAttrs = set: + all (a: elem a (bases ++ meta)) (attrNames set); + + hasAllRequiredAttrs = set: + all (a: elem a (attrNames set)) bases; + + isSchemeOrOverride = value: + types.path.check value || + (builtins.isAttrs value && hasOnlyPermittedAttrs value); + + isScheme = value: + types.path.check value || + (builtins.isAttrs value && hasAllRequiredAttrs value); - (typeModule { - name = "overridableScheme"; - description = "base16 scheme with overrides"; - descriptionClass = "conjunction"; - emptyValue.value = { }; - check = value: - config.lib.stylix.types.scheme.check value || - config.lib.stylix.types.override.check value; merge = optionName: definitions: let values = catAttrs "value" definitions; - partitioned = partition config.lib.stylix.types.scheme.check values; - scheme = - if length partitioned.right < 1 + + partitioned = partition isScheme values; + schemes = partitioned.right; + overrides = partitioned.wrong; + + schemeDefinition = + if length schemes < 1 then - # If only overrides were provided, try applying them to the option default. + # If only overrides were found, try looking at the option default for a scheme. if hasAttrByPath (optionName ++ [ "default" ]) options then getAttrFromPath (optionName ++ [ "default" ]) options - else throw "At least one definition for `${showOption optionName}' must be a whole scheme." + else throw "At least one definition for `${showOption optionName}' must contain a whole scheme." else - if length partitioned.right > 1 - then throw "Only one definition for `${showOption optionName}' may be a whole scheme." - else elemAt partitioned.right 0; - in foldr - (o: s: s.override o) - (base16.mkSchemeAttrs scheme) - partitioned.wrong; + if length schemes > 1 + then throw "Only one definition for `${showOption optionName}' may contain a whole scheme." + else elemAt schemes 0; + + scheme = base16.mkSchemeAttrs schemeDefinition; + + in foldr (o: s: s.override o) scheme overrides; + + in typeModule { + name = "scheme"; + description = "base16 scheme"; + descriptionClass = "noun"; + check = isSchemeOrOverride; + inherit merge; }) ] diff --git a/stylix/palette.nix b/stylix/palette.nix index 53dc61c5a..145d1b3c9 100644 --- a/stylix/palette.nix +++ b/stylix/palette.nix @@ -111,7 +111,7 @@ in { }; colors = mkOption { - type = config.lib.stylix.types.overridableScheme; + type = config.lib.stylix.types.scheme; default = config.stylix.wallpaper.colors; defaultText = literalMD "generated scheme based on `stylix.wallpaper`"; description = '' @@ -127,6 +127,8 @@ in { - Anything from `base00` to `base0F`, but not all of them - Optionally `scheme`, `author`, `description` or `slug` + There must be exactly one whole scheme. + Popular files can be imported from [`base16-schemes`](https://github.com/tinted-theming/base16-schemes): @@ -137,7 +139,7 @@ in { } ``` - To choose a scheme and override it from the same place, use `mkMerge`: + To choose a scheme and override it from the same file, use `mkMerge`: ```nix { pkgs, lib, ... }: