matugen/module.nix
Neurarian 5d31db687e feat: add vibrant color scheme
vibrant scheme was missing so far.
2025-02-22 15:55:16 +01:00

230 lines
7.7 KiB
Nix

# this arg is the matugen flake input
matugen: {
pkgs,
lib,
config,
...
} @ args: let
cfg = config.programs.matugen;
osCfg = args.osConfig.programs.matugen or {};
hexColorRegex = ''#([0-9a-fA-F]{3}){1,2}'';
hexStrippedColorRegex = ''([0-9a-fA-F]{3}){1,2}'';
rgbColorRegex = ''rgb\([0-9]{1,3}, ?[0-9]{1,3}, ?[0-9]{1,3}\)'';
rgbaColorRegex = ''rgba\([0-9]{1,3}, ?[0-9]{1,3}, ?[0-9]{1,3}, ?[0-9]{1,3}\)'';
hslColorRegex = ''hsl\([0-9]{1,3}(\.[0-9]*)?, ?[0-9]{1,3}(\.[0-9]*)?%, ?[0-9]{1,3}(\.[0-9]*)?%\)'';
hslaColorRegex = ''hsla\([0-9]{1,3}(\.[0-9]*)?, ?[0-9]{1,3}(\.[0-9]*)?%, ?[0-9]{1,3}(\.[0-9]*)?%, ?[0,1](\.[0-9]*)?\)'';
hexColor = lib.types.strMatching hexColorRegex;
hexStrippedColor = lib.types.strMatching hexStrippedColorRegex;
rgbColor = lib.types.strMatching rgbColorRegex;
rgbaColor = lib.types.strMatching rgbaColorRegex;
hslColor = lib.types.strMatching hslColorRegex;
hslaColor = lib.types.strMatching hslaColorRegex;
sourceColorType = lib.types.oneOf [hexColor rgbColor hslColor];
customColorType = hexColor; # Only hexColor is currently supported for custom_colors.
configFormat = pkgs.formats.toml {};
capitalize = str: let
inherit (builtins) substring stringLength;
firstChar = substring 0 1 str;
restOfString = substring 1 (stringLength str) str;
in
lib.concatStrings [(lib.toUpper firstChar) restOfString];
# don't use ~, use $HOME
sanitizedTemplates =
builtins.mapAttrs (_: v: {
mode = capitalize cfg.variant;
input_path = builtins.toString v.input_path;
output_path = builtins.replaceStrings ["$HOME"] ["~"] v.output_path;
})
cfg.templates;
matugenConfig = configFormat.generate "matugen-config.toml" {
config = {
custom_colors = cfg.custom_colors;
} // cfg.config;
templates = sanitizedTemplates;
};
# get matugen package
pkg = matugen.packages.${pkgs.system}.default;
# takes in a source color string and returns the subcommand needed to generate
# a color scheme using that color type.
sourceColorTypeMatcher = color: (lib.lists.findSingle (p: null != builtins.match p.regex color) {} {} [
{ regex = hexColorRegex; code = "hex"; }
{ regex = rgbColorRegex; code = "rgb"; }
{ regex = hslColorRegex; code = "hsl"; }
]).code;
command = if (builtins.isNull cfg.source_color) then
"image ${cfg.wallpaper}" else
"color ${sourceColorTypeMatcher cfg.source_color} \"${cfg.source_color}\"";
themePackage = builtins.trace command (pkgs.runCommandLocal "matugen-themes-${cfg.variant}" {} ''
mkdir -p $out
cd $out
export HOME=$(pwd)
${cfg.package}/bin/matugen \
${command} \
--config ${matugenConfig} \
--mode ${cfg.variant} \
--type ${cfg.type} \
--json ${cfg.jsonFormat} \
--contrast ${lib.strings.floatToString cfg.contrast} \
--quiet \
> $out/theme.json
'');
colors = (builtins.fromJSON (builtins.readFile "${themePackage}/theme.json")).colors;
in {
options.programs.matugen = {
enable = lib.mkEnableOption "Matugen declarative theming";
package =
lib.mkPackageOption pkgs "matugen" {}
// {
default = pkg;
};
source_color = lib.mkOption {
description = "Hex color to generate the colorschemes from. If this and wallpaper are defined, will use this.";
type = lib.types.nullOr sourceColorType;
default = osCfg.source_color or null;
example = "#ff1243";
};
wallpaper = lib.mkOption {
description = "Path to `wallpaper` that matugen will generate the colorschemes from";
type = lib.types.path;
default = osCfg.wallpaper or "${pkgs.nixos-artwork.wallpapers.simple-blue}/share/backgrounds/nixos/nix-wallpaper-simple-blue.png";
defaultText = lib.literalExample ''
"${pkgs.nixos-artwork.wallpapers.simple-blue}/share/backgrounds/nixos/nix-wallpaper-simple-blue.png"
'';
};
templates = lib.mkOption {
type = with lib.types;
attrsOf (submodule {
options = {
input_path = lib.mkOption {
type = path;
description = "Path to the template";
example = "./style.css";
};
output_path = lib.mkOption {
type = str;
description = "Path where the generated file will be written to";
example = "~/.config/sytle.css";
};
};
});
default = osCfg.templates or {};
description = ''
Templates that have `@{placeholders}` which will be replaced by the respective colors.
See <https://github.com/InioX/matugen/wiki/Configuration#example-of-all-the-color-keywords> for a list of colors.
'';
};
custom_colors = lib.mkOption {
description = "Other colors that should be included in the colorsheme.";
type = with lib.types;
attrsOf (submodule {
options = {
color = lib.mkOption {
description = "Color value for this custom color.";
type = customColorType;
example = "#d03e3e";
};
blend = lib.mkOption {
description = "Whether to pick a color close to the given value, or to pass the value through to the final colorscheme unchanged.";
type = bool;
default = true;
};
};
});
default = osCfg.custom_colors or {};
example = ''
{
light-red.color = "#d03e3e";
light-orange.color = "#d7691d";
light-yellow.color = "#ad8200";
red = {
color = "#ff0000";
blend = false;
};
}
'';
};
type = lib.mkOption {
description = "Palette used when generating the colorschemes.";
type = lib.types.enum ["scheme-content" "scheme-expressive" "scheme-fidelity" "scheme-fruit-salad" "scheme-monochrome" "scheme-neutral" "scheme-rainbow" "scheme-tonal-spot" "scheme-vibrant"];
default = osCfg.palette or "scheme-tonal-spot";
example = "scheme-content";
};
jsonFormat = lib.mkOption {
description = "Color format of the colorschemes.";
type = lib.types.enum ["rgb" "rgba" "hsl" "hsla" "hex" "strip"];
default = osCfg.jsonFormat or "strip";
example = "rgba";
};
variant = lib.mkOption {
description = "Colorscheme variant.";
type = lib.types.enum ["light" "dark" "amoled"];
default = osCfg.variant or "dark";
example = "light";
};
contrast = lib.mkOption {
description = "Value from -1 to 1. -1 represents minimum contrast, 0 represents standard (i.e. the design as spec'd), and 1 represents maximum contrast.";
type = lib.types.numbers.between (-1) 1;
default = 0;
example = "0.2";
};
config = lib.mkOption {
description = "Add things to the config not covered by other options.";
type = lib.types.attrs;
default = osCfg.config or {};
example = ''
{
custom_keywords.font1 = "Google Sans";
}
'';
};
theme.files = lib.mkOption {
type = lib.types.package;
readOnly = true;
default =
if builtins.hasAttr "templates" osCfg
then
if cfg.templates != osCfg.templates
then themePackage
else osCfg.theme.files
else themePackage;
description = "Generated theme files. Including only the variant chosen.";
};
theme.colors = lib.mkOption {
inherit (pkgs.formats.json {}) type;
readOnly = true;
default =
if builtins.hasAttr "templates" osCfg
then
if cfg.templates != osCfg.templates
then colors
else osCfg.theme.colors
else colors;
description = "Generated theme colors. Includes all variants.";
};
};
}