Skip to content

Commit

Permalink
fix(theme): fix dynamic theme loading
Browse files Browse the repository at this point in the history
  • Loading branch information
thesimonho committed Mar 6, 2025
1 parent 7e75186 commit 67101b9
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 168 deletions.
106 changes: 69 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# 🌊 kanagawa-paper.nvim

Remixed light and dark Kanagawa colourscheme with muted colors. For Neovim.
Remixed light and dark Kanagawa color scheme with muted colors. For Neovim.

![screenshot](https://github.com/thesimonho/kanagawa-paper.nvim/assets/5199715/cf75d935-d8b4-430c-a1d8-04f453151924)

## 💡 Motivation

I love the original [kanagawa.nvim](https://github.com/rebelot/kanagawa.nvim) colourscheme, but I found some of the colours of the dark themes a bit too bright and distracting. What I wanted was a more muted theme overall, combining the less saturated syntax colours of the dragon theme, while keeping the blue background of the wave theme.
I love the original [kanagawa.nvim](https://github.com/rebelot/kanagawa.nvim) color scheme, but I found some of the colors of the dark themes a bit too bright and distracting. What I wanted was a more muted theme overall, using less saturated colors inspired by the original theme.

kanagawa-paper combines both the dragon and wave themes, with a few additions and tweaks to work better with certain plugins.
kanagawa-paper provides 2 theme variants; `canvas` for sunny days and `ink` for late nights.

I have also ported the colourscheme to VSCode, which you can find here: [kanagawa-paper.vscode](https://github.com/thesimonho/kanagawa-paper.vscode)
I have also ported the color scheme to VSCode, which you can find here: [kanagawa-paper.vscode](https://github.com/thesimonho/kanagawa-paper.vscode)

## ⚡️ Requirements

Expand All @@ -36,50 +36,29 @@ Install the theme with your preferred package manager, such as [lazy.nvim](https

```vim
colorscheme kanagawa-paper
colorscheme kanagawa-paper-ink
colorscheme kanagawa-paper-canvas
```

### Lua

```lua
vim.cmd("colorscheme kanagawa-paper")
```

### External Plugins

#### [Lualine](https://github.com/nvim-lualine/lualine.nvim)

```lua
local kanagawa_paper = require("lualine.themes.kanagawa-paper-ink")
-- local kanagawa_paper = require("lualine.themes.kanagawa-paper-canvas")

require("lualine").setup({
options = {
theme = kanagawa_paper,
-- ... your lualine config
},
})
```

If you want to set the lualine theme dynamically to match the Neovim theme, you can do something like this:

```lua
require("lualine").setup({
options = {
theme = function()
return require("lualine.themes." .. vim.g.colors_name)
end,
-- ...
},
})
vim.cmd("colorscheme kanagawa-paper-ink")
vim.cmd("colorscheme kanagawa-paper-canvas")
```

## ⚙️ Configuration

> ❗️ Set the configuration **BEFORE** loading the color scheme with `colorscheme kanagawa-paper`.
> [!IMPORTANT]
> Set the configuration **BEFORE** loading the color scheme with `colorscheme kanagawa-paper`.
```lua
require("kanagawa-paper").setup({
theme = "ink", -- one of "ink" or "canvas"
--- "ink" : dark theme
--- "canvas" : light theme
--- "kanagawa-paper" : automatically set theme based on background color
theme = "kanagawa-paper",

-- features and appearance
undercurl = true,
Expand All @@ -100,7 +79,7 @@ require("kanagawa-paper").setup({

-- color overrides
colors = { palette = {}, theme = {ink = {}, canvas = {}} }, -- override default palette and theme colors
overrides = function() -- override highlight groups
overrides = function(colors) -- override highlight groups
return {}
end,

Expand All @@ -120,7 +99,60 @@ require("kanagawa-paper").setup({
vim.cmd("colorscheme kanagawa-paper")
```

The code that defines the default configuration can be found [here](lua/kanagawa-paper/config.lua)
The default configuration can be found [here](lua/kanagawa-paper/config.lua)

If you want to switch between light and dark themes within a Neovim session, you can set the theme to `kanagawa-paper` and change `vim.o.background` to `light` or `dark`.

This can also be mapped to the time of day via an autocommand or dynamically setting `vim.o.background` at startup. For example:

```lua
local hour = os.date("*t").hour
vim.o.background = (hour >= 7 and hour < 19) and "light" or "dark"
```

## [Lualine](https://github.com/nvim-lualine/lualine.nvim)

This color scheme comes with matching Lualine themes for both `ink` and `canvas` variants. This will set the theme at startup:

```lua
local kanagawa_paper = require("lualine.themes.kanagawa-paper") -- switches based on vim.o.background
-- local kanagawa_paper = require("lualine.themes.kanagawa-paper-ink")
-- local kanagawa_paper = require("lualine.themes.kanagawa-paper-canvas")

require("lualine").setup({
options = {
theme = kanagawa_paper,
-- ... your lualine config
},
})
```

For a more advanced use case you can make use of the stored global variable `vim.g.colors_name` to dynamically set the Lualine theme:

```lua
require("lualine").setup({
options = {
theme = function()
if vim.g.colors_name then
-- pcall to handle the case of theme switching/previewing
local ok, t = pcall(require, "lualine.themes." .. vim.g.colors_name)
if ok then
return t
end
end
-- default fallback
return require("lualine.themes.kanagawa-paper")
end,
-- ...
},
})
```

Examples of situations where this might be useful:

- You want to change the theme mid-session
- You want to change background color mid-session (either by manually setting `vim.o.background` or with something like dark background toggle in LazyVim)
- You use a plugin for live previews of color schemes

## 🔧 Customizing Colors

Expand Down
12 changes: 5 additions & 7 deletions lua/kanagawa-paper/colors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -170,21 +170,19 @@ local palette = {
}

local M = {}
---@param opts KanagawaConfig
---@param opts? KanagawaConfig
---@return KanagawaColors
function M.setup(opts)
opts = require("kanagawa-paper.config").extend(opts) or {}

local override_colors = opts.colors or require("kanagawa-paper.config").options.colors
opts = require("kanagawa-paper.config").extend(opts)

-- Add to and/or override palette_colors
local updated_palette_colors = vim.tbl_extend("force", palette, override_colors.palette or {})
local updated_palette_colors = vim.tbl_extend("force", palette, opts.colors.palette or {})

-- Generate the theme according to the updated palette colors
local theme_colors = require("kanagawa-paper.themes").setup(opts, updated_palette_colors)
local theme_colors = require("kanagawa-paper.themes." .. opts.theme).get(opts, updated_palette_colors)

-- Add to and/or override theme_colors
local updated_theme_colors = vim.tbl_deep_extend("force", theme_colors, override_colors.theme[opts.theme] or {})
local updated_theme_colors = vim.tbl_deep_extend("force", theme_colors, opts.colors.theme[opts.theme] or {})

-- return palette_colors and theme_colors
return {
Expand Down
23 changes: 8 additions & 15 deletions lua/kanagawa-paper/config.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
local M = {}

---@class KanagawaConfig
M.defaults = {
theme = "ink", -- one of "ink" or "canvas"
theme = "kanagawa-paper", -- one of "ink" or "canvas"

-- features and appearance
undercurl = true,
transparent = false,
gutter = false,
Expand All @@ -13,21 +13,17 @@ M.defaults = {
brightnessOffset = 0, -- adjust brightness of the theme [-1, 1]
saturationOffset = 0, -- adjust saturation of the theme [-1, 1]

-- style options
commentStyle = { italic = true },
functionStyle = { italic = false },
keywordStyle = { italic = false, bold = false },
statementStyle = { italic = false, bold = false },
typeStyle = { italic = false },

-- color overrides
colors = { palette = {}, theme = { ink = {}, canvas = {} } }, -- override default palette and theme colors
---@type fun(colors: KanagawaColors): table<string, vim.api.keyset.highlight>
overrides = function() -- override highlight groups
overrides = function(colors) -- override highlight groups
return {}
end,

-- enable/disable plugins
auto_plugins = true, -- uses lazy.nvim, if installed, to automatically enable needed plugins
all_plugins = package.loaded.lazy == nil, -- enable highlights for all plugins (disabled if using lazy.nvim)
plugins = {
Expand All @@ -42,25 +38,22 @@ M.defaults = {
---@type KanagawaConfig
M.options = nil

---@param options? KanagawaConfig user configuration
---@param options? KanagawaConfig
function M.setup(options)
M.options = vim.tbl_deep_extend("force", {}, M.defaults, options or {})
end

---@param options? KanagawaConfig user configuration
function M.extend(options)
M.options = vim.tbl_deep_extend("force", {}, M.options, options or {})
return M.options
---@param opts? KanagawaConfig
function M.extend(opts)
return opts and vim.tbl_deep_extend("force", {}, M.options, opts) or M.options
end

setmetatable(M, {
__index = function(_, k)
if k == "options" then
return M.options or M.defaults
return M.defaults
end
end,
})

M.setup()

return M
72 changes: 0 additions & 72 deletions lua/kanagawa-paper/groups/init.lua
Original file line number Diff line number Diff line change
@@ -1,78 +1,6 @@
local color = require("kanagawa-paper.lib.color")
local util = require("kanagawa-paper.lib.util")
local M = {}
M.plugins = {}

---@param hex ColorSpec
---@param offset number
---@return ColorSpec
local function apply_brightness(hex, offset)
if offset == 0 then
return hex
end
local clamped_offset = util.clamp(offset, -1, 1)
local rescaled_offset = util.scale_log(clamped_offset, 3, 0.2)
return color(hex):brighten(rescaled_offset):to_hex()
end

---@param hex ColorSpec
---@param offset number
---@return ColorSpec
local function apply_saturation(hex, offset)
if offset == 0 then
return hex
end
local clamped_offset = util.clamp(offset, -1, 1)
local rescaled_offset = util.scale_log_asymmetric(clamped_offset, 3, 0.2, 0.5)
return color(hex):saturate(rescaled_offset):to_hex()
end

---@param groups KanagawaGroups
---@param colors KanagawaColors
---@param config { defaults?: KanagawaConfig, options: KanagawaConfig }
function M.highlight(groups, colors, config)
for hl, spec in pairs(groups) do
for _, field in ipairs({ "bg", "fg", "sp" }) do
if spec[field] then
spec[field] = apply_saturation(spec[field], config.options.saturationOffset)
spec[field] = apply_brightness(spec[field], config.options.brightnessOffset)
end
end
vim.api.nvim_set_hl(0, hl, spec)
end

if config.options.terminalColors and next(colors.theme.term) then
local ordered_keys = {
"black",
"red",
"green",
"yellow",
"blue",
"magenta",
"cyan",
"white",
"black_bright",
"red_bright",
"green_bright",
"yellow_bright",
"blue_bright",
"magenta_bright",
"cyan_bright",
"white_bright",
"indexed1",
"indexed2",
}
for i, key in ipairs(ordered_keys) do
vim.g["terminal_color_" .. (i - 1)] = function()
local c = colors.theme.term[key]
c = apply_saturation(c, config.options.saturationOffset)
c = apply_brightness(c, config.options.brightnessOffset)
return c
end
end
end
end

-- Get and store all available plugins
function M.get_all_plugins()
local plugin_dir = vim.api.nvim_get_runtime_file("**/kanagawa-paper/groups/plugins", false)
Expand Down
37 changes: 12 additions & 25 deletions lua/kanagawa-paper/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,23 @@ local config = require("kanagawa-paper.config")

local M = {}

--- load the colorscheme
-- BUG: user theme choice is not respected. its overriden by the background color selection
---@param opts? KanagawaConfig
---@return KanagawaColors, KanagawaGroups, KanagawaConfig
function M.load(opts)
if opts then
config.extend(opts)
opts = require("kanagawa-paper.config").extend(opts)
local bg = vim.o.background
local theme_bg = opts.theme == "canvas" and "light" or "dark"

if bg ~= theme_bg then
if vim.g.colors_name == "kanagawa-paper-" .. opts.theme then
opts.theme = bg == "light" and "canvas" or "ink"
else
vim.o.background = theme_bg
end
end

-- only needed to clear when not the default colorscheme
if vim.g.colors_name then
vim.cmd("hi clear")
end

vim.o.termguicolors = true
vim.g.colors_name = "kanagawa-paper-" .. config.options.theme

if config.options.theme == "ink" then
vim.o.background = "dark"
elseif config.options.theme == "canvas" then
vim.o.background = "light"
else
vim.notify("Invalid theme: " .. config.options.theme, vim.log.levels.ERROR)
end

local colors = require("kanagawa-paper.colors").setup(config.options)
local groups = require("kanagawa-paper.groups").setup(colors, config.options)

require("kanagawa-paper.groups").highlight(groups, colors, config)

return colors, groups, config
return require("kanagawa-paper.themes").setup(opts)
end

M.setup = config.setup
Expand Down
Loading

0 comments on commit 67101b9

Please # to comment.