1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-04 05:50:06 +08:00
SpaceVim/bundle/neo-tree.nvim/lua/neo-tree/ui/highlights.lua
2023-05-30 21:09:18 +08:00

272 lines
10 KiB
Lua

local log = require("neo-tree.log")
local utils = require("neo-tree.utils")
local vim = vim
local M = {}
---@type integer
M.ns_id = vim.api.nvim_create_namespace("neo-tree.nvim")
M.BUFFER_NUMBER = "NeoTreeBufferNumber"
M.CURSOR_LINE = "NeoTreeCursorLine"
M.DIM_TEXT = "NeoTreeDimText"
M.DIRECTORY_ICON = "NeoTreeDirectoryIcon"
M.DIRECTORY_NAME = "NeoTreeDirectoryName"
M.DOTFILE = "NeoTreeDotfile"
M.FADE_TEXT_1 = "NeoTreeFadeText1"
M.FADE_TEXT_2 = "NeoTreeFadeText2"
M.FILE_ICON = "NeoTreeFileIcon"
M.FILE_NAME = "NeoTreeFileName"
M.FILE_NAME_OPENED = "NeoTreeFileNameOpened"
M.FILTER_TERM = "NeoTreeFilterTerm"
M.FLOAT_BORDER = "NeoTreeFloatBorder"
M.FLOAT_NORMAL = "NeoTreeFloatNormal"
M.FLOAT_TITLE = "NeoTreeFloatTitle"
M.GIT_ADDED = "NeoTreeGitAdded"
M.GIT_CONFLICT = "NeoTreeGitConflict"
M.GIT_DELETED = "NeoTreeGitDeleted"
M.GIT_IGNORED = "NeoTreeGitIgnored"
M.GIT_MODIFIED = "NeoTreeGitModified"
M.GIT_RENAMED = "NeoTreeGitRenamed"
M.GIT_STAGED = "NeoTreeGitStaged"
M.GIT_UNTRACKED = "NeoTreeGitUntracked"
M.GIT_UNSTAGED = "NeoTreeGitUnstaged"
M.HIDDEN_BY_NAME = "NeoTreeHiddenByName"
M.INDENT_MARKER = "NeoTreeIndentMarker"
M.MESSAGE = "NeoTreeMessage"
M.MODIFIED = "NeoTreeModified"
M.NORMAL = "NeoTreeNormal"
M.NORMALNC = "NeoTreeNormalNC"
M.SIGNCOLUMN = "NeoTreeSignColumn"
M.STATUS_LINE = "NeoTreeStatusLine"
M.STATUS_LINE_NC = "NeoTreeStatusLineNC"
M.TAB_ACTIVE = "NeoTreeTabActive"
M.TAB_INACTIVE = "NeoTreeTabInactive"
M.TAB_SEPARATOR_ACTIVE = "NeoTreeTabSeparatorActive"
M.TAB_SEPARATOR_INACTIVE = "NeoTreeTabSeparatorInactive"
M.VERTSPLIT = "NeoTreeVertSplit"
M.WINSEPARATOR = "NeoTreeWinSeparator"
M.END_OF_BUFFER = "NeoTreeEndOfBuffer"
M.ROOT_NAME = "NeoTreeRootName"
M.SYMBOLIC_LINK_TARGET = "NeoTreeSymbolicLinkTarget"
M.TITLE_BAR = "NeoTreeTitleBar"
M.INDENT_MARKER = "NeoTreeIndentMarker"
M.EXPANDER = "NeoTreeExpander"
M.WINDOWS_HIDDEN = "NeoTreeWindowsHidden"
M.PREVIEW = "NeoTreePreview"
local function dec_to_hex(n, chars)
chars = chars or 6
local hex = string.format("%0" .. chars .. "x", n)
while #hex < chars do
hex = "0" .. hex
end
return hex
end
---If the given highlight group is not defined, define it.
---@param hl_group_name string The name of the highlight group.
---@param link_to_if_exists table A list of highlight groups to link to, in
--order of priority. The first one that exists will be used.
---@param background string|nil The background color to use, in hex, if the highlight group
--is not defined and it is not linked to another group.
---@param foreground string|nil The foreground color to use, in hex, if the highlight group
--is not defined and it is not linked to another group.
---@gui string|nil The gui to use, if the highlight group is not defined and it is not linked
--to another group.
---@return table table The highlight group values.
M.create_highlight_group = function(hl_group_name, link_to_if_exists, background, foreground, gui)
local success, hl_group = pcall(vim.api.nvim_get_hl_by_name, hl_group_name, true)
if not success or not hl_group.foreground or not hl_group.background then
for _, link_to in ipairs(link_to_if_exists) do
success, hl_group = pcall(vim.api.nvim_get_hl_by_name, link_to, true)
if success then
local new_group_has_settings = background or foreground or gui
local link_to_has_settings = hl_group.foreground or hl_group.background
if link_to_has_settings or not new_group_has_settings then
vim.cmd("highlight default link " .. hl_group_name .. " " .. link_to)
return hl_group
end
end
end
if type(background) == "number" then
background = dec_to_hex(background)
end
if type(foreground) == "number" then
foreground = dec_to_hex(foreground)
end
local cmd = "highlight default " .. hl_group_name
if background then
cmd = cmd .. " guibg=#" .. background
end
if foreground then
cmd = cmd .. " guifg=#" .. foreground
else
cmd = cmd .. " guifg=NONE"
end
if gui then
cmd = cmd .. " gui=" .. gui
end
vim.cmd(cmd)
return {
background = background and tonumber(background, 16) or nil,
foreground = foreground and tonumber(foreground, 16) or nil,
}
end
return hl_group
end
local faded_highlight_group_cache = {}
M.get_faded_highlight_group = function(hl_group_name, fade_percentage)
if type(hl_group_name) ~= "string" then
error("hl_group_name must be a string")
end
if type(fade_percentage) ~= "number" then
error("hl_group_name must be a number")
end
if fade_percentage < 0 or fade_percentage > 1 then
error("fade_percentage must be between 0 and 1")
end
local key = hl_group_name .. "_" .. tostring(math.floor(fade_percentage * 100))
if faded_highlight_group_cache[key] then
return faded_highlight_group_cache[key]
end
local normal = vim.api.nvim_get_hl_by_name("Normal", true)
if type(normal.foreground) ~= "number" then
if vim.api.nvim_get_option("background") == "dark" then
normal.foreground = 0xffffff
else
normal.foreground = 0x000000
end
end
if type(normal.background) ~= "number" then
if vim.api.nvim_get_option("background") == "dark" then
normal.background = 0x000000
else
normal.background = 0xffffff
end
end
local foreground = dec_to_hex(normal.foreground)
local background = dec_to_hex(normal.background)
local hl_group = vim.api.nvim_get_hl_by_name(hl_group_name, true)
if type(hl_group.foreground) == "number" then
foreground = dec_to_hex(hl_group.foreground)
end
if type(hl_group.background) == "number" then
background = dec_to_hex(hl_group.background)
end
local gui = {}
if hl_group.bold then
table.insert(gui, "bold")
end
if hl_group.italic then
table.insert(gui, "italic")
end
if hl_group.underline then
table.insert(gui, "underline")
end
if hl_group.undercurl then
table.insert(gui, "undercurl")
end
if #gui > 0 then
gui = table.concat(gui, ",")
else
gui = nil
end
local f_red = tonumber(foreground:sub(1, 2), 16)
local f_green = tonumber(foreground:sub(3, 4), 16)
local f_blue = tonumber(foreground:sub(5, 6), 16)
local b_red = tonumber(background:sub(1, 2), 16)
local b_green = tonumber(background:sub(3, 4), 16)
local b_blue = tonumber(background:sub(5, 6), 16)
local red = (f_red * fade_percentage) + (b_red * (1 - fade_percentage))
local green = (f_green * fade_percentage) + (b_green * (1 - fade_percentage))
local blue = (f_blue * fade_percentage) + (b_blue * (1 - fade_percentage))
local new_foreground =
string.format("%s%s%s", dec_to_hex(red, 2), dec_to_hex(green, 2), dec_to_hex(blue, 2))
M.create_highlight_group(key, {}, hl_group.background, new_foreground, gui)
faded_highlight_group_cache[key] = key
return key
end
M.setup = function()
-- Reset this here in case of color scheme change
faded_highlight_group_cache = {}
local normal_hl = M.create_highlight_group(M.NORMAL, { "Normal" })
local normalnc_hl = M.create_highlight_group(M.NORMALNC, { "NormalNC", M.NORMAL })
M.create_highlight_group(M.SIGNCOLUMN, { "SignColumn", M.NORMAL })
M.create_highlight_group(M.STATUS_LINE, { "StatusLine" })
M.create_highlight_group(M.STATUS_LINE_NC, { "StatusLineNC" })
M.create_highlight_group(M.VERTSPLIT, { "VertSplit" })
M.create_highlight_group(M.WINSEPARATOR, { "WinSeparator" })
M.create_highlight_group(M.END_OF_BUFFER, { "EndOfBuffer" })
local float_border_hl =
M.create_highlight_group(M.FLOAT_BORDER, { "FloatBorder" }, normalnc_hl.background, "444444")
M.create_highlight_group(M.FLOAT_NORMAL, { "NormalFloat", M.NORMAL })
M.create_highlight_group(M.FLOAT_TITLE, {}, float_border_hl.background, normal_hl.foreground)
local title_fg = normal_hl.background
if title_fg == float_border_hl.foreground then
title_fg = normal_hl.foreground
end
M.create_highlight_group(M.TITLE_BAR, {}, float_border_hl.foreground, title_fg)
M.create_highlight_group(M.BUFFER_NUMBER, { "SpecialChar" })
M.create_highlight_group(M.DIM_TEXT, {}, nil, "505050")
M.create_highlight_group(M.MESSAGE, {}, nil, "505050", "italic")
M.create_highlight_group(M.FADE_TEXT_1, {}, nil, "626262")
M.create_highlight_group(M.FADE_TEXT_2, {}, nil, "444444")
M.create_highlight_group(M.DOTFILE, {}, nil, "626262")
M.create_highlight_group(M.HIDDEN_BY_NAME, { M.DOTFILE }, nil, nil)
M.create_highlight_group(M.CURSOR_LINE, { "CursorLine" }, nil, nil, "bold")
M.create_highlight_group(M.DIRECTORY_NAME, { "Directory" }, "NONE", "NONE")
M.create_highlight_group(M.DIRECTORY_ICON, { "Directory" }, nil, "73cef4")
M.create_highlight_group(M.FILE_ICON, { M.DIRECTORY_ICON })
M.create_highlight_group(M.FILE_NAME, {}, "NONE", "NONE")
M.create_highlight_group(M.FILE_NAME_OPENED, {}, nil, nil, "bold")
M.create_highlight_group(M.SYMBOLIC_LINK_TARGET, { M.FILE_NAME })
M.create_highlight_group(M.FILTER_TERM, { "SpecialChar", "Normal" })
M.create_highlight_group(M.ROOT_NAME, {}, nil, nil, "bold,italic")
M.create_highlight_group(M.INDENT_MARKER, { M.DIM_TEXT })
M.create_highlight_group(M.EXPANDER, { M.DIM_TEXT })
M.create_highlight_group(M.MODIFIED, {}, nil, "d7d787")
M.create_highlight_group(M.WINDOWS_HIDDEN, { M.DOTFILE }, nil, nil)
M.create_highlight_group(M.PREVIEW, { "Search" }, nil, nil)
M.create_highlight_group(M.GIT_ADDED, { "GitGutterAdd", "GitSignsAdd" }, nil, "5faf5f")
M.create_highlight_group(M.GIT_DELETED, { "GitGutterDelete", "GitSignsDelete" }, nil, "ff5900")
M.create_highlight_group(M.GIT_MODIFIED, { "GitGutterChange", "GitSignsChange" }, nil, "d7af5f")
local conflict = M.create_highlight_group(M.GIT_CONFLICT, {}, nil, "ff8700", "italic,bold")
M.create_highlight_group(M.GIT_IGNORED, { M.DOTFILE }, nil, nil)
M.create_highlight_group(M.GIT_RENAMED, { M.GIT_MODIFIED }, nil, nil)
M.create_highlight_group(M.GIT_STAGED, { M.GIT_ADDED }, nil, nil)
M.create_highlight_group(M.GIT_UNSTAGED, { M.GIT_CONFLICT }, nil, nil)
M.create_highlight_group(M.GIT_UNTRACKED, {}, nil, conflict.foreground, "italic")
M.create_highlight_group(M.TAB_ACTIVE, {}, nil, nil, "bold")
M.create_highlight_group(M.TAB_INACTIVE, {}, "141414", "777777")
M.create_highlight_group(M.TAB_SEPARATOR_ACTIVE, {}, nil, "0a0a0a")
M.create_highlight_group(M.TAB_SEPARATOR_INACTIVE, {}, "141414", "101010")
end
return M