aboutsummaryrefslogtreecommitdiff
path: root/test/functional/api/extmark_spec.lua
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
commit1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch)
treecd08258054db80bb9a11b1061bb091c70b76926a /test/functional/api/extmark_spec.lua
parenteaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-1b7b916b7631ddf73c38e3a0070d64e4636cb2f3.tar.gz
rneovim-1b7b916b7631ddf73c38e3a0070d64e4636cb2f3.tar.bz2
rneovim-1b7b916b7631ddf73c38e3a0070d64e4636cb2f3.zip
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'test/functional/api/extmark_spec.lua')
-rw-r--r--test/functional/api/extmark_spec.lua234
1 files changed, 203 insertions, 31 deletions
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua
index 9902826c72..44a151cf6a 100644
--- a/test/functional/api/extmark_spec.lua
+++ b/test/functional/api/extmark_spec.lua
@@ -11,6 +11,7 @@ local insert = helpers.insert
local feed = helpers.feed
local clear = helpers.clear
local command = helpers.command
+local exec = helpers.exec
local meths = helpers.meths
local assert_alive = helpers.assert_alive
@@ -101,12 +102,31 @@ describe('API/extmarks', function()
ns2 = request('nvim_create_namespace', "my-fancy-plugin2")
end)
+ it('validation', function()
+ eq("Invalid 'end_col': expected Integer, got Array", pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = {}, end_row = 1 }))
+ eq("Invalid 'end_row': expected Integer, got Array", pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = {} }))
+ eq("Invalid 'virt_text_pos': expected String, got Integer", pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 0 }))
+ eq("Invalid 'virt_text_pos': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 'foo' }))
+ eq("Invalid 'hl_mode': expected String, got Integer", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 0 }))
+ eq("Invalid 'hl_mode': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 'foo' }))
+ eq("Invalid 'id': expected Integer, got Array", pcall_err(set_extmark, ns, {}, 0, 0, { end_col = 1, end_row = 1 }))
+ eq("Invalid mark position: expected 2 Integer items", pcall_err(get_extmarks, ns, {}, {-1, -1}))
+ eq("Invalid mark position: expected mark id Integer or 2-item Array", pcall_err(get_extmarks, ns, true, {-1, -1}))
+ -- No memory leak with virt_text, virt_lines, sign_text
+ eq("right_gravity is not a boolean", pcall_err(set_extmark, ns, marks[2], 0, 0, {
+ virt_text = {{'foo', 'Normal'}},
+ virt_lines = {{{'bar', 'Normal'}}},
+ sign_text = 'a',
+ right_gravity = 'baz',
+ }))
+ end)
+
it("can end extranges past final newline using end_col = 0", function()
set_extmark(ns, marks[1], 0, 0, {
end_col = 0,
end_row = 1
})
- eq("end_col value outside range",
+ eq("Invalid 'end_col': out of range",
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 }))
end)
@@ -188,6 +208,23 @@ describe('API/extmarks', function()
eq({}, get_extmarks(ns2, {0, 0}, {-1, -1}))
end)
+ it('can undo with extmarks (#25147)', function()
+ feed('itest<esc>')
+ set_extmark(ns, 1, 0, 0)
+ set_extmark(ns, 2, 1, 0)
+ eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1}))
+ feed('dd')
+ eq({ { 1, 1, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1}))
+ curbufmeths.clear_namespace(ns, 0, -1)
+ eq({}, get_extmarks(ns, {0, 0}, {-1, -1}))
+ set_extmark(ns, 1, 0, 0, { right_gravity = false })
+ set_extmark(ns, 2, 1, 0, { right_gravity = false })
+ eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1}))
+ feed('u')
+ eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1}))
+ curbufmeths.clear_namespace(ns, 0, -1)
+ end)
+
it('querying for information and ranges', function()
--marks = {1, 2, 3}
--positions = {{0, 0,}, {0, 2}, {0, 3}}
@@ -733,7 +770,14 @@ describe('API/extmarks', function()
})
end)
- -- TODO(bfredl): add more tests!
+ it('can get overlapping extmarks', function()
+ set_extmark(ns, 1, 0, 0, {end_row = 5, end_col=0})
+ set_extmark(ns, 2, 2, 5, {end_row = 2, end_col=30})
+ set_extmark(ns, 3, 0, 5, {end_row = 2, end_col=10})
+ set_extmark(ns, 4, 0, 0, {end_row = 1, end_col=0})
+ eq({{ 2, 2, 5 }}, get_extmarks(ns, {2, 0}, {2, -1}, { overlap=false }))
+ eq({{ 1, 0, 0 }, { 3, 0, 5}, {2, 2, 5}}, get_extmarks(ns, {2, 0}, {2, -1}, { overlap=true }))
+ end)
end)
it('replace works', function()
@@ -1344,10 +1388,10 @@ describe('API/extmarks', function()
it('throws consistent error codes', function()
local ns_invalid = ns2 + 1
- eq("Invalid ns_id", pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2]))
- eq("Invalid ns_id", pcall_err(curbufmeths.del_extmark, ns_invalid, marks[1]))
- eq("Invalid ns_id", pcall_err(get_extmarks, ns_invalid, positions[1], positions[2]))
- eq("Invalid ns_id", pcall_err(get_extmark_by_id, ns_invalid, marks[1]))
+ eq("Invalid 'ns_id': 3", pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2]))
+ eq("Invalid 'ns_id': 3", pcall_err(curbufmeths.del_extmark, ns_invalid, marks[1]))
+ eq("Invalid 'ns_id': 3", pcall_err(get_extmarks, ns_invalid, positions[1], positions[2]))
+ eq("Invalid 'ns_id': 3", pcall_err(get_extmark_by_id, ns_invalid, marks[1]))
end)
it('when col = line-length, set the mark on eol', function()
@@ -1362,13 +1406,13 @@ describe('API/extmarks', function()
it('when col = line-length, set the mark on eol', function()
local invalid_col = init_text:len() + 1
- eq("col value outside range", pcall_err(set_extmark, ns, marks[1], 0, invalid_col))
+ eq("Invalid 'col': out of range", pcall_err(set_extmark, ns, marks[1], 0, invalid_col))
end)
it('fails when line > line_count', function()
local invalid_col = init_text:len() + 1
local invalid_lnum = 3
- eq('line value outside range', pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col))
+ eq("Invalid 'line': out of range", pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col))
eq({}, get_extmark_by_id(ns, marks[1]))
end)
@@ -1385,7 +1429,7 @@ describe('API/extmarks', function()
it('in read-only buffer', function()
command("view! runtime/doc/help.txt")
- eq(true, curbufmeths.get_option('ro'))
+ eq(true, meths.get_option_value('ro', {}))
local id = set_extmark(ns, 0, 0, 2)
eq({{id, 0, 2}}, get_extmarks(ns,0, -1))
end)
@@ -1398,12 +1442,12 @@ describe('API/extmarks', function()
end)
it('does not crash with append/delete/undo sequence', function()
- meths.exec([[
+ exec([[
let ns = nvim_create_namespace('myplugin')
call nvim_buf_set_extmark(0, ns, 0, 0, {})
call append(0, '')
%delete
- undo]],false)
+ undo]])
assert_alive()
end)
@@ -1435,7 +1479,7 @@ describe('API/extmarks', function()
feed('u')
-- handles pasting
- meths.exec([[let @a='asdfasdf']], false)
+ exec([[let @a='asdfasdf']])
feed([["ap]])
eq({ {1, 0, 0}, {2, 0, 8} },
meths.buf_get_extmarks(0, ns, 0, -1, {}))
@@ -1447,6 +1491,7 @@ describe('API/extmarks', function()
end_line = 1
})
eq({ {1, 0, 0, {
+ ns_id = 1,
end_col = 0,
end_row = 1,
right_gravity = true,
@@ -1457,57 +1502,184 @@ describe('API/extmarks', function()
it('in prompt buffer', function()
feed('dd')
local id = set_extmark(ns, marks[1], 0, 0, {})
- curbufmeths.set_option('buftype', 'prompt')
+ meths.set_option_value('buftype', 'prompt', {})
feed('i<esc>')
eq({{id, 0, 2}}, get_extmarks(ns, 0, -1))
end)
it('can get details', function()
set_extmark(ns, marks[1], 0, 0, {
+ conceal = "c",
+ cursorline_hl_group = "Statement",
end_col = 0,
- end_row = 1,
- right_gravity = false,
end_right_gravity = true,
- priority = 0,
+ end_row = 1,
hl_eol = true,
- hl_mode = "blend",
hl_group = "String",
- virt_text = { { "text", "Statement" } },
- virt_text_pos = "right_align",
- virt_text_hide = true,
- virt_lines = { { { "lines", "Statement" } }},
+ hl_mode = "blend",
+ line_hl_group = "Statement",
+ number_hl_group = "Statement",
+ priority = 0,
+ right_gravity = false,
+ sign_hl_group = "Statement",
+ sign_text = ">>",
+ spell = true,
+ virt_lines = {
+ { { "lines", "Macro" }, { "???" } },
+ { { "stack", { "Type", "Search" } }, { "!!!" } },
+ },
virt_lines_above = true,
virt_lines_leftcol = true,
+ virt_text = { { "text", "Macro" }, { "???" }, { "stack", { "Type", "Search" } } },
+ virt_text_hide = true,
+ virt_text_pos = "right_align",
})
set_extmark(ns, marks[2], 0, 0, {
priority = 0,
- virt_text = { { "text", "Statement" } },
+ virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } },
virt_text_win_col = 1,
})
eq({0, 0, {
+ conceal = "c",
+ cursorline_hl_group = "Statement",
end_col = 0,
- end_row = 1,
- right_gravity = false,
end_right_gravity = true,
- priority = 0,
+ end_row = 1,
hl_eol = true,
- hl_mode = "blend",
hl_group = "String",
- virt_text = { { "text", "Statement" } },
- virt_text_pos = "right_align",
- virt_text_hide = true,
- virt_lines = { { { "lines", "Statement" } }},
+ hl_mode = "blend",
+ line_hl_group = "Statement",
+ ns_id = 1,
+ number_hl_group = "Statement",
+ priority = 0,
+ right_gravity = false,
+ sign_hl_group = "Statement",
+ sign_text = ">>",
+ spell = true,
+ virt_lines = {
+ { { "lines", "Macro" }, { "???" } },
+ { { "stack", { "Type", "Search" } }, { "!!!" } },
+ },
virt_lines_above = true,
virt_lines_leftcol = true,
+ virt_text = { { "text", "Macro" }, { "???" }, { "stack", { "Type", "Search" } } },
+ virt_text_hide = true,
+ virt_text_pos = "right_align",
} }, get_extmark_by_id(ns, marks[1], { details = true }))
eq({0, 0, {
+ ns_id = 1,
right_gravity = true,
priority = 0,
- virt_text = { { "text", "Statement" } },
+ virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } },
virt_text_hide = false,
virt_text_pos = "win_col",
virt_text_win_col = 1,
} }, get_extmark_by_id(ns, marks[2], { details = true }))
+ set_extmark(ns, marks[3], 0, 0, { cursorline_hl_group = "Statement" })
+ eq({0, 0, {
+ ns_id = 1,
+ cursorline_hl_group = "Statement",
+ priority = 4096,
+ right_gravity = true,
+ } }, get_extmark_by_id(ns, marks[3], { details = true }))
+ curbufmeths.clear_namespace(ns, 0, -1)
+ -- legacy sign mark includes sign name
+ command('sign define sign1 text=s1 texthl=Title linehl=LineNR numhl=Normal culhl=CursorLine')
+ command('sign place 1 name=sign1 line=1')
+ eq({ {1, 0, 0, {
+ cursorline_hl_group = 'CursorLine',
+ invalidate = true,
+ line_hl_group = 'LineNr',
+ ns_id = 0,
+ number_hl_group = 'Normal',
+ priority = 10,
+ right_gravity = true,
+ sign_hl_group = 'Title',
+ sign_name = 'sign1',
+ sign_text = 's1',
+ undo_restore = false
+ } } }, get_extmarks(-1, 0, -1, { details = true }))
+ end)
+
+ it('can get marks from anonymous namespaces', function()
+ ns = request('nvim_create_namespace', "")
+ ns2 = request('nvim_create_namespace', "")
+ set_extmark(ns, 1, 0, 0, {})
+ set_extmark(ns2, 2, 1, 0, {})
+ eq({{ 1, 0, 0, { ns_id = ns, right_gravity = true }},
+ { 2, 1, 0, { ns_id = ns2, right_gravity = true }}},
+ get_extmarks(-1, 0, -1, { details = true }))
+ end)
+
+ it('can filter by extmark properties', function()
+ set_extmark(ns, 1, 0, 0, {})
+ set_extmark(ns, 2, 0, 0, { hl_group = 'Normal' })
+ set_extmark(ns, 3, 0, 0, { sign_text = '>>' })
+ set_extmark(ns, 4, 0, 0, { virt_text = {{'text', 'Normal'}}})
+ set_extmark(ns, 5, 0, 0, { virt_lines = {{{ 'line', 'Normal' }}}})
+ eq(5, #get_extmarks(-1, 0, -1, {}))
+ eq({{ 2, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'highlight' }))
+ eq({{ 3, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'sign' }))
+ eq({{ 4, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'virt_text' }))
+ eq({{ 5, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'virt_lines' }))
+ end)
+
+ it("invalidated marks are deleted", function()
+ screen = Screen.new(40, 6)
+ screen:attach()
+ feed('dd6iaaa bbb ccc<CR><ESC>gg')
+ set_extmark(ns, 1, 0, 0, { invalidate = true, sign_text = 'S1' })
+ set_extmark(ns, 2, 1, 0, { invalidate = true, sign_text = 'S2' })
+ -- mark with invalidate is removed
+ command('d')
+ screen:expect([[
+ S2^aaa bbb ccc |
+ aaa bbb ccc |
+ aaa bbb ccc |
+ aaa bbb ccc |
+ aaa bbb ccc |
+ |
+ ]])
+ -- mark is restored with undo_restore == true
+ command('silent undo')
+ screen:expect([[
+ S1^aaa bbb ccc |
+ S2aaa bbb ccc |
+ aaa bbb ccc |
+ aaa bbb ccc |
+ aaa bbb ccc |
+ |
+ ]])
+ -- mark is deleted with undo_restore == false
+ set_extmark(ns, 1, 0, 0, { invalidate = true, undo_restore = false, sign_text = 'S1' })
+ set_extmark(ns, 2, 1, 0, { invalidate = true, undo_restore = false, sign_text = 'S2' })
+ command('1d 2')
+ eq(0, #get_extmarks(-1, 0, -1, {}))
+ -- mark is not removed when deleting bytes before the range
+ set_extmark(ns, 3, 0, 4, { invalidate = true, undo_restore = false,
+ hl_group = 'Error', end_col = 7 })
+ feed('dw')
+ eq(3, get_extmark_by_id(ns, 3, { details = true })[3].end_col)
+ -- mark is not removed when deleting bytes at the start of the range
+ feed('x')
+ eq(2, get_extmark_by_id(ns, 3, { details = true })[3].end_col)
+ -- mark is not removed when deleting bytes from the end of the range
+ feed('lx')
+ eq(1, get_extmark_by_id(ns, 3, { details = true})[3].end_col)
+ -- mark is not removed when deleting bytes beyond end of the range
+ feed('x')
+ eq(1, get_extmark_by_id(ns, 3, { details = true})[3].end_col)
+ -- mark is removed when all bytes in the range are deleted
+ feed('hx')
+ eq({}, get_extmark_by_id(ns, 3, {}))
+ -- multiline mark is not removed when start of its range is deleted
+ set_extmark(ns, 4, 1, 4, { undo_restore = false, invalidate = true,
+ hl_group = 'Error', end_col = 7, end_row = 3 })
+ feed('ddDdd')
+ eq({0, 0}, get_extmark_by_id(ns, 4, {}))
+ -- multiline mark is removed when entirety of its range is deleted
+ feed('vj2ed')
+ eq({}, get_extmark_by_id(ns, 4, {}))
end)
end)