539 lines
15 KiB
Nix
539 lines
15 KiB
Nix
{
|
|
config,
|
|
inputs,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
let
|
|
cfg = config.theme;
|
|
|
|
init = pkgs.writeShellApplication {
|
|
name = "theme-init";
|
|
runtimeInputs = with pkgs; [ matugen ];
|
|
text = ''
|
|
[[ ! -d "${cfg.configDir}" ]] && mkdir -p "${cfg.configDir}"
|
|
[[ ! -L "${cfg.configDir}"/wallpaper ]] && ln -sf "${cfg.wallpaper}" "${cfg.configDir}"/wallpaper
|
|
[[ ! -f "${cfg.configDir}"/mode ]] && echo "${cfg.mode}" > "${cfg.configDir}"/mode
|
|
|
|
matugen image "${cfg.configDir}/wallpaper" \
|
|
--type scheme-${cfg.flavour} \
|
|
--mode "$(cat "${cfg.configDir}/mode")" \
|
|
--contrast ${builtins.toString cfg.contrast}
|
|
|
|
${cfg.initExtraConfig}
|
|
wait
|
|
'';
|
|
};
|
|
|
|
reload = pkgs.writeShellApplication {
|
|
name = "theme-reload";
|
|
text = ''
|
|
${cfg.reloadExtraConfig}
|
|
wait
|
|
'';
|
|
};
|
|
|
|
theme = pkgs.writeShellApplication {
|
|
name = "theme";
|
|
runtimeInputs = with pkgs; [ coreutils ];
|
|
runtimeEnv = {
|
|
CONFIG = cfg.configDir;
|
|
DEFAULT_WALLPAPER = cfg.wallpaper;
|
|
DEFAULT_MODE = cfg.mode;
|
|
INIT = lib.meta.getExe init;
|
|
RELOAD = lib.meta.getExe reload;
|
|
};
|
|
text = builtins.readFile ./theme.sh;
|
|
};
|
|
in
|
|
{
|
|
# https://github.com/Theaninova/TheaninovOS/blob/master/modules/home-manager/theme/md3-evo.nix
|
|
options.theme =
|
|
with lib;
|
|
with types;
|
|
{
|
|
enable = mkEnableOption "theme";
|
|
|
|
configDir = mkOption {
|
|
type = str;
|
|
default = "${config.xdg.configHome}/theme";
|
|
description = "The path to the theme config directory.";
|
|
};
|
|
|
|
wallpaper = mkOption {
|
|
type = path;
|
|
description = "The path to the default wallpaper";
|
|
};
|
|
|
|
pkg = mkOption {
|
|
type = package;
|
|
default = theme;
|
|
readOnly = true;
|
|
description = "The package containing the `theme` script";
|
|
};
|
|
|
|
initExtraConfig = mkOption {
|
|
type = lines;
|
|
default = "";
|
|
description = "Extra configuration lines to add to the theme initialization script.";
|
|
};
|
|
|
|
reloadExtraConfig = mkOption {
|
|
type = lines;
|
|
default = "";
|
|
description = "Extra configuration lines to add to the theme reload script.";
|
|
};
|
|
|
|
template = mkOption {
|
|
type = attrsOf (
|
|
submodule (
|
|
{ name, config, ... }:
|
|
{
|
|
options = {
|
|
source = mkOption {
|
|
type = nullOr path;
|
|
description = "Path of the source file or directory.";
|
|
default = null;
|
|
};
|
|
|
|
text = mkOption {
|
|
type = nullOr str;
|
|
description = "Text of the file.";
|
|
default = null;
|
|
};
|
|
|
|
target = mkOption {
|
|
type = str;
|
|
defaultText = literalExpression "name";
|
|
description = "Path to target relative to the user's {env}`HOME`.";
|
|
};
|
|
};
|
|
|
|
config.target = mkDefault name;
|
|
}
|
|
)
|
|
);
|
|
default = { };
|
|
description = "Templates to fill with theme colors.";
|
|
};
|
|
|
|
flavour = mkOption {
|
|
type = enum [
|
|
"content"
|
|
"expressive"
|
|
"fidelity"
|
|
"fruit-salad"
|
|
"monochrome"
|
|
"neutral"
|
|
"rainbow"
|
|
"tonal-spot"
|
|
];
|
|
default = "tonal-spot";
|
|
description = "The flavour of the theme.";
|
|
};
|
|
|
|
mode = mkOption {
|
|
type = enum [
|
|
"dark"
|
|
"light"
|
|
];
|
|
default = "dark";
|
|
description = "The default mode of the theme.";
|
|
};
|
|
|
|
contrast = mkOption {
|
|
type = numbers.between (-1) 1;
|
|
default = 0;
|
|
description = "Use a modified contrast.";
|
|
};
|
|
|
|
opacity = mkOption {
|
|
type = numbers.between 0 1;
|
|
default = 1;
|
|
description = "The opacity of apps.";
|
|
};
|
|
|
|
radius = mkOption {
|
|
type = ints.unsigned;
|
|
default = 8;
|
|
description = "The radius of corners.";
|
|
};
|
|
|
|
padding = mkOption {
|
|
type = ints.unsigned;
|
|
default = 8;
|
|
description = "The padding of windows.";
|
|
};
|
|
|
|
blur = mkOption {
|
|
type = ints.unsigned;
|
|
default = 0;
|
|
description = "The blur amount of windows.";
|
|
};
|
|
|
|
color = {
|
|
semantic = {
|
|
blend = mkOption {
|
|
type = bool;
|
|
default = true;
|
|
description = "Blend the colors.";
|
|
};
|
|
|
|
danger = mkOption {
|
|
type = str;
|
|
default = "#ff0000";
|
|
description = "The color of danger.";
|
|
};
|
|
|
|
warning = mkOption {
|
|
type = str;
|
|
default = "#ffff00";
|
|
description = "The color of warning.";
|
|
};
|
|
|
|
success = mkOption {
|
|
type = str;
|
|
default = "#00ff00";
|
|
description = "The color of success.";
|
|
};
|
|
|
|
info = mkOption {
|
|
type = str;
|
|
default = "#0000ff";
|
|
description = "The color of info.";
|
|
};
|
|
};
|
|
|
|
syntax = {
|
|
blend = mkOption {
|
|
type = bool;
|
|
default = true;
|
|
description = "Blend the colors.";
|
|
};
|
|
|
|
keywords = mkOption {
|
|
type = str;
|
|
default = "#ff8000";
|
|
description = "The color of keywords.";
|
|
};
|
|
|
|
functions = mkOption {
|
|
type = str;
|
|
default = "#0000ff";
|
|
description = "The color of functions.";
|
|
};
|
|
|
|
properties = mkOption {
|
|
type = str;
|
|
default = "#ff00ff";
|
|
description = "The color of properties.";
|
|
};
|
|
|
|
constants = mkOption {
|
|
type = str;
|
|
default = "#ff00ff";
|
|
description = "The color of constants.";
|
|
};
|
|
|
|
strings = mkOption {
|
|
type = str;
|
|
default = "#00ff00";
|
|
description = "The color of variables.";
|
|
};
|
|
|
|
numbers = mkOption {
|
|
type = str;
|
|
default = "#00ffff";
|
|
description = "The color of numbers.";
|
|
};
|
|
|
|
structures = mkOption {
|
|
type = str;
|
|
default = "#ffff00";
|
|
description = "The color of structures.";
|
|
};
|
|
|
|
types = mkOption {
|
|
type = str;
|
|
default = "#00ffff";
|
|
description = "The color of types.";
|
|
};
|
|
};
|
|
|
|
basic = {
|
|
blend = mkOption {
|
|
type = bool;
|
|
default = true;
|
|
description = "Blend the colors.";
|
|
};
|
|
|
|
red = mkOption {
|
|
type = str;
|
|
default = "#ff0000";
|
|
description = "The color of red.";
|
|
};
|
|
|
|
orange = mkOption {
|
|
type = str;
|
|
default = "#ff8000";
|
|
description = "The color of orange.";
|
|
};
|
|
|
|
yellow = mkOption {
|
|
type = str;
|
|
default = "#ffff00";
|
|
description = "The color of yellow.";
|
|
};
|
|
|
|
green = mkOption {
|
|
type = str;
|
|
default = "#00ff00";
|
|
description = "The color of green.";
|
|
};
|
|
|
|
cyan = mkOption {
|
|
type = str;
|
|
default = "#00ffff";
|
|
description = "The color of cyan.";
|
|
};
|
|
|
|
blue = mkOption {
|
|
type = str;
|
|
default = "#0000ff";
|
|
description = "The color of blue.";
|
|
};
|
|
|
|
magenta = mkOption {
|
|
type = str;
|
|
default = "#ff00ff";
|
|
description = "The color of magenta.";
|
|
};
|
|
|
|
pink = mkOption {
|
|
type = str;
|
|
default = "#ffc0cb";
|
|
description = "The color of pink.";
|
|
};
|
|
};
|
|
};
|
|
|
|
font = {
|
|
sansSerif = {
|
|
names = mkOption {
|
|
type = listOf str;
|
|
default = [ "Roboto" ];
|
|
description = "The sans serif font families.";
|
|
};
|
|
|
|
packages = mkOption {
|
|
type = listOf package;
|
|
default = with pkgs; [ roboto ];
|
|
description = "The sans serif font packages.";
|
|
};
|
|
};
|
|
|
|
serif = {
|
|
names = mkOption {
|
|
type = listOf str;
|
|
default = [ "Roboto Serif" ];
|
|
description = "The serif font families.";
|
|
};
|
|
|
|
packages = mkOption {
|
|
type = listOf package;
|
|
default = with pkgs; [ roboto-serif ];
|
|
description = "The serif font packages.";
|
|
};
|
|
};
|
|
|
|
monospace = {
|
|
names = mkOption {
|
|
type = listOf str;
|
|
default = [ "JetBrainsMono Nerd Font" ];
|
|
description = "The monospace font families.";
|
|
};
|
|
|
|
packages = mkOption {
|
|
type = listOf package;
|
|
default = with pkgs; [ nerd-fonts.jetbrains-mono ];
|
|
description = "The monospace font packages.";
|
|
};
|
|
};
|
|
|
|
emoji = {
|
|
names = mkOption {
|
|
type = listOf str;
|
|
default = [
|
|
"Noto Emoji"
|
|
"Font Awesome"
|
|
];
|
|
description = "The emoji font families.";
|
|
};
|
|
|
|
packages = mkOption {
|
|
type = listOf package;
|
|
default = with pkgs; [
|
|
noto-fonts-color-emoji
|
|
font-awesome
|
|
];
|
|
description = "The emoji font packages.";
|
|
};
|
|
};
|
|
|
|
size = mkOption {
|
|
type = ints.positive;
|
|
default = 12;
|
|
description = "The font size.";
|
|
};
|
|
};
|
|
|
|
icon = {
|
|
names = mkOption {
|
|
type = listOf str;
|
|
default = [ "Adwaita" ];
|
|
description = "The icon theme names.";
|
|
};
|
|
|
|
packages = mkOption {
|
|
type = listOf package;
|
|
default = with pkgs; [
|
|
adwaita-icon-theme
|
|
nixos-icons
|
|
];
|
|
description = "The icon theme packages.";
|
|
};
|
|
};
|
|
|
|
cursor = {
|
|
names = mkOption {
|
|
type = listOf str;
|
|
default = [ "Adwaita" ];
|
|
description = "The cursor names.";
|
|
};
|
|
|
|
packages = mkOption {
|
|
type = listOf package;
|
|
default = with pkgs; [ adwaita-icon-theme ];
|
|
description = "The cursor theme packages.";
|
|
};
|
|
|
|
size = mkOption {
|
|
type = ints.positive;
|
|
default = 32;
|
|
description = "The cursor size.";
|
|
};
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
home = {
|
|
activation.themeInit = inputs.home-manager.lib.hm.dag.entryAfter [
|
|
"writeBoundary"
|
|
"dconfSettings"
|
|
] "run ${lib.meta.getExe init}";
|
|
|
|
packages =
|
|
with pkgs;
|
|
[
|
|
matugen
|
|
theme
|
|
]
|
|
++ cfg.font.sansSerif.packages
|
|
++ cfg.font.serif.packages
|
|
++ cfg.font.monospace.packages
|
|
++ cfg.font.emoji.packages
|
|
++ cfg.icon.packages
|
|
++ cfg.cursor.packages;
|
|
|
|
pointerCursor = {
|
|
name = builtins.head cfg.cursor.names;
|
|
package = builtins.head cfg.cursor.packages;
|
|
inherit (cfg.cursor) size;
|
|
};
|
|
};
|
|
|
|
fonts.fontconfig = {
|
|
enable = true;
|
|
defaultFonts = {
|
|
sansSerif = cfg.font.sansSerif.names;
|
|
serif = cfg.font.serif.names;
|
|
monospace = cfg.font.monospace.names;
|
|
emoji = cfg.font.emoji.names;
|
|
};
|
|
};
|
|
|
|
xdg.configFile."matugen/config.toml".source = (
|
|
(pkgs.formats.toml { }).generate "matugen" {
|
|
config = {
|
|
custom_colors =
|
|
let
|
|
mkColor = category: color: {
|
|
color = cfg.color.${category}.${color};
|
|
blend = cfg.color.${category}.blend;
|
|
};
|
|
in
|
|
{
|
|
danger = mkColor "semantic" "danger";
|
|
warning = mkColor "semantic" "warning";
|
|
success = mkColor "semantic" "success";
|
|
info = mkColor "semantic" "info";
|
|
|
|
red = mkColor "basic" "red";
|
|
orange = mkColor "basic" "orange";
|
|
yellow = mkColor "basic" "yellow";
|
|
green = mkColor "basic" "green";
|
|
cyan = mkColor "basic" "cyan";
|
|
blue = mkColor "basic" "blue";
|
|
magenta = mkColor "basic" "magenta";
|
|
pink = mkColor "basic" "pink";
|
|
|
|
keywords = mkColor "syntax" "keywords";
|
|
functions = mkColor "syntax" "functions";
|
|
properties = mkColor "syntax" "properties";
|
|
constants = mkColor "syntax" "constants";
|
|
strings = mkColor "syntax" "strings";
|
|
numbers = mkColor "syntax" "numbers";
|
|
structures = mkColor "syntax" "structures";
|
|
types = mkColor "syntax" "types";
|
|
};
|
|
|
|
custom_keywords =
|
|
let
|
|
zeroPad = hex: if builtins.stringLength hex == 1 then "0${hex}" else hex;
|
|
percentageToHex = percentage: zeroPad (lib.trivial.toHexString (builtins.floor (percentage * 255)));
|
|
in
|
|
{
|
|
flavour = cfg.flavour;
|
|
contrast = builtins.toString cfg.contrast;
|
|
radius = builtins.toString cfg.radius;
|
|
padding = builtins.toString cfg.padding;
|
|
padding_double = builtins.toString (cfg.padding * 2);
|
|
blur = builtins.toString cfg.blur;
|
|
opacity = builtins.toString cfg.opacity;
|
|
opacity_hex = builtins.toString (percentageToHex cfg.opacity);
|
|
opacity_shadow = builtins.toString (cfg.opacity * 0.75);
|
|
opacity_shadow_hex = builtins.toString (percentageToHex (cfg.opacity * 0.75));
|
|
font_size = builtins.toString cfg.font.size;
|
|
font_sans_serif = builtins.head cfg.font.sansSerif.names;
|
|
font_sans_serif_all = builtins.concatStringsSep ", " cfg.font.sansSerif.names;
|
|
font_serif = builtins.head cfg.font.serif.names;
|
|
font_serif_all = builtins.concatStringsSep ", " cfg.font.serif.names;
|
|
font_monospace = builtins.head cfg.font.monospace.names;
|
|
font_monospace_all = builtins.concatStringsSep ", " cfg.font.monospace.names;
|
|
font_emoji = builtins.head cfg.font.emoji.names;
|
|
font_emoji_all = builtins.concatStringsSep ", " cfg.font.emoji.names;
|
|
};
|
|
};
|
|
|
|
templates = builtins.mapAttrs (name: template: {
|
|
input_path = template.source or (pkgs.writeText name template.text);
|
|
output_path = template.target;
|
|
}) cfg.template;
|
|
}
|
|
);
|
|
|
|
programs.zsh.initExtra = builtins.readFile ./theme.completion.zsh;
|
|
};
|
|
}
|