Skip to content

Commit 0087ee1

Browse files
chore(refactor): use shared overlap logic for concealed ranges
## Details The first part of this change is to remove the `Range` class implementation. Instead a `Range` is now a simple table with integer values at `[1]` & `[2]`. We add an `interval` module to store logic for computing properties from these `Range` objects, like checking overlaps & contains as well as coalescing. With that in place we can now share the overlaps & contains check in the `Conceal` module, once support for an exclusive calculation was added as columns are end exclusive unlike rows. Add additional unit tests to validate behavior, make any necessary changes to handle removal of `Range` module and using appropriate new methods.
1 parent ec74afa commit 0087ee1

File tree

18 files changed

+209
-171
lines changed

18 files changed

+209
-171
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
### Bug Fixes
1515

1616
- prioritize hide over highlight_border [7b37aab](https://github.com/MeanderingProgrammer/render-markdown.nvim/commit/7b37aaba005df5744fc7a6bd4225983576b2a950)
17+
- add option to restart treesitter highlighter to clear invalid state [#488](https://github.com/MeanderingProgrammer/render-markdown.nvim/issues/488)
18+
[ec74afa](https://github.com/MeanderingProgrammer/render-markdown.nvim/commit/ec74afa498b6ce3ee686131adf2b3941b713f307)
1719

1820
## 8.7.0 (2025-08-08)
1921

doc/render-markdown.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*render-markdown.txt* For NVIM v0.11.3 Last change: 2025 August 18
1+
*render-markdown.txt* For NVIM v0.11.3 Last change: 2025 August 19
22

33
==============================================================================
44
Table of Contents *render-markdown-table-of-contents*

lua/render-markdown/core/log.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ function M.node(capture, node)
8080
capture = capture,
8181
type = node.type,
8282
length = #node.text,
83-
rows = { node.start_row, node.end_row },
84-
cols = { node.start_col, node.end_col },
83+
row = { node.start_row, node.end_row },
84+
col = { node.start_col, node.end_col },
8585
})
8686
end
8787

lua/render-markdown/core/ui.lua

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
local Context = require('render-markdown.request.context')
22
local Decorator = require('render-markdown.lib.decorator')
33
local Extmark = require('render-markdown.lib.extmark')
4-
local Range = require('render-markdown.lib.range')
54
local compat = require('render-markdown.lib.compat')
65
local env = require('render-markdown.lib.env')
76
local handlers = require('render-markdown.core.handlers')
@@ -211,9 +210,11 @@ function Updater:hidden()
211210
end
212211
if env.mode.is(self.mode, { 'v', 'V', '\22' }) then
213212
local start = vim.fn.getpos('v')[2] - 1
214-
return Range.new(math.min(row, start), math.max(row, start))
213+
---@type render.md.Range
214+
return { math.min(row, start), math.max(row, start) }
215215
else
216-
return Range.new(row - config.above, row + config.below)
216+
---@type render.md.Range
217+
return { row - config.above, row + config.below }
217218
end
218219
end
219220

lua/render-markdown/debug/marks.lua

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,16 @@ end
148148
local M = {}
149149

150150
function M.show()
151-
local Range = require('render-markdown.lib.range')
152151
local env = require('render-markdown.lib.env')
153152
local ui = require('render-markdown.core.ui')
154153

155154
local buf = env.buf.current()
156155
local win = env.win.current()
157156
local row = assert(env.row.get(buf, win), 'row must be known')
158-
local range = Range.new(row, row)
159157

160158
local marks = {} ---@type render.md.debug.Mark[]
161159
for _, extmark in ipairs(ui.get(buf):get()) do
162-
if extmark:overlaps(range) then
160+
if extmark:overlaps({ row, row }) then
163161
marks[#marks + 1] = Mark.new(extmark:get())
164162
end
165163
end

lua/render-markdown/health.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ local state = require('render-markdown.state')
55
local M = {}
66

77
---@private
8-
M.version = '8.7.8'
8+
M.version = '8.7.9'
99

1010
function M.check()
1111
M.start('versions')

lua/render-markdown/lib/compat.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function M.fix_lsp_window(buf, win, extmarks)
3232
end
3333

3434
-- disable line wrapping if it is not needed to contain the text
35-
local width = 0
35+
local width = 0 ---@type integer
3636
for _, line in ipairs(vim.api.nvim_buf_get_lines(buf, 0, -1, false)) do
3737
width = math.max(width, str.width(line))
3838
end

lua/render-markdown/lib/env.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ end
5252
---@param buf integer
5353
---@param win integer
5454
---@param offset integer
55-
---@return integer, integer
55+
---@return render.md.Range
5656
function M.range(buf, win, offset)
5757
local top = math.max(M.win.view(win).topline - 1 - offset, 0)
5858
local bottom = top
@@ -64,7 +64,8 @@ function M.range(buf, win, offset)
6464
size = size - 1
6565
end
6666
end
67-
return top, bottom
67+
---@type render.md.Range
68+
return { top, bottom }
6869
end
6970

7071
---@class render.md.env.Row

lua/render-markdown/lib/extmark.lua

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
local interval = require('render-markdown.lib.interval')
2+
13
---@class render.md.Extmark
24
---@field private id? integer
35
---@field private mark render.md.Mark
6+
---@field private range render.md.Range
47
local Extmark = {}
58
Extmark.__index = Extmark
69

@@ -10,6 +13,13 @@ function Extmark.new(mark)
1013
local self = setmetatable({}, Extmark)
1114
self.id = nil
1215
self.mark = mark
16+
local top = mark.start_row
17+
local bottom = mark.opts.end_row or top
18+
-- hl_eol should not include last line
19+
if mark.opts.hl_eol then
20+
bottom = bottom - 1
21+
end
22+
self.range = { top, bottom }
1323
return self
1424
end
1525

@@ -24,13 +34,7 @@ function Extmark:overlaps(range)
2434
if not range then
2535
return false
2636
end
27-
local top = self.mark.start_row
28-
local bottom = self.mark.opts.end_row or top
29-
-- overlap for hl_eol should not include last line
30-
if self.mark.opts.hl_eol then
31-
bottom = bottom - 1
32-
end
33-
return range:overlaps(top, bottom)
37+
return interval.overlaps(self.range, range)
3438
end
3539

3640
---@param ns integer
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---@class render.md.Range
2+
---@field [1] integer
3+
---@field [2] integer
4+
5+
---@class render.md.Interval
6+
local M = {}
7+
8+
---noncommutative
9+
---@param a render.md.Range
10+
---@param b render.md.Range
11+
---@return boolean
12+
function M.contains(a, b)
13+
return a[1] <= b[1] and a[2] >= b[2]
14+
end
15+
16+
---commutative
17+
---@param a render.md.Range
18+
---@param b render.md.Range
19+
---@param exclusive? boolean
20+
---@return boolean
21+
function M.overlaps(a, b, exclusive)
22+
if exclusive then
23+
return b[1] < a[2] and b[2] > a[1]
24+
else
25+
return b[1] <= a[2] and b[2] >= a[1]
26+
end
27+
end
28+
29+
---@param ranges render.md.Range[]
30+
---@return render.md.Range[]
31+
function M.coalesce(ranges)
32+
table.sort(ranges, function(a, b)
33+
if a[1] ~= b[1] then
34+
return a[1] < b[1]
35+
else
36+
return a[2] < b[2]
37+
end
38+
end)
39+
local result = {} ---@type render.md.Range[]
40+
result[#result + 1] = ranges[1]
41+
for i = 2, #ranges do
42+
local range, last = ranges[i], result[#result]
43+
if range[1] <= last[2] + 1 then
44+
last[2] = math.max(last[2], range[2])
45+
else
46+
result[#result + 1] = range
47+
end
48+
end
49+
return result
50+
end
51+
52+
return M

0 commit comments

Comments
 (0)