Skip to content

Commit 0ab72ad

Browse files
feat(treesitter)!: Use async parsing for custom highlighter (#1029)
1 parent c058767 commit 0ab72ad

File tree

3 files changed

+49
-13
lines changed

3 files changed

+49
-13
lines changed

.github/workflows/tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ jobs:
2929
- windows-latest
3030
- macos-latest
3131
version:
32-
- v0.10.3
33-
- v0.10.4
3432
- v0.11.0
3533
- v0.11.1
3634
- v0.11.2
35+
- v0.11.3
36+
- v0.11.4
3737
- nightly
3838
runs-on: ${{ matrix.os }}
3939
steps:

lua/orgmode/colors/highlighter/init.lua

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
---@field private todos OrgTodosHighlighter
66
---@field private foldtext OrgFoldtextHighlighter
77
---@field private _ephemeral boolean
8-
---@field private buffers table<number, { language_tree: vim.treesitter.LanguageTree, tree: TSTree }>
8+
---@field private buffers table<number, { language_tree: vim.treesitter.LanguageTree | nil, tree: TSTree }>
9+
---@field private parsing table<number, boolean>
910
local OrgHighlighter = {}
1011

1112
function OrgHighlighter:new()
1213
local data = {
1314
namespace = vim.api.nvim_create_namespace('org_custom_highlighter'),
1415
buffers = {},
16+
parsing = {},
1517
-- Use ephemeral for highlights. Added to config to allow toggling from tests.
1618
_ephemeral = true,
1719
}
@@ -38,29 +40,57 @@ function OrgHighlighter:_setup()
3840
})
3941
end
4042

41-
function OrgHighlighter:_on_win(_, _, bufnr, topline, botline)
43+
---@param bufnr number
44+
---@param win number
45+
---@param range { start_line: number, end_line: number } | false
46+
function OrgHighlighter:_parse_tree(bufnr, win, range)
47+
self.parsing[win] = self.parsing[win]
48+
or nil
49+
== self.buffers[bufnr].language_tree:parse(range, function(_, parsed_trees)
50+
self.buffers[bufnr].tree = parsed_trees and parsed_trees[1]
51+
if self.parsing[win] then
52+
self.parsing[win] = false
53+
if vim.api.nvim_win_is_valid(win) then
54+
vim.api.nvim__redraw({ win = win, valid = false, flush = false })
55+
end
56+
end
57+
end)
58+
end
59+
60+
function OrgHighlighter:_on_win(_, win, bufnr, topline, botline)
4261
local is_org_buffer = vim.bo[bufnr].filetype == 'org'
4362
if not is_org_buffer then
4463
return false
4564
end
46-
local parsed_trees = {}
4765
if not self.buffers[bufnr] then
4866
self.buffers[bufnr] = { language_tree = vim.treesitter.get_parser(bufnr, 'org') }
49-
parsed_trees = self.buffers[bufnr].language_tree:parse()
67+
self:_parse_tree(bufnr, win, false)
5068
self.buffers[bufnr].language_tree:register_cbs({
5169
on_detach = function(buf)
5270
self:_on_detach(buf)
5371
end,
5472
})
5573
else
56-
parsed_trees = self.buffers[bufnr].language_tree:parse({ topline, botline + 1 })
74+
self:_parse_tree(bufnr, win, { topline, botline + 1 })
75+
if self.parsing[win] then
76+
for line = topline, botline do
77+
self:_on_line_impl(bufnr, line, true)
78+
end
79+
return false
80+
end
5781
end
58-
self.buffers[bufnr].tree = parsed_trees and parsed_trees[1]
5982
end
6083

6184
function OrgHighlighter:_on_line(_, _, bufnr, line)
85+
self:_on_line_impl(bufnr, line)
86+
end
87+
88+
---@param bufnr number
89+
---@param line number
90+
---@param use_cache? boolean
91+
function OrgHighlighter:_on_line_impl(bufnr, line, use_cache)
6292
if self.buffers[bufnr].tree then
63-
self.markup:on_line(bufnr, line, self.buffers[bufnr].tree)
93+
self.markup:on_line(bufnr, line, self.buffers[bufnr].tree, use_cache)
6494
self.stars:on_line(bufnr, line)
6595
self.foldtext:on_line(bufnr, line)
6696
end

lua/orgmode/colors/highlighter/markup/init.lua

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ end
3030
---@param bufnr number
3131
---@param line number
3232
---@param tree TSTree
33-
function OrgMarkup:on_line(bufnr, line, tree)
34-
local highlights = self:_get_highlights(bufnr, line, tree)
33+
---@param use_cache? boolean
34+
function OrgMarkup:on_line(bufnr, line, tree, use_cache)
35+
local highlights = self:_get_highlights(bufnr, line, tree, use_cache)
3536

3637
for type, highlight in pairs(highlights) do
3738
self.parsers[type]:highlight(highlight, bufnr)
@@ -41,11 +42,16 @@ end
4142
---@param bufnr number
4243
---@param line number
4344
---@param tree TSTree
45+
---@param use_cache? boolean
4446
---@return { emphasis: OrgMarkupHighlight[], link: OrgMarkupHighlight[], latex: OrgMarkupHighlight[], date: OrgMarkupHighlight[] }
45-
function OrgMarkup:_get_highlights(bufnr, line, tree)
47+
function OrgMarkup:_get_highlights(bufnr, line, tree, use_cache)
4648
local line_content = vim.api.nvim_buf_get_lines(bufnr, line, line + 1, false)[1]
4749

48-
if self.cache[bufnr] and self.cache[bufnr][line] and self.cache[bufnr][line].line_content == line_content then
50+
if
51+
self.cache[bufnr]
52+
and self.cache[bufnr][line]
53+
and (use_cache or self.cache[bufnr][line].line_content == line_content)
54+
then
4955
return self.cache[bufnr][line].highlights
5056
end
5157

0 commit comments

Comments
 (0)