mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-02 19:46:58 -04:00
fix(fold): don't include whitespace end regions
Some languages that are difficult to parse via Treesitter may incorrectly include whitespace lines at the end of regions. This can makes the calculated folds sub-optimal. To recitfy, use a custom directive (trim), to calculate the range with the trailing whitespace lines removed. Note this only works if the region end column is 0. Also added folds for Make.
This commit is contained in:
parent
2bc82e814b
commit
2eaf188269
5 changed files with 59 additions and 9 deletions
|
|
@ -39,8 +39,13 @@ local folds_levels = tsutils.memoize_by_buf_tick(function(bufnr)
|
|||
|
||||
local min_fold_lines = api.nvim_win_get_option(0, "foldminlines")
|
||||
|
||||
for _, node in ipairs(matches) do
|
||||
local start, _, stop, stop_col = node.node:range()
|
||||
for _, match in ipairs(matches) do
|
||||
local start, stop, stop_col
|
||||
if match.metadata and match.metadata.range then
|
||||
start, _, stop, stop_col = unpack(match.metadata.range)
|
||||
else
|
||||
start, _, stop, stop_col = match.node:range()
|
||||
end
|
||||
|
||||
if stop_col == 0 then
|
||||
stop = stop - 1
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
|||
local matches = query:iter_matches(qnode, bufnr, start_row, end_row)
|
||||
|
||||
local function iterator()
|
||||
local pattern, match = matches()
|
||||
local pattern, match, metadata = matches()
|
||||
if pattern ~= nil then
|
||||
local prepared_match = {}
|
||||
|
||||
|
|
@ -219,6 +219,8 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
|||
if name ~= nil then
|
||||
local path = split(name .. ".node")
|
||||
insert_to_path(prepared_match, path, node)
|
||||
local metadata_path = split(name .. ".metadata")
|
||||
insert_to_path(prepared_match, metadata_path, metadata[id])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -153,3 +153,36 @@ query.add_directive("exclude_children!", function(match, _pattern, _bufnr, pred,
|
|||
end
|
||||
metadata.content = ranges
|
||||
end)
|
||||
|
||||
-- Trim blank lines from end of the region
|
||||
-- Arguments are the captures to trim.
|
||||
query.add_directive("trim!", function(match, _, bufnr, pred, metadata)
|
||||
for _, id in ipairs { select(2, unpack(pred)) } do
|
||||
local node = match[id]
|
||||
local start_row, start_col, end_row, end_col = node:range()
|
||||
|
||||
-- Don't trim if region ends in middle of a line
|
||||
if end_col ~= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
while true do
|
||||
-- As we only care when end_col == 0, always inspect one line above end_row.
|
||||
local end_line = vim.api.nvim_buf_get_lines(bufnr, end_row - 1, end_row, true)[1]
|
||||
|
||||
if end_line ~= "" then
|
||||
break
|
||||
end
|
||||
|
||||
end_row = end_row - 1
|
||||
end
|
||||
|
||||
-- If this produces an invalid range, we just skip it.
|
||||
if start_row < end_row or (start_row == end_row and start_col <= end_col) then
|
||||
if not metadata[id] then
|
||||
metadata[id] = {}
|
||||
end
|
||||
metadata[id].range = { start_row, start_col, end_row, end_col }
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
|
|
|||
7
queries/make/folds.scm
Normal file
7
queries/make/folds.scm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
(
|
||||
[
|
||||
(conditional)
|
||||
(rule)
|
||||
] @fold
|
||||
(#trim! @fold)
|
||||
)
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
[
|
||||
(fenced_code_block)
|
||||
(indented_code_block)
|
||||
(list)
|
||||
(section)
|
||||
] @fold
|
||||
(
|
||||
[
|
||||
(fenced_code_block)
|
||||
(indented_code_block)
|
||||
(list)
|
||||
(section)
|
||||
] @fold
|
||||
(#trim! @fold)
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue