mirror of
https://github.com/neovim/neovim
synced 2025-07-17 17:51:48 +00:00
fix(api): clamp range lines in nvim__redraw()
(#31710)
Problem: `nvim__redraw()` doesn't clamp the lines in the `range` parameter before truncating to int. The resulting range may be empty when the original range contained buffer lines and vice versa. E.g. for a buffer with 4 lines, these are the redrawn lines: ```lua { 2, 2 ^ 31 } -> none (should be { 2, 3 }) { 2, 2 ^ 32 } -> none (should be { 2, 3 }) { 2 ^ 32 - 1, 2 } -> { 0, 1 } (should be none) ``` Solution: Clamp `range` values before truncating to int.
This commit is contained in:
@ -2374,13 +2374,23 @@ void nvim__redraw(Dict(redraw) *opts, Error *err)
|
|||||||
"%s", "Invalid 'range': Expected 2-tuple of Integers", {
|
"%s", "Invalid 'range': Expected 2-tuple of Integers", {
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
linenr_T first = (linenr_T)kv_A(opts->range, 0).data.integer + 1;
|
int64_t begin_raw = kv_A(opts->range, 0).data.integer;
|
||||||
linenr_T last = (linenr_T)kv_A(opts->range, 1).data.integer;
|
int64_t end_raw = kv_A(opts->range, 1).data.integer;
|
||||||
|
|
||||||
buf_T *rbuf = win ? win->w_buffer : (buf ? buf : curbuf);
|
buf_T *rbuf = win ? win->w_buffer : (buf ? buf : curbuf);
|
||||||
if (last == -1) {
|
linenr_T line_count = rbuf->b_ml.ml_line_count;
|
||||||
last = rbuf->b_ml.ml_line_count;
|
|
||||||
|
int begin = (int)MIN(begin_raw, line_count);
|
||||||
|
int end;
|
||||||
|
if (end_raw == -1) {
|
||||||
|
end = line_count;
|
||||||
|
} else {
|
||||||
|
end = (int)MIN(MAX(begin, end_raw), line_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (begin < end) {
|
||||||
|
redraw_buf_range_later(rbuf, 1 + begin, end);
|
||||||
}
|
}
|
||||||
redraw_buf_range_later(rbuf, first, last);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redraw later types require update_screen() so call implicitly unless set to false.
|
// Redraw later types require update_screen() so call implicitly unless set to false.
|
||||||
|
@ -5385,8 +5385,53 @@ describe('API', function()
|
|||||||
13 |
|
13 |
|
||||||
]],
|
]],
|
||||||
})
|
})
|
||||||
-- takes buffer line count from correct buffer with "win" and {0, -1} "range"
|
end)
|
||||||
api.nvim__redraw({ win = 0, range = { 0, -1 } })
|
|
||||||
|
it('nvim__redraw range parameter', function()
|
||||||
|
Screen.new(10, 5)
|
||||||
|
fn.setline(1, fn.range(4))
|
||||||
|
|
||||||
|
exec_lua([[
|
||||||
|
_G.lines_list = {}
|
||||||
|
ns = vim.api.nvim_create_namespace('')
|
||||||
|
vim.api.nvim_set_decoration_provider(ns, {
|
||||||
|
on_win = function()
|
||||||
|
end,
|
||||||
|
on_line = function(_, _, _, line)
|
||||||
|
table.insert(_G.lines_list, line)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
function _G.get_lines()
|
||||||
|
local lines = _G.lines_list
|
||||||
|
_G.lines_list = {}
|
||||||
|
return lines
|
||||||
|
end
|
||||||
|
]])
|
||||||
|
|
||||||
|
api.nvim__redraw({ flush = true, valid = false })
|
||||||
|
exec_lua('_G.get_lines()')
|
||||||
|
|
||||||
|
local actual_lines = {}
|
||||||
|
local function test(range)
|
||||||
|
api.nvim__redraw({ win = 0, range = range })
|
||||||
|
table.insert(actual_lines, exec_lua('return _G.get_lines()'))
|
||||||
|
end
|
||||||
|
|
||||||
|
test({ 0, -1 })
|
||||||
|
test({ 2, 2 ^ 31 })
|
||||||
|
test({ 2, 2 ^ 32 })
|
||||||
|
test({ 2 ^ 31 - 1, 2 })
|
||||||
|
test({ 2 ^ 32 - 1, 2 })
|
||||||
|
|
||||||
|
local expected_lines = {
|
||||||
|
{ 0, 1, 2, 3 },
|
||||||
|
{ 2, 3 },
|
||||||
|
{ 2, 3 },
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
}
|
||||||
|
eq(expected_lines, actual_lines)
|
||||||
|
|
||||||
n.assert_alive()
|
n.assert_alive()
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
Reference in New Issue
Block a user