194 lines
6.3 KiB
Lua
194 lines
6.3 KiB
Lua
---@diagnostic disable: inject-field
|
|
|
|
-- Copy global highlights and overrides highlights to the custom namespace, only external buffers use global namespace
|
|
|
|
local api = vim.api
|
|
local vscode = require("vscode.api")
|
|
|
|
local NS = api.nvim_create_namespace("vscode.highlight")
|
|
|
|
vim.opt.conceallevel = 0
|
|
vim.g.html_ignore_conceal = 1
|
|
vim.g.vim_json_conceal = 0
|
|
vim.g.markdown_recommended_style = 0
|
|
vim.g.markdown_folding = 0
|
|
|
|
---Link highlights with same values to the same highlight, to avoid performance
|
|
---and rendering issues with vscode decorations caused by a large number of
|
|
---highlight IDs due to highlight merging.
|
|
---Currently, only handle highlights that need to be cleared
|
|
api.nvim_set_hl(0, "VSCodeNone", {})
|
|
|
|
---@param id number
|
|
---@param name string
|
|
---@param value table
|
|
local function set_hl(id, name, value)
|
|
if vim.tbl_isempty(value) then
|
|
return api.nvim_set_hl(id, name, { link = "VSCodeNone" })
|
|
end
|
|
return api.nvim_set_hl(id, name, value)
|
|
end
|
|
|
|
local function setup_globals()
|
|
local custom_hls = vscode.get_config("vscode-neovim.highlightGroups.highlights")
|
|
if type(custom_hls) ~= "table" then
|
|
custom_hls = {}
|
|
end
|
|
for hl in pairs(custom_hls) do
|
|
-- If we directly clear the highlighting, it may cause the highlighting to
|
|
-- become "unavailable". For example, nvim_buf_set_extmark will ignore the
|
|
-- highlighting that has no visual effect on the screen.
|
|
-- So we use this special and useless attribute to allow highlighting to
|
|
-- trigger rendering normally.
|
|
-- In vscode, we will remove this attribute so that we can use the empty
|
|
-- attribute to determine whether to use custom highlighting. This allows
|
|
-- other highlights to be rendered correctly when mixed with custom
|
|
-- highlighting.
|
|
set_hl(0, hl, { altfont = true })
|
|
end
|
|
|
|
-- stylua: ignore start
|
|
local hls = {
|
|
Normal = {},
|
|
NormalNC = {},
|
|
NormalFloat = {},
|
|
Visual = {},
|
|
VisualNC = {},
|
|
VisualNOS = {},
|
|
Substitute = {},
|
|
Whitespace = {},
|
|
LineNr = {},
|
|
LineNrAbove = {},
|
|
LineNrBelow = {},
|
|
CursorLine = {},
|
|
CursorLineNr = {},
|
|
ColorColumn = {},
|
|
FoldColumn = {},
|
|
Folded = {},
|
|
Sign = {},
|
|
SignColumn = {},
|
|
MsgSeparator = {},
|
|
MsgArea = {},
|
|
Question = {},
|
|
QuickFixLine = {},
|
|
EndOfBuffer = {},
|
|
Debug = {},
|
|
MatchParen = {},
|
|
CursorColumn = {},
|
|
NonText = {},
|
|
-- make cursor visible for plugins that use fake cursor
|
|
Cursor = { reverse = true },
|
|
}
|
|
-- stylua: ignore end
|
|
for name, attrs in pairs(hls) do
|
|
if not custom_hls[name] then
|
|
set_hl(0, name, attrs)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- stylua: ignore start
|
|
local overrides = {
|
|
Delimiter = {}, Identifier = {}, SpecialChar = {}, Number = {}, Type = {},
|
|
String = {}, Error = {}, Comment = {}, Constant = {}, Special = {},
|
|
Statement = {}, PreProc = {}, Underlined = {}, Ignore = {}, Todo = {},
|
|
Character = {}, Boolean = {}, Float = {}, Function = {}, Conditional = {},
|
|
Repeat = {}, Label = {}, Keyword = {}, Exception = {}, Include = {},
|
|
Define = {}, Macro = {}, PreCondit = {}, StorageClass = {}, Structure = {},
|
|
Typedef = {}, Tag = {}, SpecialComment = {}, Operator = {}, Debug = {},
|
|
}
|
|
-- stylua: ignore end
|
|
local overridden = {}
|
|
local function setup_syntax_overrides()
|
|
for name, attrs in pairs(overrides) do
|
|
if not overridden[name] then
|
|
overridden[name] = true
|
|
set_hl(NS, name, attrs)
|
|
end
|
|
end
|
|
end
|
|
|
|
local cleared_syntax_groups = {}
|
|
local function setup_syntax_groups()
|
|
local output = api.nvim_exec2("syntax", { output = true })
|
|
local items = vim.split(output.output, "\n")
|
|
for _, item in ipairs(items) do
|
|
local group = item:match([[([%w@_%.]+)%s+xxx]])
|
|
if group and not cleared_syntax_groups[group] then
|
|
cleared_syntax_groups[group] = true
|
|
set_hl(NS, group, {})
|
|
end
|
|
end
|
|
end
|
|
|
|
local function setup_win_hl_ns()
|
|
local ok, curr_ns, target_ns, vscode_controlled
|
|
for _, win in ipairs(api.nvim_list_wins()) do
|
|
local buf = api.nvim_win_get_buf(win)
|
|
|
|
ok, curr_ns = pcall(api.nvim_win_get_var, win, "_vscode_hl_ns")
|
|
curr_ns = ok and curr_ns or 0
|
|
|
|
ok, vscode_controlled = pcall(api.nvim_buf_get_var, buf, "vscode_controlled")
|
|
target_ns = (ok and vscode_controlled) and NS or 0
|
|
|
|
if curr_ns ~= target_ns then
|
|
api.nvim_win_set_var(win, "_vscode_hl_ns", target_ns)
|
|
api.nvim_win_set_hl_ns(win, target_ns)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function disable_treesitter_highlights()
|
|
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
|
|
pcall(function()
|
|
-- Hack to disable treesitter highlighting by monkey patching
|
|
-- `for_each_highlight_state()`. Could use `vim.treesitter.stop()`, but
|
|
-- this seems to have unintended side-effects as per
|
|
-- https://github.com/vscode-neovim/vscode-neovim/issues/2355
|
|
local highlighter = vim.treesitter.highlighter.active[buf]
|
|
---@diagnostic disable-next-line: duplicate-set-field
|
|
function highlighter:for_each_highlight_state() end
|
|
end)
|
|
end
|
|
end
|
|
|
|
local function setup()
|
|
local group = api.nvim_create_augroup("vscode.highlight", { clear = true })
|
|
-- WinScrolled is perhaps not strictly necessary (or shouldn't be), but is useful in ensuring
|
|
-- we don't get syntax highlights in peek windows.
|
|
api.nvim_create_autocmd({ "WinNew", "WinEnter", "WinScrolled", "BufNew", "BufEnter", "BufWinEnter" }, {
|
|
group = group,
|
|
callback = function()
|
|
setup_win_hl_ns()
|
|
disable_treesitter_highlights()
|
|
end,
|
|
})
|
|
api.nvim_create_autocmd({ "ColorScheme", "Syntax", "FileType" }, {
|
|
group = group,
|
|
callback = function(ev)
|
|
api.nvim_set_hl(0, "VSCodeNone", {})
|
|
if ev.event == "ColorScheme" then
|
|
setup_globals()
|
|
-- highlights of custom namespace
|
|
setup_syntax_overrides()
|
|
end
|
|
setup_syntax_groups()
|
|
-- wait syntax things done
|
|
vim.defer_fn(setup_syntax_groups, 200)
|
|
end,
|
|
})
|
|
api.nvim_create_autocmd({ "VimEnter", "UIEnter" }, {
|
|
group = group,
|
|
callback = function()
|
|
disable_treesitter_highlights()
|
|
setup_globals()
|
|
setup_syntax_groups()
|
|
setup_syntax_overrides()
|
|
setup_win_hl_ns()
|
|
end,
|
|
})
|
|
end
|
|
|
|
return { setup = setup }
|