Skip to content

Commit 96b71a1

Browse files
Cache markup tree-sitter queries by changetick to improve performance (#468)
1 parent 1c48acd commit 96b71a1

File tree

3 files changed

+51
-78
lines changed

3 files changed

+51
-78
lines changed

lua/orgmode/colors/custom_highlighter.lua

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@ local MarkupHighlighter = nil
55
local valid_bufnrs = {}
66

77
---@param bufnr number
8-
---@param first_line number
9-
---@param last_line number
10-
local function apply_highlights(bufnr, first_line, last_line, tick_changed)
11-
local changed_lines = vim.api.nvim_buf_get_lines(bufnr, first_line, last_line, false)
12-
HideLeadingStars.apply(namespace, bufnr, changed_lines, first_line, last_line)
13-
MarkupHighlighter.apply(namespace, bufnr, changed_lines, first_line, last_line, tick_changed)
8+
local function apply_highlights(bufnr, line)
9+
HideLeadingStars.apply(namespace, bufnr, line)
10+
MarkupHighlighter.apply(namespace, bufnr, line)
1411
end
1512

1613
local function setup()
@@ -25,18 +22,19 @@ local function setup()
2522
MarkupHighlighter.setup()
2623

2724
vim.api.nvim_set_decoration_provider(namespace, {
28-
on_win = function(_, _, bufnr, topline, botline)
29-
local changedtick = vim.api.nvim_buf_get_var(bufnr, 'changedtick')
30-
local tick_changed = not valid_bufnrs[bufnr] or valid_bufnrs[bufnr] ~= changedtick
31-
if valid_bufnrs[bufnr] then
32-
valid_bufnrs[bufnr] = changedtick
33-
return apply_highlights(bufnr, topline, botline, tick_changed)
34-
end
35-
local ft = vim.api.nvim_buf_get_option(bufnr, 'filetype')
36-
if ft == 'org' then
37-
valid_bufnrs[bufnr] = changedtick
38-
return apply_highlights(bufnr, topline, botline, tick_changed)
25+
on_start = function(_, tick)
26+
local bufnr = vim.api.nvim_get_current_buf()
27+
if valid_bufnrs[bufnr] == tick or vim.bo[bufnr].filetype ~= 'org' then
28+
return false
3929
end
30+
valid_bufnrs[bufnr] = tick
31+
return true
32+
end,
33+
on_win = function(_, _, bufnr)
34+
return vim.bo[bufnr].filetype == 'org'
35+
end,
36+
on_line = function(_, _, bufnr, line)
37+
return apply_highlights(bufnr, line)
4038
end,
4139
})
4240
end
Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
local config = require('orgmode.config')
22

3-
local function update_line_highlight(namespace, bufnr, line_index, line)
3+
local function apply(namespace, bufnr, line_index)
4+
if not config.org_hide_leading_stars then
5+
return
6+
end
7+
local line = vim.api.nvim_buf_get_lines(bufnr, line_index, line_index + 1, false)[1]
48
local stars = line:match('^%*+')
59
if stars then
610
vim.api.nvim_buf_set_extmark(bufnr, namespace, line_index, 0, {
@@ -12,16 +16,6 @@ local function update_line_highlight(namespace, bufnr, line_index, line)
1216
end
1317
end
1418

15-
local function apply(namespace, bufnr, changed_lines, first_line, _)
16-
if not config.org_hide_leading_stars then
17-
return
18-
end
19-
20-
for i, line in ipairs(changed_lines) do
21-
update_line_highlight(namespace, bufnr, first_line + i - 1, line)
22-
end
23-
end
24-
2519
return {
2620
apply = apply,
2721
}

lua/orgmode/colors/markup_highlighter.lua

Lines changed: 31 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
local config = require('orgmode.config')
2-
local utils = require('orgmode.utils')
32
local ts_utils = require('nvim-treesitter.ts_utils')
43
local query = nil
54

@@ -64,6 +63,11 @@ local markers = {
6463
},
6564
}
6665

66+
---@param node userdata
67+
---@param source number
68+
---@param offset_col_start? number
69+
---@param offset_col_end? number
70+
---@return string
6771
local function get_node_text(node, source, offset_col_start, offset_col_end)
6872
local start_row, start_col = node:start()
6973
local end_row, end_col = node:end_()
@@ -73,7 +77,7 @@ local function get_node_text(node, source, offset_col_start, offset_col_end)
7377
local lines
7478
local eof_row = vim.api.nvim_buf_line_count(source)
7579
if start_row >= eof_row then
76-
return nil
80+
return ''
7781
end
7882

7983
if end_col == 0 then
@@ -107,7 +111,7 @@ local function get_predicate_nodes(match, n)
107111
local total = n or 2
108112
local counter = 1
109113
local nodes = {}
110-
for i, node in pairs(match) do
114+
for _, node in pairs(match) do
111115
nodes[counter] = node
112116
counter = counter + 1
113117
if counter > total then
@@ -228,21 +232,14 @@ local function load_deps()
228232
vim.treesitter.query.add_predicate('org-is-valid-latex-range?', is_valid_latex_range)
229233
end
230234

231-
---@param bufnr? number
232-
---@param first_line? number
233-
---@param last_line? number
234-
---@return table[]
235-
local function get_matches(bufnr, first_line, last_line)
236-
bufnr = bufnr or 0
237-
local root = get_tree(bufnr)
238-
if not root then
239-
return
240-
end
241-
235+
---@param bufnr number
236+
---@param line_index number
237+
---@return table
238+
local get_matches = ts_utils.memoize_by_buf_tick(function(bufnr, line_index, root)
242239
local ranges = {}
243240
local taken_locations = {}
244241

245-
for _, match, _ in query:iter_matches(root, bufnr, first_line, last_line) do
242+
for _, match, _ in query:iter_matches(root, bufnr, line_index, line_index + 1) do
246243
for _, node in pairs(match) do
247244
local char = node:type()
248245
-- saves unnecessary parsing, since \\ is not used below
@@ -357,44 +354,28 @@ local function get_matches(bufnr, first_line, last_line)
357354
end
358355
end
359356

360-
return result, link_result, latex_result
361-
end
362-
363-
local function apply(namespace, bufnr, _, first_line, last_line, _)
364-
-- Add some offset to make sure everything is covered
365-
local line_ranges = { {} }
366-
local current_line_range = 1
367-
local last_valid_line = -1
368-
for i = first_line, last_line do
369-
if vim.fn.foldclosed(i + 1) == -1 then
370-
-- Generate list of valid ranges
371-
if last_valid_line < 0 or (i - 1) == last_valid_line then
372-
table.insert(line_ranges[current_line_range], i)
373-
else
374-
current_line_range = current_line_range + 1
375-
line_ranges[current_line_range] = { i }
376-
end
377-
last_valid_line = i
378-
end
379-
end
357+
return {
358+
ranges = result,
359+
link_ranges = link_result,
360+
latex_ranges = latex_result,
361+
}
362+
end, {
363+
key = function(bufnr, line_index)
364+
return bufnr .. '__' .. line_index
365+
end,
366+
})
380367

381-
-- None of the lines are valid
382-
if last_valid_line < 0 then
368+
local function apply(namespace, bufnr, line_index)
369+
bufnr = bufnr or 0
370+
local root = get_tree(bufnr)
371+
if not root then
383372
return
384373
end
385-
local ranges = {}
386-
local link_ranges = {}
387-
local latex_ranges = {}
388-
389-
for _, range in ipairs(line_ranges) do
390-
local r, link_r, latex_r = get_matches(bufnr, math.max(1, range[1] - 5), range[#range] + 5)
391-
utils.concat(ranges, r or {})
392-
utils.concat(link_ranges, link_r or {})
393-
utils.concat(latex_ranges, latex_r or {})
394-
end
374+
375+
local result = get_matches(bufnr, line_index, root)
395376
local hide_markers = config.org_hide_emphasis_markers
396377

397-
for _, range in ipairs(ranges) do
378+
for _, range in ipairs(result.ranges) do
398379
vim.api.nvim_buf_set_extmark(bufnr, namespace, range.from.start.line, range.from.start.character, {
399380
ephemeral = true,
400381
end_col = range.to['end'].character,
@@ -416,7 +397,7 @@ local function apply(namespace, bufnr, _, first_line, last_line, _)
416397
end
417398
end
418399

419-
for _, link_range in ipairs(link_ranges) do
400+
for _, link_range in ipairs(result.link_ranges) do
420401
local line = vim.api.nvim_buf_get_lines(bufnr, link_range.from.start.line, link_range.from.start.line + 1, false)[1]
421402
local link = line:sub(link_range.from.start.character + 1, link_range.to['end'].character)
422403
local alias = link:find('%]%[') or 1
@@ -441,7 +422,7 @@ local function apply(namespace, bufnr, _, first_line, last_line, _)
441422
})
442423
end
443424

444-
for _, latex_range in ipairs(latex_ranges) do
425+
for _, latex_range in ipairs(result.latex_ranges) do
445426
vim.api.nvim_buf_set_extmark(bufnr, namespace, latex_range.from.start.line, latex_range.from.start.character, {
446427
ephemeral = true,
447428
end_col = latex_range.to['end'].character,

0 commit comments

Comments
 (0)