feat: "day" variant

This commit is contained in:
Folke Lemaitre 2021-04-24 22:24:40 +02:00
parent 002bae49d4
commit 8889ad8848
5 changed files with 388 additions and 76 deletions

View File

@ -1,7 +1,7 @@
# 🏙 Tokyo Night # 🏙 Tokyo Night
A dark Neovim theme written in Lua ported from the Visual Studio Code [TokyoNight](https://github.com/enkia/tokyo-night-vscode-theme) theme. Includes extra themes for Kitty, Alacritty, iTerm and Fish. A dark and light Neovim theme written in Lua ported from the Visual Studio Code [TokyoNight](https://github.com/enkia/tokyo-night-vscode-theme) theme. Includes extra themes for Kitty, Alacritty, iTerm and Fish.
## Storm ## Storm
@ -11,6 +11,8 @@ A dark Neovim theme written in Lua ported from the Visual Studio Code [TokyoNigh
![image](https://user-images.githubusercontent.com/292349/115295327-7afdce80-a10e-11eb-89b3-2591262bf95a.png) ![image](https://user-images.githubusercontent.com/292349/115295327-7afdce80-a10e-11eb-89b3-2591262bf95a.png)
## Day
## ✨ Features ## ✨ Features
+ supports the latest Neovim 5.0 features like TreeSitter and LSP + supports the latest Neovim 5.0 features like TreeSitter and LSP
@ -86,11 +88,11 @@ require('lualine').setup {
## ⚙️ Configuration ## ⚙️ Configuration
The theme comes in two styles, `storm` and a darker variant `night`. The theme comes in three styles, `storm`, a darker variant `night` and `day`.
| Option | Default | Description | | Option | Default | Description |
| ----------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ----------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| tokyonight_style | `"storm"` | The theme comes in two styles, `"storm"` and a darker variant `"night"`. | | tokyonight_style | `"storm"` | The theme comes in three styles, `storm`, a darker variant `night` and `day`. |
| tokyonight_terminal_colors | `true` | Configure the colors used when opening a `:terminal` in Neovim | | tokyonight_terminal_colors | `true` | Configure the colors used when opening a `:terminal` in Neovim |
| tokyonight_italic_comments | `true` | Make comments italic | | tokyonight_italic_comments | `true` | Make comments italic |
| tokyonight_italic_keywords | `true` | Make keywords italic | | tokyonight_italic_keywords | `true` | Make keywords italic |

View File

@ -1,4 +1,6 @@
local colors = require("tokyonight.colors").setup() local config = require("tokyonight.config")
local colors = require("tokyonight.colors").setup(config)
local util = require("tokyonight.util")
local tokyonight = {} local tokyonight = {}
@ -34,4 +36,13 @@ tokyonight.inactive = {
c = { bg = colors.bg_statusline, fg = colors.fg_gutter }, c = { bg = colors.bg_statusline, fg = colors.fg_gutter },
} }
if config.style == "day" then
for _, mode in pairs(tokyonight) do
for _, section in pairs(mode) do
if section.bg then section.bg = util.getColor(section.bg, config) end
if section.fg then section.fg = util.getColor(section.fg, config) end
end
end
end
return tokyonight return tokyonight

View File

@ -11,38 +11,6 @@ function M.setup(config)
---@class ColorScheme ---@class ColorScheme
local colors = {} local colors = {}
if config.style == "day" then
colors = {
none = "NONE",
bg_dark = "#F3F4F6",
bg = "#ffffff",
bg_highlight = "#F9FAFB",
terminal_black = "#414868",
fg = "#4B5563",
fg_dark = "#374151",
fg_gutter = "#D1D5DB",
dark3 = "#545c7e",
comment = "#9CA3AF",
dark5 = "#737aa2",
blue0 = "#90CAF9",
blue = "#3B82F6",
cyan = "#00B0FF",
blue1 = "#10B981",
blue5 = "#80D8FF",
blue6 = "#B4F9F8",
magenta = "#8B5CF6",
purple = "#A78BFA",
orange = "#F57F17",
yellow = "#FBBF24",
green = "#9CCC65",
green1 = "#00BFA5",
teal = "#1abc9c",
red = "#f7768e",
red1 = "#db4b4b",
diff = { change = "#394b70", add = "#164846", delete = "#823c41" },
git = { change = "#6183bb", add = "#449dab", delete = "#914c54" },
}
else
colors = { colors = {
none = "NONE", none = "NONE",
bg_dark = "#1f2335", bg_dark = "#1f2335",
@ -74,8 +42,7 @@ function M.setup(config)
diff = { change = "#394b70", add = "#164846", delete = "#823c41" }, diff = { change = "#394b70", add = "#164846", delete = "#823c41" },
git = { change = "#6183bb", add = "#449dab", delete = "#f7768e" }, git = { change = "#6183bb", add = "#449dab", delete = "#f7768e" },
} }
if config.style == "night" then colors.bg = "#1a1b26" end if config.style == "night" or config.style == "day" then colors.bg = "#1a1b26" end
end
util.bg = colors.bg util.bg = colors.bg
colors.git.ignore = colors.dark3 colors.git.ignore = colors.dark3
@ -101,6 +68,7 @@ function M.setup(config)
colors.hint = colors.teal colors.hint = colors.teal
util.color_overrides(colors, config) util.color_overrides(colors, config)
return colors return colors
end end

291
lua/tokyonight/hsluv.lua Normal file
View File

@ -0,0 +1,291 @@
--[[
Lua implementation of HSLuv and HPLuv color spaces
Homepage: http://www.hsluv.org/
Copyright (C) 2019 Alexei Boronine
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.
]] local hsluv = {}
local hexChars = "0123456789abcdef"
local distance_line_from_origin = function(line)
return math.abs(line.intercept) / math.sqrt((line.slope ^ 2) + 1)
end
local length_of_ray_until_intersect = function(theta, line)
return line.intercept / (math.sin(theta) - line.slope * math.cos(theta))
end
hsluv.get_bounds = function(l)
local result = {};
local sub2;
local sub1 = ((l + 16) ^ 3) / 1560896;
if sub1 > hsluv.epsilon then
sub2 = sub1;
else
sub2 = l / hsluv.kappa;
end
for i = 1, 3 do
local m1 = hsluv.m[i][1];
local m2 = hsluv.m[i][2];
local m3 = hsluv.m[i][3];
for t = 0, 1 do
local top1 = (284517 * m1 - 94839 * m3) * sub2;
local top2 = (838422 * m3 + 769860 * m2 + 731718 * m1) * l * sub2 - 769860 * t * l;
local bottom = (632260 * m3 - 126452 * m2) * sub2 + 126452 * t;
table.insert(result, { slope = top1 / bottom, intercept = top2 / bottom })
end
end
return result
end
hsluv.max_safe_chroma_for_l = function(l)
local bounds = hsluv.get_bounds(l);
local min = 1.7976931348623157e+308;
for i = 1, 6 do
local length = distance_line_from_origin(bounds[i]);
if length >= 0 then min = math.min(min, length); end
end
return min;
end
hsluv.max_safe_chroma_for_lh = function(l, h)
local hrad = h / 360 * math.pi * 2;
local bounds = hsluv.get_bounds(l);
local min = 1.7976931348623157e+308;
for i = 1, 6 do
local bound = bounds[i];
local length = length_of_ray_until_intersect(hrad, bound);
if length >= 0 then min = math.min(min, length); end
end
return min
end
hsluv.dot_product = function(a, b)
local sum = 0;
for i = 1, 3 do sum = sum + a[i] * b[i]; end
return sum
end
hsluv.from_linear = function(c)
if c <= 0.0031308 then
return 12.92 * c
else
return 1.055 * (c ^ 0.416666666666666685) - 0.055
end
end
hsluv.to_linear = function(c)
if c > 0.04045 then
return ((c + 0.055) / 1.055) ^ 2.4
else
return c / 12.92
end
end
hsluv.xyz_to_rgb = function(tuple)
return {
hsluv.from_linear(hsluv.dot_product(hsluv.m[1], tuple)),
hsluv.from_linear(hsluv.dot_product(hsluv.m[2], tuple)),
hsluv.from_linear(hsluv.dot_product(hsluv.m[3], tuple)),
}
end
hsluv.rgb_to_xyz = function(tuple)
local rgbl = { hsluv.to_linear(tuple[1]), hsluv.to_linear(tuple[2]), hsluv.to_linear(tuple[3]) };
return {
hsluv.dot_product(hsluv.minv[1], rgbl),
hsluv.dot_product(hsluv.minv[2], rgbl),
hsluv.dot_product(hsluv.minv[3], rgbl),
}
end
hsluv.y_to_l = function(Y)
if Y <= hsluv.epsilon then
return Y / hsluv.refY * hsluv.kappa
else
return 116 * ((Y / hsluv.refY) ^ 0.333333333333333315) - 16
end
end
hsluv.l_to_y = function(L)
if L <= 8 then
return hsluv.refY * L / hsluv.kappa
else
return hsluv.refY * (((L + 16) / 116) ^ 3)
end
end
hsluv.xyz_to_luv = function(tuple)
local X = tuple[1];
local Y = tuple[2];
local divider = X + 15 * Y + 3 * tuple[3];
local varU = 4 * X;
local varV = 9 * Y;
if divider ~= 0 then
varU = varU / divider;
varV = varV / divider;
else
varU = 0;
varV = 0;
end
local L = hsluv.y_to_l(Y);
if L == 0 then return { 0, 0, 0 } end
return { L, 13 * L * (varU - hsluv.refU), 13 * L * (varV - hsluv.refV) }
end
hsluv.luv_to_xyz = function(tuple)
local L = tuple[1];
local U = tuple[2];
local V = tuple[3];
if L == 0 then return { 0, 0, 0 } end
local varU = U / (13 * L) + hsluv.refU;
local varV = V / (13 * L) + hsluv.refV;
local Y = hsluv.l_to_y(L);
local X = 0 - (9 * Y * varU) / ((((varU - 4) * varV) - varU * varV));
return { X, Y, (9 * Y - 15 * varV * Y - varV * X) / (3 * varV) }
end
hsluv.luv_to_lch = function(tuple)
local L = tuple[1];
local U = tuple[2];
local V = tuple[3];
local C = math.sqrt(U * U + V * V);
local H
if C < 0.00000001 then
H = 0;
else
H = math.atan2(V, U) * 180.0 / 3.1415926535897932;
if H < 0 then H = 360 + H; end
end
return { L, C, H }
end
hsluv.lch_to_luv = function(tuple)
local L = tuple[1];
local C = tuple[2];
local Hrad = tuple[3] / 360.0 * 2 * math.pi;
return { L, math.cos(Hrad) * C, math.sin(Hrad) * C };
end
hsluv.hsluv_to_lch = function(tuple)
local H = tuple[1];
local S = tuple[2];
local L = tuple[3];
if L > 99.9999999 then return { 100, 0, H } end
if L < 0.00000001 then return { 0, 0, H } end
return { L, hsluv.max_safe_chroma_for_lh(L, H) / 100 * S, H }
end
hsluv.lch_to_hsluv = function(tuple)
local L = tuple[1];
local C = tuple[2];
local H = tuple[3];
local max_chroma = hsluv.max_safe_chroma_for_lh(L, H)
if L > 99.9999999 then return { H, 0, 100 } end
if L < 0.00000001 then return { H, 0, 0 } end
return { H, C / max_chroma * 100, L }
end
hsluv.hpluv_to_lch = function(tuple)
local H = tuple[1];
local S = tuple[2];
local L = tuple[3];
if L > 99.9999999 then return { 100, 0, H } end
if L < 0.00000001 then return { 0, 0, H } end
return { L, hsluv.max_safe_chroma_for_l(L) / 100 * S, H }
end
hsluv.lch_to_hpluv = function(tuple)
local L = tuple[1];
local C = tuple[2];
local H = tuple[3];
if L > 99.9999999 then return { H, 0, 100 } end
if L < 0.00000001 then return { H, 0, 0 } end
return { H, C / hsluv.max_safe_chroma_for_l(L) * 100, L }
end
hsluv.rgb_to_hex = function(tuple)
local h = "#";
for i = 1, 3 do
local c = math.floor(tuple[i] * 255 + 0.5);
local digit2 = math.fmod(c, 16);
local x = (c - digit2) / 16;
local digit1 = math.floor(x);
h = h .. string.sub(hexChars, digit1 + 1, digit1 + 1)
h = h .. string.sub(hexChars, digit2 + 1, digit2 + 1)
end
return h
end
hsluv.hex_to_rgb = function(hex)
hex = string.lower(hex)
local ret = {}
for i = 0, 2 do
local char1 = string.sub(hex, i * 2 + 2, i * 2 + 2);
local char2 = string.sub(hex, i * 2 + 3, i * 2 + 3);
local digit1 = string.find(hexChars, char1) - 1
local digit2 = string.find(hexChars, char2) - 1
ret[i + 1] = (digit1 * 16 + digit2) / 255.0;
end
return ret
end
hsluv.lch_to_rgb = function(tuple) return
hsluv.xyz_to_rgb(hsluv.luv_to_xyz(hsluv.lch_to_luv(tuple))) end
hsluv.rgb_to_lch = function(tuple) return
hsluv.luv_to_lch(hsluv.xyz_to_luv(hsluv.rgb_to_xyz(tuple))) end
hsluv.hsluv_to_rgb = function(tuple) return hsluv.lch_to_rgb(hsluv.hsluv_to_lch(tuple)) end
hsluv.rgb_to_hsluv = function(tuple) return hsluv.lch_to_hsluv(hsluv.rgb_to_lch(tuple)) end
hsluv.hpluv_to_rgb = function(tuple) return hsluv.lch_to_rgb(hsluv.hpluv_to_lch(tuple)) end
hsluv.rgb_to_hpluv = function(tuple) return hsluv.lch_to_hpluv(hsluv.rgb_to_lch(tuple)) end
hsluv.hsluv_to_hex = function(tuple) return hsluv.rgb_to_hex(hsluv.hsluv_to_rgb(tuple)) end
hsluv.hpluv_to_hex = function(tuple) return hsluv.rgb_to_hex(hsluv.hpluv_to_rgb(tuple)) end
hsluv.hex_to_hsluv = function(s) return hsluv.rgb_to_hsluv(hsluv.hex_to_rgb(s)) end
hsluv.hex_to_hpluv = function(s) return hsluv.rgb_to_hpluv(hsluv.hex_to_rgb(s)) end
hsluv.m = {
{ 3.240969941904521, -1.537383177570093, -0.498610760293 },
{ -0.96924363628087, 1.87596750150772, 0.041555057407175 },
{ 0.055630079696993, -0.20397695888897, 1.056971514242878 },
}
hsluv.minv = {
{ 0.41239079926595, 0.35758433938387, 0.18048078840183 },
{ 0.21263900587151, 0.71516867876775, 0.072192315360733 },
{ 0.019330818715591, 0.11919477979462, 0.95053215224966 },
}
hsluv.refY = 1.0
hsluv.refU = 0.19783000664283
hsluv.refV = 0.46831999493879
hsluv.kappa = 903.2962962
hsluv.epsilon = 0.0088564516
return hsluv

View File

@ -1,6 +1,7 @@
local util = {} local util = {}
util.colorsUsed = {} util.colorsUsed = {}
util.colorCache = {}
util.bg = "#000000" util.bg = "#000000"
util.fg = "#ffffff" util.fg = "#ffffff"
@ -34,15 +35,32 @@ end
function util.darken(hex, amount, bg) return util.blend(hex, bg or util.bg, math.abs(amount)) end function util.darken(hex, amount, bg) return util.blend(hex, bg or util.bg, math.abs(amount)) end
function util.lighten(hex, amount, fg) return util.blend(hex, fg or util.fg, math.abs(amount)) end function util.lighten(hex, amount, fg) return util.blend(hex, fg or util.fg, math.abs(amount)) end
function util.highlight(group, color) function util.getDayColor(color)
local hsluv = require("tokyonight.hsluv")
if color ~= "NONE" then
local hsl = hsluv.hex_to_hsluv(color)
hsl[3] = 100 - hsl[3]
hsl[3] = hsl[3] + (100 - hsl[3]) * .1
return hsluv.hsluv_to_hex(hsl)
end
return color
end
function util.getColor(color, config)
if config.style ~= "day" then return color end
if not util.colorCache[color] then util.colorCache[color] = util.getDayColor(color) end
return util.colorCache[color]
end
function util.highlight(group, color, opts)
if color.fg then util.colorsUsed[color.fg] = true end if color.fg then util.colorsUsed[color.fg] = true end
if color.bg then util.colorsUsed[color.bg] = true end if color.bg then util.colorsUsed[color.bg] = true end
if color.sp then util.colorsUsed[color.sp] = true end if color.sp then util.colorsUsed[color.sp] = true end
local style = color.style and "gui=" .. color.style or "gui=NONE" local style = color.style and "gui=" .. color.style or "gui=NONE"
local fg = color.fg and "guifg=" .. color.fg or "guifg=NONE" local fg = color.fg and "guifg=" .. util.getColor(color.fg, opts) or "guifg=NONE"
local bg = color.bg and "guibg=" .. color.bg or "guibg=NONE" local bg = color.bg and "guibg=" .. util.getColor(color.bg, opts) or "guibg=NONE"
local sp = color.sp and "guisp=" .. color.sp or "" local sp = color.sp and "guisp=" .. util.getColor(color.sp, opts) or ""
local hl = "highlight " .. group .. " " .. style .. " " .. fg .. " " .. bg .. " " .. sp local hl = "highlight " .. group .. " " .. style .. " " .. fg .. " " .. bg .. " " .. sp
@ -99,7 +117,9 @@ function util.template(str, table)
return (str:gsub("($%b{})", function(w) return table[w:sub(3, -2)] or w end)) return (str:gsub("($%b{})", function(w) return table[w:sub(3, -2)] or w end))
end end
function util.syntax(syntax) for group, colors in pairs(syntax) do util.highlight(group, colors) end end function util.syntax(syntax, opts)
for group, colors in pairs(syntax) do util.highlight(group, colors, opts) end
end
---@param colors ColorScheme ---@param colors ColorScheme
function util.terminal(colors) function util.terminal(colors)
@ -140,13 +160,13 @@ function util.load(theme)
vim.g.colors_name = "tokyonight" vim.g.colors_name = "tokyonight"
-- load base theme -- load base theme
util.syntax(theme.base) util.syntax(theme.base, theme.config)
-- load syntax for plugins and terminal async -- load syntax for plugins and terminal async
local async local async
async = vim.loop.new_async(vim.schedule_wrap(function() async = vim.loop.new_async(vim.schedule_wrap(function()
util.terminal(theme.colors) util.terminal(theme.colors)
util.syntax(theme.plugins) util.syntax(theme.plugins, theme.config)
util.autocmds(theme.config) util.autocmds(theme.config)
async:close() async:close()
end)) end))
@ -172,5 +192,25 @@ function util.color_overrides(colors, config)
end end
end end
function util.light()
for hl_name, hl in pairs(vim.api.nvim__get_hl_defs(0)) do
local def = {}
for key, def_key in pairs({ foreground = "fg", background = "bg", special = "sp" }) do
if type(hl[key]) == "number" then
local hex = string.format("#%06x", hl[key])
local color = util.getDayColor(hex)
table.insert(def, "gui" .. def_key .. "=" .. color)
end
end
if hl_name ~= "" and #def > 0 then
for _, style in pairs({ "bold", "italic", "underline", "undercurl" }) do
if hl[style] then table.insert(def, "gui=" .. style) end
end
vim.cmd("highlight! " .. hl_name .. " " .. table.concat(def, " "))
end
end
end
return util return util