diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b69190e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,45 @@
+# Compiled Lua sources
+luac.out
+
+# luarocks build files
+*.src.rock
+*.zip
+*.tar.gz
+
+# Object files
+*.o
+*.os
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+*.def
+*.exp
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+.DS_Store
+
+# nvim session management
+.nvim
diff --git a/.luacheckrc b/.luacheckrc
new file mode 100644
index 0000000..a07be16
--- /dev/null
+++ b/.luacheckrc
@@ -0,0 +1,20 @@
+stds.nvim = {
+ read_globals = { "jit" },
+}
+
+std = "lua51+nvim"
+
+read_globals = {
+ "vim",
+}
+
+globals = {
+ "vim.g",
+ "vim.b",
+ "vim.w",
+ "vim.o",
+ "vim.bo",
+ "vim.wo",
+ "vim.go",
+ "vim.env",
+}
diff --git a/.luarc.json b/.luarc.json
new file mode 100644
index 0000000..8895244
--- /dev/null
+++ b/.luarc.json
@@ -0,0 +1,15 @@
+{
+ "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",
+ "runtime.version": "LuaJIT",
+ "diagnostics.globals": [
+ "vim"
+ ],
+ "runtime.settings.path": [
+ "?.lua",
+ "?/init.lua"
+ ],
+ "workspace.checkThirdParty": false,
+ "workspace.library": [
+ "$VIMRUNTIME"
+ ]
+}
diff --git a/.yamllint.yaml b/.yamllint.yaml
new file mode 100644
index 0000000..7214609
--- /dev/null
+++ b/.yamllint.yaml
@@ -0,0 +1,5 @@
+---
+extends: default
+rules:
+ truthy:
+ check-keys: false
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..dc19184
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 mistweaver.co
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0753c2f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,47 @@
+
+
+![retro theme Logo](logo.svg)
+
+# retro-theme.nvim
+
+![Lua](https://img.shields.io/badge/Made%20with%20Lua-blueviolet.svg?style=for-the-badge&logo=lua)
+[![GitHub release (latest by date)](https://img.shields.io/github/v/release/mistweaverco/retro-theme.nvim?style=for-the-badge)](https://github.com/mistweaverco/retro-theme.nvim/releases/latest)
+[![Discord](https://img.shields.io/badge/discord-join-7289da?style=for-the-badge&logo=discord)](https://discord.gg/QyVQmfY4Rt)
+
+[Requirements](#requirements) • [Install](#install) • [Configuration](#configuration)
+
+
+
+A minimal retro theme for Neovim.
+
+
+
+
+
+## Requirements
+
+> [!WARNING]
+> Requires Neovim 0.10.0+.
+
+## Install
+
+Via [lazy.nvim](https://github.com/folke/lazy.nvim):
+
+```lua
+{ 'mistweaverco/retro-theme.nvim' },
+```
+See [configuration options](#configuration) for more information.
+
+## Configuration
+
+```lua
+{
+ 'mistweaverco/retro-theme.nvim',
+ opts = {
+ italic_comments = true,
+ disable_cache = false,
+ hot_reload = false,
+ }
+},
+```
+
diff --git a/colors/retro-theme.lua b/colors/retro-theme.lua
new file mode 100644
index 0000000..7d0b0c2
--- /dev/null
+++ b/colors/retro-theme.lua
@@ -0,0 +1 @@
+require('retro-theme').load()
diff --git a/logo.png b/logo.png
new file mode 100644
index 0000000..cae74d6
Binary files /dev/null and b/logo.png differ
diff --git a/logo.svg b/logo.svg
new file mode 100644
index 0000000..7762205
--- /dev/null
+++ b/logo.svg
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lua/lualine/themes/retro-theme.lua b/lua/lualine/themes/retro-theme.lua
new file mode 100644
index 0000000..f10bd76
--- /dev/null
+++ b/lua/lualine/themes/retro-theme.lua
@@ -0,0 +1,47 @@
+local t = {
+ bg = "#1c1e26",
+ fg = "#c8d0e0",
+ normalFG = "#c8d0e0",
+ green = "#00ffbf",
+ red = "#ff445d",
+ purple = "#bd93f9",
+ blue = "#00dfff",
+ blueDark = "#336699",
+ grey3 = "#1b1d23",
+ grey5 = "#2d333e",
+ grey7 = "#384252",
+ grey20 = "#4a5a73",
+}
+
+return {
+ normal = {
+ a = { bg = t.blue, fg = t.bg },
+ b = { bg = t.grey7, fg = t.fg },
+ c = { bg = t.grey3, fg = t.fg }
+ },
+ insert = {
+ a = { bg = t.blueDark, fg = t.bg },
+ b = { bg = t.grey7, fg = t.blueDark },
+ c = { bg = t.grey3, fg = t.fg }
+ },
+ visual = {
+ a = { bg = t.purple, fg = t.bg },
+ b = { bg = t.grey7, fg = t.purple },
+ c = { bg = t.grey3, fg = t.fg }
+ },
+ replace = {
+ a = { bg = t.red, fg = t.bg },
+ b = { bg = t.grey7, fg = t.red },
+ c = { bg = t.grey3, fg = t.fg }
+ },
+ command = {
+ a = { bg = t.green, fg = t.bg },
+ b = { bg = t.grey7, fg = t.green },
+ c = { bg = t.grey3, fg = t.fg }
+ },
+ inactive = {
+ a = { bg = t.grey20, fg = t.grey3, },
+ b = { bg = t.grey5, fg = t.grey20 },
+ c = { bg = t.grey5, fg = t.grey20 }
+ }
+}
diff --git a/lua/retro-theme/cache/.gitignore b/lua/retro-theme/cache/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/lua/retro-theme/cache/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/lua/retro-theme/colorscheme.lua b/lua/retro-theme/colorscheme.lua
new file mode 100644
index 0000000..db74fe0
--- /dev/null
+++ b/lua/retro-theme/colorscheme.lua
@@ -0,0 +1,16 @@
+local cache = require("retro-theme.lib.cache")
+local colors = {}
+
+if cache.exists() then
+ colors = cache.read()
+else
+ colors = require("retro-theme.palette.colors")
+ cache.write(colors)
+end
+
+vim.cmd("highlight clear")
+vim.cmd("set t_Co=256")
+
+for group, attrs in pairs(colors) do
+ vim.api.nvim_set_hl(0, group, attrs)
+end
diff --git a/lua/retro-theme/icons.lua b/lua/retro-theme/icons.lua
new file mode 100644
index 0000000..bb2dda7
--- /dev/null
+++ b/lua/retro-theme/icons.lua
@@ -0,0 +1,89 @@
+return {
+ kind = {
+ Codeium = "",
+ Copilot = "",
+ TabNine = "",
+
+ Class = "",
+ Color = "",
+ Constant = "",
+ Constructor = "",
+ Enum = "",
+ EnumMember = "",
+ Event = "",
+ Field = "",
+ File = "",
+ Folder = "",
+ Function = "",
+ Interface = "",
+ Keyword = "",
+ Method = "",
+ Module = "",
+ Operator = "",
+ Property = "",
+ Reference = "",
+ Snippet = "",
+ Text = "",
+ TypeParameter = "",
+ Unit = "",
+ Value = "",
+
+ Array = "",
+ Boolean = "",
+ Collapsed = "",
+ Control = "",
+ Key = "",
+ Namespace = "",
+ Null = "",
+ Number = "",
+ Object = "",
+ Package = "",
+ String = "",
+ Struct = "",
+ Variable = "",
+ },
+ git = {
+ LineAdded = "",
+ LineModified = "",
+ LineRemoved = "",
+ LineLeft = "▎",
+ LineMiddle = "│",
+ },
+ ui = {
+ Search = "",
+ Selected = "❯",
+ Pointer = "➜",
+ Bug = "",
+ Circle = "",
+ Round = "",
+ Ellipsis = "",
+ Plus = "",
+ Robot = "",
+ LSP = "",
+ Fold = "",
+ },
+ task = {
+ Canceled = " ",
+ Failure = " ",
+ Success = " ",
+ Running = " ",
+ },
+ diagnostics = {
+ BoldError = "",
+ Error = "",
+ BoldWarning = "",
+ Warning = "",
+ BoldInformation = "",
+ Information = "",
+ BoldHint = "",
+ Hint = "",
+ },
+ spinner = { "", "", "", "", "", "", "", "", "", "", "", "", "" },
+ dap = {
+ Stopped = { " ", "DiagnosticWarn", "DapStoppedLine" },
+ Breakpoint = " ",
+ BreakpointCondition = " ",
+ BreakpointRejected = { " ", "DiagnosticError" },
+ LogPoint = " ",
+ },
+}
diff --git a/lua/retro-theme/init.lua b/lua/retro-theme/init.lua
new file mode 100644
index 0000000..301f2c2
--- /dev/null
+++ b/lua/retro-theme/init.lua
@@ -0,0 +1,32 @@
+local M = {}
+
+local defaultConfig = {
+ italic_comments = true,
+ disable_cache = false,
+ hot_reload = false,
+}
+
+M.config = defaultConfig
+
+function M.reload()
+ M.load()
+end
+
+function M.load()
+ require('retro-theme.colorscheme')
+ vim.g.colors_name = 'retro-theme'
+end
+
+function M.clear_cache()
+ require('retro-theme.lib.cache').clear()
+end
+
+function M.setup(options)
+ M.config = vim.tbl_deep_extend("force", {}, defaultConfig, options or {})
+ if M.config.hot_reload then
+ local path = require("retro-theme.lib.path")
+ require("retro-theme.lib.hotreload").watch(path.palette_colors)
+ end
+end
+
+return M
diff --git a/lua/retro-theme/lib/cache.lua b/lua/retro-theme/lib/cache.lua
new file mode 100644
index 0000000..1ee95d3
--- /dev/null
+++ b/lua/retro-theme/lib/cache.lua
@@ -0,0 +1,44 @@
+local config = require("retro-theme").config
+local path = require("retro-theme.lib.path")
+
+local M = {}
+
+M.clear = function()
+ if config.disable_cache or config.hot_reload then
+ return
+ end
+ if vim.fn.filereadable(path.cache) == 1 then
+ assert(os.remove(path.cache))
+ end
+end
+
+M.exists = function()
+ if config.disable_cache or config.hot_reload then
+ return false
+ end
+ return vim.fn.filereadable(path.cache) == 1
+end
+
+M.write = function(colors)
+ if (config.disable_cache or config.hot_reload) then
+ return
+ end
+ local serpent = require("retro-theme.lib.serpent")
+ local str = serpent.dump(colors)
+ local file = io.open(path.cache, "wb")
+ file:write(str)
+ file:close()
+end
+
+M.read = function()
+ if (config.disable_cache or config.hot_reload) then
+ return nil
+ end
+ local colors = require('retro-theme.cache.default')
+ if not colors then
+ return nil
+ end
+ return colors
+end
+
+return M
diff --git a/lua/retro-theme/lib/colorparser.lua b/lua/retro-theme/lib/colorparser.lua
new file mode 100644
index 0000000..b8b80f4
--- /dev/null
+++ b/lua/retro-theme/lib/colorparser.lua
@@ -0,0 +1,58 @@
+local config = require("retro-theme").config
+
+local M = {}
+
+local has_no_gui = vim.fn.has("gui") == 0
+
+local function is_valid_key(key)
+ return key == "fg" or key == "bg" or key == "sp" or key == "gui" or key == "blend" or key == "italic" or key == "bold"
+end
+
+local is_valid_color_table = function(color)
+ return type(color) == "table" and color.hex ~= nil
+end
+
+local is_embedded_table = function(color)
+ return type(color) == "table" and color.hex == nil
+end
+
+local merge_groups = function(group_def_table, group_def_table_value)
+ for key, value in pairs(group_def_table_value) do
+ if group_def_table[key] == nil then
+ group_def_table[key] = value
+ end
+ end
+end
+
+M.parse = function(colors)
+ for _, group_def_table in pairs(colors) do
+ if type(group_def_table) ~= "table" then
+ vim.print("Invalid group definition: " .. vim.inspect(group_def_table))
+ return
+ end
+ for group_def_table_key, group_def_table_value in pairs(group_def_table) do
+ if is_embedded_table(group_def_table_value) then
+ merge_groups(group_def_table, group_def_table_value)
+ end
+ if is_valid_key(group_def_table_key) == false then
+ group_def_table[group_def_table_key] = nil
+ end
+ end
+ end
+
+ for _, group_def_table in pairs(colors) do
+ for group_def_table_key, group_def_table_value in pairs(group_def_table) do
+ if group_def_table_key == "gui" and has_no_gui then
+ group_def_table[group_def_table_key] = nil
+ else
+ if is_valid_color_table(group_def_table_value) then
+ group_def_table[group_def_table_key] = group_def_table_value.hex
+ else
+ group_def_table[group_def_table_key] = group_def_table_value
+ end
+ end
+ end
+ end
+end
+
+return M
diff --git a/lua/retro-theme/lib/hotreload.lua b/lua/retro-theme/lib/hotreload.lua
new file mode 100644
index 0000000..7ea93b9
--- /dev/null
+++ b/lua/retro-theme/lib/hotreload.lua
@@ -0,0 +1,46 @@
+local serpent = require("retro-theme.lib.serpent")
+local uv = vim.loop
+
+local function get_plugin()
+ local plug = require("lazy.core.config").plugins["retro-theme.nvim"]
+ return plug
+end
+
+local on_event = function(err, filename, events)
+ if err then
+ vim.notify("Error in retro-theme.nvim hot_reload fs_event: " .. err)
+ else
+ if events.change == nil then
+ return
+ end
+ local plugin = get_plugin()
+ require("lazy.core.loader").reload(plugin)
+ vim.cmd("colorscheme retro-theme")
+ end
+end
+
+local M = {}
+
+M.watch = function(path)
+ local handle = uv.new_fs_event()
+
+ local flags = {
+ watch_entry = false,
+ stat = false,
+ recursive = false,
+ }
+
+ local event_cb = function(err, filename, events)
+ if err then
+ vim.notify("Error in retro-theme.nvim hot_reload fs_event: " .. err)
+ else
+ vim.schedule(function()
+ on_event(err, filename, events)
+ end)
+ end
+ end
+
+ uv.fs_event_start(handle, path, flags, event_cb)
+end
+
+return M
diff --git a/lua/retro-theme/lib/hsl.lua b/lua/retro-theme/lib/hsl.lua
new file mode 100644
index 0000000..ae040d0
--- /dev/null
+++ b/lua/retro-theme/lib/hsl.lua
@@ -0,0 +1,312 @@
+local clamp = require('retro-theme.lib.math').clamp
+local round = require('retro-theme.lib.math').round
+
+--
+-- HSL-like colour functions
+--
+-- Vivid supports both HSL and HSLuv colourspaces, which functionally
+-- behave the same except when they are converting out into RGB.
+--
+-- This module provides common operations on hsl-like colours.
+--
+
+local function hsl_clamp(color)
+ local h, s, l
+ h = round(color.h % 360)
+ s = round(clamp(color.s, 0, 100))
+ l = round(clamp(color.l, 0, 100))
+ return { h = h, s = s, l = l }
+end
+
+-- (color, key) -> (value) -> {h, s, l}
+-- Given a color and key (h, s or l), returns a function which accepts a value which will
+-- return a new color with the key set to given value
+local function make_abs_fn(color, key)
+ return function(abs_value)
+ if type(abs_value) ~= "number" then error("Must provide number to HSL modifiers", 0) end
+ local new_values = {h = color.h, s = color.s, l = color.l}
+ new_values[key] = new_values[key] + abs_value
+ return new_values
+ end
+end
+
+-- (color, key) -> (value) -> {h, s, l}
+-- Given a color and key (h, s or l), returns a function which accepts a value which will
+-- return a new color with the key lerped by given value
+local function make_lerp_fn(color, key)
+ return function(percent)
+ if type(percent) ~= "number" then error("Must provide number to HSL modifiers", 0) end
+
+ -- we never modifiy the caller
+ local new_values = {h = color.h, s = color.s, l = color.l}
+ -- we can safely bounds all relative adjustments to 0, 100
+ -- because you can't 'relatively rotate' hue
+ local min, max = 0, 100
+ -- we want to lerp between the current value, and the potential largest
+ -- change for -percent this is [0, current], +percent, [0, max - current]
+ local lerp_space = percent < min and new_values[key] or (max - new_values[key])
+ -- perform the lerp
+ new_values[key] = new_values[key] + (lerp_space * (percent / 100))
+ return new_values
+ end
+end
+
+-- (color) -> (n) -> {h + n, s, l}
+local function op_rotate(color)
+ return make_abs_fn(color, "h")
+end
+
+-- (color) -> (n) -> {h, s lerp n, l}
+local function op_saturate(color)
+ return make_lerp_fn(color, "s")
+end
+
+-- (color) -> (n) -> {h, s + n, l}
+local function op_abs_saturate(color)
+ return make_abs_fn(color, "s")
+end
+
+-- (color) -> (n) -> {h, s lerp -n, l}
+local function op_desaturate(color)
+ return function(percent)
+ if type(percent) ~= "number" then error("Must provide number to HSL modifiers", 0) end
+ return make_lerp_fn(color, "s")(-percent)
+ end
+end
+
+-- (color) -> (n) -> {h, s - n, l}
+local function op_abs_desaturate(color)
+ return function(abs_value)
+ if type(abs_value) ~= "number" then error("Must provide number to HSL modifiers", 0) end
+ return make_abs_fn(color, "s")(-abs_value)
+ end
+end
+
+-- (color) -> (n) -> {h, s, l lerp n}
+local function op_lighten(color)
+ return make_lerp_fn(color, "l")
+end
+
+-- (color) -> (n) -> {h, s, l + n}
+local function op_abs_lighten(color)
+ return make_abs_fn(color, "l")
+end
+
+-- (color) -> (n) -> {h, s, l lerp -n}
+local function op_darken(color)
+ return function(percent)
+ if type(percent) ~= "number" then error("Must provide number to HSL modifiers", 0) end
+ return make_lerp_fn(color, "l")(-percent)
+ end
+end
+
+-- (color) -> (n) -> {h, s, l - n}
+local function op_abs_darken(color)
+ return function(abs_value)
+ if type(abs_value) ~= "number" then error("Must provide number to HSL modifiers", 0) end
+ return make_abs_fn(color, "l")(-abs_value)
+ end
+end
+
+-- mix ref:
+-- https://stackoverflow.com/questions/35816179/calculation-algorithm-to-mix-3-hsl-colors
+-- (color) -> (color, n) -> {h x h x n, s x s x n, l x l x n}
+local function op_mix(color)
+ return function(target, strength)
+ assert(strength, "must provide strength to mix")
+ strength = clamp(strength, 0, 100) / 100
+ -- strength of 0 means no mix towards target, so
+ -- color vector strength is 1
+ local cv_str = (1 - strength)
+ -- target strength is the remainder, so
+ -- str = 0, cv_str = 1, tv_str = 0
+ -- str = 100, cv_str = 0, tv_str = 1
+ local tv_str = 1 - cv_str
+
+ -- convert colors to vector
+ local cv = {
+ x = math.cos(color.h / 180 * math.pi) * color.s,
+ y = math.sin(color.h / 180 * math.pi) * color.s,
+ z = color.l
+ }
+ local tv = {
+ x = math.cos(target.h / 180 * math.pi) * target.s,
+ y = math.sin(target.h / 180 * math.pi) * target.s,
+ z = target.l
+ }
+ -- combine
+ local rv = {
+ x = ((cv.x * cv_str) + (tv.x * tv_str)) / 1,
+ y = ((cv.y * cv_str) + (tv.y * tv_str)) / 1,
+ z = ((cv.z * cv_str) + (tv.z * tv_str)) / 1,
+ }
+ -- back to color
+ local new_values = {
+ h = math.atan2(rv.y, rv.x) * (180 / math.pi),
+ s = math.sqrt(rv.x * rv.x + rv.y * rv.y),
+ l = rv.z
+ }
+ return new_values
+ end
+end
+
+-- (color) -> (n) -> {n, s, l}
+local function op_hue(color)
+ return function(hue)
+ if type(hue) ~= "number" then error("Must provide number to HSL modifiers", 0) end
+ return {h = hue, s = color.s, l = color.l}
+ end
+end
+
+-- (color) -> (n) -> {h, n, l}
+local function op_saturation(color)
+ return function(saturation)
+ if type(saturation) ~= "number" then error("Must provide number to HSL modifiers", 0) end
+ return {h = color.h, s = saturation, l = color.l}
+ end
+end
+
+-- (color) -> (n) -> {h, s, n}
+local function op_lightness(color)
+ return function(lightness)
+ if type(lightness) ~= "number" then error("Must provide number to HSL modifiers", 0) end
+ return {h = color.h, s = color.s, l = lightness}
+ end
+end
+
+-- (color) -> (n) -> {h, s, 0 | 100}
+local function op_readable(color)
+ return function()
+ if color.l >= 50 then
+ return {h = color.h, s = color.s, l = 0}
+ else
+ return {h = color.h, s = color.s, l = 100}
+ end
+ end
+end
+
+local function decorate_hsl_table(color, to_hex_fn)
+ -- make sure our color is valid
+ color = hsl_clamp(color)
+
+ local op_fns = {
+ rotate = op_rotate,
+ ro = op_rotate,
+
+ saturate = op_saturate,
+ sa = op_saturate,
+ abs_saturate = op_abs_saturate,
+ abs_sa = op_abs_saturate,
+
+ desaturate = op_desaturate,
+ de = op_desaturate,
+ abs_desaturate = op_abs_desaturate,
+ abs_de = op_abs_desaturate,
+
+ lighten = op_lighten,
+ li = op_lighten,
+ abs_lighten = op_abs_lighten,
+ abs_li = op_abs_lighten,
+
+ darken = op_darken,
+ da = op_darken,
+ abs_darken = op_abs_darken,
+ abs_da = op_abs_darken,
+
+ mix = op_mix,
+ readable = op_readable,
+
+ hue = op_hue,
+ saturation = op_saturation,
+ lightness = op_lightness,
+ }
+
+ return setmetatable({}, {
+ -- it's hsl colors all the way down
+ __index = function(_, key_name)
+ if key_name == "h" then return color.h end
+ if key_name == "s" then return color.s end
+ if key_name == "l" then return color.l end
+ if key_name == "hsl" then return {h = color.h, s = color.s, l = color.l} end
+ if key_name == "hex" then return to_hex_fn(color) end
+ if key_name == "rgb" then
+ local hex = to_hex_fn(color)
+ local cnv = require("lush.vivid.rgb.convert")
+ return cnv.hex_to_rgb(hex)
+ end
+
+ -- look up requested key in operations table and call out
+ -- if it exists, else try to show a nice warning.
+ if op_fns[key_name] then
+ return function(...)
+ local altered_color = op_fns[key_name](color)(...)
+ return decorate_hsl_table(altered_color, to_hex_fn)
+ end
+ else
+ local ops = ""
+ for op, _ in pairs(op_fns) do
+ ops = ops .. " " .. op
+ end
+ ops = ops .. " h s l hex hsl"
+ error("Invalid hsl operation: '"
+ .. key_name
+ .. "', valid operations:"
+ .. ops, 2)
+ end
+ end,
+
+ -- possibly this won't be useless, but for now disable
+ __newindex = function(_, _, _)
+ error('Member setting disabled', 2)
+ end,
+
+ __tostring = function(hsl)
+ return to_hex_fn(hsl)
+ end,
+
+ __concat = function(lhs, rhs)
+ return tostring(lhs) .. tostring(rhs)
+ end,
+
+ -- if we call, return the raw value
+ __call = function()
+ return color
+ end
+ })
+end
+
+local M = function(h_or_hex, s, l, type_fns)
+ assert(type_fns, "must provide type_fns")
+ assert(type_fns.name, "must provide name() type_fn")
+ assert(type_fns.from_hex, type_fns.name() .. " must provide from_hex() type_fn")
+ assert(type_fns.to_hex, type_fns.name() .. " must provide to_hex() type_fn")
+
+ assert(h_or_hex, type_fns.name() .. " expects (number, number, number) or (string)")
+
+ local h, hex_str = h_or_hex, h_or_hex
+ local hsl
+
+ if type(hex_str) == "string" then
+ -- normalise
+ local hex = "[abcdef0-9][abcdef0-9]"
+ local pat = "^#("..hex..")("..hex..")("..hex..")$"
+ hex_str = string.lower(hex_str)
+
+ -- smoke test
+ assert(string.find(hex_str, pat) ~= nil,
+ "hex_to_rgb: invalid hex_str: " .. tostring(hex_str))
+
+ hsl = type_fns.from_hex(hex_str)
+ else
+ if type(h) ~= "number" or
+ type(s) ~= "number" or
+ type(l) ~= "number" then
+ error(type_fns.name() .. " expects (number, number, number) or (string)", 2)
+ end
+ hsl = {h = h, s = s, l = l}
+ end
+
+ return decorate_hsl_table(hsl, type_fns.to_hex)
+end
+
+return M
diff --git a/lua/retro-theme/lib/hsl/convert.lua b/lua/retro-theme/lib/hsl/convert.lua
new file mode 100644
index 0000000..c3c5944
--- /dev/null
+++ b/lua/retro-theme/lib/hsl/convert.lua
@@ -0,0 +1,88 @@
+-- Support module to convert between HSL and RGB_HEX values
+--
+-- RGB -> HSL and HSL -> RGB adapted from
+-- https://github.com/EmmanuelOga/columns/blob/master/utils/color.lua
+
+local round = require('retro-theme.lib.math').round
+local rgb_convert = require('retro-theme.lib.rgb.convert')
+
+local function hsl_to_rgb(hsl)
+ local r, g, b
+ local h, s, l = hsl.h, hsl.s, hsl.l
+
+ if s == 0 then
+ r, g, b = l, l, l -- achromatic
+ else
+ local function hue2rgb(p, q, t)
+ if t < 0 then t = t + 1 end
+ if t > 1 then t = t - 1 end
+ if t < 1/6 then return p + (q - p) * 6 * t end
+ if t < 1/2 then return q end
+ if t < 2/3 then return p + (q - p) * (2/3 - t) * 6 end
+ return p
+ end
+
+ local q
+ if l < 0.5 then q = l * (1 + s) else q = l + s - l * s end
+ local p = 2 * l - q
+
+ r = hue2rgb(p, q, h + 1/3)
+ g = hue2rgb(p, q, h)
+ b = hue2rgb(p, q, h - 1/3)
+ end
+
+ return {
+ r = round(r * 255),
+ g = round(g * 255),
+ b = round(b * 255)
+ }
+end
+
+local function rgb_to_hsl(rgb)
+ local r, g, b = rgb.r / 255, rgb.g / 255, rgb.b / 255
+
+ local max, min = math.max(r, g, b), math.min(r, g, b)
+ local h, s, l
+
+ l = (max + min) / 2
+
+ if max == min then
+ h, s = 0, 0 -- achromatic
+ else
+ local d = max - min
+ if l > 0.5 then s = d / (2 - max - min) else s = d / (max + min) end
+ if max == r then
+ h = (g - b) / d
+ if g < b then h = h + 6 end
+ elseif max == g then h = (b - r) / d + 2
+ elseif max == b then h = (r - g) / d + 4
+ end
+ h = h / 6
+ end
+
+ return {h = h, s = s, l = l}
+end
+
+local M = {
+ hex_to_hsl = function(hex)
+ local rgb = rgb_convert.hex_to_rgb(hex)
+ local hsl = rgb_to_hsl(rgb)
+ return {
+ h = round(hsl.h * 360),
+ s = round(hsl.s * 100),
+ l = round(hsl.l * 100),
+ }
+ end,
+ hsl_to_hex = function(hsl)
+ -- normalise for convert fuction
+ hsl = {
+ h = hsl.h / 360,
+ s = hsl.s / 100,
+ l = hsl.l / 100,
+ }
+ local rgb = hsl_to_rgb(hsl)
+ return rgb_convert.rgb_to_hex(rgb)
+ end
+}
+
+return M
diff --git a/lua/retro-theme/lib/hsl/type.lua b/lua/retro-theme/lib/hsl/type.lua
new file mode 100644
index 0000000..46856db
--- /dev/null
+++ b/lua/retro-theme/lib/hsl/type.lua
@@ -0,0 +1,20 @@
+local hsl_convert = require('retro-theme.lib.hsl.convert')
+local hsl = require('retro-theme.lib.hsl')
+
+--
+-- HSL Color
+--
+-- expects to be called as hsl(hue, sat, light) or hsl("#RRGGBB")
+--
+
+local type_fns = {
+ from_hex = hsl_convert.hex_to_hsl,
+ to_hex = hsl_convert.hsl_to_hex,
+ name = function() return "hsl()" end
+}
+
+local M = function(h_or_hex, s, l)
+ return hsl(h_or_hex, s, l, type_fns)
+end
+
+return M
diff --git a/lua/retro-theme/lib/math.lua b/lua/retro-theme/lib/math.lua
new file mode 100644
index 0000000..82f53b3
--- /dev/null
+++ b/lua/retro-theme/lib/math.lua
@@ -0,0 +1,13 @@
+local clamp = function(val, min, max)
+ return math.min(max, math.max(min, val))
+end
+
+-- round float, implementation rounds 0.5 upwards.
+local round = function(val)
+ return math.floor(val + 0.5)
+end
+
+return {
+ round = round,
+ clamp = clamp
+}
diff --git a/lua/retro-theme/lib/path.lua b/lua/retro-theme/lib/path.lua
new file mode 100644
index 0000000..ddbebe6
--- /dev/null
+++ b/lua/retro-theme/lib/path.lua
@@ -0,0 +1,13 @@
+local config = require("retro-theme").config
+
+local lua_path = vim.fs.dirname(debug.getinfo(1).source:sub(2)) .. "/.."
+local compile_path = lua_path .. "/cache"
+local cache_path = compile_path .. "/default.lua"
+local palette_colors_path = lua_path .. "/palette/colors.lua"
+
+local M = {}
+
+M.cache = cache_path
+M.palette_colors = palette_colors_path
+
+return M
diff --git a/lua/retro-theme/lib/rgb/convert.lua b/lua/retro-theme/lib/rgb/convert.lua
new file mode 100644
index 0000000..9826785
--- /dev/null
+++ b/lua/retro-theme/lib/rgb/convert.lua
@@ -0,0 +1,29 @@
+-- Support module to convert between RGB and HEX
+
+local function rgb_to_hex(rgb)
+ return string.format("#%02X%02X%02X", rgb.r, rgb.g, rgb.b)
+end
+
+local function hex_to_rgb(hex_str)
+ -- normalise
+ local hex = "[abcdef0-9][abcdef0-9]"
+ local pat = "^#("..hex..")("..hex..")("..hex..")$"
+ hex_str = string.lower(hex_str)
+
+ -- smoke test
+ assert(string.find(hex_str, pat) ~= nil,
+ "hex_to_rgb: invalid hex_str: " .. tostring(hex_str))
+
+ -- convert
+ local r,g,b = string.match(hex_str, pat)
+ r, g, b = tonumber(r, 16), tonumber(g, 16), tonumber(b, 16)
+
+ return {r = r, g = g, b = b}
+end
+
+local M = {
+ rgb_to_hex = rgb_to_hex,
+ hex_to_rgb = hex_to_rgb
+}
+
+return M
diff --git a/lua/retro-theme/lib/serpent.lua b/lua/retro-theme/lib/serpent.lua
new file mode 100644
index 0000000..e3bdb1a
--- /dev/null
+++ b/lua/retro-theme/lib/serpent.lua
@@ -0,0 +1,258 @@
+local n, v = "serpent", "0.302" -- (C) 2012-18 Paul Kulchenko; MIT License
+local c, d = "Paul Kulchenko", "Lua serializer and pretty printer"
+local snum =
+ { [tostring(1 / 0)] = "1/0 --[[math.huge]]", [tostring(-1 / 0)] = "-1/0 --[[-math.huge]]", [tostring(0 / 0)] = "0/0" }
+local badtype = { thread = true, userdata = true, cdata = true }
+local getmetatable = debug and debug.getmetatable or getmetatable
+local pairs = function(t)
+ return next, t
+end -- avoid using __pairs in Lua 5.2+
+local keyword, globals, G = {}, {}, (_G or _ENV)
+for _, k in ipairs({
+ "and",
+ "break",
+ "do",
+ "else",
+ "elseif",
+ "end",
+ "false",
+ "for",
+ "function",
+ "goto",
+ "if",
+ "in",
+ "local",
+ "nil",
+ "not",
+ "or",
+ "repeat",
+ "return",
+ "then",
+ "true",
+ "until",
+ "while",
+}) do
+ keyword[k] = true
+end
+for k, v in pairs(G) do
+ globals[v] = k
+end -- build func to name mapping
+for _, g in ipairs({ "coroutine", "debug", "io", "math", "string", "table", "os" }) do
+ for k, v in pairs(type(G[g]) == "table" and G[g] or {}) do
+ globals[v] = g .. "." .. k
+ end
+end
+
+local function s(t, opts)
+ local name, indent, fatal, maxnum = opts.name, opts.indent, opts.fatal, opts.maxnum
+ local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
+ local space, maxl = (opts.compact and "" or " "), (opts.maxlevel or math.huge)
+ local maxlen, metatostring = tonumber(opts.maxlength), opts.metatostring
+ local iname, comm = "_" .. (name or ""), opts.comment and (tonumber(opts.comment) or math.huge)
+ local numformat = opts.numformat or "%.17g"
+ local seen, sref, syms, symn = {}, { "local " .. iname .. "={}" }, {}, 0
+ local function gensym(val)
+ return "_"
+ .. (
+ tostring(tostring(val)):gsub("[^%w]", ""):gsub(
+ "(%d%w+)",
+ -- tostring(val) is needed because __tostring may return a non-string value
+ function(s)
+ if not syms[s] then
+ symn = symn + 1
+ syms[s] = symn
+ end
+ return tostring(syms[s])
+ end
+ )
+ )
+ end
+ local function safestr(s)
+ return type(s) == "number" and tostring(huge and snum[tostring(s)] or numformat:format(s))
+ or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
+ or ("%q"):format(s):gsub("\010", "n"):gsub("\026", "\\026")
+ end
+ local function comment(s, l)
+ return comm and (l or 0) < comm and " --[[" .. select(2, pcall(tostring, s)) .. "]]" or ""
+ end
+ local function globerr(s, l)
+ return globals[s] and globals[s] .. comment(s, l)
+ or not fatal and safestr(select(2, pcall(tostring, s)))
+ or error("Can't serialize " .. tostring(s))
+ end
+ local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
+ local n = name == nil and "" or name
+ local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
+ local safe = plain and n or "[" .. safestr(n) .. "]"
+ return (path or "") .. (plain and path and "." or "") .. safe, safe
+ end
+ local alphanumsort = type(opts.sortkeys) == "function" and opts.sortkeys
+ or function(k, o, n) -- k=keys, o=originaltable, n=padding
+ local maxn, to = tonumber(n) or 12, { number = "a", string = "b" }
+ local function padnum(d)
+ return ("%0" .. tostring(maxn) .. "d"):format(tonumber(d))
+ end
+ table.sort(k, function(a, b)
+ -- sort numeric keys first: k[key] is not nil for numerical keys
+ return (k[a] ~= nil and 0 or to[type(a)] or "z") .. (tostring(a):gsub("%d+", padnum))
+ < (k[b] ~= nil and 0 or to[type(b)] or "z") .. (tostring(b):gsub("%d+", padnum))
+ end)
+ end
+ local function val2str(t, name, indent, insref, path, plainindex, level)
+ local ttype, level, mt = type(t), (level or 0), getmetatable(t)
+ local spath, sname = safename(path, name)
+ local tag = plainindex and ((type(name) == "number") and "" or name .. space .. "=" .. space)
+ or (name ~= nil and sname .. space .. "=" .. space or "")
+ if seen[t] then -- already seen this element
+ sref[#sref + 1] = spath .. space .. "=" .. space .. seen[t]
+ return tag .. "nil" .. comment("ref", level)
+ end
+ -- protect from those cases where __tostring may fail
+ if type(mt) == "table" and metatostring ~= false then
+ local to, tr = pcall(function()
+ return mt.__tostring(t)
+ end)
+ local so, sr = pcall(function()
+ return mt.__serialize(t)
+ end)
+ if to or so then -- knows how to serialize itself
+ seen[t] = insref or spath
+ t = so and sr or tr
+ ttype = type(t)
+ end -- new value falls through to be serialized
+ end
+ if ttype == "table" then
+ if level >= maxl then
+ return tag .. "{}" .. comment("maxlvl", level)
+ end
+ seen[t] = insref or spath
+ if next(t) == nil then
+ return tag .. "{}" .. comment(t, level)
+ end -- table empty
+ if maxlen and maxlen < 0 then
+ return tag .. "{}" .. comment("maxlen", level)
+ end
+ local maxn, o, out = math.min(#t, maxnum or #t), {}, {}
+ for key = 1, maxn do
+ o[key] = key
+ end
+ if not maxnum or #o < maxnum then
+ local n = #o -- n = n + 1; o[n] is much faster than o[#o+1] on large tables
+ for key in pairs(t) do
+ if o[key] ~= key then
+ n = n + 1
+ o[n] = key
+ end
+ end
+ end
+ if maxnum and #o > maxnum then
+ o[maxnum + 1] = nil
+ end
+ if opts.sortkeys and #o > maxn then
+ alphanumsort(o, t, opts.sortkeys)
+ end
+ local sparse = sparse and #o > maxn -- disable sparsness if only numeric keys (shorter output)
+ for n, key in ipairs(o) do
+ local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
+ if
+ opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
+ or opts.keyallow and not opts.keyallow[key]
+ or opts.keyignore and opts.keyignore[key]
+ or opts.valtypeignore and opts.valtypeignore[type(value)] -- skipping ignored value types
+ or sparse and value == nil
+ then -- skipping nils; do nothing
+ elseif ktype == "table" or ktype == "function" or badtype[ktype] then
+ if not seen[key] and not globals[key] then
+ sref[#sref + 1] = "placeholder"
+ local sname = safename(iname, gensym(key)) -- iname is table for local variables
+ sref[#sref] = val2str(key, sname, indent, sname, iname, true)
+ end
+ sref[#sref + 1] = "placeholder"
+ local path = seen[t] .. "[" .. tostring(seen[key] or globals[key] or gensym(key)) .. "]"
+ sref[#sref] = path .. space .. "=" .. space .. tostring(seen[value] or val2str(value, nil, indent, path))
+ else
+ out[#out + 1] = val2str(value, key, indent, nil, seen[t], plainindex, level + 1)
+ if maxlen then
+ maxlen = maxlen - #out[#out]
+ if maxlen < 0 then
+ break
+ end
+ end
+ end
+ end
+ local prefix = string.rep(indent or "", level)
+ local head = indent and "{\n" .. prefix .. indent or "{"
+ local body = table.concat(out, "," .. (indent and "\n" .. prefix .. indent or space))
+ local tail = indent and "\n" .. prefix .. "}" or "}"
+ return (custom and custom(tag, head, body, tail, level) or tag .. head .. body .. tail) .. comment(t, level)
+ elseif badtype[ttype] then
+ seen[t] = insref or spath
+ return tag .. globerr(t, level)
+ elseif ttype == "function" then
+ seen[t] = insref or spath
+ if opts.nocode then
+ return tag .. "function() --[[..skipped..]] end" .. comment(t, level)
+ end
+ local ok, res = pcall(string.dump, t)
+ local func = ok and "((loadstring or load)(" .. safestr(res) .. ",'@serialized'))" .. comment(t, level)
+ return tag .. (func or globerr(t, level))
+ else
+ return tag .. safestr(t)
+ end -- handle all other types
+ end
+ local sepr = indent and "\n" or ";" .. space
+ local body = val2str(t, name, indent) -- this call also populates sref
+ local tail = #sref > 1 and table.concat(sref, sepr) .. sepr or ""
+ local warn = opts.comment and #sref > 1 and space .. "--[[incomplete output with shared/self-references skipped]]"
+ or ""
+ return not name and body .. warn or "do local " .. body .. sepr .. tail .. "return " .. name .. sepr .. "end"
+end
+
+local function deserialize(data, opts)
+ local env = (opts and opts.safe == false) and G
+ or setmetatable({}, {
+ __index = function(t, k)
+ return t
+ end,
+ __call = function(t, ...)
+ error("cannot call functions")
+ end,
+ })
+ local f, res = (loadstring or load)("return " .. data, nil, nil, env)
+ if not f then
+ f, res = (loadstring or load)(data, nil, nil, env)
+ end
+ if not f then
+ return f, res
+ end
+ if setfenv then
+ setfenv(f, env)
+ end
+ return pcall(f)
+end
+
+local function merge(a, b)
+ if b then
+ for k, v in pairs(b) do
+ a[k] = v
+ end
+ end
+ return a
+end
+return {
+ _NAME = n,
+ _COPYRIGHT = c,
+ _DESCRIPTION = d,
+ _VERSION = v,
+ serialize = s,
+ load = deserialize,
+ dump = function(a, opts)
+ return s(a, merge({ name = "_", compact = true, sparse = true }, opts))
+ end,
+ line = function(a, opts)
+ return s(a, merge({ sortkeys = true, comment = true }, opts))
+ end,
+ block = function(a, opts)
+ return s(a, merge({ indent = " ", sortkeys = true, comment = true }, opts))
+ end,
+}
diff --git a/lua/retro-theme/lib/shade.lua b/lua/retro-theme/lib/shade.lua
new file mode 100644
index 0000000..c9878f4
--- /dev/null
+++ b/lua/retro-theme/lib/shade.lua
@@ -0,0 +1,9 @@
+local function shade(color, value)
+ if (vim.o.background == "light") then
+ return color.darken(value)
+ else
+ return color.lighten(value)
+ end
+end
+
+return shade
diff --git a/lua/retro-theme/lib/utils.lua b/lua/retro-theme/lib/utils.lua
new file mode 100644
index 0000000..e69de29
diff --git a/lua/retro-theme/palette/colors.lua b/lua/retro-theme/palette/colors.lua
new file mode 100644
index 0000000..1829733
--- /dev/null
+++ b/lua/retro-theme/palette/colors.lua
@@ -0,0 +1,930 @@
+local colorparser = require("retro-theme.lib.colorparser")
+local hsl = require("retro-theme.lib.hsl.type")
+local shade = require("retro-theme.lib.shade")
+local config = require("retro-theme").config
+
+local t = {
+ bg = hsl("#1c1e26"),
+ bgFloat = hsl("#1b1d23"),
+ fg = hsl("#c8d0e0"),
+ cursor = hsl("#ffdd33"),
+ keyword = hsl("#ff5df4"),
+ comment = hsl("#7fd1b9"),
+ punctuation = hsl("#f4a1ff"),
+ method = hsl("#00ffbf"),
+ type = hsl("#ff6ac1"),
+ string = hsl("#b7ff6a"),
+ number = hsl("#ff57ff"),
+ constant = hsl("#bd93f9"),
+ tag = hsl("#6cdbff"),
+ attribute = hsl("#8cff8f"),
+ property = hsl("#6de0b4"),
+ parameter = hsl("#9df9ff"),
+ label = hsl("#50e3c2"),
+
+ -- workspace
+ primary = hsl("#00dfff"),
+ selection = hsl("#336699"),
+ search = hsl("#00ff88"),
+ diffAdd = hsl("#00ff88"),
+ diffChange = hsl("#00bfff"),
+ diffDelete = hsl("#ff5555"),
+ added = hsl("#2ee085"),
+ changed = hsl("#00ccff"),
+ deleted = hsl("#ff4d6a"),
+
+ diffText = hsl("#00bfff").lighten(15),
+ error = hsl("#ff445d"),
+ errorBG = hsl("#ffccd2"),
+ warning = hsl("#6be6a2"),
+ warningBG = hsl("#d4ffe0"),
+ info = hsl("#00dfff"),
+ infoBG = hsl("#d0f4ff"),
+ hint = hsl("#a3adff"),
+ mergeCurrent = hsl("#5a4472"),
+ mergeCurrentLabel = hsl("#8f5ea5"),
+ mergeIncoming = hsl("#4465b3"),
+ mergeIncomingLabel = hsl("#558edc"),
+ mergeParent = hsl("#7946b8"),
+ mergeParentLabel = hsl("#8b5edc"),
+}
+
+t.shade1 = shade(t.bg, 1)
+t.shade2 = shade(t.bg, 2)
+t.shade3 = shade(t.bg, 3)
+t.shade4 = shade(t.bg, 4)
+t.shade5 = shade(t.bg, 5)
+t.shade6 = shade(t.bg, 6)
+t.shade7 = shade(t.bg, 7)
+t.shade8 = shade(t.bg, 8)
+t.shade9 = shade(t.bg, 9)
+t.shade10 = shade(t.bg, 10)
+t.shade20 = shade(t.bg, 20)
+t.shade25 = shade(t.bg, 25)
+t.shade30 = shade(t.bg, 30)
+t.shade40 = shade(t.bg, 40)
+t.shade50 = shade(t.bg, 50)
+t.shade60 = shade(t.bg, 60)
+t.shade70 = shade(t.bg, 70)
+t.shade80 = shade(t.bg, 80)
+t.shade90 = shade(t.bg, 90)
+
+t.grey3 = t.shade3.mix(t.primary, 3)
+t.grey5 = t.shade5.mix(t.primary, 5)
+t.grey7 = t.shade7.mix(t.primary, 7)
+t.grey10 = t.shade10.mix(t.primary, 10)
+t.grey20 = t.shade20.mix(t.primary, 10)
+t.grey25 = t.shade25.mix(t.primary, 10)
+t.grey30 = t.shade30.mix(t.primary, 10)
+t.grey40 = t.shade40.mix(t.primary, 12)
+
+t.white = hsl("#ffffff")
+t.green = hsl("#008200")
+
+local colors = {}
+
+-- normal text
+colors["Normal"] = { fg = t.fg, bg = t.bg }
+
+-- Screen-line at the cursor, when 'cursorline' is set.
+-- Low-priority if foreground (ctermfg OR guifg) is not set.
+colors["CursorLine"] = { bg = t.grey7 }
+
+-- Screen-column at the cursor, when 'cursorcolumn' is set.
+colors["CursorColumn"] = colors["CursorLine"]
+colors["Whitespace"] = { fg = t.grey10 }
+
+ -- any comment
+colors["Comment"] = { fg = t.comment, italic = config.italic_comments }
+
+-- Line number for ":number" and ":#" commands,
+-- and when 'number' or 'relativenumber' option is set.
+colors["LineNr"] = { fg = t.comment }
+
+-- Like LineNr when 'cursorline' or 'relativenumber' is set for the cursor line.
+colors["CursorLineNr"] = { fg = t.comment }
+colors["Search"] = { bg = t.search }
+colors["IncSearch"] = { bg = t.cursor.mix(t.bg, 10), fg = t.bg }
+colors["CurSearch"] = colors["Search"]
+colors["NormalFloat"] = { bg = t.bgFloat, blend = 5 } -- Normal text in floating windows.
+colors["FloatBorder"] = { fg = t.punctuation }
+colors["NormalSB"] = { bg = t.bgFloat } -- Normal text in floating windows.
+colors["ColorColumn"] = { bg = t.grey5 } -- used for the columns set with 'colorcolumn'
+colors["Conceal"] = {} -- placeholder characters substituted for concealed text (see 'conceallevel')
+colors["Cursor"] = { bg = t.cursor, fg = t.bg } -- character under the cursor
+colors["lCursor"] = colors["Cursor"] -- the character under the cursor when |language-mapping| is used (see 'guicursor')
+colors["CursorIM"] = colors["Cursor"] -- like Cursor, but used when in IME mode |CursorIM|
+colors["Directory"] = { fg = t.keyword } -- directory names (and other special names in listings)
+colors["DiffAdd"] = { bg = t.diffAdd } -- diff mode: Added line |diff.txt|
+colors["DiffChange"] = { bg = t.diffChange } -- diff mode: Changed line |diff.txt|
+colors["DiffDelete"] = { bg = t.diffDelete } -- diff mode: Deleted line |diff.txt|
+colors["DiffText"] = { bg = t.diffText } -- diff mode: Changed text within a changed line |diff.txt|
+colors["EndOfBuffer"] = { fg = t.punctuation } -- filler lines (~) after the end of the buffer. By default, this is highlighted like |hl-NonText|.
+colors["TermCursor"] = colors["Cursor"] -- cursor in a focused terminal
+colors["TermCursorNC"] = {} -- cursor in an unfocused terminal
+colors["ErrorMsg"] = { fg = t.error } -- error messages on the command line
+colors["VertSplit"] = { fg = t.grey30 } -- the column separating vertically split windows
+colors["Winseparator"] = colors["VertSplit"] -- Separator between window splits. Inherts from |hl-VertSplit| by default, which it will replace eventually.
+colors["Folded"] = { bg = t.shade7, fg = t.tag } -- line used for closed folds
+colors["SignColumn"] = colors["Normal"] -- column where |signs| are displayed
+colors["FoldColumn"] = colors["SignColumn"] -- 'foldcolumn'
+colors["Substitute"] = colors["IncSearch"] -- |:substitute| replacement text highlighting
+colors["MatchParen"] = { bg = t.punctuation, fg = t.bg } -- The character under the cursor or just before it, if it is a paired bracket, and its match. |pi_paren.txt|
+colors["ModeMsg"] = colors["Normal"] -- 'showmode' message (e.g., "-- INSERT -- ")
+colors["MsgArea"] = colors["Normal"] -- Area for messages and cmdline
+-- MsgSeparator = { } -- Separator for scrolled messages, `msgsep` flag of 'display'
+colors["MoreMsg"] = { fg = t.primary } -- |more-prompt|
+colors["NonText"] = { fg = t.shade30 } -- '@' at the end of the window, characters from 'showbreak' and other characters that do not really exist in the text (e.g., ">" displayed when a double-wide character doesn't fit at the end of the line). See also |hl-EndOfBuffer|.
+colors["NormalNC"] = colors["Normal"] -- normal text in non-current windows
+-- Pmenu = { bg = t.bg, blend = 5 }
+colors["Pmenu"] = colors["NormalFloat"]
+colors["PmenuSel"] = { bg = t.selection } -- Popup menu: selected item.
+colors["PmenuSbar"] = { bg = t.grey5 } -- Popup menu: scrollbar.
+colors["PmenuThumb"] = { bg = t.shade20 } -- Popup menu: Thumb of the scrollbar.
+colors["Question"] = { fg = t.primary } -- |hit-enter| prompt and yes/no questions
+colors["QuickFixLine"] = { bg = t.primary, fg = t.white } -- Current |quickfix| item in the quickfix window. Combined with |hl-CursorLine| when the cursor is there.
+colors["SpecialKey"] = { fg = t.attribute } -- Unprintable characters: text displayed differently from what it really is. But not 'listchars' whitespace. |hl-Whitespace|
+-- TODO: spelling
+-- SpellBad { gui = "undercurl", sp = t.error } -- Word that is not recognized by the spellchecker. |spell| Combined with the highlighting used otherwise.
+-- SpellCap { } -- Word that should start with a capital. |spell| Combined with the highlighting used otherwise.
+-- SpellLocal { } -- Word that is recognized by the spellchecker as one that is used in another region. |spell| Combined with the highlighting used otherwise.
+-- SpellRare { } -- Word that is recognized by the spellchecker as one that is hardly ever used. |spell| Combined with the highlighting used otherwise.
+--
+colors["StatusLine"] = { bg = t.grey10, gui = "" } -- status line of current window
+colors["StatusLineNC"] = { bg = t.shade5 } -- status lines of not-current windows Note: if this is equal to "StatusLine" Vim will use "^^^" in the status line of the current window.
+--
+colors["TabLine"] = { bg = t.shade3, fg = t.shade30 } -- tab pages line, not active tab page label
+colors["TabLineFill"] = { bg = t.bg } -- tab pages line, where there are no labels
+colors["TabLineSel"] = { bg = t.shade10, sp = t.primary, gui = "underline" } -- tab pages line, active tab page label
+--
+colors["Title"] = { fg = t.primary } -- titles for output from ":set all", ":autocmd" etc.
+colors["Visual"] = { bg = t.selection } -- Visual mode selection
+colors["VisualNOS"] = { bg = t.selection } -- Visual mode selection when vim is "Not Owning the Selection".
+colors["WarningMsg"] = { fg = t.warning } -- warning messages
+colors["WildMenu"] = { bg = t.selection } -- current match in 'wildmenu' completion
+--
+colors["Constant"] = { fg = t.constant } -- (preferred) any constant
+colors["String"] = { fg = t.string } -- a string constant: "this is a string"
+colors["Character"] = { fg = t.attribute } -- a character constant: 'c', '\n'
+colors["Number"] = { fg = t.number } -- a number constant: 234, 0xff
+colors["Boolean"] = { fg = t.keyword } -- a boolean constant: TRUE, false
+-- Float { } -- a floating point constant: 2.3e10
+colors["Identifier"] = { fg = t.fg } -- (preferred) any variable name
+colors["Function"] = { fg = t.method } -- function name (also: methods for classes)
+colors["Method"] = { fg = t.method } -- function name (also: methods for classes)
+colors["Property"] = { fg = t.property }
+colors["Field"] = colors["Property"]
+colors["Parameter"] = { fg = t.parameter }
+colors["Statement"] = { fg = t.keyword } -- (preferred) any statement
+-- Conditional { } -- if, then, else, endif, switch, etc.
+-- Repeat { } -- for, do, while, etc.
+-- Label { } -- case, default, etc.
+colors["Punctuation"] = { fg = t.punctuation } -- "sizeof", "+", "*", etc.
+colors["Operator"] = { fg = t.punctuation } -- "sizeof", "+", "*", etc.
+colors["Keyword"] = colors["Statement"] -- any other keyword
+-- Exception { } -- try, catch, throw
+colors["PreProc"] = { fg = t.keyword } -- (preferred) generic Preprocessor
+-- Include { } -- preprocessor #include
+-- Define { } -- preprocessor #define
+-- Macro { } -- same as Define
+-- PreCondit { } -- preprocessor #if, #else, #endif, etc.
+colors["Type"] = { fg = t.type } -- (preferred) int, long, char, etc.
+colors["Struct"] = colors["Type"]
+colors["Class"] = colors["Type"]
+-- StorageClass { } -- static, register, volatile, etc.
+-- Structure { } -- struct, union, enum, etc.
+-- Typedef { } -- A typedef
+colors["Special"] = colors["Character"] -- (preferred) any special symbol
+colors["Attribute"] = colors["Character"] -- (preferred) any special symbol
+-- SpecialChar = {} -- special character in a constant
+colors["Tag"] = { fg = t.tag } -- you can use CTRL-] on this
+-- Delimiter = {} -- character that needs attention
+-- SpecialComment = { } -- special things inside a comment
+-- Debug { } -- debugging statements
+colors["Underlined"] = { gui = "underline" } -- (preferred) text that stands out, HTML links
+colors["Bold"] = { gui = "bold" }
+colors["Italic"] = { gui = "italic" }
+-- ("Ignore", below, may be invisible...)
+colors["Ignore"] = { fg = t.bg } -- (preferred) left blank, hidden |hl-Ignore|
+colors["Error"] = colors["ErrorMsg"] -- (preferred) any erroneous construct
+colors["Todo"] = { bg = t.info, fg = t.white } -- (preferred) anything that needs extra attention; mostly the keywords TODO FIXME and XXX
+colors["WinBar"] = { fg = t.tag, gui = "bold" }
+colors["WinBarNC"] = { fg = t.fg, gui = "" }
+
+--
+-- These groups are for the native LSP client and diagnostic system. Some
+-- other LSP clients may use these groups, or use their own. Consult your
+-- LSP client's documentation.
+
+-- See :h lsp-highlight, some groups may not be listed, submit a PR fix to lush-template!
+--
+-- LspReferenceText { } , -- Used for highlighting "text" references
+-- LspReferenceRead { } , -- Used for highlighting "read" references
+-- LspReferenceWrite { } , -- Used for highlighting "write" references
+-- LspCodeLens { } , -- Used to color the virtual text of the codelens. See |nvim_buf_set_extmark()|.
+-- LspCodeLensSeparator { } , -- Used to color the seperator between two or more code lens.
+-- LspSignatureActiveParameter = { } , -- Used to highlight the active parameter in the signature help. See |vim.lsp.handlers.signature_help()|.
+
+-- See :h diagnostic-highlights, some groups may not be listed, submit a PR fix to lush-template!
+--
+colors["DiagnosticError"] = colors["Error"] -- Used as the base highlight group. Other Diagnostic highlights link to this by default (except Underline)
+colors["DiagnosticWarn"] = colors["WarningMsg"] -- Used as the base highlight group. Other Diagnostic highlights link to this by default (except Underline)
+colors["DiagnosticInfo"] = { fg = t.info } -- Used as the base highlight group. Other Diagnostic highlights link to this by default (except Underline)
+colors["DiagnosticHint"] = { fg = t.hint } -- Used as the base highlight group. Other Diagnostic highlights link to this by default (except Underline)
+colors["DiagnosticVirtualTextError"] = { colors["DiagnosticError"], bg = t.bg.mix(t.error, 20) } -- Used for "Error" diagnostic virtual text.
+colors["DiagnosticVirtualTextWarn"] = { colors["DiagnosticWarn"], bg = t.bg.mix(t.warning, 20) } -- Used for "Warn" diagnostic virtual text.
+colors["DiagnosticVirtualTextInfo"] = { colors["DiagnosticInfo"], bg = t.bg.mix(t.info, 20) } -- Used for "Info" diagnostic virtual text.
+colors["DiagnosticVirtualTextHint"] = { colors["DiagnosticHint"], bg = t.bg.mix(t.hint, 20) } -- Used for "Hint" diagnostic virtual text.
+colors["DiagnosticUnderlineError"] = { gui = "undercurl", sp = t.error } -- Used to underline "Error" diagnostics.
+colors["DiagnosticUnderlineWarn"] = { gui = "undercurl", sp = t.warning } -- Used to underline "Warn" diagnostics.
+colors["DiagnosticUnderlineInfo"] = { gui = "undercurl", sp = t.info } -- Used to underline "Info" diagnostics.
+colors["DiagnosticUnderlineHint"] = { gui = "undercurl", sp = t.hint } -- Used to underline "Hint" diagnostics.
+-- DiagnosticFloatingError { } , -- Used to color "Error" diagnostic messages in diagnostics float. See |vim.diagnostic.open_float()|
+-- DiagnosticFloatingWarn { } , -- Used to color "Warn" diagnostic messages in diagnostics float.
+-- DiagnosticFloatingInfo { } , -- Used to color "Info" diagnostic messages in diagnostics float.
+-- DiagnosticFloatingHint { } , -- Used to color "Hint" diagnostic messages in diagnostics float.
+-- DiagnosticSignError { } , -- Used for "Error" signs in sign column.
+-- DiagnosticSignWarn { } , -- Used for "Warn" signs in sign column.
+-- DiagnosticSignInfo { } , -- Used for "Info" signs in sign column.
+-- DiagnosticSignHint { } , -- Used for "Hint" signs in sign column.
+
+-- These groups are for the neovim tree-sitter highlights.
+-- As of writing, tree-sitter support is a WIP, group names may change.
+-- By default, most of these groups link to an appropriate Vim group,
+-- TSError -> Error for example, so you do not have to define these unless
+-- you explicitly want to support Treesitter's improved syntax awareness.
+
+--
+-- TSError { } -- For syntax/parser errors.
+colors["@constructor"] = { fg = t.type }
+colors["@punctuation"] = { fg = t.punctuation }
+colors["@punctuation.bracket"] = { fg = t.punctuation }
+colors["@punctuation.delimiter"] = { fg = t.punctuation }
+colors["@punctuation.special"] = { fg = t.punctuation }
+colors["@symbol"] = { fg = t.constant }
+colors["@constant"] = { fg = t.constant }
+colors["@constant.builtin"] = { fg = t.keyword }
+colors["@string.escape"] = colors["Character"]
+colors["@method"] = { fg = t.method }
+colors["@function"] = { fg = t.method }
+colors["@function.call"] = { fg = t.method }
+colors["@function.builtin"] = { fg = t.method }
+colors["@parameter"] = { fg = t.parameter }
+colors["@field"] = colors["Property"]
+colors["@property"] = colors["Property"]
+colors["@label"] = { fg = t.label } -- For labels: `label:` in C and `:label:` in Lua.
+colors["@type"] = colors["Type"]
+colors["@type.builtin"] = { fg = t.keyword }
+colors["@type.qualifier"] = colors["Statement"]
+colors["@keyword"] = colors["Statement"]
+colors["@keyword.modifier"] = colors["Statement"] -- Same as @type.qualifier
+colors["@namespace"] = colors["Type"]
+colors["@annotation"] = colors["@label"] -- For labels: `label:` in C and `:label:` in Lua.
+colors["@text"] = colors["Identifier"]
+colors["@text.strong"] = colors["Bold"]
+colors["@text.italic"] = colors["Italic"]
+colors["@text.underline"] = colors["Underlined"]
+colors["@text.title"] = { fg = t.keyword }
+colors["@text.literal"] = colors["Property"]
+colors["@text.uri"] = { fg = t.tag, sp = t.tag, gui = "underline" } -- Any URI like a link or email.
+colors["@variable"] = colors["Identifier"] -- Variable names that are defined by the languages like `this` or `self`.
+colors["@variable.builtin"] = colors["Statement"] -- Variable names that are defined by the languages like `this` or `self`.
+colors["@tag"] = colors["Tag"]
+colors["@attribute"] = { fg = t.label } -- Variable names that are defined by the languages, like `this` or `self`.
+colors["@tag.attribute"] = { fg = t.attribute } -- Variable names that are defined by the languages, like `this` or `self`.
+colors["@error"] = colors["Error"] -- Variable names that are defined by the languages like `this` or `self`.
+colors["@warning"] = colors["WarningMsg"]
+colors["@info"] = { fg = t.info }
+--
+-- ["@markup.link.label"] = { } -- SpecialChar
+-- ["@character.special"] = { } -- SpecialChar
+-- ["@function.macro"] = { } -- Macro
+-- ["@keyword.debug"] = { } -- Debug
+
+-- Language Overrides
+-- JSON
+colors["@label.json"] = { fg = t.property } -- For labels: `label:` in C and `:label:` in Lua.
+colors["@label.jsonc"] = { fg = t.property } -- For labels: `label:` in C and `:label:` in Lua.
+-- help files
+colors["@label.help"] = colors["@text.uri"]
+-- html
+colors["@text.uri.html"] = { gui = "underline" }
+
+
+-- Treesitter highlight groups update
+-- Treesitter standard capture groups
+colors["@variable.parameter"] = colors["@parameter"]
+colors["@variable.member"] = colors["@field"]
+colors["@module"] = colors["@namespace"]
+colors["@string.special.symbol"] = colors["@symbol"]
+colors["@markup.strong"] = colors["@text.strong"]
+colors["@markup.underline"] = colors["@text.underline"]
+colors["@markup.heading"] = colors["@text.title"]
+colors["@markup.link.url"] = colors["@text.uri"]
+colors["@markup.raw"] = colors["@text.literal"]
+colors["@markup.list"] = colors["@punctuation.special"]
+
+-- Helix capture groups
+colors["@function.method"] = colors["@method"]
+colors["@string.special.url"] = colors["@text.uri"]
+
+
+-- semantic highlighting
+colors["@lsp.type.namespace"] = colors["@namespace"]
+colors["@lsp.type.type"] = colors["@type"]
+colors["@lsp.type.class"] = colors["@type"]
+colors["@lsp.type.enum"] = colors["@type"]
+colors["@lsp.type.interface"] = colors["@type"]
+colors["@lsp.type.struct"] = colors["@type"]
+colors["@lsp.type.parameter"] = colors["@parameter"]
+colors["@lsp.type.variable"] = colors["@variable"]
+colors["@lsp.type.property"] = colors["@property"]
+colors["@lsp.type.enumMember"] = colors["@constant"]
+colors["@lsp.type.function"] = colors["@function"]
+colors["@lsp.type.method"] = colors["@method"]
+colors["@lsp.type.macro"] = colors["@label"]
+colors["@lsp.type.decorator"] = colors["@label"]
+colors["@lsp.mod.readonly"] = colors["@constant"]
+colors["@lsp.typemod.function.declaration"] = colors["@function"]
+colors["@lsp.typemod.function.readonly"] = colors["@function"]
+
+-- gui vim
+-- VimR
+colors["VimrDefaultCursor"] = { fg = t.cursor, bg = t.bg }
+colors["VimrInsertCursor"] = { fg = t.cursor, bg = t.bg }
+-- gitsigns
+colors["GitSignsAdd"] = { fg = t.added }
+colors["GitSignsChange"] = { fg = t.changed }
+colors["GitSignsDelete"] = { fg = t.deleted }
+-- TODO: improve bufferline
+colors["BufferlineFill"] = colors["NormalFloat"]
+-- BufferlineBackground = { bg = t.bg }
+-- BufferlineDevIconLua = { bg = t.bg, fg = t.keyword }
+-- BufferlineDevIconLuaSelected = { bg = t.bg, fg = t.keyword }
+-- BufferlineBufferVisible = { bg = t.bg }
+-- BufferlineBufferSelected = { bg = t.bg }
+
+-- BufferlineIndicatorVisible = { bg = t.type } -- shows which buffers are visible in windows currently
+
+-- BufferLineSeparatorSelected = { fg = t.type, sp = t.primary, gui = "underline" }
+-- BufferLineWarningDiagnosticSelected = { fg = t.warning, sp = t.primary, gui = "underline" }
+-- BufferLineErrorDiagnosticSelected = { fg = t.error, sp = t.primary, gui = "underline" }
+-- BufferLineInfoDiagnosticSelected = { fg = t.info, sp = t.primary, gui = "underline" }
+-- BufferLineHintDiagnosticSelected = { fg = t.hint, sp = t.primary, gui = "underline" }
+-- BufferLineTabSeparatorSelected = { sp = t.primary, gui = "underline" }
+-- BufferLineCloseButtonSelected = { sp = t.primary, gui = "underline" }
+-- BufferLineDiagnosticSelected = { sp = t.primary, gui = "underline" }
+-- BufferLineDevIconLuaSelected = { sp = t.primary, gui = "underline" }
+-- BufferLineIndicatorSelected = { sp = t.primary, gui = "underline" }
+-- BufferLineDuplicateSelected = { sp = t.primary, gui = "underline" }
+-- BufferLineModifiedSelected = { sp = t.primary, gui = "underline" }
+-- BufferLineNumbersSelected = { sp = t.primary, gui = "underline" }
+-- BufferLineBufferSelected = { sp = t.primary, gui = "underline" }
+-- BufferLinePickSelected = { sp = t.primary, gui = "underline" }
+-- BufferLineTabSelected = { sp = t.primary, gui = "underline" }
+-- BufferLineWarningSelected = { fg = t.warning, sp = t.primary, gui = "underline" }
+-- BufferLineErrorSelected = { fg = t.error, sp = t.primary, gui = "underline" }
+-- BufferLineInfoSelected = { fg = t.info, sp = t.primary, gui = "underline" }
+-- BufferLineHintSelected = { fg = t.hint, sp = t.primary, gui = "underline" }
+--
+
+-- BarBar
+colors["BufferCurrent"] = colors["Normal"]
+colors["BufferCurrentIndex"] = colors["BufferCurrent"]
+colors["BufferCurrentIcon"] = colors["BufferCurrentIndex"]
+colors["BufferCurrentMod"] = colors["BufferCurrent"]
+colors["BufferCurrentSign"] = { fg = t.keyword, bg = colors["BufferCurrent"].bg }
+colors["BufferCurrentTarget"] = { colors["BufferCurrent"], fg = t.type }
+colors["BufferCurrentWARN"] = { fg = colors["DiagnosticWarn"].fg, bg = colors["BufferCurrent"].bg }
+colors["BufferCurrentINFO"] = { fg = colors["DiagnosticInfo"].fg, bg = colors["BufferCurrent"].bg }
+colors["BufferCurrentERROR"] = { fg = colors["DiagnosticError"].fg, bg = colors["BufferCurrent"].bg }
+colors["BufferCurrentHINT"] = { fg = colors["DiagnosticHint"].fg, bg = colors["BufferCurrent"].bg }
+--
+colors["BufferInactive"] = { fg = t.shade40, bg = t.bgFloat }
+colors["BufferInactiveIcon"] = colors["BufferInactive"]
+colors["BufferInactiveIndex"] = colors["BufferInactive"]
+colors["BufferInactiveMod"] = colors["BufferInactive"]
+colors["BufferInactiveSign"] = colors["BufferInactive"]
+colors["BufferInactiveTarget"] = { colors["BufferInactive"], fg = t.type }
+colors["BufferInactiveWARN"] = { colors["BufferCurrentWARN"], bg = colors["BufferInactive"].bg }
+colors["BufferInactiveINFO"] = { colors["BufferCurrentINFO"], bg = colors["BufferInactive"].bg }
+colors["BufferInactiveERROR"] = { colors["BufferCurrentERROR"], bg = colors["BufferInactive"].bg }
+colors["BufferInactiveHINT"] = { colors["BufferCurrentHINT"], bg = colors["BufferInactive"].bg }
+--
+colors["BufferVisible"] = { colors["BufferCurrent"], bg = t.bgFloat }
+colors["BufferVisibleIndex"] = colors["BufferVisible"]
+colors["BufferVisibleIcon"] = colors["BufferVisibleIndex"]
+colors["BufferVisibleMod"] = colors["BufferVisible"]
+colors["BufferVisibleSign"] = colors["BufferVisible"]
+colors["BufferVisibleTarget"] = { colors["BufferVisible"], fg = t.type }
+colors["BufferVisibleWARN"] = colors["BufferInactiveWARN"]
+colors["BufferVisibleINFO"] = colors["BufferInactiveINFO"]
+colors["BufferVisibleERROR"] = colors["BufferInactiveERROR"]
+colors["BufferVisibleHINT"] = colors["BufferInactiveHINT"]
+--
+colors["BufferAlternate"] = colors["BufferInactive"]
+colors["BufferAlternateIndex"] = colors["BufferAlternate"]
+colors["BufferAlternateIcon"] = colors["BufferAlternateIndex"]
+colors["BufferAlternateMod"] = colors["BufferInactiveMod"]
+colors["BufferAlternateSign"] = { colors["BufferInactiveSign"], fg = t.constant }
+colors["BufferAlternateTarget"] = { colors["BufferAlternate"], fg = t.type }
+colors["BufferAlternateWARN"] = colors["BufferInactiveWARN"]
+colors["BufferAlternateINFO"] = colors["BufferInactiveINFO"]
+colors["BufferAlternateERROR"] = colors["BufferInactiveERROR"]
+colors["BufferAlternateHINT"] = colors["BufferInactiveHINT"]
+--
+colors["BufferTabpages"] = { colors["BufferInactive"], fg = t.fg }
+colors["BufferTabpageFill"] = { colors["BufferTabpages"], fg = t.bg }
+colors["BufferOffset"] = colors["BufferTabpageFill"]
+--
+
+-- Telescope
+-- Sets the highlight for selected items within the picker.
+-- TelescopeSelection {}
+-- TelescopeSelectionCaret {}
+colors["TelescopeMultiSelection"] = { fg = t.attribute }
+colors["TelescopeMultiIcon"] = { fg = t.primary }
+--
+-- -- "Normal" in the floating windows created by telescope.
+-- TelescopeNormal = { fg = t.fg, bg = t.bg }
+-- TelescopeNormal = { fg = t.fg, bg = t.bg, blend = 5 }
+colors["TelescopeNormal"] = colors["NormalFloat"]
+-- TelescopePreviewNormal {}
+-- TelescopePromptNormal = { fg = t.fg, bg = t.bg }
+-- TelescopeResultsNormal {}
+
+-- Border highlight groups.
+-- Use TelescopeBorder to override the default.
+-- Otherwise set them specifically
+
+colors["TelescopeBorder"] = { colors["NormalFloat"], fg = t.punctuation }
+-- TelescopePromptBorder {}
+-- TelescopeResultsBorder {}
+-- TelescopePreviewBorder {}
+
+-- -- Title highlight groups.
+-- -- Use TelescopeTitle to override the default.
+-- -- Otherwise set them specifically
+-- TelescopeTitle {fg = t.constant}
+-- TelescopePromptTitle {}
+-- TelescopeResultsTitle {}
+-- TelescopePreviewTitle {}
+
+-- TelescopePromptCounter {}
+
+-- -- Used for highlighting characters that you match.
+colors["TelescopeMatching"] = { fg = t.keyword }
+-- -- Used for the prompt prefix
+colors["TelescopePromptPrefix"] = { fg = t.punctuation }
+-- -- Used for highlighting the matched line inside Previewer. Works only for (vim_buffer_ previewer)
+-- TelescopePreviewLine {}
+-- TelescopePreviewMatch {}
+
+-- TelescopePreviewPipe {}
+-- TelescopePreviewCharDev {}
+-- TelescopePreviewDirectory {}
+-- TelescopePreviewBlock {}
+colors["TelescopePreviewLink"] = { fg = t.label }
+colors["TelescopePreviewSocket"] = { fg = t.property }
+-- TelescopePreviewRead {}
+colors["TelescopePreviewWrite"] = { fg = t.type }
+colors["TelescopePreviewExecute"] = { fg = t.method }
+-- TelescopePreviewHyphen {}
+-- TelescopePreviewSticky {}
+colors["TelescopePreviewSize"] = { fg = t.number }
+colors["TelescopePreviewUser"] = { fg = t.property }
+colors["TelescopePreviewGroup"] = { fg = t.property }
+colors["TelescopePreviewDate"] = { fg = t.string }
+-- TelescopePreviewMessage {}
+-- TelescopePreviewMessageFillchar {}
+
+-- -- Used for Picker specific Results highlighting
+colors["TelescopeResultsClass"] = colors["Class"]
+-- TelescopeResultsConstant {}
+colors["TelescopeResultsField"] = colors["Field"]
+-- TelescopeResultsFunction {}
+-- TelescopeResultsMethod {}
+-- TelescopeResultsOperator {}
+-- TelescopeResultsStruct {}
+colors["TelescopeResultsVariable"] = colors["Identifier"]
+-- TelescopeResultsLineNr {}
+-- TelescopeResultsIdentifier {}
+-- TelescopeResultsNumber {}
+-- TelescopeResultsComment {}
+colors["TelescopeResultsSpecialComment"] = colors["Comment"]
+-- -- Used for git status Results highlighting
+-- TelescopeResultsDiffChange {}
+-- TelescopeResultsDiffAdd {}
+-- TelescopeResultsDiffDelete {}
+-- TelescopeResultsDiffUntracked {}
+--
+
+-- lspsaga
+colors["TitleIcon"] = colors["Function"]
+colors["SagaNormal"] = colors["NormalFloat"]
+colors["SagaExpand"] = colors["Normal"]
+colors["SagaCollapse"] = colors["SagaExpand"]
+colors["SagaCount"] = colors["Number"]
+colors["SagaBeacon"] = { bg = t.cursor, blend = 70 }
+colors["CodeActionNumber"] = colors["Statement"]
+colors["FinderSelection"] = colors["Visual"]
+-- FinderFileName = colors["Comment"]
+colors["FinderCount"] = colors["Number"]
+colors["FinderIcon"] = colors["Punctuation"]
+colors["FinderType"] = colors["Title"]
+colors["SagaLightBulb"] = colors["Attribute"]
+-- SagaShadow = colors["FloatShadow"]
+colors["OutlineIndent"] = colors["Whitespace"]
+--
+-- lspsaga winbar
+-- SagaWinbarModule = {}
+-- SagaWinbarInterface = {}
+-- SagaWinbarConstructor = {}
+-- SagaWinbarStruct = {}
+-- SagaWinbarObject = {}
+-- SagaWinbarUnit = {}
+colors["SagaWinbarFile"] = { fg = t.fg }
+colors["SagaWinbarSnippet"] = { fg = t.label }
+-- SagaWinbarText = {}
+-- SagaWinbarTypeAlias = {}
+-- SagaWinbarEvent = {}
+-- SagaWinbarParameter = {}
+colors["SagaWinbarKey"] = colors["Property"]
+colors["SagaWinbarValue"] = colors["String"]
+-- SagaWinbarMacro = {}
+-- SagaWinbarNumber = {}
+-- SagaWinbarConstant = {}
+-- SagaWinbarFunction = {}
+colors["SagaWinbarEnum"] = colors["Type"]
+-- SagaWinbarField = {}
+-- SagaWinbarProperty = {}
+-- SagaWinbarMethod = {}
+colors["SagaWinbarClass"] = colors["Type"]
+colors["SagaWinbarFolder"] = colors["Tag"]
+-- SagaWinbarPackage = {}
+-- SagaWinbarStaticMethod = {}
+-- SagaWinbarTypeParameter = {}
+colors["SagaWinbarEnumMember"] = colors["Property"]
+-- SagaWinbarOperator = {}
+colors["SagaWinbarNull"] = colors["Statement"]
+-- SagaWinbarNamespace = {}
+-- SagaWinbarArray = {}
+-- SagaWinbarBoolean = {}
+-- SagaWinbarString = {}
+-- SagaWinbarVariable = {}
+colors["SagaWinbarFilename"] = colors["SagaWinbarFile"]
+colors["SagaWinbarFolderName"] = {}
+colors["SagaWinbarFileIcon"] = {}
+colors["SagaWinbarSep"] = { fg = t.punctuation }
+--
+
+-- Trouble
+colors["TroubleCount"] = { fg = t.number }
+colors["TroubleNormal"] = { bg = t.bgFloat }
+-- TroubleTextInformation = {}
+-- TroubleSignWarning = {}
+colors["TroubleLocation"] = { fg = t.attribute }
+-- TroubleWarning = {}
+-- TroublePreview = {}
+-- TroubleTextError = {}
+-- TroubleSignInformation = {}
+-- TroubleIndent = {}
+-- TroubleSource = {}
+-- TroubleSignHint = {}
+-- TroubleSignOther = {}
+-- TroubleFoldIcon = {}
+-- TroubleTextWarning = {}
+-- TroubleCode = {}
+-- TroubleInformation = {}
+-- TroubleSignError = { fg = t.number}
+-- TroubleFile = {}
+-- TroubleHint = {}
+-- TroubleTextHint = {}
+colors["TroubleText"] = {}
+--
+
+-- Cmp
+colors["CmpDocumentation"] = { fg = t.fg, bg = t.bgFloat }
+colors["CmpDocumentationBorder"] = { fg = t.punctuation, bg = t.bgFloat }
+colors["CmpItemAbbr"] = { fg = t.fg }
+colors["CmpItemAbbrDeprecated"] = { fg = t.fg, gui = "strikethrough" }
+colors["CmpItemAbbrMatch"] = { fg = t.primary }
+colors["CmpItemAbbrMatchFuzzy"] = { fg = t.primary }
+colors["CmpItemMenu"] = { fg = t.attribute }
+colors["CmpItemKindText"] = { fg = t.comment }
+colors["CmpItemKindDefault"] = { fg = t.fb }
+colors["CmpItemKindKeyword"] = { fg = t.keyword }
+colors["CmpItemKindVariable"] = { fg = t.fg }
+colors["CmpItemKindConstant"] = { fg = t.constant }
+colors["CmpItemKindReference"] = { fg = t.fg }
+colors["CmpItemKindValue"] = { fg = t.fg }
+colors["CmpItemKindFunction"] = { fg = t.method }
+colors["CmpItemKindMethod"] = { fg = t.method }
+colors["CmpItemKindConstructor"] = { fg = t.type }
+colors["CmpItemKindClass"] = { fg = t.type }
+colors["CmpItemKindInterface"] = { fg = t.type }
+colors["CmpItemKindStruct"] = { fg = t.type }
+colors["CmpItemKindEvent"] = { fg = t.label }
+colors["CmpItemKindEnum"] = { fg = t.type }
+colors["CmpItemKindUnit"] = { fg = t.number }
+colors["CmpItemKindModule"] = { fg = t.keyword }
+colors["CmpItemKindProperty"] = { fg = t.property }
+colors["CmpItemKindField"] = { fg = t.property }
+colors["CmpItemKindTypeParameter"] = { fg = t.type }
+colors["CmpItemKindEnumMember"] = { fg = t.type }
+colors["CmpItemKindOperator"] = { fg = t.punctuation }
+colors["CmpItemKindSnippet"] = { fg = t.label }
+--
+
+-- nvim illuminate
+colors["IlluminatedWordText"] = { bg = t.grey7 }
+colors["IlluminatedWordRead"] = { bg = t.grey7 }
+colors["IlluminatedWordWrite"] = { bg = t.grey7 }
+--
+
+-- cursor word
+colors["CursorWord"] = { bg = t.grey7 }
+colors["CursorWord0"] = { bg = t.grey7 }
+colors["CursorWord1"] = { bg = t.grey7 }
+--
+
+-- mason
+colors["MasonNormal"] = colors["NormalFloat"]
+colors["MasonHeader"] = { bg = t.primary, fg = t.bg }
+colors["MasonHeaderSecondary"] = { bg = t.constant, fg = t.bg }
+colors["MasonHighlight"] = { fg = t.primary }
+colors["MasonHighlightBlock"] = { bg = t.primary, fg = t.bg }
+colors["MasonHighlightBlockBold"] = { bg = t.primary, fg = t.bg, gui = "bold" }
+colors["MasonHighlightSecondary"] = { fg = t.constant }
+colors["MasonHighlightBlockSecondary"] = { bg = t.constant, fg = t.bg }
+colors["MasonHighlightBlockBoldSecondary"] = { bg = t.constant, fg = t.bg, gui = "bold" }
+colors["MasonLink"] = colors["@text.uri"]
+colors["MasonMuted"] = { fg = t.shade50 }
+colors["MasonMutedBlock"] = { bg = t.shade40, fg = t.bg }
+colors["MasonMutedBlockBold"] = { bg = t.shade40, fg = t.bg, gui = "bold" }
+colors["MasonError"] = colors["Error"]
+colors["MasonHeading"] = { gui = "bold,underline", fg = t.fg }
+--
+
+-- which-key
+colors["WhichKey"] = colors["Character"]
+colors["WhichKeyGroup"] = colors["Tag"]
+colors["WhichKeySeparator"] = colors["Operator"]
+colors["WhichKeyDesc"] = colors["@text.title"]
+-- WhichKeyFloat = {}
+-- WhichKeyBorder = {}
+-- WhichKeyValue = colors["Character"]
+
+
+-- Diffview
+colors["DiffviewStatusAdded"] = { fg = t.method }
+colors["DiffviewStatusModified"] = { fg = t.keyword }
+colors["DiffviewStatusRenamed"] = { fg = t.keyword }
+colors["DiffviewStatusCopied"] = { fg = t.keyword }
+colors["DiffviewStatusTypeChanged"] = { fg = t.keyword }
+colors["DiffviewStatusUnmerged"] = { fg = t.number }
+colors["DiffviewStatusUnknown"] = { fg = t.property }
+colors["DiffviewStatusDeleted"] = { fg = t.type }
+-- DiffviewStatusBroken = {}
+colors["DiffviewStatusIgnored"] = { fg = t.comment }
+colors["DiffviewFilePanelInsertions"] = { fg = t.added }
+colors["DiffviewFilePanelDeletions"] = { fg = t.deleted }
+colors["DiffviewFilePanelRootPath"] = { fg = t.tag }
+colors["DiffviewFilePanelTitle"] = { fg = t.constant }
+colors["DiffviewFilePanelCounter"] = { fg = t.attribute }
+-- DiffviewFilePanelFileName = {}
+colors["DiffviewFilePanelPath"] = { fg = t.comment }
+colors["DiffviewFilePanelConflicts"] = { fg = t.number }
+colors["DiffviewFolderName"] = colors["Directory"]
+-- DiffviewFolderSign = {}
+-- DiffviewReference = {}
+colors["DiffviewPrimary"] = { fg = t.keyword }
+colors["DiffviewSecondary"] = { fg = t.tag }
+--
+
+-- vim-fugitive
+colors["diffAdded"] = { fg = t.method }
+colors["diffRemoved"] = { fg = t.type }
+--
+
+-- nvim tree
+colors["NvimTreeNormal"] = { bg = t.bgFloat }
+colors["NvimTreeNormalNC"] = { bg = t.bgFloat }
+colors["NvimTreeWindowPicker"] = { fg = t.fg, bg = t.selection, gui = "bold" }
+colors["NvimTreeIndentMarker"] = { fg = t.punctuation }
+colors["NvimTreeRootFolder"] = { fg = t.tag }
+colors["NvimTreeFolderIcon"] = { fg = t.keyword }
+colors["NvimTreeFolderName"] = { fg = t.tag }
+colors["NvimTreeOpenedFolderName"] = { fg = t.keyword }
+colors["NvimTreeSpecialFile"] = { fg = t.constant }
+colors["NvimTreeExecFile"] = { fg = t.method }
+colors["NvimTreeGitStaged"] = { fg = t.method }
+colors["NvimTreeGitDirty"] = { fg = t.type }
+colors["NvimTreeGitMerge"] = { fg = t.number }
+colors["NvimTreeGitDeleted"] = { fg = t.deleted }
+colors["NvimTreeGitNew"] = { fg = t.method }
+--
+
+-- git-conflict
+colors["GitConflictCurrent"] = { bg = t.mergeCurrent, blend = 5 }
+colors["GitConflictIncoming"] = { bg = t.mergeIncoming, blend = 5 }
+colors["GitConflictAncestor"] = { bg = t.mergeParent, blend = 5 }
+colors["GitConflictCurrentLabel"] = { bg = t.mergeCurrentLabel, blend = 5 }
+colors["GitConflictIncomingLabel"] = { bg = t.mergeIncomingLabel, blend = 5 }
+colors["GitConflictAncestorLabel"] = { bg = t.mergeParentLabel, blend = 5 }
+--
+
+-- notify
+colors["NotifyBackground"] = colors["NormalFloat"]
+colors["NotifyERRORBorder"] = { colors["Normal"], fg = t.error }
+colors["NotifyWARNBorder"] = { colors["Normal"], fg = t.warning }
+colors["NotifyINFOBorder"] = { colors["Normal"], fg = t.info }
+colors["NotifyDEBUGBorder"] = { colors["Normal"], fg = t.punctuation }
+colors["NotifyTRACEBorder"] = { colors["Normal"], fg = t.property }
+colors["NotifyERRORIcon"] = colors["NotifyERRORBorder"]
+colors["NotifyWARNIcon"] = colors["NotifyWARNBorder"]
+colors["NotifyINFOIcon"] = colors["NotifyINFOBorder"]
+colors["NotifyDEBUGIcon"] = colors["NotifyDEBUGBorder"]
+colors["NotifyTRACEIcon"] = colors["NotifyTRACEBorder"]
+colors["NotifyERRORTitle"] = colors["NotifyERRORBorder"]
+colors["NotifyWARNTitle"] = colors["NotifyWARNBorder"]
+colors["NotifyINFOTitle"] = colors["NotifyINFOBorder"]
+colors["NotifyDEBUGTitle"] = colors["NotifyDEBUGBorder"]
+colors["NotifyTRACETitle"] = colors["NotifyTRACEBorder"]
+--
+
+-- -- Visual Multi.
+-- VM_Extend = { bg = colors.selection_inactive }
+-- VM_Cursor = { bg = colors.selection_inactive, sp = colors.fg, underline = true }
+-- VM_Insert = { sp = colors.fg, underline = true }
+-- VM_Mono = { fg = colors.bg, bg = colors.comment }
+--
+
+-- hlargs (semantic parameter highlighting)
+colors["Hlargs"] = colors["@parameter"]
+--
+
+-- virt-column
+colors["VirtColumn"] = colors["Whitespace"]
+--
+
+-- indent blankline
+-- IblScope = {}
+-- RainbowDelimiterRed = {}
+-- RainbowDelimiterYellow = {}
+-- RainbowDelimiterBlue = {}
+-- RainbowDelimiterOrange = {}
+-- RainbowDelimiterGreen = {}
+-- RainbowDelimiterViolet = {}
+-- RainbowDelimiterCyan = {}
+
+-- Neotest
+colors["NeotestPassed"] = { fg = t.added }
+colors["NeotestRunning"] = colors["DiagnosticInfo"]
+colors["NeotestSkipped"] = colors["DiagnosticWarn"]
+colors["NeotestFailed"] = colors["DiagnosticError"]
+colors["NeotestAdapterName"] = {}
+colors["NeotestBorder"] = {}
+colors["NeotestDir"] = colors["Directory"]
+colors["NeotestExpandMarker"] = {}
+colors["NeotestFile"] = { fg = t.tag }
+colors["NeotestFocused"] = {}
+colors["NeotestIndent"] = {}
+colors["NeotestMarked"] = {}
+colors["NeotestNamespace"] = {}
+colors["NeotestWinSelect"] = {}
+colors["NeotestTarget"] = {}
+colors["NeotestTest"] = {}
+colors["NeotestUnknown"] = {}
+colors["NeotestWatching"] = { fg = t.constant }
+
+-- basic highlighting without treesitter
+--
+
+-- javascript
+colors["javaScript"] = colors["Identifier"]
+colors["javaScriptIdentifier"] = colors["Statement"]
+colors["javaScriptFunction"] = colors["Statement"]
+colors["javaScriptParens"] = colors["Punctuation"]
+colors["javaScriptBraces"] = colors["Punctuation"]
+colors["javaScriptNumber"] = colors["Number"]
+--
+
+-- typescript
+colors["typeScriptImport"] = colors["Statement"]
+colors["typeScriptExport"] = colors["Statement"]
+colors["typeScriptIdentifier"] = colors["Statement"]
+colors["typescriptVariable"] = colors["Statement"]
+colors["typeScriptFunction"] = colors["Statement"]
+colors["typescriptPredefinedType"] = colors["@type.builtin"]
+colors["typescriptClassStatic"] = colors["Statement"]
+colors["typescriptNodeGlobal"] = colors["Statement"]
+colors["typescriptExceptions"] = colors["Statement"]
+colors["typeScriptParens"] = colors["Punctuation"]
+colors["typeScriptBraces"] = colors["Punctuation"]
+colors["typescriptTypeBrackets"] = colors["Punctuation"]
+colors["typescriptInterfaceTypeParameter"] = colors["Punctuation"]
+colors["typescriptConditionalType"] = colors["Punctuation"]
+colors["typeScriptNumber"] = colors["Number"]
+colors["typeScriptAliasDeclaration"] = colors["Type"]
+colors["typeScriptTypeReference"] = colors["Type"]
+colors["typeScriptTypeParameter"] = colors["Type"]
+colors["typescriptClassName"] = colors["Type"]
+colors["typescriptClassHeritage"] = colors["Type"]
+colors["typescriptProp"] = colors["Property"]
+colors["typescriptOperator"] = colors["Operator"]
+colors["typescriptBinaryOp"] = colors["Operator"]
+colors["typescriptDocNotation"] = { fg = t.shade50 }
+colors["typescriptDocTags"] = colors["typescriptDocNotation"]
+--
+
+-- json
+colors["jsonKeyword"] = colors["Property"]
+colors["jsonQuote"] = colors["String"]
+colors["jsonBraces"] = colors["Punctuation"]
+colors["jsonBraces"] = colors["jsonBraces"]
+--
+
+--html
+colors["htmlTagName"] = colors["Tag"]
+colors["htmlSpecialTagName"] = colors["Tag"]
+colors["htmlTag"] = colors["htmlTagName"]
+colors["htmlEndTag"] = colors["htmlTagName"]
+colors["htmlTagN"] = colors["htmlTagName"]
+colors["htmlArg"] = colors["Special"]
+colors["htmlSpecialChar"] = colors["Constant"]
+--
+
+-- xml
+colors["xmlTag"] = colors["Tag"]
+colors["xmlProcessing"] = colors["Tag"]
+colors["xmlProcessingDelim"] = colors["Tag"]
+colors["xmlDoctypeDecl"] = colors["Tag"]
+colors["xmlTagName"] = colors["Tag"]
+colors["xmlDoctype"] = colors["Statement"]
+colors["xmlAttrib"] = colors["Attribute"]
+colors["xmlEqual"] = colors["Punctuation"]
+colors["xmlEntityPunct"] = colors["Punctuation"]
+colors["xmlEntity"] = colors["Constant"]
+colors["xmlCdataStart"] = colors["@label"]
+--
+
+-- css
+colors["cssProp"] = colors["Property"]
+colors["cssBraces"] = colors["Punctuation"]
+colors["cssNoise"] = colors["Punctuation"]
+colors["cssSelectorOp"] = colors["Punctuation"]
+colors["cssSelectorOp2"] = colors["Punctuation"]
+colors["cssAttrComma"] = colors["Punctuation"]
+colors["cssClassNameDot"] = colors["Punctuation"]
+colors["cssFunctionComma"] = colors["Punctuation"]
+colors["cssClassName"] = colors["Special"]
+colors["cssIdentifier"] = colors["Type"]
+colors["cssImportant"] = colors["Statement"]
+colors["cssTagName"] = colors["Tag"]
+colors["cssUrl"] = { colors["String"], gui = "underline" }
+colors["cssUnitDecorators"] = colors["Constant"]
+--
+
+-- rust
+colors["rustModPathSep"] = colors["Punctuation"]
+colors["rustFoldBraces"] = colors["Punctuation"]
+colors["rustBoxPlacementBalance"] = colors["Punctuation"]
+colors["rustSigil"] = colors["Punctuation"]
+colors["rustStorage"] = colors["Statement"]
+--
+
+-- ruby
+colors["rubyConstant"] = colors["Constant"]
+colors["rubyCurlyBlockDelimiter"] = colors["Punctuation"]
+colors["rubyInterpolation"] = colors["Punctuation"]
+colors["rubyInterpolationDelimiter"] = colors["Punctuation"]
+colors["rubyStringDelimiter"] = colors["String"]
+colors["rubyKeywordAsMethod"] = colors["Function"]
+--
+
+-- python
+colors["pythonDecorator"] = colors["@annotation"]
+colors["pythonDecoratorName"] = colors["@annotation"]
+colors["pythonAttribute"] = colors["Property"]
+colors["pythonBuiltin"] = colors["@type.builtin"]
+--
+
+-- yaml
+colors["yamlBlockMappingKey"] = colors["Property"]
+colors["yamlKeyValueDelimiter"] = colors["Punctuation"]
+colors["yamlNodeTag"] = colors["Statement"]
+
+-- flash.nvim
+--https://github.com/folke/flash.nvim?tab=readme-ov-file#-highlights
+colors["FlashBackdrop"] = { fg = t.fg, bg = t.bg }
+colors["FlashMatch"] = { fg = t.selection, bg = t.grey40 }
+colors["FlashCurrent"] = { fg = t.fg, bg = t.bg }
+colors["FlashLabel"] = { fg = t.primary, bg = t.bg }
+colors["FlashPrompt"] = { fg = t.fg, bg = t.bg }
+colors["FlashCursor"] = { fg = t.fg, bg = t.bg }
+-- colors["FlashPromptIcon"] = { fg = t.fg, bg = t.bg }
+
+colorparser.parse(colors)
+
+return colors
diff --git a/stylua.toml b/stylua.toml
new file mode 100644
index 0000000..da39b71
--- /dev/null
+++ b/stylua.toml
@@ -0,0 +1,5 @@
+indent_type = "Spaces"
+indent_width = 2
+column_width = 120
+[sort_requires]
+enabled = false