This commit is contained in:
raf 2025-12-04 19:50:39 +01:00 committed by GitHub
commit 9a99e39f8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 320 additions and 198 deletions

View file

@ -5,115 +5,98 @@
inherit (lib.strings) optionalString splitString;
inherit (lib.attrsets) mapCartesianProduct;
inherit (lib.lists) intersectLists;
inherit (lib.trivial) boolToString warnIf;
inherit (lib.trivial) warnIf;
inherit (lib.nvim.lua) toLuaObject;
in {
# FIXME: those all need to be converted to setupOpts format
# or else we explode...
base16 = {
setup = {base16-colors, ...}: ''
setup = setupOpts: ''
-- Base16 theme
require('base16-colorscheme').setup(${toLuaObject base16-colors})
require('base16-colorscheme').setup(${toLuaObject setupOpts})
'';
};
mini-base16 = {
setup = {base16-colors, ...}: ''
setup = setupOpts: ''
-- Base16 theme
require('mini.base16').setup({
palette = ${toLuaObject base16-colors}
palette = ${toLuaObject setupOpts}
})
'';
};
onedark = {
setup = {
style ? "dark",
transparent,
...
}: ''
styles = ["dark" "darker" "cool" "deep" "warm" "warmer"];
setup = setupOpts: ''
-- OneDark theme
require('onedark').setup {
transparent = ${boolToString transparent},
style = "${style}"
}
require('onedark').setup(${toLuaObject setupOpts})
require('onedark').load()
'';
styles = ["dark" "darker" "cool" "deep" "warm" "warmer"];
};
tokyonight = {
setup = {
style ? "night",
transparent,
...
}: ''
require('tokyonight').setup {
transparent = ${boolToString transparent};
styles = {
sidebars = ${
if transparent
then ''"transparent"''
else ''"dark"''
},
floats = ${
if transparent
then ''"transparent"''
else ''"dark"''
},
},
}
vim.cmd[[colorscheme tokyonight-${style}]]
'';
styles = ["day" "night" "storm" "moon"];
setup = setupOpts: ''
require('tokyonight').setup(${toLuaObject setupOpts})
vim.cmd[[colorscheme tokyonight-${setupOpts.style or "night"}]]
'';
};
dracula = {
setup = {transparent, ...}: ''
require('dracula').setup({
transparent_bg = ${boolToString transparent},
});
setup = setupOpts: let
cleanedOpts =
(removeAttrs setupOpts ["transparent"])
// {
transparent_bg = setupOpts.transparent or false;
};
in ''
require('dracula').setup(${toLuaObject cleanedOpts});
require('dracula').load();
'';
};
catppuccin = {
setup = {
style ? "mocha",
transparent ? false,
...
}: ''
-- Catppuccin theme
require('catppuccin').setup {
flavour = "${style}",
transparent_background = ${boolToString transparent},
float = {
transparent = ${boolToString transparent},
},
term_colors = true,
integrations = {
nvimtree = {
enabled = true,
transparent_panel = ${boolToString transparent},
show_root = true,
},
setup = setupOpts: let
cleanedOpts =
(removeAttrs setupOpts ["style" "transparent"])
// {
flavour = setupOpts.style or "mocha";
transparent_background = setupOpts.transparent or false;
float = {
transparent = setupOpts.transparent or false;
};
term_colors = true;
integrations = {
nvimtree = {
enabled = true;
transparent_panel = setupOpts.transparent or false;
show_root = true;
};
hop = true,
gitsigns = true,
telescope = true,
treesitter = true,
treesitter_context = true,
ts_rainbow = true,
fidget = true,
alpha = true,
leap = true,
lsp_saga = true,
markdown = true,
noice = true,
notify = true, -- nvim-notify
which_key = true,
navic = {
enabled = true,
custom_bg = "NONE", -- "lualine" will set background to mantle
},
},
}
hop = true;
gitsigns = true;
telescope = true;
treesitter = true;
treesitter_context = true;
ts_rainbow = true;
fidget = true;
alpha = true;
leap = true;
lsp_saga = true;
markdown = true;
noice = true;
notify = true; # nvim-notify
which_key = true;
navic = {
enabled = true;
custom_bg = "NONE"; # "lualine" will set background to mantle
};
};
};
in ''
-- Catppuccin theme
require('catppuccin').setup(${toLuaObject cleanedOpts})
-- setup must be called before loading
vim.cmd.colorscheme "catppuccin"
'';
@ -121,17 +104,14 @@ in {
};
oxocarbon = {
setup = {
style ? "dark",
transparent ? false,
...
}: let
style' =
warnIf (style == "light") "oxocarbon: light theme is not well-supported" style;
setup = setupOpts: let
style = setupOpts.style or "dark";
style' = warnIf (style == "light") "oxocarbon: light theme is not well-supported" style;
transparent = setupOpts.transparent or false;
in ''
require('oxocarbon')
vim.opt.background = "${style'}"
vim.cmd.colorscheme = "oxocarbon"
vim.cmd.colorscheme "oxocarbon"
${optionalString transparent ''
vim.api.nvim_set_hl(0, "Normal", { bg = "none" })
vim.api.nvim_set_hl(0, "NormalFloat", { bg = "none" })
@ -146,93 +126,99 @@ in {
};
gruvbox = {
setup = {
style ? "dark",
transparent ? false,
...
}: ''
setup = setupOpts: let
cleanedOpts =
(removeAttrs setupOpts ["transparent" "style"])
// {
terminal_colors = true; # add neovim terminal colors
undercurl = true;
underline = true;
bold = true;
italic = {
strings = true;
emphasis = true;
comments = true;
operators = false;
folds = true;
};
strikethrough = true;
invert_selection = false;
invert_signs = false;
invert_tabline = false;
invert_intend_guides = false;
inverse = true;
contrast = "";
palette_overrides = {};
overrides = {};
dim_inactive = false;
transparent_mode = setupOpts.transparent or false;
};
style = setupOpts.style or "dark";
in ''
styles = ["dark" "light"];
-- Gruvbox theme
require("gruvbox").setup({
terminal_colors = true, -- add neovim terminal colors
undercurl = true,
underline = true,
bold = true,
italic = {
strings = true,
emphasis = true,
comments = true,
operators = false,
folds = true,
},
strikethrough = true,
invert_selection = false,
invert_signs = false,
invert_tabline = false,
invert_intend_guides = false,
inverse = true,
contrast = "",
palette_overrides = {},
overrides = {},
dim_inactive = false,
transparent_mode = ${boolToString transparent},
})
require("gruvbox").setup(${toLuaObject cleanedOpts})
vim.o.background = "${style}"
vim.cmd("colorscheme gruvbox")
'';
styles = ["dark" "light"];
};
rose-pine = {
setup = {
style ? "main",
transparent ? false,
...
}: ''
require("rose-pine").setup({
dark_variant = "${style}", -- main, moon, or dawn
dim_inactive_windows = false,
extend_background_behind_borders = true,
setup = setupOpts: let
cleanedOpts =
(removeAttrs setupOpts ["style" "transparent"])
// {
dark_variant = setupOpts.style or "main"; # main, moon, or dawn
dim_inactive_windows = false;
extend_background_behind_borders = true;
enable = {
terminal = true,
migrations = true,
},
styles = {
bold = false,
italic = false, -- I would like to add more options for this
transparency = ${boolToString transparent},
},
})
enable = {
terminal = true;
migrations = true;
};
styles = {
bold = false;
italic = false; # I would like to add more options for this
transparency = setupOpts.transparent or false;
};
};
in ''
require("rose-pine").setup(${toLuaObject cleanedOpts})
vim.cmd("colorscheme rose-pine")
'';
styles = ["main" "moon" "dawn"];
};
nord = {
setup = {transparent ? false, ...}: ''
require("nord").setup({
transparent = ${boolToString transparent},
search = "vscode", -- [vim|vscode]
})
nord = {
setup = setupOpts: let
cleanedOpts =
(removeAttrs setupOpts ["transparent"])
// {
transparent = setupOpts.transparent or false;
search = "vscode"; # [vim|vscode]
};
in ''
require("nord").setup(${toLuaObject cleanedOpts})
vim.cmd.colorscheme("nord")
'';
};
github = {
setup = {
style ? "dark",
transparent ? false,
...
}: ''
require('github-theme').setup({
options = {
transparent = ${boolToString transparent},
},
})
github = {
styles = ["dark" "light" "dark_dimmed" "dark_default" "light_default" "dark_high_contrast" "light_high_contrast" "dark_colorblind" "light_colorblind" "dark_tritanopia" "light_tritanopia"];
setup = setupOpts: let
cleanedOpts =
(removeAttrs setupOpts ["transparent" "style"])
// {
options = {
transparent = setupOpts.transparent or false;
};
};
style = setupOpts.style or "dark";
in ''
require('github-theme').setup(${toLuaObject cleanedOpts})
vim.cmd[[colorscheme github_${style}]]
'';
styles = ["dark" "light" "dark_dimmed" "dark_default" "light_default" "dark_high_contrast" "light_high_contrast" "dark_colorblind" "light_colorblind" "dark_tritanopia" "light_tritanopia"];
};
solarized = let
@ -240,11 +226,8 @@ in {
palettes = ["solarized" "selenized"];
variants = ["spring" "summer" "autumn" "winter"];
in {
setup = {
style ? "", # use plugin defaults
transparent ? false,
...
}: let
setup = setupOpts: let
style = setupOpts.style or "";
parts = splitString "-" style;
detect = list: let
intersection = intersectLists parts list;
@ -255,15 +238,28 @@ in {
background = detect backgrounds;
palette = detect palettes;
variant = detect variants;
baseSetup =
{
transparent = {
enabled = setupOpts.transparent or false;
};
}
// (removeAttrs setupOpts ["style" "transparent"]);
finalSetup =
baseSetup
// (
if palette != null
then {palette = palette;}
else {}
)
// (
if variant != null
then {variant = variant;}
else {}
);
in ''
-- Solarized theme
require('solarized').setup {
transparent = {
enabled = ${boolToString transparent},
},
${optionalString (palette != null) ''palette = "${palette}",''}
${optionalString (variant != null) ''variant = "${variant}",''}
}
require('solarized').setup(${toLuaObject finalSetup})
${optionalString (background != null) ''vim.opt.background = "${background}"''}
vim.cmd.colorscheme "solarized"
'';
@ -284,25 +280,28 @@ in {
};
solarized-osaka = {
setup = {transparent ? false, ...}: ''
require("solarized-osaka").setup({
transparent = ${boolToString transparent},
styles = {
comments = { italic = false },
keywords = { italic = false },
}
})
setup = setupOpts: let
cleanedOpts =
(removeAttrs setupOpts ["transparent"])
// {
transparent = setupOpts.transparent or false;
styles = {
comments = {italic = false;};
keywords = {italic = false;};
};
};
in ''
require("solarized-osaka").setup(${toLuaObject cleanedOpts})
vim.cmd.colorscheme("solarized-osaka")
'';
};
everforest = {
setup = {
style ? "medium",
transparent ? false,
...
}: ''
styles = ["hard" "medium" "soft"];
setup = setupOpts: let
style = setupOpts.style or "medium";
transparent = setupOpts.transparent or false;
in ''
vim.g.everforest_background = "${style}"
vim.g.everforest_transparent_background = ${
if transparent
@ -312,8 +311,6 @@ in {
vim.cmd.colorscheme("everforest")
'';
styles = ["hard" "medium" "soft"];
};
mellow = {

View file

@ -3,14 +3,15 @@
lib,
...
}: let
inherit (lib.options) mkOption;
inherit (lib.attrsets) attrNames;
inherit (lib.strings) hasPrefix;
inherit (lib.types) bool lines enum;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf;
inherit (lib.types) bool lines enum submodule attrsOf nullOr;
inherit (lib.attrsets) attrNames filterAttrs;
inherit (lib.strings) hasPrefix;
inherit (lib.nvim.attrsets) mapListToAttrs;
inherit (lib.nvim.dag) entryBefore;
inherit (lib.nvim.types) hexColor;
inherit (lib.nvim.types) hexColor mkPluginSetupOption;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.theme;
supportedThemes = import ./supported-themes.nix {
@ -31,45 +32,169 @@
};
})
numbers;
# Get all enabled themes
enabledThemes = filterAttrs (_: themeCfg: themeCfg.enable) cfg.themes;
# Get the default theme configuration
defaultTheme =
if cfg.default != null && enabledThemes ? ${cfg.default}
then enabledThemes.${cfg.default}
else null;
in {
options.vim.theme = {
enable = mkOption {
type = bool;
description = "Enable theming";
enable = mkEnableOption "theming";
default = mkOption {
type = nullOr enum (attrNames supportedThemes);
default = null;
description = ''
The default theme to load in the built configuration. While this option
is set and the matching theme is enabled in {option}`vim.theme.themes`
the theme specified by this option will be set automatically as the
default theme. If `null`, the user is responsible for setting their
preferred theme either by explicitly setting this option, or using Lua.
'';
};
themes = let
themeType = {name, ...}: {
options = {
enable = mkEnableOption "the ${name} theme";
setupOpts = mkPluginSetupOption name {};
};
};
in
mkOption {
type = attrsOf (submodule themeType);
default = {};
example = {
tokyonight = {
enable = true;
setupOpts = {
style = "night";
transparent = true;
};
};
catppuccin = {
enable = true;
setupOpts = {
flavour = "mocha";
transparent_background = true;
integrations = {
nvimtree = {
enabled = true;
transparent_panel = true;
};
telescope = true;
treesitter = true;
};
};
};
onedark = {
enable = false; # Available but not loaded
setupOpts = {
style = "darker";
transparent = false;
};
};
};
description = ''
New theme configuration option for v0.8 and above. This system allows
you to set multiple themes at once, where **all** enabled themes will
be loaded in the configuration. While {option}`vim.theme.default` is
set, the default theme will be set automatically in the configuration.
'';
};
# Legacy options for backwards compatibility
# FIXME: this could have been handled directly with mkRenamedOptionModule
# or similar, but I found it too difficult to handle it gracefully. Those
# are kept here **with a warning** but without completely removing the
# relevant options. Worth completely dropping in the future.
name = mkOption {
type = enum (attrNames supportedThemes);
default = "onedark";
description = ''
Supported themes can be found in {file}`supportedThemes.nix`.
Setting the theme to "base16" enables base16 theming and
requires all of the colors in {option}`vim.theme.base16-colors` to be set.
::: {.note}
Legacy option: use vim.theme.themes.<name>.enable = true and vim.theme.default = "<name>" instead.
:::
'';
};
base16-colors = base16Options;
style = mkOption {
type = enum supportedThemes.${cfg.name}.styles;
description = "Specific style for theme if it supports it";
default = builtins.head supportedThemes.${cfg.name}.styles;
description = "Legacy option: use `vim.theme.themes.<name>.setupOpts.style` instead";
};
transparent = mkOption {
type = bool;
default = false;
description = "Whether or not transparency should be enabled. Has no effect for themes that do not support transparency";
description = "Legacy option: use `vim.theme.themes.<name>.setupOpts.transparent` instead";
};
base16-colors = base16Options;
extraConfig = mkOption {
type = lines;
description = "Additional lua configuration to add before setup";
default = "";
description = "Additional Lua configuration to add before setup";
};
};
config = mkIf cfg.enable {
vim = {
startPlugins = [cfg.name];
# Include plugins for all enabled themes
startPlugins = attrNames enabledThemes;
luaConfigRC.theme = entryBefore ["pluginConfigs" "lazyConfigs"] ''
-- Theme configurations
${cfg.extraConfig}
${supportedThemes.${cfg.name}.setup {inherit (cfg) style transparent base16-colors;}}
${lib.concatStringsSep "\n" (lib.mapAttrsToList (
# FIXME: this only works when the plugin accepts setupOpts. We need to
# either check for this in Lua, or list the plugins that support the
# setup table instead of using globals.
themeName: themeCfg: ''
-- Setup ${themeName} theme
require('${themeName}').setup(${toLuaObject themeCfg.setupOpts})
''
)
enabledThemes)}
${lib.optionalString (defaultTheme != null) ''
-- Load default theme:
-- ${cfg.default}
vim.cmd.colorscheme "${cfg.default}"
''}
'';
};
# We'd like to warn when the user is using a completely legacy configuration
warnings = let
# FIXME: what
legacyUsed = cfg.style != builtins.head supportedThemes.${cfg.name}.styles || !cfg.transparent;
newConfigUsed = builtins.length (attrNames enabledThemes) > 0;
in
mkIf (legacyUsed && !newConfigUsed) [
''
The theming module has been refactored to allow more powerful configurations and multiple theme setups
through the module system in v0.8. This warning indicates that you are using the legacy API and have not
yet used any of the new APIs. Please migrate your configuration to 'vim.theme.themes' API.
Refer to the documentation for more details.
''
];
};
}