Palette is a Neovim theme system to make creating and customising themes easy.
Highlight groups are logically arranged to strike a harmonious balance between clarity and aesthetic appeal.
Caching ensures themes are performant.
Build easily distributable themes using the provided build
script.
Generate application color schemes, such as for LS_COLORS
and iterm2
for matching terminal feel.
The theme is broken up into three sets of colors: main, accent, and state.
The main colors are used for the background, cursorline color, and to color the code and comments.
Accent colors can be used to bring special attention to highlight groups, in this case constants and integers are highlighted with colors not in the main palette:
There are five different state colors which represent:
error
warn
hint
ok
info
These are used by Diagnostics, git, etc. Anywhere where a state is represented:
There are two built-in main palettes: dark and light.
There are three built-in accent palettes: pastel, dark and bright.
There are three built-in state palettes: pastel, dark and bright.
Custom palettes can be defined like this:
{
"roobert/palette.nvim",
lazy = false,
priority = 1000,
config = function()
require("palette").setup({
palettes = {
main = "custom_main_palette",
accent = "custom_accent_palette",
state = "custom_state_palette",
},
custom_palettes = {
main = {
custom_main_palette = {
color0 = "#191d33",
color1 = "#1A1E39",
color2 = "#383f5e",
color3 = "#4e5470",
color4 = "#7b7f94",
color5 = "#a7a9b7",
color6 = "#bdbfc9",
color7 = "#d3d4db",
color8 = "#e9e9ed",
},
},
accent = {
custom_accent_palette = {
accent0 = "#D97C8F",
accent1 = "#D9AE7E",
accent2 = "#D9D87E",
accent3 = "#A5D9A7",
accent4 = "#8BB9C8",
accent5 = "#C9A1D3",
accent6 = "#B8A1D9",
},
},
state = {
custom_state_palette = {
error = "#D97C8F",
warning = "#D9AE7E",
hint = "#D9D87E",
ok = "#A5D9A7",
info = "#8BB9C8",
},
},
},
})
vim.cmd([[colorscheme palette]])
end,
},
The highlight groups are spit into multiple files, _defaults.lua
contains the default highlight groups, and then there is a file for each set of additional highlight groups, e.g: python.lua
.
The highlight groups use the following colors:
color0
-color8
accent0
-accent7
error
, warning
, hint
, ok
, info
Additional colors can be added to any palette, with any name, and then used in custom highlight overrides.
Palettes (including the defaults) can be used to generate new color schemes.
This works by the user specifying a base color and the base palette which is then used to establish the tone difference to generate a new palette.
Note: The resulting colors will match the length of the source color table.
See an example of a derived theme in the next section.
Palette implements automatic caching.
The cache is stored in the palette
(or theme name, if a distributable) directory under your users cache directory, typically: ~/.cache/nvim/palette/
Built-in dark main palette:
Built-in light main palette:
A custom derived theme inspired by Life Aquatic's Team Zissou colors:
{
'roobert/palette.nvim',
lazy = false,
priority = 1000,
config = function()
vim.cmd("colorscheme palette")
end
}
Example overriding the default palettes:
{
"roobert/palette.nvim",
lazy = false,
priority = 1000,
config = function()
require("palette").setup({
palettes = {
-- dark or light
main = "light",
-- pastel, bright or dark
accent = "dark",
state = "dark",
},
italics = true,
transparent_background = false,
})
end,
},
An example of using a custom main palette:
{
"roobert/palette.nvim",
lazy = false,
priority = 1000,
config = function()
require("palette").setup({
palettes = {
main = "dust_dusk",
},
italics = true,
transparent_background = false,
custom_palettes = {
main = {
-- dusk theme taken from roobert/dust.nvim
dust_dusk = {
color0 = "#121527",
color1 = "#1A1E39",
color2 = "#232A4D",
color3 = "#3E4D89",
color4 = "#687BBA",
color5 = "#A4B1D6",
color6 = "#bdbfc9",
color7 = "#DFE5F1",
color8 = "#e9e9ed",
}
},
accent = {},
state = {},
}
})
vim.cmd([[colorscheme palette]])
end,
},
An example of using a derived theme based on the built-in dark palette, with a couple of color overrides merged into the generated palette table:
{
"roobert/palette.nvim",
lazy = false,
priority = 1000,
config = function()
require("palette").setup({
palettes = {
main = "team_zissou",
accent = "pastel",
state = "pastel",
},
custom_palettes = {
main = {
-- a blue theme, based off the built-in dark palette
team_zissou = vim.tbl_extend(
"force",
require("palette.generator").generate_colors(
require("palette.colors").main["dark"],
"#04213b"
),
{
-- override background and cursor-line
color0 = "#191d33",
color1 = "#1A1E39",
-- override most prominent colors (strings, etc.)
color7 = "#e9e9ed",
color8 = "#d3d4db",
}
),
},
}
})
vim.cmd([[colorscheme palette]])
end,
},
It's possible to use lighten()
and darken()
to lighten and darken colors. In this
example a default color is being overridden:
{
"roobert/palette.nvim",
lazy = false,
priority = 1000,
config = function()
-- Reference the dark palette
local dark_palette = require("palette.colors").main["dark"]
-- Lighten the cursor-line
dark_palette.color1 = require("palette.utils").lighten(dark_palette["color1"])
require("palette").setup({
palettes = {
-- Reference the custom theme
main = "custom_lighter_cursorline",
},
custom_palettes = {
main = {
-- Create a custom theme
custom_lighter_cursorline = dark_palette,
}
},
})
vim.cmd([[colorscheme palette]])
end,
}
An example of overriding specific highlight groups using the built-in method:
{
"roobert/palette.nvim",
lazy = false,
priority = 1000,
config = function()
-- alias so we can easily reference theme colors
a = require("palette.theme").accent
require("palette").setup({
-- custom highlight groups can override any highlight groups
custom_highlight_group = "group_name",
custom_highlight_groups = {
group_name = {
-- add one table per override:
{
-- highlight group, or nil
"Normal",
-- foreground, or nil
a.accent0,
-- background, or nil
"#00ff00",
-- style(s) to apply, or nil
{ "italic", "underline", "bold" },
},
}
}
})
vim.cmd([[colorscheme palette]])
end,
},
Alternatively highlight groups can be overridden in the normal way:
{
"roobert/palette.nvim",
lazy = false,
priority = 1000,
config = function()
require("palette").setup({})
vim.cmd([[colorscheme palette]])
-- example of specific highlight group override..
vim.cmd([[highlight Normal guifg="#ff0000"]])
-- example of specific highlight group override using palette color
a = require("palette.theme").accent
vim.cmd([[highlight Normal guifg=a.accent0]])
end,
},
To adjust caching or set a custom cache path:
{
"roobert/palette.nvim",
lazy = false,
priority = 1000,
config = function()
require("palette").setup({
caching = true,
-- typically: ~/.cache/nvim/palette/
cache_dir = vim.fn.stdpath("cache") .. "/palette",
})
vim.cmd([[colorscheme palette]])
end,
},
LS_COLORS
Vivid is a generator for the
LS_COLORS
environment variable that controls the colorized output ofls
,tree
,fd
,bfs
,dust
and many other tools.
Use the vivid.lua
script to generate a vivid
config file:
brew install vivid
mkdir -p ~/.config/vivid/themes
# optionally:
# * customize vivid/filetypes.yml
# * change which palettes are used
./bin/vivid.lua palette dark pastel bright palette_dark
cp -v vivid/themes/* ~/.config/vivid/themes/
# brew install coreutils
# add to ~/.zshrc or ~/.bashrc
if which gdircolors > /dev/null 2>&1; then
eval $(gdircolors)
fi
LS_COLORS="$(vivid generate palette_dark)"
iterm2
Generate theme for iterm2:
./bin/iterm2.lua palette dark pastel > terminal/palette.itermcolors
Import the theme through Settings -> Profiles -> Colors -> Import
and then select from the preset list.
It's always possible to share your theme by sharing a code block like this:
{
"roobert/palette.nvim",
lazy = false,
priority = 1000,
config = function()
require("palette").setup({
palettes = {
-- built in colorscheme: grey
main = "dust_dusk",
-- built in accents: pastel, bright, dark
accent = "pastel",
state = "pastel",
},
italics = true,
transparent_background = false,
custom_palettes = {
main = {
dust_dusk = {
color0 = "#121527",
color1 = "#1A1E39",
color2 = "#232A4D",
color3 = "#3E4D89",
color4 = "#687BBA",
color5 = "#A4B1D6",
color6 = "#bdbfc9",
color7 = "#DFE5F1",
color8 = "#e9e9ed",
},
},
},
accent = {},
state = {},
})
vim.cmd([[colorscheme palette]])
end,
},
However, if you'd like to be able to give people a code block like this:
{
"username/colorscheme_name.nvim",
lazy = false,
priority = 1000,
config = function()
vim.cmd([[colorscheme colorscheme_name]])
end,
},
A build script is provided and can be used like this:
<your-theme-name>.nvim
:lua print(vim.inspect(require("palette.theme")))
lua/palette/colors.lua
./bin/build.sh <new theme name> <main palette name> <accent palette name> <state palette name>
# e.g:
./bin/build.sh dust dusk pastel pastel