Skip to content

Commit

Permalink
feat(highlights)!: redesign of highlighting approach (#1449)
Browse files Browse the repository at this point in the history
* feat(highlights)!: redesign of highlighting approach

* fix: fix string width calculation and index error

* feat: Improve the inline behavior of tabs

* chore: remove outdated and unused code

* fix: null check

* chore(lint): turn off explicit function return type :(

* fix: fix extmark test

* chore: update highliting config schema

* feat: handle emojis

* fix: fix calculation of valid cell count

chore: improve readability

* chore: rename cur to curr

* fix: disable eol virt text for now

* fix: fix rendering of multi-byte characters

* fix: fix potential undefined virt text

chore: improved readability of types

* fix: leave some space for the fake cursor.

* fix: fix calculation of valid cells

* perf: create class CellIter

* perf: check length of cells

* chore: clear `CursorLine`, use `NonText` for statuscolumn

* feat(highlight): rework 'syntax' (#1)

* feat(highlight): rework 'syntax'

* chore: enable syntax by default

* fix: fix debouncing

avoid unnecessary refreshing

* fix: improve setting namespace of windows

* fix: should set w:_vscode_hl_ns

* fix!: fix highlight refresh

* refactor!: only clear overrides  and syntax highlights

plugins should not link to builtin groups

* chore: setup highlight before VimEnter

* chore: tweak comments
  • Loading branch information
xiyaowong committed Oct 5, 2023
1 parent e76c00f commit f688d23
Show file tree
Hide file tree
Showing 13 changed files with 474 additions and 276 deletions.
9 changes: 1 addition & 8 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,7 @@ module.exports = {
argsIgnorePattern: "^_",
},
],
"@typescript-eslint/explicit-function-return-type": [
"warn",
{
allowExpressions: true,
allowTypedFunctionExpressions: true,
allowHigherOrderFunctions: true,
},
],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-non-null-assertion": "off",
},
overrides: [
Expand Down
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 24 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,29 @@
"title": "Highlight Groups Configuration",
"description": "Define colors for various VIM highlight groups. Values may be 'vim' to use colors from vim or text decoration properties object",
"additionalProperties": {
"oneOf": [
{
"type": "object"
"type": "object",
"properties": {
"backgroundColor": {
"type": "string",
"description": "CSS styling property that will be applied to the decoration attachment"
},
"color": {
"type": "string",
"description": "CSS styling property that will be applied to the decoration attachment"
},
"border": {
"type": "string",
"description": "CSS styling property that will be applied to the decoration attachment"
},
{
"borderColor": {
"type": "string",
"const": "vim"
"description": "CSS styling property that will be applied to the decoration attachment"
},
"textDecoration": {
"type": "string",
"description": "CSS styling property that will be applied to the decoration attachment"
}
]
}
},
"default": {
"IncSearch": {
Expand Down Expand Up @@ -1295,10 +1309,11 @@
"webpack-cli": "^5.1.4"
},
"dependencies": {
"fast-diff": "^1.3.0",
"async-mutex": "^0.4.0",
"fast-diff": "^1.3.0",
"grapheme-splitter": "^1.0.4",
"lodash-es": "^4.17.21",
"ts-wcwidth": "^2.0.3",
"neovim": "^4.9.0"
"neovim": "^4.9.0",
"ts-wcwidth": "^2.0.3"
}
}
2 changes: 2 additions & 0 deletions runtime/lua/vscode-neovim.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ local api = require("vscode-neovim.api")
local defaults = require("vscode-neovim.defaults")
local cursor = require("vscode-neovim.cursor")

require("vscode-neovim.highlight")

local M = {}

M.notify = api.notify
Expand Down
4 changes: 1 addition & 3 deletions runtime/lua/vscode-neovim/cursor.lua
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,12 @@ function M.highlight_fake_cursor()
local line = vim.fn.line(".")
local col = vim.fn.col(".")
local ch = util.get_char_at(line, col) or " "
-- !nvim won't send tab, so we use ❥ instead
ch = ch == "\t" and "" or ch
M.fake_cursor = vim.api.nvim_buf_set_extmark(
0,
M.fake_ns,
line - 1,
col - 1,
{ virt_text = { { ch, "Cursor" } }, virt_text_pos = "overlay", hl_mode = "combine", priority = 65534 }
{ virt_text = { { ch, "Cursor" } }, virt_text_pos = "overlay", hl_mode = "replace", priority = 65534 }
)
end
end
Expand Down
24 changes: 1 addition & 23 deletions runtime/lua/vscode-neovim/defaults.lua
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
-- this module is responsible for setting default vim options and hiding undesired syntax groups
-- this module is responsible for setting default vim options
local M = {}

-- ignore syntax groups by default but can be overridden by `vscode-neovim.highlightGroups.highlights` or init.vim config (inside ColorScheme au)
function M.default_highlights()
vim.api.nvim_set_hl(0, "Normal", {})
vim.api.nvim_set_hl(0, "NormalNC", {})
vim.api.nvim_set_hl(0, "NormalFloat", {})
vim.api.nvim_set_hl(0, "NonText", {})
vim.api.nvim_set_hl(0, "Visual", {})
vim.api.nvim_set_hl(0, "VisualNOS", {})
vim.api.nvim_set_hl(0, "Substitute", {})
vim.api.nvim_set_hl(0, "Whitespace", {})
vim.api.nvim_set_hl(0, "LineNr", {})
vim.api.nvim_set_hl(0, "LineNrAbove", {})
vim.api.nvim_set_hl(0, "LineNrBelow", {})
vim.api.nvim_set_hl(0, "CursorLineNr", {})

-- make cursor visible for plugins that use fake cursor
vim.api.nvim_set_hl(0, "Cursor", { reverse = true })
end

function M.setup()
-- customise statusbar
vim.opt.shortmess = "filnxtToOFI"
Expand All @@ -33,9 +14,6 @@ function M.setup()

-- disable matchparen because we don't need it
vim.g.loaded_matchparen = 1

M.default_highlights()
vim.api.nvim_create_autocmd({ "FileType", "ColorScheme" }, { callback = M.default_highlights })
end

return M
12 changes: 3 additions & 9 deletions runtime/lua/vscode-neovim/force-options.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ vim.opt.colorcolumn = nil
vim.opt.modeline = false
vim.opt.modelines = 0

--- Allow to use vim HL for external buffers, vscode buffers explicitly disable it
vim.cmd([[syntax on]])
vim.cmd.syntax("on")

-- --------------------- forced global and local critical options -------------------- --
local function forceoptions(opt)
Expand All @@ -39,14 +38,9 @@ local function forceoptions(opt)
-- Fix the gutter width, no need to consider highlighting issues caused by number, signcolumn, foldcolumn anymore.
-- {{
opt.numberwidth = 1
opt.statuscolumn = ("-"):rep(20) -- max-signcolumn(9) + max-foldcolumn(9) + numberwidth(1) + 1
opt.statuscolumn = "%#NonText#" .. ("-"):rep(20) -- max-signcolumn(9) + max-foldcolumn(9) + numberwidth(1) + 1
-- }}
--- Need to know tabs for HL
opt.listchars = { tab = "❥♥" }
-- disable syntax hl for vscode buffers
if vim.b.vscode_controlled and opt == vim.opt_local then
opt.syntax = "off"
end
opt.listchars = { tab = " " }
--- Turn off auto-folding
opt.foldenable = false
opt.foldcolumn = "0"
Expand Down
105 changes: 105 additions & 0 deletions runtime/lua/vscode-neovim/highlight.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---@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 NS = api.nvim_create_namespace("-- vscode buffer highlights --")

vim.opt.conceallevel = 0
vim.g.html_ignore_conceal = 1
vim.g.vim_json_conceal = 0

local function setup_globals()
api.nvim_set_hl(0, "Normal", {})
api.nvim_set_hl(0, "NormalNC", {})
api.nvim_set_hl(0, "NormalFloat", {})
api.nvim_set_hl(0, "NonText", {})
api.nvim_set_hl(0, "Visual", {})
api.nvim_set_hl(0, "VisualNOS", {})
api.nvim_set_hl(0, "Substitute", {})
api.nvim_set_hl(0, "Whitespace", {})
api.nvim_set_hl(0, "LineNr", {})
api.nvim_set_hl(0, "LineNrAbove", {})
api.nvim_set_hl(0, "LineNrBelow", {})
api.nvim_set_hl(0, "CursorLine", {})
api.nvim_set_hl(0, "CursorLineNr", {})
-- make cursor visible for plugins that use fake cursor
api.nvim_set_hl(0, "Cursor", { reverse = true })
end

-- stylua: ignore start
local overrides = {
NonText = {}, EndOfBuffer = {}, ErrorMsg = {}, MoreMsg = {}, ModeMsg = {},
Question = {}, VisualNC = {}, WarningMsg = {}, Sign = {}, SignColumn = {},
ColorColumn = {}, QuickFixLine = {}, MsgSeparator = {}, MsgArea = {}, Operator = {},
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 = {}, Debug = {}, Folded = {},
FoldColumn = {},
}
-- stylua: ignore end
local overridden = {}
local function setup_overrides()
for name, attrs in pairs(overrides) do
if not overridden[name] then
overridden[name] = true
api.nvim_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
api.nvim_set_hl(NS, group, {})
end
end
end

local function set_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

-- {{{ autocmds
local group = api.nvim_create_augroup("VSCodeNeovimHighlight", { clear = true })
api.nvim_create_autocmd({ "BufWinEnter", "BufEnter", "WinEnter", "WinNew", "WinScrolled" }, {
group = group,
callback = set_win_hl_ns,
})
api.nvim_create_autocmd({ "VimEnter", "ColorScheme", "Syntax", "FileType" }, {
group = group,
callback = function()
setup_globals()
-- highlights of custom namespace
setup_overrides()
vim.defer_fn(setup_syntax_groups, 200) -- wait syntax things done
end,
})
-- }}}

setup_globals()
setup_overrides()
setup_syntax_groups()
3 changes: 0 additions & 3 deletions src/buffer_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -651,9 +651,6 @@ export class BufferManager implements Disposable, NeovimRedrawProcessable, Neovi
// used for synchronization of number options
["nvim_buf_set_var", [bufId, "vscode_number", number]],
["nvim_buf_set_var", [bufId, "vscode_relativenumber", relativeNumber]],
// make sure to disable syntax (yeah we're doing it neovim files, but better to be safe than not)
// !Setting to false breaks filetype detection
// ["nvim_buf_set_option", [bufId, "syntax", false]],
// buffer name = document URI
["nvim_buf_set_name", [bufId, BUFFER_NAME_PREFIX + document.uri.toString()]],
// Turn off modifications for external documents
Expand Down
37 changes: 20 additions & 17 deletions src/highlight_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Disposable, TextEditorLineNumbersStyle } from "vscode";
import { HighlightConfiguration, HighlightProvider } from "./highlight_provider";
import { MainController } from "./main_controller";
import { NeovimRedrawProcessable } from "./neovim_events_processable";
import { calculateEditorColFromVimScreenCol, GridLineEvent } from "./utils";
import { GridLineEvent } from "./utils";

// const LOG_PREFIX = "HighlightManager";

Expand Down Expand Up @@ -93,34 +93,37 @@ export class HighlightManager implements Disposable, NeovimRedrawProcessable {
}
continue;
}
const lineText = editor.document.lineAt(highlightLine).text;
let vimCol = col + gridOffset.character;

// remove cells from statuscolumn
if (col < 20) {
col = 0;
if (vimCol < 20) {
vimCol = 0;
cells.splice(0, 1);
} else {
col -= 20;
vimCol -= 20;
}

const line = editor.document.lineAt(highlightLine).text;
const colStart = col + gridOffset.character;
const tabSize = editor.options.tabSize as number;
const finalStartCol = calculateEditorColFromVimScreenCol(line, colStart, tabSize);
const update = this.highlightProvider.processHLCellsEvent(
grid,
row,
finalStartCol,
line,
cells,
);
if (update) {
gridHLUpdates.add(grid);
if (cells.length) {
const tabSize = editor.options.tabSize as number;
const update = this.highlightProvider.processHLCellsEvent(
grid,
row,
vimCol,
cells,
lineText,
tabSize,
);
if (update) {
gridHLUpdates.add(grid);
}
}
}
break;
}
}
}

if (gridHLUpdates.size) {
this.applyHLGridUpdates(gridHLUpdates);
}
Expand Down

0 comments on commit f688d23

Please sign in to comment.