From 030b422d1e9517ed1b1c70fd8002b74881c80650 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 24 Aug 2022 23:48:52 +0200 Subject: feat(treesitter)!: use @foo.bar style highlight groups This removes the support for defining links via vim.treesitter.highlighter.hl_map (never documented, but plugins did anyway), or the uppercase-only `@FooGroup.Bar` to `FooGroup` rule. The fallback is now strictly `@foo.bar.lang` to `@foo.bar` to `@foo`, and casing is irrelevant (as it already was outside of treesitter) For compatibility, define default links to builting syntax groups as defined by pre-existing color schemes --- runtime/lua/vim/treesitter/highlighter.lua | 109 ++--------------------------- 1 file changed, 4 insertions(+), 105 deletions(-) (limited to 'runtime/lua/vim/treesitter/highlighter.lua') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index e27a5fa9c3..1f242b0fdd 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -12,105 +12,18 @@ TSHighlighterQuery.__index = TSHighlighterQuery local ns = a.nvim_create_namespace('treesitter/highlighter') -local _default_highlights = {} -local _link_default_highlight_once = function(from, to) - if not _default_highlights[from] then - _default_highlights[from] = true - a.nvim_set_hl(0, from, { link = to, default = true }) - end - - return from -end - --- If @definition.special does not exist use @definition instead -local subcapture_fallback = { - __index = function(self, capture) - local rtn - local shortened = capture - while not rtn and shortened do - shortened = shortened:match('(.*)%.') - rtn = shortened and rawget(self, shortened) - end - rawset(self, capture, rtn or '__notfound') - return rtn - end, -} - -TSHighlighter.hl_map = setmetatable({ - ['error'] = 'Error', - ['text.underline'] = 'Underlined', - ['todo'] = 'Todo', - ['debug'] = 'Debug', - - -- Miscs - ['comment'] = 'Comment', - ['punctuation.delimiter'] = 'Delimiter', - ['punctuation.bracket'] = 'Delimiter', - ['punctuation.special'] = 'Delimiter', - - -- Constants - ['constant'] = 'Constant', - ['constant.builtin'] = 'Special', - ['constant.macro'] = 'Define', - ['define'] = 'Define', - ['macro'] = 'Macro', - ['string'] = 'String', - ['string.regex'] = 'String', - ['string.escape'] = 'SpecialChar', - ['character'] = 'Character', - ['character.special'] = 'SpecialChar', - ['number'] = 'Number', - ['boolean'] = 'Boolean', - ['float'] = 'Float', - - -- Functions - ['function'] = 'Function', - ['function.special'] = 'Function', - ['function.builtin'] = 'Special', - ['function.macro'] = 'Macro', - ['parameter'] = 'Identifier', - ['method'] = 'Function', - ['field'] = 'Identifier', - ['property'] = 'Identifier', - ['constructor'] = 'Special', - - -- Keywords - ['conditional'] = 'Conditional', - ['repeat'] = 'Repeat', - ['label'] = 'Label', - ['operator'] = 'Operator', - ['keyword'] = 'Keyword', - ['exception'] = 'Exception', - - ['type'] = 'Type', - ['type.builtin'] = 'Type', - ['type.qualifier'] = 'Type', - ['type.definition'] = 'Typedef', - ['storageclass'] = 'StorageClass', - ['structure'] = 'Structure', - ['include'] = 'Include', - ['preproc'] = 'PreProc', -}, subcapture_fallback) - ----@private -local function is_highlight_name(capture_name) - local firstc = string.sub(capture_name, 1, 1) - return firstc ~= string.lower(firstc) -end - ---@private function TSHighlighterQuery.new(lang, query_string) local self = setmetatable({}, { __index = TSHighlighterQuery }) self.hl_cache = setmetatable({}, { __index = function(table, capture) - local hl, is_vim_highlight = self:_get_hl_from_capture(capture) - if not is_vim_highlight then - hl = _link_default_highlight_once(lang .. hl, hl) + local name = self._query.captures[capture] + local id = 0 + if not vim.startswith(name, '_') then + id = a.nvim_get_hl_id_by_name('@' .. name .. '.' .. lang) end - local id = a.nvim_get_hl_id_by_name(hl) - rawset(table, capture, id) return id end, @@ -130,20 +43,6 @@ function TSHighlighterQuery:query() return self._query end ----@private ---- Get the hl from capture. ---- Returns a tuple { highlight_name: string, is_builtin: bool } -function TSHighlighterQuery:_get_hl_from_capture(capture) - local name = self._query.captures[capture] - - if is_highlight_name(name) then - -- From "Normal.left" only keep "Normal" - return vim.split(name, '.', true)[1], true - else - return TSHighlighter.hl_map[name] or 0, false - end -end - --- Creates a new highlighter using @param tree --- ---@param tree The language tree to use for highlighting -- cgit From 75adfefc85bcf0d62d2c0f51a951e6003b595cea Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Mon, 18 Jul 2022 14:21:40 +0200 Subject: feat(extmarks,ts,spell): full support for spelling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added 'spell' option to extmarks: Extmarks with this set will have the region spellchecked. - Added 'noplainbuffer' option to 'spelloptions': This is used to tell Neovim not to spellcheck the buffer. The old behaviour was to spell check the whole buffer unless :syntax was set. - Added spelling support to the treesitter highlighter: @spell captures in highlights.scm are used to define regions which should be spell checked. - Added support for navigating spell errors for extmarks: Works for both ephemeral and static extmarks - Added '_on_spell_nav' callback for decoration providers: Since ephemeral callbacks are only drawn for the visible screen, providers must implement this callback to instruct Neovim which regions in the buffer need can be spell checked. The callback takes a start position and an end position. Note: this callback is subject to change hence the _ prefix. - Added spell captures for built-in support languages Co-authored-by: Lewis Russell Co-authored-by: Björn Linse --- runtime/lua/vim/treesitter/highlighter.lua | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim/treesitter/highlighter.lua') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 1f242b0fdd..9e95af98db 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -97,6 +97,7 @@ function TSHighlighter.new(tree, opts) if vim.g.syntax_on ~= 1 then vim.api.nvim_command('runtime! syntax/synload.vim') end + vim.bo[self.bufnr].spelloptions = 'noplainbuffer' self.tree:parse() @@ -156,7 +157,7 @@ function TSHighlighter:get_query(lang) end ---@private -local function on_line_impl(self, buf, line) +local function on_line_impl(self, buf, line, spell) self.tree:for_each_tree(function(tstree, tree) if not tstree then return @@ -193,7 +194,9 @@ local function on_line_impl(self, buf, line) local start_row, start_col, end_row, end_col = node:range() local hl = highlighter_query.hl_cache[capture] - if hl and end_row >= line then + local is_spell = highlighter_query:query().captures[capture] == 'spell' + + if hl and end_row >= line and (not spell or is_spell) then a.nvim_buf_set_extmark(buf, ns, start_row, start_col, { end_line = end_row, end_col = end_col, @@ -201,6 +204,7 @@ local function on_line_impl(self, buf, line) ephemeral = true, priority = tonumber(metadata.priority) or 100, -- Low but leaves room below conceal = metadata.conceal, + spell = is_spell, }) end if start_row > line then @@ -217,7 +221,21 @@ function TSHighlighter._on_line(_, _win, buf, line, _) return end - on_line_impl(self, buf, line) + on_line_impl(self, buf, line, false) +end + +---@private +function TSHighlighter._on_spell_nav(_, _, buf, srow, _, erow, _) + local self = TSHighlighter.active[buf] + if not self then + return + end + + self:reset_highlight_state() + + for row = srow, erow do + on_line_impl(self, buf, row, true) + end end ---@private @@ -244,6 +262,7 @@ a.nvim_set_decoration_provider(ns, { on_buf = TSHighlighter._on_buf, on_win = TSHighlighter._on_win, on_line = TSHighlighter._on_line, + _on_spell_nav = TSHighlighter._on_spell_nav, }) return TSHighlighter -- cgit From 707edfc9e6a1745f268d1a9184183da521dc86b8 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 6 Sep 2022 19:22:05 +0100 Subject: fix(ts): do not clobber spelloptions (#20095) --- runtime/lua/vim/treesitter/highlighter.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim/treesitter/highlighter.lua') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 9e95af98db..1e625eddb8 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -86,7 +86,7 @@ function TSHighlighter.new(tree, opts) end end - a.nvim_buf_set_option(self.bufnr, 'syntax', '') + vim.bo[self.bufnr].syntax = '' TSHighlighter.active[self.bufnr] = self @@ -95,9 +95,12 @@ function TSHighlighter.new(tree, opts) -- syntax FileType autocmds. Later on we should integrate with the -- `:syntax` and `set syntax=...` machinery properly. if vim.g.syntax_on ~= 1 then - vim.api.nvim_command('runtime! syntax/synload.vim') + vim.cmd.runtime({ 'syntax/synload.vim', bang = true }) end - vim.bo[self.bufnr].spelloptions = 'noplainbuffer' + + a.nvim_buf_call(self.bufnr, function() + vim.opt_local.spelloptions:append('noplainbuffer') + end) self.tree:parse() -- cgit From ddb762f4013ac2532ad45704466058d867e3a6ed Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 14 Sep 2022 11:08:31 +0200 Subject: docs(treesitter): clean up and update treesitter.txt (#20142) * add type annotations to code * clean up and expand static documentation * consistent use of tags for static and generated docs --- runtime/lua/vim/treesitter/highlighter.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim/treesitter/highlighter.lua') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 1e625eddb8..83a26aff13 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -2,6 +2,7 @@ local a = vim.api local query = require('vim.treesitter.query') -- support reload for quick experimentation +---@class TSHighlighter local TSHighlighter = rawget(vim.treesitter, 'TSHighlighter') or {} TSHighlighter.__index = TSHighlighter @@ -45,9 +46,10 @@ end --- Creates a new highlighter using @param tree --- ----@param tree The language tree to use for highlighting ----@param opts Table used to configure the highlighter ---- - queries: Table to overwrite queries used by the highlighter +---@param tree LanguageTree |LanguageTree| parser object to use for highlighting +---@param opts (table|nil) Configuration of the highlighter: +--- - queries table overwrite queries used by the highlighter +---@return TSHighlighter Created highlighter object function TSHighlighter.new(tree, opts) local self = setmetatable({}, TSHighlighter) @@ -149,8 +151,10 @@ function TSHighlighter:on_changedtree(changes) end --- Gets the query used for @param lang ---- ----@param lang A language used by the highlighter. +-- +---@private +---@param lang string Language used by the highlighter. +---@return Query function TSHighlighter:get_query(lang) if not self._queries[lang] then self._queries[lang] = TSHighlighterQuery.new(lang) -- cgit From 07eb4263caa671de63186e9bbd650ec4b1fbce1a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 28 Oct 2022 13:09:22 +0100 Subject: feat(spell): support nospell in treesitter queries --- runtime/lua/vim/treesitter/highlighter.lua | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim/treesitter/highlighter.lua') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 83a26aff13..f5e5ca1988 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -164,7 +164,7 @@ function TSHighlighter:get_query(lang) end ---@private -local function on_line_impl(self, buf, line, spell) +local function on_line_impl(self, buf, line, is_spell_nav) self.tree:for_each_tree(function(tstree, tree) if not tstree then return @@ -201,17 +201,26 @@ local function on_line_impl(self, buf, line, spell) local start_row, start_col, end_row, end_col = node:range() local hl = highlighter_query.hl_cache[capture] - local is_spell = highlighter_query:query().captures[capture] == 'spell' + local capture_name = highlighter_query:query().captures[capture] + local spell = nil + if capture_name == 'spell' then + spell = true + elseif capture_name == 'nospell' then + spell = false + end + + -- Give nospell a higher priority so it always overrides spell captures. + local spell_pri_offset = capture_name == 'nospell' and 1 or 0 - if hl and end_row >= line and (not spell or is_spell) then + if hl and end_row >= line and (not is_spell_nav or spell ~= nil) then a.nvim_buf_set_extmark(buf, ns, start_row, start_col, { end_line = end_row, end_col = end_col, hl_group = hl, ephemeral = true, - priority = tonumber(metadata.priority) or 100, -- Low but leaves room below + priority = (tonumber(metadata.priority) or 100) + spell_pri_offset, -- Low but leaves room below conceal = metadata.conceal, - spell = is_spell, + spell = spell, }) end if start_row > line then -- cgit From d127c684faa9a112575798a81c87babb1c83a7ea Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 14 Dec 2022 15:00:48 +0000 Subject: fix(treesitter): properly restore `'syntax'` (#21358) --- runtime/lua/vim/treesitter/highlighter.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'runtime/lua/vim/treesitter/highlighter.lua') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index f5e5ca1988..99aedf60c5 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -88,7 +88,9 @@ function TSHighlighter.new(tree, opts) end end + self.orig_syntax = vim.bo[self.bufnr].syntax vim.bo[self.bufnr].syntax = '' + vim.b[self.bufnr].ts_highlight = true TSHighlighter.active[self.bufnr] = self @@ -114,6 +116,8 @@ function TSHighlighter:destroy() if TSHighlighter.active[self.bufnr] then TSHighlighter.active[self.bufnr] = nil end + + vim.bo[self.bufnr].syntax = self.orig_syntax end ---@private -- cgit From 0887ad1cbb050d2bc6169ad46aa07cf42c90493f Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 14 Dec 2022 22:54:58 +0000 Subject: fix(ts): check buffer is loaded when restoring options (#21419) fix(treesitter): check buffer is loaded when restoring options Also restore spelloptions Fixes #21416 --- runtime/lua/vim/treesitter/highlighter.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim/treesitter/highlighter.lua') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 99aedf60c5..e99994c8a9 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -89,6 +89,8 @@ function TSHighlighter.new(tree, opts) end self.orig_syntax = vim.bo[self.bufnr].syntax + self.orig_spelloptions = vim.bo[self.bufnr].spelloptions + vim.bo[self.bufnr].syntax = '' vim.b[self.bufnr].ts_highlight = true @@ -117,7 +119,10 @@ function TSHighlighter:destroy() TSHighlighter.active[self.bufnr] = nil end - vim.bo[self.bufnr].syntax = self.orig_syntax + if vim.api.nvim_buf_is_loaded(self.bufnr) then + vim.bo[self.bufnr].syntax = self.orig_syntax + vim.bo[self.bufnr].spelloptions = self.orig_spelloptions + end end ---@private -- cgit From 20b7be2d1024b6e9eac68e0cb92cf663e95e51ca Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 17 Jan 2023 16:56:23 +0000 Subject: fix(treesitter): really restore syntax - also unset b:ts_highlight on stop() Fixes: #21836 --- runtime/lua/vim/treesitter/highlighter.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim/treesitter/highlighter.lua') diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index e99994c8a9..d77a0d0d03 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -88,7 +88,6 @@ function TSHighlighter.new(tree, opts) end end - self.orig_syntax = vim.bo[self.bufnr].syntax self.orig_spelloptions = vim.bo[self.bufnr].spelloptions vim.bo[self.bufnr].syntax = '' @@ -120,8 +119,11 @@ function TSHighlighter:destroy() end if vim.api.nvim_buf_is_loaded(self.bufnr) then - vim.bo[self.bufnr].syntax = self.orig_syntax vim.bo[self.bufnr].spelloptions = self.orig_spelloptions + vim.b[self.bufnr].ts_highlight = nil + if vim.g.syntax_on == 1 then + a.nvim_exec_autocmds('FileType', { group = 'syntaxset', buffer = self.bufnr }) + end end end -- cgit