Skip to content

Commit 8355c85

Browse files
feat: better anti-conceal for multi-line decorations
## Details Previously only the starting row of a mark would be used when deciding whether the mark should be hidden or shown. This means if a mark spanned multiple rows (like with scope highlights) we would only hide the decoration if the users cursor was on the first line, but show it when the cursor was anywhere in the middle. This is okay, but definitely not ideal, so now the logic uses both the start and end row of a mark and hides it if the current row overlaps the mark. We use overlap since in visual mode it is not a single row, but multiple. Now any overlapping marks within the cursor range are hidden. There is a special case for `hl_eol` marks, which specify an end row but do not actually impact that row, instead their impact effectively ends one row earlier. So we handle this case specifically and offset the end of a mark by 1 if `hl_eol` is specified. Hopefully there are no other such edge cases. Minor other changes: - Add unit tests for `range` class - Rename `render.md.Renderer` to `render.md.Render` - Match order of fields in `default_buffer_config()` with class
1 parent 8bb0d47 commit 8355c85

34 files changed

+130
-69
lines changed

Diff for: benches/medium_table_spec.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ local util = require('benches.util')
44

55
describe('medium-table.md', function()
66
it('default', function()
7-
local base_marks = 337
7+
local base_marks = 341
88
util.less_than(util.setup('temp/medium-table.md'), 120)
99
util.num_marks(base_marks)
1010

Diff for: benches/util.lua

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---@module 'luassert'
22

3-
local eq = assert.are.same
4-
local truthy = assert.truthy
3+
local Eq = assert.are.same
4+
local True = assert.True
55

66
---@class render.md.bench.Util
77
local M = {}
@@ -52,14 +52,14 @@ end
5252
---@param actual number
5353
---@param max number
5454
function M.less_than(actual, max)
55-
truthy(actual < max, string.format('expected %f < %f', actual, max))
55+
True(actual < max, string.format('expected %f < %f', actual, max))
5656
end
5757

5858
---@param expected integer
5959
function M.num_marks(expected)
6060
local ui = require('render-markdown.core.ui')
6161
local marks = vim.api.nvim_buf_get_extmarks(0, ui.ns, 0, -1, {})
62-
eq(expected, #marks)
62+
Eq(expected, #marks)
6363
end
6464

6565
return M

Diff for: doc/render-markdown.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*render-markdown.txt* For 0.11.0 Last change: 2025 April 11
1+
*render-markdown.txt* For 0.11.0 Last change: 2025 April 15
22

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

Diff for: lua/render-markdown/config.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ end
119119
---@return render.md.Range?
120120
function Config:hidden(mode, row)
121121
-- Anti-conceal is not enabled -> hide nothing
122-
-- Row is not known means buffer is not active -> hide nothing
122+
-- Row is not known -> buffer is not active -> hide nothing
123123
if not self.anti_conceal.enabled or row == nil then
124124
return nil
125125
end

Diff for: lua/render-markdown/core/extmark.lua

+8-3
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,17 @@ end
2222

2323
---@param range? render.md.Range
2424
---@return boolean
25-
function Extmark:inside(range)
25+
function Extmark:overlaps(range)
2626
if range == nil then
2727
return false
2828
end
29-
local row = self.mark.start_row
30-
return range:contains(row, row)
29+
local top = self.mark.start_row
30+
local bottom = self.mark.opts.end_row or top
31+
-- overlap for hl_eol should not include last line
32+
if self.mark.opts.hl_eol then
33+
bottom = bottom - 1
34+
end
35+
return range:overlaps(top, bottom)
3136
end
3237

3338
---@param ns integer

Diff for: lua/render-markdown/core/range.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ end
3636
---@param bottom integer
3737
---@return boolean
3838
function Range:overlaps(top, bottom)
39-
return top < self.bottom and bottom >= self.top
39+
return top <= self.bottom and bottom >= self.top
4040
end
4141

4242
---@param ranges render.md.Range[]

Diff for: lua/render-markdown/core/ui.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function M.get_row_marks(buf, win)
6464

6565
local marks = {}
6666
for _, extmark in ipairs(buffer:get_marks()) do
67-
if extmark:inside(hidden) then
67+
if extmark:overlaps(hidden) then
6868
marks[#marks + 1] = extmark:get()
6969
end
7070
end
@@ -167,7 +167,7 @@ function M.run_update(buf, win, change)
167167
state.on.initial({ buf = buf, win = win })
168168
end
169169
for _, extmark in ipairs(extmarks) do
170-
if extmark:get().conceal and extmark:inside(hidden) then
170+
if extmark:get().conceal and extmark:overlaps(hidden) then
171171
extmark:hide(M.ns, buf)
172172
else
173173
extmark:show(M.ns, buf)

Diff for: lua/render-markdown/debug/marks.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ end
5656
---@return string
5757
function Mark:__tostring()
5858
local lines = {}
59-
lines[#lines + 1] = string.rep('=', vim.o.columns - 10)
59+
lines[#lines + 1] = string.rep('=', vim.o.columns - 1)
6060
lines[#lines + 1] = string.format('row: %s', Mark.collapse(self.row))
6161
lines[#lines + 1] = string.format('column: %s', Mark.collapse(self.col))
6262
lines[#lines + 1] = string.format('hide: %s', vim.inspect(self.conceal))

Diff for: lua/render-markdown/handler/html.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ local ts = require('render-markdown.integ.ts')
88
---@field private context render.md.Context
99
---@field private marks render.md.Marks
1010
---@field private query vim.treesitter.Query
11-
---@field private renderers table<string, render.md.Renderer>
11+
---@field private renderers table<string, render.md.Render>
1212
local Handler = {}
1313
Handler.__index = Handler
1414

Diff for: lua/render-markdown/handler/markdown.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ local ts = require('render-markdown.integ.ts')
88
---@field private context render.md.Context
99
---@field private marks render.md.Marks
1010
---@field private query vim.treesitter.Query
11-
---@field private renderers table<string, render.md.Renderer>
11+
---@field private renderers table<string, render.md.Render>
1212
local Handler = {}
1313
Handler.__index = Handler
1414

Diff for: lua/render-markdown/handler/markdown_inline.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ local ts = require('render-markdown.integ.ts')
88
---@field private context render.md.Context
99
---@field private marks render.md.Marks
1010
---@field private query vim.treesitter.Query
11-
---@field private renderers table<string, render.md.Renderer>
11+
---@field private renderers table<string, render.md.Render>
1212
local Handler = {}
1313
Handler.__index = Handler
1414

Diff for: lua/render-markdown/health.lua

+1-1
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.2.10'
8+
M.version = '8.2.11'
99

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

Diff for: lua/render-markdown/render/base.lua

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@ local Iter = require('render-markdown.lib.iter')
22
local Str = require('render-markdown.lib.str')
33
local colors = require('render-markdown.colors')
44

5-
---@class render.md.Renderer
5+
---@class render.md.Render
66
---@field protected marks render.md.Marks
77
---@field protected config render.md.BufferConfig
88
---@field protected context render.md.Context
99
---@field protected node render.md.Node
10-
---@field setup fun(self: render.md.Renderer): boolean
11-
---@field render fun(self: render.md.Renderer)
10+
---@field setup fun(self: render.md.Render): boolean
11+
---@field render fun(self: render.md.Render)
1212
local Base = {}
1313
Base.__index = Base
1414

1515
---@param marks render.md.Marks
1616
---@param config render.md.BufferConfig
1717
---@param context render.md.Context
1818
---@param node render.md.Node
19-
---@return render.md.Renderer
19+
---@return render.md.Render
2020
function Base:new(marks, config, context, node)
2121
local instance = setmetatable({}, self)
2222
instance.marks = marks

Diff for: lua/render-markdown/render/bullet.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ local Str = require('render-markdown.lib.str')
88
---@field spaces integer
99
---@field checkbox? render.md.checkbox.custom.Config
1010

11-
---@class render.md.render.ListMarker: render.md.Renderer
11+
---@class render.md.render.Bullet: render.md.Render
1212
---@field private info render.md.bullet.Config
1313
---@field private data render.md.bullet.Data
1414
local Render = setmetatable({}, Base)

Diff for: lua/render-markdown/render/checkbox.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local Base = require('render-markdown.render.base')
22

3-
---@class render.md.render.Checkbox: render.md.Renderer
3+
---@class render.md.render.Checkbox: render.md.Render
44
---@field private info render.md.checkbox.component.Config
55
local Render = setmetatable({}, Base)
66
Render.__index = Render

Diff for: lua/render-markdown/render/code.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ local colors = require('render-markdown.colors')
1010
---@field margin integer
1111
---@field indent integer
1212

13-
---@class render.md.render.Code: render.md.Renderer
13+
---@class render.md.render.Code: render.md.Render
1414
---@field private info render.md.code.Config
1515
---@field private data render.md.code.Data
1616
local Render = setmetatable({}, Base)

Diff for: lua/render-markdown/render/code_inline.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
local Base = require('render-markdown.render.base')
22
local colors = require('render-markdown.colors')
33

4-
---@class render.md.render.CodeInline: render.md.Renderer
4+
---@class render.md.render.CodeInline: render.md.Render
55
---@field private info render.md.code.Config
66
local Render = setmetatable({}, Base)
77
Render.__index = Render

Diff for: lua/render-markdown/render/dash.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local Base = require('render-markdown.render.base')
22

3-
---@class render.md.render.Dash: render.md.Renderer
3+
---@class render.md.render.Dash: render.md.Render
44
---@field private info render.md.dash.Config
55
local Render = setmetatable({}, Base)
66
Render.__index = Render

Diff for: lua/render-markdown/render/heading.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ local colors = require('render-markdown.colors')
2323
---@field padding integer
2424
---@field content integer
2525

26-
---@class render.md.render.Heading: render.md.Renderer
26+
---@class render.md.render.Heading: render.md.Render
2727
---@field private info render.md.heading.Config
2828
---@field private data render.md.heading.Data
2929
local Render = setmetatable({}, Base)

Diff for: lua/render-markdown/render/html_comment.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local Base = require('render-markdown.render.base')
22

3-
---@class render.md.render.html.Comment: render.md.Renderer
3+
---@class render.md.render.html.Comment: render.md.Render
44
---@field private info render.md.html.comment.Config
55
local Render = setmetatable({}, Base)
66
Render.__index = Render

Diff for: lua/render-markdown/render/html_tag.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local Base = require('render-markdown.render.base')
22

3-
---@class render.md.render.html.Tag: render.md.Renderer
3+
---@class render.md.render.html.Tag: render.md.Render
44
---@field private info render.md.html.Tag
55
local Render = setmetatable({}, Base)
66
Render.__index = Render

Diff for: lua/render-markdown/render/inline_highlight.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local Base = require('render-markdown.render.base')
22

3-
---@class render.md.render.InlineHighlight: render.md.Renderer
3+
---@class render.md.render.InlineHighlight: render.md.Render
44
---@field private info render.md.inline.highlight.Config
55
local Render = setmetatable({}, Base)
66
Render.__index = Render

Diff for: lua/render-markdown/render/link.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ local Base = require('render-markdown.render.base')
55
---@field highlight string
66
---@field autolink boolean
77

8-
---@class render.md.render.Link: render.md.Renderer
8+
---@class render.md.render.Link: render.md.Render
99
---@field private data render.md.link.Data
1010
local Render = setmetatable({}, Base)
1111
Render.__index = Render

Diff for: lua/render-markdown/render/paragraph.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local Base = require('render-markdown.render.base')
22

3-
---@class render.md.render.Paragraph: render.md.Renderer
3+
---@class render.md.render.Paragraph: render.md.Render
44
---@field private info render.md.paragraph.Config
55
local Render = setmetatable({}, Base)
66
Render.__index = Render

Diff for: lua/render-markdown/render/quote.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ local ts = require('render-markdown.integ.ts')
77
---@field highlight string
88
---@field repeat_linebreak? boolean
99

10-
---@class render.md.render.Quote: render.md.Renderer
10+
---@class render.md.render.Quote: render.md.Render
1111
---@field private data render.md.quote.Data
1212
local Render = setmetatable({}, Base)
1313
Render.__index = Render

Diff for: lua/render-markdown/render/section.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
local Base = require('render-markdown.render.base')
22
local Str = require('render-markdown.lib.str')
33

4-
---@class render.md.render.Section: render.md.Renderer
4+
---@class render.md.render.Section: render.md.Render
55
---@field private info render.md.indent.Config
66
---@field private level_change integer
77
local Render = setmetatable({}, Base)

Diff for: lua/render-markdown/render/shortcut.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ local Base = require('render-markdown.render.base')
22
local Converter = require('render-markdown.lib.converter')
33
local Str = require('render-markdown.lib.str')
44

5-
---@class render.md.render.Shortcut: render.md.Renderer
5+
---@class render.md.render.Shortcut: render.md.Render
66
local Render = setmetatable({}, Base)
77
Render.__index = Render
88

Diff for: lua/render-markdown/render/table.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ local Alignment = {
3939
---@field left integer
4040
---@field right integer
4141

42-
---@class render.md.render.Table: render.md.Renderer
42+
---@class render.md.render.Table: render.md.Render
4343
---@field private info render.md.table.Config
4444
---@field private data render.md.table.Data
4545
local Render = setmetatable({}, Base)

Diff for: lua/render-markdown/state.lua

+13-13
Original file line numberDiff line numberDiff line change
@@ -107,26 +107,26 @@ function M.default_buffer_config()
107107
---@type render.md.buffer.Config
108108
local buffer_config = {
109109
enabled = true,
110+
render_modes = config.render_modes,
110111
max_file_size = config.max_file_size,
111112
debounce = config.debounce,
112-
render_modes = config.render_modes,
113113
anti_conceal = config.anti_conceal,
114-
padding = config.padding,
115-
heading = config.heading,
116-
paragraph = config.paragraph,
117-
code = config.code,
118-
dash = config.dash,
119114
bullet = config.bullet,
120-
checkbox = config.checkbox,
121-
quote = config.quote,
122-
pipe_table = config.pipe_table,
123115
callout = config.callout,
124-
link = config.link,
125-
sign = config.sign,
126-
inline_highlight = config.inline_highlight,
116+
checkbox = config.checkbox,
117+
code = config.code,
118+
dash = config.dash,
119+
heading = config.heading,
120+
html = config.html,
127121
indent = config.indent,
122+
inline_highlight = config.inline_highlight,
128123
latex = config.latex,
129-
html = config.html,
124+
link = config.link,
125+
padding = config.padding,
126+
paragraph = config.paragraph,
127+
pipe_table = config.pipe_table,
128+
quote = config.quote,
129+
sign = config.sign,
130130
win_options = config.win_options,
131131
}
132132
return vim.deepcopy(buffer_config)

Diff for: tests/comp_spec.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
local util = require('tests.util')
44

5-
local eq = assert.are.same
5+
local Eq = assert.are.same
66

77
---@param row integer
88
---@param col integer
@@ -13,7 +13,7 @@ local function assert_items(row, col, expected)
1313
table.sort(actual, function(a, b)
1414
return a.label < b.label
1515
end)
16-
eq(expected, actual)
16+
Eq(expected, actual)
1717
end
1818

1919
---@param prefix string

Diff for: tests/latex_spec.lua

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@
33
local stub = require('luassert.stub')
44
local util = require('tests.util')
55

6-
local eq = assert.are.same
7-
local truthy = assert.truthy
6+
local Eq = assert.are.same
7+
local True = assert.True
88

99
---@param converter string
1010
---@param responses table<string, string>
1111
local function set_responses(converter, responses)
1212
stub.new(vim.fn, 'executable', function(expr)
13-
eq(converter, expr)
13+
Eq(converter, expr)
1414
return 1
1515
end)
1616
stub.new(vim.fn, 'system', function(cmd, input)
17-
eq(converter, cmd)
17+
Eq(converter, cmd)
1818
local result = responses[input]
19-
truthy(result, 'No output for: ' .. input)
19+
True(result ~= nil, 'No output for: ' .. input)
2020
return result
2121
end)
2222
end

0 commit comments

Comments
 (0)