diff options
| author | Lewis Russell <lewis6991@gmail.com> | 2022-04-21 10:48:47 +0100 |
|---|---|---|
| committer | Lewis Russell <me@lewisr.dev> | 2022-09-12 11:49:51 +0100 |
| commit | 2eaf18826988f921ddb39e4a2e7d23d95bb0e52a (patch) | |
| tree | 4d4d76fd369b82f7a0ab26725f9c24cef13e6250 | |
| parent | Update lockfile.json (diff) | |
| download | nvim-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.lua | 9 | ||||
| -rw-r--r-- | lua/nvim-treesitter/query.lua | 4 | ||||
| -rw-r--r-- | lua/nvim-treesitter/query_predicates.lua | 33 | ||||
| -rw-r--r-- | queries/make/folds.scm | 7 | ||||
| -rw-r--r-- | queries/markdown/folds.scm | 15 |
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) +) |
