diff --git a/modules/programs/kitty.nix b/modules/programs/kitty.nix index ac184596..0c4809be 100644 --- a/modules/programs/kitty.nix +++ b/modules/programs/kitty.nix @@ -168,10 +168,52 @@ in in `kitty-themes`, without the `.conf` suffix. See for a list of themes. + + Note that if any automatic themes are configured via + `programs.kitty.autoThemeFiles`, Kitty will prefer them based on the + OS color scheme and they will override other color and background image + settings. ''; example = "SpaceGray_Eighties"; }; + autoThemeFiles = mkOption { + type = types.nullOr ( + types.submodule { + options = { + light = mkOption { + type = types.str; + description = "Theme name for light color scheme."; + }; + dark = mkOption { + type = types.str; + description = "Theme name for dark color scheme."; + }; + noPreference = mkOption { + type = types.str; + description = "Theme name for no-preference color scheme."; + }; + }; + } + ); + default = null; + description = '' + Configure Kitty automatic color themes. This creates + {file}`$XDG_CONFIG_HOME/kitty/light-theme.auto.conf`, + {file}`$XDG_CONFIG_HOME/kitty/dark-theme.auto.conf`, and + {file}`$XDG_CONFIG_HOME/kitty/no-preference-theme.auto.conf`. + Kitty applies these based on the OS color scheme, and they override + other color and background image settings. + ''; + example = literalExpression '' + { + light = "GitHub"; + dark = "TokyoNight"; + noPreference = "OneDark"; + } + ''; + }; + font = mkOption { type = types.nullOr lib.hm.types.fontType; default = null; @@ -358,15 +400,35 @@ in ''; }; - home.activation.checkKittyTheme = mkIf (cfg.themeFile != null) ( + xdg.configFile."kitty/light-theme.auto.conf" = mkIf (cfg.autoThemeFiles != null) { + text = "include ${pkgs.kitty-themes}/share/kitty-themes/themes/${cfg.autoThemeFiles.light}.conf\n"; + }; + + xdg.configFile."kitty/dark-theme.auto.conf" = mkIf (cfg.autoThemeFiles != null) { + text = "include ${pkgs.kitty-themes}/share/kitty-themes/themes/${cfg.autoThemeFiles.dark}.conf\n"; + }; + + xdg.configFile."kitty/no-preference-theme.auto.conf" = mkIf (cfg.autoThemeFiles != null) { + text = "include ${pkgs.kitty-themes}/share/kitty-themes/themes/${cfg.autoThemeFiles.noPreference}.conf\n"; + }; + + home.activation.checkKittyTheme = mkIf (cfg.themeFile != null || cfg.autoThemeFiles != null) ( let - themePath = "${pkgs.kitty-themes}/share/kitty-themes/themes/${cfg.themeFile}.conf"; + themePath = name: "${pkgs.kitty-themes}/share/kitty-themes/themes/${name}.conf"; + checkThemeFile = name: '' + if [[ ! -f "${themePath name}" ]]; then + errorEcho "kitty-themes does not contain the theme file ${themePath name}!" + exit 1 + fi + ''; in lib.hm.dag.entryBefore [ "writeBoundary" ] '' - if [[ ! -f "${themePath}" ]]; then - errorEcho "kitty-themes does not contain the theme file ${themePath}!" - exit 1 - fi + ${lib.optionalString (cfg.themeFile != null) (checkThemeFile cfg.themeFile)} + ${lib.optionalString (cfg.autoThemeFiles != null) '' + ${checkThemeFile cfg.autoThemeFiles.light} + ${checkThemeFile cfg.autoThemeFiles.dark} + ${checkThemeFile cfg.autoThemeFiles.noPreference} + ''} '' ); diff --git a/tests/integration/standalone/kitty-auto-theme-bad-home.nix b/tests/integration/standalone/kitty-auto-theme-bad-home.nix new file mode 100644 index 00000000..b6e0ab06 --- /dev/null +++ b/tests/integration/standalone/kitty-auto-theme-bad-home.nix @@ -0,0 +1,17 @@ +{ + home.username = "alice"; + home.homeDirectory = "/home/alice"; + home.stateVersion = "24.11"; + + # Let Home Manager install and manage itself. + programs.home-manager.enable = true; + + programs.kitty = { + enable = true; + autoThemeFiles = { + light = "GitHub"; + dark = "No Such Theme"; + noPreference = "OneDark"; + }; + }; +} diff --git a/tests/integration/standalone/kitty.nix b/tests/integration/standalone/kitty.nix index f9692792..2addf12a 100644 --- a/tests/integration/standalone/kitty.nix +++ b/tests/integration/standalone/kitty.nix @@ -59,6 +59,14 @@ assert expected in actual, \ f"expected home-manager switch to contain {expected}, but got {actual}" + with subtest("Switch to Bad Kitty Auto Theme"): + succeed_as_alice("cp ${./kitty-auto-theme-bad-home.nix} /home/alice/.config/home-manager/home.nix") + + actual = fail_as_alice("home-manager switch") + expected = "kitty-themes does not contain the theme file" + assert expected in actual, \ + f"expected home-manager switch to contain {expected}, but got {actual}" + with subtest("Switch to Good Kitty"): succeed_as_alice("cp ${./kitty-theme-good-home.nix} /home/alice/.config/home-manager/home.nix") diff --git a/tests/modules/programs/kitty/auto-theme-files.nix b/tests/modules/programs/kitty/auto-theme-files.nix new file mode 100644 index 00000000..e0bf6510 --- /dev/null +++ b/tests/modules/programs/kitty/auto-theme-files.nix @@ -0,0 +1,27 @@ +{ config, pkgs, ... }: +{ + programs.kitty = { + enable = true; + autoThemeFiles = { + light = "GitHub"; + dark = "TokyoNight"; + noPreference = "OneDark"; + }; + }; + + test = { + assertFileExists = [ + "home-files/.config/kitty/light-theme.auto.conf" + "home-files/.config/kitty/dark-theme.auto.conf" + "home-files/.config/kitty/no-preference-theme.auto.conf" + ]; + assertFileRegex = [ + "home-files/.config/kitty/light-theme.auto.conf" + "^include .*themes/GitHub\\.conf$" + "home-files/.config/kitty/dark-theme.auto.conf" + "^include .*themes/TokyoNight\\.conf$" + "home-files/.config/kitty/no-preference-theme.auto.conf" + "^include .*themes/OneDark\\.conf$" + ]; + }; +} diff --git a/tests/modules/programs/kitty/default.nix b/tests/modules/programs/kitty/default.nix index bbb3afae..78965036 100644 --- a/tests/modules/programs/kitty/default.nix +++ b/tests/modules/programs/kitty/default.nix @@ -4,4 +4,5 @@ kitty-null-shellIntegration = ./null-shellIntegration.nix; kitty-example-mkOrder = ./example-mkOrder.nix; kitty-example-quickAccessTerminalConfig = ./example-quickAccessTerminalConfig.nix; + kitty-auto-theme-files = ./auto-theme-files.nix; }