Skip to content

Commit dd61059

Browse files
committed
detach after config.highlight.max_lines
1 parent 1eb986b commit dd61059

File tree

5 files changed

+37
-172
lines changed

5 files changed

+37
-172
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,11 @@ require("quicker").setup({
198198
-- Keep the cursor to the right of the filename and lnum columns
199199
constrain_cursor = true,
200200
highlight = {
201-
-- Attach parser to qf buffer, highlight text in real time as you edit.
202-
attach_parser = true,
203-
-- Additionally query treesitter highlight groups using string parser,
204-
-- those highlights only update when you save or refresh.
201+
-- Attach treesitter parser to qf buffer, highlight text in real time as you edit.
205202
treesitter = true,
203+
-- Do not register callbacks when buffer line counts exceed this limit. In other words,
204+
-- highlight won't get updated as you edit.
205+
max_lines = 10000,
206206
-- Use LSP semantic token highlighting
207207
lsp = true,
208208
-- Load the referenced buffers to apply more accurate highlights (may be slow)

lua/quicker/config.lua

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ local default_config = {
2626
-- Keep the cursor to the right of the filename and lnum columns
2727
constrain_cursor = true,
2828
highlight = {
29-
-- Use treesitter highlighting
29+
-- Attach treesitter parser to qf buffer, highlight text in real time as you edit.
3030
treesitter = true,
31+
-- Do not register callbacks when buffer line counts exceed this limit. In other words,
32+
-- highlight won't get updated as you edit.
33+
max_lines = 10000,
3134
-- Use LSP semantic token highlighting
3235
lsp = true,
3336
-- Load the referenced buffers to apply more accurate highlights (may be slow)
@@ -154,8 +157,8 @@ end
154157
---@field soft_end? string
155158

156159
---@class (exact) quicker.HighlightConfig
157-
---@field attach_parser boolean
158160
---@field treesitter boolean
161+
---@field max_lines integer
159162
---@field lsp boolean
160163
---@field load_buffers boolean
161164

lua/quicker/display.lua

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -216,27 +216,6 @@ local function add_item_highlights_from_buf(qfbufnr, item, line, lnum)
216216
offset = offset - item_space
217217
end
218218

219-
-- Add treesitter highlights
220-
if config.highlight.treesitter then
221-
for _, hl in ipairs(highlight.buf_get_ts_highlights(item.bufnr, item.lnum)) do
222-
local start_col, end_col, hl_group = hl[1], hl[2], hl[3]
223-
if end_col == -1 then
224-
end_col = src_line:len()
225-
end
226-
-- If the highlight starts at the beginning of the source line, then it might be off the
227-
-- buffer in the quickfix because we've removed leading whitespace. If so, clamp the value
228-
-- to 0. Except, for some reason 0 gives incorrect results, but -1 works properly even
229-
-- though -1 should indicate the *end* of the line. Not sure why this work, but it does.
230-
local hl_start = math.max(-1, start_col + offset)
231-
vim.api.nvim_buf_set_extmark(qfbufnr, ns, lnum - 1, hl_start, {
232-
hl_group = hl_group,
233-
end_col = end_col + offset,
234-
priority = 100,
235-
strict = false,
236-
})
237-
end
238-
end
239-
240219
-- Add LSP semantic token highlights
241220
if config.highlight.lsp then
242221
for _, hl in ipairs(highlight.buf_get_lsp_highlights(item.bufnr, item.lnum)) do
@@ -342,7 +321,7 @@ add_qf_highlights = function(info)
342321
end
343322

344323
local ft = vim.filetype.match({ buf = item.bufnr })
345-
if config.highlight.attach_parser and ft then
324+
if config.highlight.treesitter and ft then
346325
info.regions[ft] = info.regions[ft] or {}
347326
info.empty_regions[ft] = info.empty_regions[ft] or {}
348327
local filename = vim.split(line, EM_QUAD, { plain = true })[1]
@@ -370,21 +349,6 @@ add_qf_highlights = function(info)
370349
})
371350
end
372351
info.previous_item = item
373-
elseif config.highlight.treesitter then
374-
local filename = vim.split(line, EM_QUAD, { plain = true })[1]
375-
local offset = filename:len() + EM_QUAD_LEN
376-
local text = line:sub(offset + 1)
377-
for _, hl in ipairs(highlight.get_heuristic_ts_highlights(item, text)) do
378-
local start_col, end_col, hl_group = hl[1], hl[2], hl[3]
379-
start_col = start_col + offset
380-
end_col = end_col + offset
381-
vim.api.nvim_buf_set_extmark(qfbufnr, ns, i - 1, start_col, {
382-
hl_group = hl_group,
383-
end_col = end_col,
384-
priority = 100,
385-
strict = false,
386-
})
387-
end
388352
end
389353
if loaded then
390354
add_item_highlights_from_buf(qfbufnr, item, line, i)
@@ -415,7 +379,7 @@ add_qf_highlights = function(info)
415379
return
416380
end
417381
end
418-
if config.highlight.attach_parser then
382+
if config.highlight.treesitter then
419383
-- cleanup previous regions each time we call setqflist.
420384
require("quicker.treesitter").attach(qf_list.qfbufnr, info.empty_regions)
421385
require("quicker.treesitter").attach(qf_list.qfbufnr, info.regions)

lua/quicker/highlight.lua

Lines changed: 0 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -19,71 +19,6 @@ local function get_highlight_query(lang)
1919
end
2020
end
2121

22-
---@param bufnr integer
23-
---@param lnum integer
24-
---@return quicker.TSHighlight[]
25-
function M.buf_get_ts_highlights(bufnr, lnum)
26-
local filetype = vim.bo[bufnr].filetype
27-
if not filetype or filetype == "" then
28-
filetype = vim.filetype.match({ buf = bufnr }) or ""
29-
end
30-
local lang = vim.treesitter.language.get_lang(filetype) or filetype
31-
if lang == "" then
32-
return {}
33-
end
34-
local ok, parser = pcall(vim.treesitter.get_parser, bufnr, lang)
35-
if not ok or not parser then
36-
return {}
37-
end
38-
39-
local row = lnum - 1
40-
if not parser:is_valid() then
41-
parser:parse(true)
42-
end
43-
44-
local highlights = {}
45-
parser:for_each_tree(function(tstree, tree)
46-
if not tstree then
47-
return
48-
end
49-
50-
local root_node = tstree:root()
51-
local root_start_row, _, root_end_row, _ = root_node:range()
52-
53-
-- Only worry about trees within the line range
54-
if root_start_row > row or root_end_row < row then
55-
return
56-
end
57-
58-
local query = get_highlight_query(tree:lang())
59-
60-
-- Some injected languages may not have highlight queries.
61-
if not query then
62-
return
63-
end
64-
65-
for capture, node, metadata in query:iter_captures(root_node, bufnr, row, root_end_row + 1) do
66-
if capture == nil then
67-
break
68-
end
69-
70-
local range = vim.treesitter.get_range(node, bufnr, metadata[capture])
71-
local start_row, start_col, _, end_row, end_col, _ = unpack(range)
72-
if start_row > row then
73-
break
74-
end
75-
local capture_name = query.captures[capture]
76-
local hl = string.format("@%s.%s", capture_name, tree:lang())
77-
if end_row > start_row then
78-
end_col = -1
79-
end
80-
table.insert(highlights, { start_col, end_col, hl })
81-
end
82-
end)
83-
84-
return highlights
85-
end
86-
8722
---@class quicker.LSPHighlight
8823
---@field [1] integer start_col
8924
---@field [2] integer end_col
@@ -157,50 +92,6 @@ function M.buf_get_lsp_highlights(bufnr, lnum)
15792
return lsp_highlights
15893
end
15994

160-
---@param item QuickFixItem
161-
---@param line string
162-
---@return quicker.TSHighlight[]
163-
M.get_heuristic_ts_highlights = function(item, line)
164-
local filetype = vim.filetype.match({ buf = item.bufnr })
165-
if not filetype then
166-
return {}
167-
end
168-
169-
local lang = vim.treesitter.language.get_lang(filetype)
170-
if not lang then
171-
return {}
172-
end
173-
174-
local has_parser, parser = pcall(vim.treesitter.get_string_parser, line, lang)
175-
if not has_parser then
176-
return {}
177-
end
178-
179-
local root = parser:parse(true)[1]:root()
180-
local query = vim.treesitter.query.get(lang, "highlights")
181-
if not query then
182-
return {}
183-
end
184-
185-
local highlights = {}
186-
for capture, node, metadata in query:iter_captures(root, line) do
187-
if capture == nil then
188-
break
189-
end
190-
191-
local range = vim.treesitter.get_range(node, line, metadata[capture])
192-
local start_row, start_col, _, end_row, end_col, _ = unpack(range)
193-
local capture_name = query.captures[capture]
194-
local hl = string.format("@%s.%s", capture_name, lang)
195-
if end_row > start_row then
196-
end_col = -1
197-
end
198-
table.insert(highlights, { start_col, end_col, hl })
199-
end
200-
201-
return highlights
202-
end
203-
20495
function M.set_highlight_groups()
20596
if vim.tbl_isempty(vim.api.nvim_get_hl(0, { name = "QuickFixHeaderHard" })) then
20697
vim.api.nvim_set_hl(0, "QuickFixHeaderHard", { link = "Delimiter", default = true })

lua/quicker/treesitter.lua

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
---@alias quicker.LangRegions table<string, Range4[][]>
1+
local config = require("quicker.config")
22

33
local M = {}
44

@@ -42,6 +42,8 @@ function M.setup()
4242
})
4343
end
4444

45+
---@alias quicker.LangRegions table<string, Range4[][]>
46+
4547
---@param buf number
4648
---@param regions quicker.LangRegions
4749
function M.attach(buf, regions)
@@ -51,35 +53,40 @@ function M.attach(buf, regions)
5153
cache[buf][lang].enabled = regions[lang] ~= nil
5254
end
5355

56+
local counts = 0
57+
for _, region in pairs(regions) do
58+
counts = counts + #vim.iter(region):flatten():totable()
59+
end
60+
5461
for lang in pairs(regions) do
55-
M._attach_lang(buf, lang, regions[lang])
62+
M._attach_lang(buf, lang, regions[lang], counts > config.highlight.max_lines)
5663
end
5764
end
5865

5966
---@param buf number
60-
---@param lang? string
67+
---@param lang string
6168
---@param regions quicker.LangRegions
62-
function M._attach_lang(buf, lang, regions)
63-
lang = lang or "markdown"
64-
lang = lang == "markdown" and "markdown_inline" or lang
65-
69+
---@param detach boolean detach callbacks after the full parse
70+
function M._attach_lang(buf, lang, regions, detach)
6671
cache[buf] = cache[buf] or {}
6772

68-
if not cache[buf][lang] then
69-
local ok, parser = pcall(vim.treesitter.get_parser, buf, lang)
70-
if not ok then
71-
return
72-
end
73-
parser:set_included_regions(vim.deepcopy(regions))
74-
cache[buf][lang] = {
75-
parser = parser,
76-
highlighter = TSHighlighter.new(parser),
77-
}
73+
local ok, parser
74+
if detach then
75+
-- This avoids registering callbacks on the languagetree.
76+
ok, parser = pcall(vim.treesitter.languagetree.new, buf, lang)
77+
else
78+
ok, parser = pcall(vim.treesitter.get_parser, buf, lang)
79+
end
80+
if not ok then
81+
return
7882
end
83+
parser:set_included_regions(vim.deepcopy(regions))
84+
cache[buf][lang] = {
85+
parser = parser,
86+
highlighter = TSHighlighter.new(parser),
87+
}
7988
cache[buf][lang].enabled = true
80-
local parser = cache[buf][lang].parser
8189

82-
parser:set_included_regions(vim.deepcopy(regions))
8390
-- Run a full parse for all included regions. There are two reasons:
8491
-- 1. When we call `vim.treesitter.get_parser`, we have not set any
8592
-- injection ranges.

0 commit comments

Comments
 (0)