aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2022-04-21 10:48:47 +0100
committerLewis Russell <me@lewisr.dev>2022-09-12 11:49:51 +0100
commit2eaf18826988f921ddb39e4a2e7d23d95bb0e52a (patch)
tree4d4d76fd369b82f7a0ab26725f9c24cef13e6250
parentUpdate lockfile.json (diff)
downloadnvim-treesitter-2eaf18826988f921ddb39e4a2e7d23d95bb0e52a.tar
nvim-treesitter-2eaf18826988f921ddb39e4a2e7d23d95bb0e52a.tar.gz
nvim-treesitter-2eaf18826988f921ddb39e4a2e7d23d95bb0e52a.tar.bz2
nvim-treesitter-2eaf18826988f921ddb39e4a2e7d23d95bb0e52a.tar.lz
nvim-treesitter-2eaf18826988f921ddb39e4a2e7d23d95bb0e52a.tar.xz
nvim-treesitter-2eaf18826988f921ddb39e4a2e7d23d95bb0e52a.tar.zst
nvim-treesitter-2eaf18826988f921ddb39e4a2e7d23d95bb0e52a.zip
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.
-rw-r--r--lua/nvim-treesitter/fold.lua9
-rw-r--r--lua/nvim-treesitter/query.lua4
-rw-r--r--lua/nvim-treesitter/query_predicates.lua33
-rw-r--r--queries/make/folds.scm7
-rw-r--r--queries/markdown/folds.scm15
5 files changed, 59 insertions, 9 deletions
diff --git a/lua/nvim-treesitter/fold.lua b/lua/nvim-treesitter/fold.lua
index 01a7c08e9..1f417414f 100644
--- a/lua/nvim-treesitter/fold.lua
+++ b/lua/nvim-treesitter/fold.lua
@@ -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
diff --git a/lua/nvim-treesitter/query.lua b/lua/nvim-treesitter/query.lua
index bad1c27e6..aeaa683be 100644
--- a/lua/nvim-treesitter/query.lua
+++ b/lua/nvim-treesitter/query.lua
@@ -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
diff --git a/lua/nvim-treesitter/query_predicates.lua b/lua/nvim-treesitter/query_predicates.lua
index 75f0efc04..0638b6e79 100644
--- a/lua/nvim-treesitter/query_predicates.lua
+++ b/lua/nvim-treesitter/query_predicates.lua
@@ -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)
diff --git a/queries/make/folds.scm b/queries/make/folds.scm
new file mode 100644
index 000000000..a2b472761
--- /dev/null
+++ b/queries/make/folds.scm
@@ -0,0 +1,7 @@
+(
+ [
+ (conditional)
+ (rule)
+ ] @fold
+ (#trim! @fold)
+)
diff --git a/queries/markdown/folds.scm b/queries/markdown/folds.scm
index efda6675f..5900f7ffb 100644
--- a/queries/markdown/folds.scm
+++ b/queries/markdown/folds.scm
@@ -1,6 +1,9 @@
-[
- (fenced_code_block)
- (indented_code_block)
- (list)
- (section)
-] @fold
+(
+ [
+ (fenced_code_block)
+ (indented_code_block)
+ (list)
+ (section)
+ ] @fold
+ (#trim! @fold)
+)