mirror of
https://github.com/neovim/neovim.git
synced 2026-07-21 08:31:47 +00:00
Merge pull request #31400 from vanaigr/decor-provider-range
feat(decor): add range-based highlighting
This commit is contained in:
@@ -8,7 +8,7 @@ describe('decor perf', function()
|
||||
it('can handle long lines', function()
|
||||
Screen.new(100, 101)
|
||||
|
||||
local result = exec_lua [==[
|
||||
local result = exec_lua(function()
|
||||
local ephemeral_pattern = {
|
||||
{ 0, 4, 'Comment', 11 },
|
||||
{ 0, 3, 'Keyword', 12 },
|
||||
@@ -61,7 +61,7 @@ describe('decor perf', function()
|
||||
return true
|
||||
end,
|
||||
on_line = function()
|
||||
add_pattern(ephemeral_pattern, true)
|
||||
add_pattern(ephemeral_pattern, true)
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -69,16 +69,16 @@ describe('decor perf', function()
|
||||
|
||||
local total = {}
|
||||
local provider = {}
|
||||
for i = 1, 100 do
|
||||
for _ = 1, 100 do
|
||||
local tic = vim.uv.hrtime()
|
||||
vim.cmd'redraw!'
|
||||
vim.cmd 'redraw!'
|
||||
local toc = vim.uv.hrtime()
|
||||
table.insert(total, toc - tic)
|
||||
table.insert(provider, pe - ps)
|
||||
end
|
||||
|
||||
return { total, provider }
|
||||
]==]
|
||||
end)
|
||||
|
||||
local total, provider = unpack(result)
|
||||
table.sort(total)
|
||||
@@ -137,4 +137,39 @@ describe('decor perf', function()
|
||||
)
|
||||
print('\nTotal ' .. res)
|
||||
end)
|
||||
|
||||
it('can handle long lines with treesitter highlighting', function()
|
||||
Screen.new(100, 51)
|
||||
|
||||
local result = exec_lua(function()
|
||||
local long_line = 'local a = { ' .. ('a = 5, '):rep(2000) .. '}'
|
||||
vim.api.nvim_buf_set_lines(0, 0, 0, false, { long_line })
|
||||
vim.api.nvim_win_set_cursor(0, { 1, 0 })
|
||||
vim.treesitter.start(0, 'lua')
|
||||
|
||||
local total = {}
|
||||
for _ = 1, 50 do
|
||||
local tic = vim.uv.hrtime()
|
||||
vim.cmd 'redraw!'
|
||||
local toc = vim.uv.hrtime()
|
||||
table.insert(total, toc - tic)
|
||||
end
|
||||
|
||||
return { total }
|
||||
end)
|
||||
|
||||
local total = unpack(result)
|
||||
table.sort(total)
|
||||
|
||||
local ms = 1 / 1000000
|
||||
local res = string.format(
|
||||
'min, 25%%, median, 75%%, max:\n\t%0.1fms,\t%0.1fms,\t%0.1fms,\t%0.1fms,\t%0.1fms',
|
||||
total[1] * ms,
|
||||
total[1 + math.floor(#total * 0.25)] * ms,
|
||||
total[1 + math.floor(#total * 0.5)] * ms,
|
||||
total[1 + math.floor(#total * 0.75)] * ms,
|
||||
total[#total] * ms
|
||||
)
|
||||
print('\nTotal ' .. res)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
local n = require('test.functional.testnvim')()
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
|
||||
local clear = n.clear
|
||||
local exec_lua = n.exec_lua
|
||||
|
||||
describe('treesitter perf', function()
|
||||
setup(function()
|
||||
before_each(function()
|
||||
clear()
|
||||
end)
|
||||
|
||||
@@ -47,4 +48,144 @@ describe('treesitter perf', function()
|
||||
return vim.uv.hrtime() - start
|
||||
]]
|
||||
end)
|
||||
|
||||
local function test_long_line(_pos, _wrap, _line, grid)
|
||||
local screen = Screen.new(20, 11)
|
||||
|
||||
local result = exec_lua(function(...)
|
||||
local pos, wrap, line = ...
|
||||
|
||||
vim.api.nvim_buf_set_lines(0, 0, 0, false, { line })
|
||||
vim.api.nvim_win_set_cursor(0, pos)
|
||||
vim.api.nvim_set_option_value('wrap', wrap, { win = 0 })
|
||||
|
||||
vim.treesitter.start(0, 'lua')
|
||||
|
||||
local total = {}
|
||||
for _ = 1, 100 do
|
||||
local tic = vim.uv.hrtime()
|
||||
vim.cmd 'redraw!'
|
||||
local toc = vim.uv.hrtime()
|
||||
table.insert(total, toc - tic)
|
||||
end
|
||||
|
||||
return { total }
|
||||
end, _pos, _wrap, _line)
|
||||
|
||||
screen:expect({ grid = grid or '' })
|
||||
|
||||
local total = unpack(result)
|
||||
table.sort(total)
|
||||
|
||||
local ms = 1 / 1000000
|
||||
local res = string.format(
|
||||
'min, 25%%, median, 75%%, max:\n\t%0.2fms,\t%0.2fms,\t%0.2fms,\t%0.2fms,\t%0.2fms',
|
||||
total[1] * ms,
|
||||
total[1 + math.floor(#total * 0.25)] * ms,
|
||||
total[1 + math.floor(#total * 0.5)] * ms,
|
||||
total[1 + math.floor(#total * 0.75)] * ms,
|
||||
total[#total] * ms
|
||||
)
|
||||
print('\nTotal ' .. res)
|
||||
end
|
||||
|
||||
local long_line = 'local a = { ' .. ('a = 5, '):rep(500) .. '}'
|
||||
it('can redraw the beginning of a long line with wrapping', function()
|
||||
local grid = [[
|
||||
{15:^local} {25:a} {15:=} {16:{} {25:a} {15:=} {26:5}{16:,} {25:a}|
|
||||
{15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} |
|
||||
{25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,}|
|
||||
{25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}|
|
||||
{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} |
|
||||
{26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=}|
|
||||
{26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} |
|
||||
{15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a}|
|
||||
{15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} |
|
||||
{25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,}|
|
||||
|
|
||||
]]
|
||||
test_long_line({ 1, 0 }, true, long_line, grid)
|
||||
end)
|
||||
|
||||
it('can redraw the middle of a long line with wrapping', function()
|
||||
local grid = [[
|
||||
{1:<<<}{26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} |
|
||||
{25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,}|
|
||||
{25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}|
|
||||
{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} |
|
||||
{26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=}|
|
||||
{26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} |
|
||||
{15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a}|
|
||||
{15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} |
|
||||
{25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,}|
|
||||
{25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a}^ {15:=} {26:5}|
|
||||
|
|
||||
]]
|
||||
test_long_line({ 1, math.floor(#long_line / 2) }, true, long_line, grid)
|
||||
end)
|
||||
|
||||
it('can redraw the end of a long line with wrapping', function()
|
||||
local grid = [[
|
||||
{1:<<<}{25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=}|
|
||||
{26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} |
|
||||
{15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a}|
|
||||
{15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} |
|
||||
{25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,}|
|
||||
{25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}|
|
||||
{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} |
|
||||
{26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=}|
|
||||
{26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {25:a} |
|
||||
{15:=} {26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {16:^}} |
|
||||
|
|
||||
]]
|
||||
test_long_line({ 1, #long_line - 1 }, true, long_line, grid)
|
||||
end)
|
||||
|
||||
it('can redraw the beginning of a long line without wrapping', function()
|
||||
local grid = [[
|
||||
{15:^local} {25:a} {15:=} {16:{} {25:a} {15:=} {26:5}{16:,} {25:a}|
|
||||
|
|
||||
{1:~ }|*8
|
||||
|
|
||||
]]
|
||||
test_long_line({ 1, 0 }, false, long_line, grid)
|
||||
end)
|
||||
|
||||
it('can redraw the middle of a long line without wrapping', function()
|
||||
local grid = [[
|
||||
{16:,} {25:a} {15:=} {26:5}{16:,} {25:a}^ {15:=} {26:5}{16:,} {25:a} {15:=} |
|
||||
|
|
||||
{1:~ }|*8
|
||||
|
|
||||
]]
|
||||
test_long_line({ 1, math.floor(#long_line / 2) }, false, long_line, grid)
|
||||
end)
|
||||
|
||||
it('can redraw the end of a long line without wrapping', function()
|
||||
local grid = [[
|
||||
{26:5}{16:,} {25:a} {15:=} {26:5}{16:,} {16:^}} |
|
||||
|
|
||||
{1:~ }|*8
|
||||
|
|
||||
]]
|
||||
test_long_line({ 1, #long_line - 1 }, false, long_line, grid)
|
||||
end)
|
||||
|
||||
local long_line_mb = 'local a = { ' .. ('À = 5, '):rep(500) .. '}'
|
||||
it('can redraw the middle of a long line with multibyte characters', function()
|
||||
local grid = [[
|
||||
{1:<<<}{26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} |
|
||||
{25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,}|
|
||||
{25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}|
|
||||
{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=} |
|
||||
{26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=}|
|
||||
{26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} |
|
||||
{15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À}|
|
||||
{15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} |
|
||||
{25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,}|
|
||||
{25:À} {15:=} {26:5}{16:,} {25:À} {15:=} {26:5}{16:,} {25:À}^ {15:=} {26:5}|
|
||||
|
|
||||
]]
|
||||
test_long_line({ 1, math.floor(#long_line_mb / 2) }, true, long_line_mb, grid)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -747,6 +747,47 @@ void ui_refresh(void)
|
||||
eq({ { 1, 10, 1, 13 } }, ret)
|
||||
end)
|
||||
|
||||
it('iter_captures supports columns', function()
|
||||
local txt = table.concat({
|
||||
'int aaa = 1, bbb = 2;',
|
||||
'int foo = 1, bar = 2;',
|
||||
'int baz = 3, qux = 4;',
|
||||
'int ccc = 1, ddd = 2;',
|
||||
}, '\n')
|
||||
|
||||
local function test(opts)
|
||||
local parser = vim.treesitter.get_string_parser(txt, 'c')
|
||||
|
||||
local nodes = {}
|
||||
local query = vim.treesitter.query.parse('c', '((identifier) @foo)')
|
||||
local root = assert(parser:parse()[1]:root())
|
||||
local iter = query:iter_captures(root, txt, 1, 2, opts)
|
||||
|
||||
while true do
|
||||
local capture, node = iter()
|
||||
if not capture then
|
||||
break
|
||||
end
|
||||
table.insert(nodes, { node:range() })
|
||||
end
|
||||
|
||||
return nodes
|
||||
end
|
||||
|
||||
local ret
|
||||
ret = exec_lua(test, { start_col = 7, end_col = 13 })
|
||||
eq({ { 1, 13, 1, 16 }, { 2, 4, 2, 7 } }, ret)
|
||||
|
||||
ret = exec_lua(test, { start_col = 7 })
|
||||
eq({ { 1, 13, 1, 16 } }, ret)
|
||||
|
||||
ret = exec_lua(test, { end_col = 13 })
|
||||
eq({ { 1, 4, 1, 7 }, { 1, 13, 1, 16 }, { 2, 4, 2, 7 } }, ret)
|
||||
|
||||
ret = exec_lua(test, {})
|
||||
eq({ { 1, 4, 1, 7 }, { 1, 13, 1, 16 } }, ret)
|
||||
end)
|
||||
|
||||
it('fails to load queries', function()
|
||||
local function test(exp, cquery)
|
||||
eq(exp, pcall_err(exec_lua, "vim.treesitter.query.parse('c', ...)", cquery))
|
||||
|
||||
@@ -28,39 +28,43 @@ local function setup_provider(code)
|
||||
]]) .. [[
|
||||
api.nvim_set_decoration_provider(_G.ns1, {
|
||||
on_start = on_do; on_buf = on_do;
|
||||
on_win = on_do; on_line = on_do;
|
||||
on_win = on_do; on_line = on_do; on_range = on_do;
|
||||
on_end = on_do; _on_spell_nav = on_do;
|
||||
})
|
||||
return _G.ns1
|
||||
]])
|
||||
end
|
||||
|
||||
local function setup_screen(screen)
|
||||
screen:set_default_attr_ids {
|
||||
[1] = { bold = true, foreground = Screen.colors.Blue },
|
||||
[2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
|
||||
[3] = { foreground = Screen.colors.Brown },
|
||||
[4] = { foreground = Screen.colors.Blue1 },
|
||||
[5] = { foreground = Screen.colors.Magenta },
|
||||
[6] = { bold = true, foreground = Screen.colors.Brown },
|
||||
[7] = { background = Screen.colors.Gray90 },
|
||||
[8] = { bold = true, reverse = true },
|
||||
[9] = { reverse = true },
|
||||
[10] = { italic = true, background = Screen.colors.Magenta },
|
||||
[11] = { foreground = Screen.colors.Red, background = tonumber('0x005028') },
|
||||
[12] = { foreground = tonumber('0x990000') },
|
||||
[13] = { background = Screen.colors.LightBlue },
|
||||
[14] = { background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue },
|
||||
[15] = { special = Screen.colors.Blue, undercurl = true },
|
||||
[16] = { special = Screen.colors.Red, undercurl = true },
|
||||
[17] = { foreground = Screen.colors.Red },
|
||||
[18] = { bold = true, foreground = Screen.colors.SeaGreen },
|
||||
[19] = { bold = true },
|
||||
}
|
||||
end
|
||||
|
||||
describe('decorations providers', function()
|
||||
local screen ---@type test.functional.ui.screen
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = Screen.new(40, 8)
|
||||
screen:set_default_attr_ids {
|
||||
[1] = { bold = true, foreground = Screen.colors.Blue },
|
||||
[2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
|
||||
[3] = { foreground = Screen.colors.Brown },
|
||||
[4] = { foreground = Screen.colors.Blue1 },
|
||||
[5] = { foreground = Screen.colors.Magenta },
|
||||
[6] = { bold = true, foreground = Screen.colors.Brown },
|
||||
[7] = { background = Screen.colors.Gray90 },
|
||||
[8] = { bold = true, reverse = true },
|
||||
[9] = { reverse = true },
|
||||
[10] = { italic = true, background = Screen.colors.Magenta },
|
||||
[11] = { foreground = Screen.colors.Red, background = tonumber('0x005028') },
|
||||
[12] = { foreground = tonumber('0x990000') },
|
||||
[13] = { background = Screen.colors.LightBlue },
|
||||
[14] = { background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue },
|
||||
[15] = { special = Screen.colors.Blue, undercurl = true },
|
||||
[16] = { special = Screen.colors.Red, undercurl = true },
|
||||
[17] = { foreground = Screen.colors.Red },
|
||||
[18] = { bold = true, foreground = Screen.colors.SeaGreen },
|
||||
[19] = { bold = true },
|
||||
}
|
||||
setup_screen(screen)
|
||||
end)
|
||||
|
||||
local mulholland = [[
|
||||
@@ -110,12 +114,19 @@ describe('decorations providers', function()
|
||||
{ 'start', 4 },
|
||||
{ 'win', 1000, 1, 0, 6 },
|
||||
{ 'line', 1000, 1, 0 },
|
||||
{ 'range', 1000, 1, 0, 0, 1, 0 },
|
||||
{ 'line', 1000, 1, 1 },
|
||||
{ 'range', 1000, 1, 1, 0, 2, 0 },
|
||||
{ 'line', 1000, 1, 2 },
|
||||
{ 'range', 1000, 1, 2, 0, 3, 0 },
|
||||
{ 'line', 1000, 1, 3 },
|
||||
{ 'range', 1000, 1, 3, 0, 4, 0 },
|
||||
{ 'line', 1000, 1, 4 },
|
||||
{ 'range', 1000, 1, 4, 0, 5, 0 },
|
||||
{ 'line', 1000, 1, 5 },
|
||||
{ 'range', 1000, 1, 5, 0, 6, 0 },
|
||||
{ 'line', 1000, 1, 6 },
|
||||
{ 'range', 1000, 1, 6, 0, 7, 0 },
|
||||
{ 'end', 4 },
|
||||
}
|
||||
|
||||
@@ -137,6 +148,7 @@ describe('decorations providers', function()
|
||||
{ 'buf', 1, 5 },
|
||||
{ 'win', 1000, 1, 0, 6 },
|
||||
{ 'line', 1000, 1, 6 },
|
||||
{ 'range', 1000, 1, 6, 0, 7, 0 },
|
||||
{ 'end', 5 },
|
||||
}
|
||||
end)
|
||||
@@ -206,9 +218,13 @@ describe('decorations providers', function()
|
||||
{ 'start', 5 },
|
||||
{ 'win', 1000, 1, 0, 3 },
|
||||
{ 'line', 1000, 1, 0 },
|
||||
{ 'range', 1000, 1, 0, 0, 1, 0 },
|
||||
{ 'line', 1000, 1, 1 },
|
||||
{ 'range', 1000, 1, 1, 0, 2, 0 },
|
||||
{ 'line', 1000, 1, 2 },
|
||||
{ 'range', 1000, 1, 2, 0, 3, 0 },
|
||||
{ 'line', 1000, 1, 3 },
|
||||
{ 'range', 1000, 1, 3, 0, 4, 0 },
|
||||
{ 'end', 5 },
|
||||
}
|
||||
|
||||
@@ -806,6 +822,126 @@ describe('decorations providers', function()
|
||||
]])
|
||||
end)
|
||||
|
||||
it('on_range is invoked on all visible characters', function()
|
||||
clear()
|
||||
screen = Screen.new(20, 4)
|
||||
setup_screen(screen)
|
||||
|
||||
local function record()
|
||||
exec_lua(function()
|
||||
_G.p_min = { math.huge, math.huge }
|
||||
_G.p_max = { -math.huge, -math.huge }
|
||||
function _G.pos_gt(a, b)
|
||||
return a[1] > b[1] or (a[1] == b[1] and a[2] > b[2])
|
||||
end
|
||||
function _G.pos_lt(a, b)
|
||||
return a[1] < b[1] or (a[1] == b[1] and a[2] < b[2])
|
||||
end
|
||||
end)
|
||||
setup_provider [[
|
||||
local function on_do(kind, _, bufnr, br, bc, er, ec)
|
||||
if kind == 'range' then
|
||||
local b = { br, bc }
|
||||
local e = { er, ec }
|
||||
if _G.pos_gt(_G.p_min, b) then
|
||||
_G.p_min = b
|
||||
end
|
||||
if _G.pos_lt(_G.p_max, e) then
|
||||
_G.p_max = e
|
||||
end
|
||||
end
|
||||
end
|
||||
]]
|
||||
end
|
||||
local function check(min, max)
|
||||
local p_min = exec_lua('return _G.p_min')
|
||||
assert(
|
||||
p_min[1] < min[1] or (p_min[1] == min[1] and p_min[2] <= min[2]),
|
||||
'minimum position ' .. vim.inspect(p_min) .. ' should be before the first char'
|
||||
)
|
||||
local p_max = exec_lua('return _G.p_max')
|
||||
assert(
|
||||
p_max[1] > max[1] or (p_max[1] == max[1] and p_max[2] >= max[2]),
|
||||
'maximum position ' .. vim.inspect(p_max) .. ' should be on or after the last char'
|
||||
)
|
||||
end
|
||||
|
||||
-- Multiple lines.
|
||||
exec_lua([[
|
||||
local lines = { ('a'):rep(40), ('b'):rep(40), ('c'):rep(40) }
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, true, lines)
|
||||
vim.api.nvim_win_set_cursor(0, { 2, 0 })
|
||||
]])
|
||||
record()
|
||||
screen:expect([[
|
||||
^bbbbbbbbbbbbbbbbbbbb|
|
||||
bbbbbbbbbbbbbbbbbbbb|
|
||||
ccccccccccccccccc{1:@@@}|
|
||||
|
|
||||
]])
|
||||
check({ 1, 0 }, { 2, 21 })
|
||||
|
||||
-- One long line.
|
||||
exec_lua([[
|
||||
local lines = { ('a'):rep(100) }
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, true, lines)
|
||||
vim.api.nvim_win_set_cursor(0, { 1, 70 })
|
||||
]])
|
||||
record()
|
||||
screen:expect([[
|
||||
{1:<<<}aaaaaaaaaaaaaaaaa|
|
||||
aaaaaaaaaaaaaaaaaaaa|
|
||||
aaaaaaaaaa^aaaaaaaaaa|
|
||||
|
|
||||
]])
|
||||
check({ 0, 20 }, { 0, 81 })
|
||||
|
||||
-- Multibyte characters.
|
||||
exec_lua([[
|
||||
local lines = { ('\195\162'):rep(100) }
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, true, lines)
|
||||
vim.api.nvim_win_set_cursor(0, { 1, 70 * 2 })
|
||||
]])
|
||||
record()
|
||||
screen:expect([[
|
||||
{1:<<<}âââââââââââââââââ|
|
||||
ââââââââââââââââââââ|
|
||||
ââââââââââ^ââââââââââ|
|
||||
|
|
||||
]])
|
||||
check({ 0, 20 * 2 }, { 0, 81 * 2 })
|
||||
|
||||
-- Tabs.
|
||||
exec_lua([[
|
||||
local lines = { 'a' .. ('\t'):rep(100) }
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, true, lines)
|
||||
vim.api.nvim_win_set_cursor(0, { 1, 39 })
|
||||
]])
|
||||
record()
|
||||
screen:expect([[
|
||||
{1:<<<} |
|
||||
|
|
||||
^ |
|
||||
|
|
||||
]])
|
||||
check({ 0, 33 }, { 0, 94 })
|
||||
|
||||
-- One long line without wrapping.
|
||||
command('set nowrap')
|
||||
exec_lua([[
|
||||
local lines = { ('a'):rep(50) .. ('b'):rep(50) }
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, true, lines)
|
||||
vim.api.nvim_win_set_cursor(0, { 1, 50 })
|
||||
]])
|
||||
record()
|
||||
screen:expect([[
|
||||
aaaaaaaaaa^bbbbbbbbbb|
|
||||
{1:~ }|*2
|
||||
|
|
||||
]])
|
||||
check({ 0, 40 }, { 0, 60 })
|
||||
end)
|
||||
|
||||
it('can add new providers during redraw #26652', function()
|
||||
setup_provider [[
|
||||
local ns = api.nvim_create_namespace('test_no_add')
|
||||
|
||||
Reference in New Issue
Block a user