2017-01-18 05:20:07 -07:00
|
|
|
|
local helpers = require('test.functional.helpers')(after_each)
|
|
|
|
|
local Screen = require('test.functional.ui.screen')
|
|
|
|
|
|
|
|
|
|
local request = helpers.request
|
|
|
|
|
local eq = helpers.eq
|
|
|
|
|
local ok = helpers.ok
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local pcall_err = helpers.pcall_err
|
2017-01-18 05:20:07 -07:00
|
|
|
|
local insert = helpers.insert
|
|
|
|
|
local feed = helpers.feed
|
|
|
|
|
local clear = helpers.clear
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local command = helpers.command
|
2023-03-25 19:49:32 -07:00
|
|
|
|
local exec = helpers.exec
|
2024-01-12 10:59:57 -07:00
|
|
|
|
local api = helpers.api
|
2021-09-01 09:42:53 -07:00
|
|
|
|
local assert_alive = helpers.assert_alive
|
2020-01-14 04:45:09 -07:00
|
|
|
|
|
|
|
|
|
local function expect(contents)
|
|
|
|
|
return eq(contents, helpers.curbuf_contents())
|
|
|
|
|
end
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local function set_extmark(ns_id, id, line, col, opts)
|
|
|
|
|
if opts == nil then
|
|
|
|
|
opts = {}
|
|
|
|
|
end
|
2020-01-21 06:01:40 -07:00
|
|
|
|
if id ~= nil and id ~= 0 then
|
|
|
|
|
opts.id = id
|
|
|
|
|
end
|
2024-01-12 10:59:57 -07:00
|
|
|
|
return api.nvim_buf_set_extmark(0, ns_id, line, col, opts)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function get_extmarks(ns_id, start, end_, opts)
|
|
|
|
|
if opts == nil then
|
|
|
|
|
opts = {}
|
|
|
|
|
end
|
2024-01-12 10:59:57 -07:00
|
|
|
|
return api.nvim_buf_get_extmarks(0, ns_id, start, end_, opts)
|
2020-09-04 10:11:26 -07:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function get_extmark_by_id(ns_id, id, opts)
|
|
|
|
|
if opts == nil then
|
|
|
|
|
opts = {}
|
|
|
|
|
end
|
2024-01-12 10:59:57 -07:00
|
|
|
|
return api.nvim_buf_get_extmark_by_id(0, ns_id, id, opts)
|
2020-09-04 10:11:26 -07:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function check_undo_redo(ns, mark, sr, sc, er, ec) --s = start, e = end
|
|
|
|
|
local rv = get_extmark_by_id(ns, mark)
|
|
|
|
|
eq({ er, ec }, rv)
|
|
|
|
|
feed('u')
|
|
|
|
|
rv = get_extmark_by_id(ns, mark)
|
|
|
|
|
eq({ sr, sc }, rv)
|
|
|
|
|
feed('<c-r>')
|
|
|
|
|
rv = get_extmark_by_id(ns, mark)
|
|
|
|
|
eq({ er, ec }, rv)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
end
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
local function batch_set(ns_id, positions)
|
|
|
|
|
local ids = {}
|
|
|
|
|
for _, pos in ipairs(positions) do
|
|
|
|
|
table.insert(ids, set_extmark(ns_id, 0, pos[1], pos[2]))
|
|
|
|
|
end
|
|
|
|
|
return ids
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function batch_check(ns_id, ids, positions)
|
|
|
|
|
local actual, expected = {}, {}
|
|
|
|
|
for i, id in ipairs(ids) do
|
|
|
|
|
expected[id] = positions[i]
|
|
|
|
|
end
|
|
|
|
|
for _, mark in pairs(get_extmarks(ns_id, 0, -1, {})) do
|
|
|
|
|
actual[mark[1]] = { mark[2], mark[3] }
|
|
|
|
|
end
|
|
|
|
|
eq(expected, actual)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function batch_check_undo_redo(ns_id, ids, before, after)
|
|
|
|
|
batch_check(ns_id, ids, after)
|
|
|
|
|
feed('u')
|
|
|
|
|
batch_check(ns_id, ids, before)
|
|
|
|
|
feed('<c-r>')
|
|
|
|
|
batch_check(ns_id, ids, after)
|
|
|
|
|
end
|
|
|
|
|
|
2019-11-25 02:08:02 -07:00
|
|
|
|
describe('API/extmarks', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
local screen
|
2020-01-14 04:45:09 -07:00
|
|
|
|
local marks, positions, init_text, row, col
|
2017-01-18 05:20:07 -07:00
|
|
|
|
local ns, ns2
|
|
|
|
|
|
|
|
|
|
before_each(function()
|
|
|
|
|
-- Initialize some namespaces and insert 12345 into a buffer
|
|
|
|
|
marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
|
|
|
|
|
positions = { { 0, 0 }, { 0, 2 }, { 0, 3 } }
|
|
|
|
|
|
|
|
|
|
init_text = '12345'
|
|
|
|
|
row = 0
|
|
|
|
|
col = 2
|
|
|
|
|
|
|
|
|
|
clear()
|
|
|
|
|
|
|
|
|
|
insert(init_text)
|
2020-01-14 04:45:09 -07:00
|
|
|
|
ns = request('nvim_create_namespace', 'my-fancy-plugin')
|
|
|
|
|
ns2 = request('nvim_create_namespace', 'my-fancy-plugin2')
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2023-02-14 12:19:28 -07:00
|
|
|
|
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 })
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2023-02-14 12:19:28 -07:00
|
|
|
|
eq(
|
|
|
|
|
"Invalid 'end_row': expected Integer, got Array",
|
|
|
|
|
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = {} })
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2023-06-21 22:59:57 -07:00
|
|
|
|
eq(
|
|
|
|
|
"Invalid 'virt_text_pos': expected String, got Integer",
|
|
|
|
|
pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 0 })
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2023-06-21 22:59:57 -07:00
|
|
|
|
eq(
|
|
|
|
|
"Invalid 'virt_text_pos': 'foo'",
|
|
|
|
|
pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 'foo' })
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2023-06-21 22:59:57 -07:00
|
|
|
|
eq(
|
|
|
|
|
"Invalid 'hl_mode': expected String, got Integer",
|
|
|
|
|
pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 0 })
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2023-06-21 22:59:57 -07:00
|
|
|
|
eq("Invalid 'hl_mode': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 'foo' }))
|
2023-08-01 05:01:19 -07:00
|
|
|
|
eq(
|
|
|
|
|
"Invalid 'id': expected Integer, got Array",
|
|
|
|
|
pcall_err(set_extmark, ns, {}, 0, 0, { end_col = 1, end_row = 1 })
|
2023-02-14 12:19:28 -07:00
|
|
|
|
)
|
|
|
|
|
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 })
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2023-03-04 16:09:28 -07:00
|
|
|
|
-- 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',
|
|
|
|
|
})
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2023-02-14 12:19:28 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-09-08 05:14:15 -07:00
|
|
|
|
it('can end extranges past final newline using end_col = 0', function()
|
|
|
|
|
set_extmark(ns, marks[1], 0, 0, {
|
|
|
|
|
end_col = 0,
|
2021-12-08 08:44:48 -07:00
|
|
|
|
end_row = 1,
|
2020-09-08 05:14:15 -07:00
|
|
|
|
})
|
2023-02-14 06:07:38 -07:00
|
|
|
|
eq(
|
|
|
|
|
"Invalid 'end_col': out of range",
|
2021-12-08 08:44:48 -07:00
|
|
|
|
pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 })
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2020-09-08 05:14:15 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2022-01-15 09:37:44 -07:00
|
|
|
|
it('can end extranges past final newline when strict mode is false', function()
|
|
|
|
|
set_extmark(ns, marks[1], 0, 0, {
|
|
|
|
|
end_col = 1,
|
|
|
|
|
end_row = 1,
|
2022-01-15 10:00:01 -07:00
|
|
|
|
strict = false,
|
2022-01-15 09:37:44 -07:00
|
|
|
|
})
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('can end extranges past final column when strict mode is false', function()
|
|
|
|
|
set_extmark(ns, marks[1], 0, 0, {
|
2022-01-15 10:00:01 -07:00
|
|
|
|
end_col = 6,
|
|
|
|
|
end_row = 0,
|
|
|
|
|
strict = false,
|
2022-01-15 09:37:44 -07:00
|
|
|
|
})
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('adds, updates and deletes marks', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq(marks[1], rv)
|
2020-09-04 10:11:26 -07:00
|
|
|
|
rv = get_extmark_by_id(ns, marks[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ positions[1][1], positions[1][2] }, rv)
|
|
|
|
|
-- Test adding a second mark on same row works
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = set_extmark(ns, marks[2], positions[2][1], positions[2][2])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq(marks[2], rv)
|
|
|
|
|
|
|
|
|
|
-- Test an update, (same pos)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2])
|
|
|
|
|
eq(marks[1], rv)
|
2020-09-04 10:11:26 -07:00
|
|
|
|
rv = get_extmark_by_id(ns, marks[2])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ positions[2][1], positions[2][2] }, rv)
|
|
|
|
|
-- Test an update, (new pos)
|
|
|
|
|
row = positions[1][1]
|
|
|
|
|
col = positions[1][2] + 1
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = set_extmark(ns, marks[1], row, col)
|
|
|
|
|
eq(marks[1], rv)
|
2020-09-04 10:11:26 -07:00
|
|
|
|
rv = get_extmark_by_id(ns, marks[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ row, col }, rv)
|
|
|
|
|
|
|
|
|
|
-- remove the test marks
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq(true, api.nvim_buf_del_extmark(0, ns, marks[1]))
|
|
|
|
|
eq(false, api.nvim_buf_del_extmark(0, ns, marks[1]))
|
|
|
|
|
eq(true, api.nvim_buf_del_extmark(0, ns, marks[2]))
|
|
|
|
|
eq(false, api.nvim_buf_del_extmark(0, ns, marks[3]))
|
|
|
|
|
eq(false, api.nvim_buf_del_extmark(0, ns, 1000))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('can clear a specific namespace range', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, 1, 0, 1)
|
|
|
|
|
set_extmark(ns2, 1, 0, 1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- force a new undo buffer
|
|
|
|
|
feed('o<esc>')
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_clear_namespace(0, ns2, 0, -1)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq({ { 1, 0, 1 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
|
|
|
|
|
eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('u')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq({ { 1, 0, 1 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
|
2020-01-14 04:45:09 -07:00
|
|
|
|
eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-r>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq({ { 1, 0, 1 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
|
|
|
|
|
eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('can clear a namespace range using 0,-1', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, 1, 0, 1)
|
|
|
|
|
set_extmark(ns2, 1, 0, 1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- force a new undo buffer
|
|
|
|
|
feed('o<esc>')
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_clear_namespace(0, -1, 0, -1)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
|
|
|
|
|
eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('u')
|
2020-01-14 04:45:09 -07:00
|
|
|
|
eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
|
|
|
|
|
eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-r>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
|
|
|
|
|
eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2023-09-15 21:43:49 -07:00
|
|
|
|
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 }))
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
2023-09-15 21:43:49 -07:00
|
|
|
|
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 }))
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
2023-09-15 21:43:49 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('querying for information and ranges', function()
|
|
|
|
|
--marks = {1, 2, 3}
|
|
|
|
|
--positions = {{0, 0,}, {0, 2}, {0, 3}}
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- add some more marks
|
|
|
|
|
for i, m in ipairs(marks) do
|
|
|
|
|
if positions[i] ~= nil then
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local rv = set_extmark(ns, m, positions[i][1], positions[i][2])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq(m, rv)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- {0, 0} and {-1, -1} work as extreme values
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq({ { 1, 0, 0 } }, get_extmarks(ns, { 0, 0 }, { 0, 0 }))
|
|
|
|
|
eq({}, get_extmarks(ns, { -1, -1 }, { -1, -1 }))
|
|
|
|
|
local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
for i, m in ipairs(marks) do
|
|
|
|
|
if positions[i] ~= nil then
|
|
|
|
|
eq({ m, positions[i][1], positions[i][2] }, rv[i])
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- 0 and -1 works as short hand extreme values
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq({ { 1, 0, 0 } }, get_extmarks(ns, 0, 0))
|
|
|
|
|
eq({}, get_extmarks(ns, -1, -1))
|
|
|
|
|
rv = get_extmarks(ns, 0, -1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
for i, m in ipairs(marks) do
|
|
|
|
|
if positions[i] ~= nil then
|
|
|
|
|
eq({ m, positions[i][1], positions[i][2] }, rv[i])
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- next with mark id
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, marks[1], { -1, -1 }, { limit = 1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[1], positions[1][1], positions[1][2] } }, rv)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, marks[2], { -1, -1 }, { limit = 1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[2], positions[2][1], positions[2][2] } }, rv)
|
|
|
|
|
-- next with positional when mark exists at position
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, positions[1], { -1, -1 }, { limit = 1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[1], positions[1][1], positions[1][2] } }, rv)
|
|
|
|
|
-- next with positional index (no mark at position)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, { positions[1][1], positions[1][2] + 1 }, { -1, -1 }, { limit = 1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[2], positions[2][1], positions[2][2] } }, rv)
|
|
|
|
|
-- next with Extremity index
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[1], positions[1][1], positions[1][2] } }, rv)
|
|
|
|
|
|
|
|
|
|
-- nextrange with mark id
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, marks[1], marks[3])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ marks[1], positions[1][1], positions[1][2] }, rv[1])
|
|
|
|
|
eq({ marks[2], positions[2][1], positions[2][2] }, rv[2])
|
2019-11-25 02:08:02 -07:00
|
|
|
|
-- nextrange with `limit`
|
|
|
|
|
rv = get_extmarks(ns, marks[1], marks[3], { limit = 2 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- nextrange with positional when mark exists at position
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, positions[1], positions[3])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ marks[1], positions[1][1], positions[1][2] }, rv[1])
|
|
|
|
|
eq({ marks[2], positions[2][1], positions[2][2] }, rv[2])
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, positions[2], positions[3])
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- nextrange with positional index (no mark at position)
|
|
|
|
|
local lower = { positions[1][1], positions[2][2] - 1 }
|
|
|
|
|
local upper = { positions[2][1], positions[3][2] - 1 }
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, lower, upper)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[2], positions[2][1], positions[2][2] } }, rv)
|
|
|
|
|
lower = { positions[3][1], positions[3][2] + 1 }
|
|
|
|
|
upper = { positions[3][1], positions[3][2] + 2 }
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, lower, upper)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({}, rv)
|
|
|
|
|
-- nextrange with extremity index
|
|
|
|
|
lower = { positions[2][1], positions[2][2] + 1 }
|
|
|
|
|
upper = { -1, -1 }
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, lower, upper)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[3], positions[3][1], positions[3][2] } }, rv)
|
|
|
|
|
|
|
|
|
|
-- prev with mark id
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, marks[3], { 0, 0 }, { limit = 1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[3], positions[3][1], positions[3][2] } }, rv)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, marks[2], { 0, 0 }, { limit = 1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[2], positions[2][1], positions[2][2] } }, rv)
|
|
|
|
|
-- prev with positional when mark exists at position
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, positions[3], { 0, 0 }, { limit = 1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[3], positions[3][1], positions[3][2] } }, rv)
|
|
|
|
|
-- prev with positional index (no mark at position)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, { positions[1][1], positions[1][2] + 1 }, { 0, 0 }, { limit = 1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[1], positions[1][1], positions[1][2] } }, rv)
|
|
|
|
|
-- prev with Extremity index
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, { -1, -1 }, { 0, 0 }, { limit = 1 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[3], positions[3][1], positions[3][2] } }, rv)
|
|
|
|
|
|
|
|
|
|
-- prevrange with mark id
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, marks[3], marks[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ marks[3], positions[3][1], positions[3][2] }, rv[1])
|
|
|
|
|
eq({ marks[2], positions[2][1], positions[2][2] }, rv[2])
|
|
|
|
|
eq({ marks[1], positions[1][1], positions[1][2] }, rv[3])
|
2019-11-25 02:08:02 -07:00
|
|
|
|
-- prevrange with limit
|
|
|
|
|
rv = get_extmarks(ns, marks[3], marks[1], { limit = 2 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- prevrange with positional when mark exists at position
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, positions[3], positions[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({
|
|
|
|
|
{ marks[3], positions[3][1], positions[3][2] },
|
|
|
|
|
{ marks[2], positions[2][1], positions[2][2] },
|
|
|
|
|
{ marks[1], positions[1][1], positions[1][2] },
|
|
|
|
|
}, rv)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, positions[2], positions[1])
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- prevrange with positional index (no mark at position)
|
|
|
|
|
lower = { positions[2][1], positions[2][2] + 1 }
|
|
|
|
|
upper = { positions[3][1], positions[3][2] + 1 }
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, upper, lower)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[3], positions[3][1], positions[3][2] } }, rv)
|
|
|
|
|
lower = { positions[3][1], positions[3][2] + 1 }
|
|
|
|
|
upper = { positions[3][1], positions[3][2] + 2 }
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, upper, lower)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({}, rv)
|
|
|
|
|
-- prevrange with extremity index
|
|
|
|
|
lower = { 0, 0 }
|
|
|
|
|
upper = { positions[2][1], positions[2][2] - 1 }
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, upper, lower)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[1], positions[1][1], positions[1][2] } }, rv)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('querying for information with limit', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- add some more marks
|
|
|
|
|
for i, m in ipairs(marks) do
|
|
|
|
|
if positions[i] ~= nil then
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local rv = set_extmark(ns, m, positions[i][1], positions[i][2])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq(m, rv)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2019-11-25 02:08:02 -07:00
|
|
|
|
local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(1, #rv)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 2 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 3 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(3, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
-- now in reverse
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(1, #rv)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 2 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 3 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(3, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('get_marks works when mark col > upper col', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>12345<esc>')
|
|
|
|
|
feed('A<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, 10, 0, 2) -- this shouldn't be found
|
|
|
|
|
set_extmark(ns, 11, 2, 1) -- this shouldn't be found
|
|
|
|
|
set_extmark(ns, marks[1], 0, 4) -- check col > our upper bound
|
|
|
|
|
set_extmark(ns, marks[2], 1, 1) -- check col < lower bound
|
|
|
|
|
set_extmark(ns, marks[3], 2, 0) -- check is inclusive
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq(
|
|
|
|
|
{ { marks[1], 0, 4 }, { marks[2], 1, 1 }, { marks[3], 2, 0 } },
|
2019-11-09 04:41:50 -07:00
|
|
|
|
get_extmarks(ns, { 0, 3 }, { 2, 0 })
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('get_marks works in reverse when mark col < lower col', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>12345<esc>')
|
|
|
|
|
feed('A<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, 10, 0, 1) -- this shouldn't be found
|
|
|
|
|
set_extmark(ns, 11, 2, 4) -- this shouldn't be found
|
|
|
|
|
set_extmark(ns, marks[1], 2, 1) -- check col < our lower bound
|
|
|
|
|
set_extmark(ns, marks[2], 1, 4) -- check col > upper bound
|
|
|
|
|
set_extmark(ns, marks[3], 0, 2) -- check is inclusive
|
|
|
|
|
local rv = get_extmarks(ns, { 2, 3 }, { 0, 2 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ { marks[1], 2, 1 }, { marks[2], 1, 4 }, { marks[3], 0, 2 } }, rv)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('get_marks limit=0 returns nothing', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], positions[1][1], positions[1][2])
|
2019-11-25 02:08:02 -07:00
|
|
|
|
local rv = get_extmarks(ns, { -1, -1 }, { -1, -1 }, { limit = 0 })
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({}, rv)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with line insertations', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('yyP')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 0, 1, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with multiline insertations', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('a<cr>22<cr>33<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('ggVGyP')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 1, 4, 1)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with line join', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_join in ops.c
|
|
|
|
|
feed('a<cr>222<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('ggJ')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 0, 0, 6)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('join works when no marks are present', function()
|
|
|
|
|
screen = Screen.new(15, 10)
|
|
|
|
|
screen:attach()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('a<cr>1<esc>')
|
|
|
|
|
feed('kJ')
|
|
|
|
|
-- This shouldn't seg fault
|
|
|
|
|
screen:expect([[
|
|
|
|
|
12345^ 1 |
|
2023-12-09 05:42:00 -07:00
|
|
|
|
~ |*8
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
|
]])
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with multiline join', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_join in ops.c
|
|
|
|
|
feed('a<cr>222<cr>333<cr>444<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 3, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('2GVGJ')
|
|
|
|
|
check_undo_redo(ns, marks[1], 3, 0, 1, 8)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with line deletes', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('a<cr>222<cr>333<cr>444<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 2, 1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('ggjdd')
|
|
|
|
|
check_undo_redo(ns, marks[1], 2, 1, 1, 1)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with multiline deletes', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('a<cr>222<cr>333<cr>444<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 3, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('gg2dd')
|
|
|
|
|
check_undo_redo(ns, marks[1], 3, 0, 1, 0)
|
|
|
|
|
-- regression test, undoing multiline delete when mark is on row 1
|
|
|
|
|
feed('ugg3dd')
|
|
|
|
|
check_undo_redo(ns, marks[1], 3, 0, 0, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with open line', function()
|
2021-12-10 16:09:54 -07:00
|
|
|
|
-- open_line in change.c
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- testing marks below are also moved
|
|
|
|
|
feed('yyP')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[2], 1, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('1G<s-o><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 4, 1, 4)
|
|
|
|
|
check_undo_redo(ns, marks[2], 1, 4, 2, 4)
|
|
|
|
|
feed('2Go<esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 4, 1, 4)
|
|
|
|
|
check_undo_redo(ns, marks[2], 2, 4, 3, 4)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with char inserts', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- insertchar in edit.c (the ins_str branch)
|
2020-01-14 04:45:09 -07:00
|
|
|
|
screen = Screen.new(15, 10)
|
|
|
|
|
screen:attach()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 3)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0')
|
|
|
|
|
insert('abc')
|
|
|
|
|
screen:expect([[
|
|
|
|
|
ab^c12345 |
|
2023-12-09 05:42:00 -07:00
|
|
|
|
~ |*8
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
|
]])
|
2020-09-04 10:11:26 -07:00
|
|
|
|
local rv = get_extmark_by_id(ns, marks[1])
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq({ 0, 6 }, rv)
|
2020-01-14 04:45:09 -07:00
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 6)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
-- gravity right as definted in tk library
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks have gravity right', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- insertchar in edit.c (the ins_str branch)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('03l')
|
|
|
|
|
insert('X')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
|
|
|
|
|
-- check multibyte chars
|
|
|
|
|
feed('03l<esc>')
|
|
|
|
|
insert('~~')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('we can insert multibyte chars', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- insertchar in edit.c
|
|
|
|
|
feed('a<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- Insert a fullwidth (two col) tilde, NICE
|
|
|
|
|
feed('0i~<esc>')
|
2019-11-14 12:24:17 -07:00
|
|
|
|
check_undo_redo(ns, marks[1], 1, 2, 1, 5)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with blockwise inserts', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- op_insert in ops.c
|
|
|
|
|
feed('a<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0<c-v>lkI9<esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 2, 1, 3)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with line splits (using enter)', function()
|
2021-12-10 16:09:54 -07:00
|
|
|
|
-- open_line in change.c
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- testing marks below are also moved
|
|
|
|
|
feed('yyP')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[2], 1, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('1Gla<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 4, 1, 2)
|
|
|
|
|
check_undo_redo(ns, marks[2], 1, 4, 2, 4)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks at last line move on insert new line', function()
|
2021-12-10 16:09:54 -07:00
|
|
|
|
-- open_line in change.c
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0i<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 4, 1, 4)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('yet again marks move with line splits', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- the first test above wasn't catching all errors..
|
|
|
|
|
feed('A67890<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('04li<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 4, 1, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('and one last time line splits...', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 1)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('02li<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 1, 0, 1)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 2, 1, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('multiple marks move with mark splits', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 1)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0li<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 1, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 1, 2)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('deleting right before a mark works', function()
|
2019-11-14 12:06:13 -07:00
|
|
|
|
-- op_delete in ops.c
|
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
feed('0lx')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 1)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('deleting right after a mark works', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- op_delete in ops.c
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('02lx')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with char deletes', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- op_delete in ops.c
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('02dl')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 0)
|
|
|
|
|
-- from the other side (nothing should happen)
|
|
|
|
|
feed('$x')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 0, 0, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with char deletes over a range', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- op_delete in ops.c
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0l3dl<esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 1)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 1)
|
2019-11-26 05:15:14 -07:00
|
|
|
|
-- delete 1, nothing should happen to our marks
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('u')
|
|
|
|
|
feed('$x')
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 3)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('deleting marks at end of line works', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('$x')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 4, 0, 4)
|
|
|
|
|
-- check the copy happened correctly on delete at eol
|
|
|
|
|
feed('$x')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 4, 0, 3)
|
|
|
|
|
feed('u')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 4, 0, 4)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with blockwise deletes', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- op_delete in ops.c
|
|
|
|
|
feed('a<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('h<c-v>hhkd')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 4, 1, 1)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with blockwise deletes over a range', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- op_delete in ops.c
|
|
|
|
|
feed('a<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 1)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[3], 1, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0<c-v>k3lx')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 1, 0, 0)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 0)
|
|
|
|
|
check_undo_redo(ns, marks[3], 1, 2, 1, 0)
|
2019-11-26 05:15:14 -07:00
|
|
|
|
-- delete 1, nothing should happen to our marks
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('u')
|
|
|
|
|
feed('$<c-v>jx')
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 3)
|
|
|
|
|
check_undo_redo(ns, marks[3], 1, 2, 1, 2)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('works with char deletes over multilines', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('a<cr>12345<cr>test-me<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 2, 5)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('gg')
|
|
|
|
|
feed('dv?-m?<cr>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 2, 5, 0, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks outside of deleted range move with visual char deletes', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- op_delete in ops.c
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 3)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0vx<esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 2)
|
|
|
|
|
|
|
|
|
|
feed('u')
|
|
|
|
|
feed('0vlx<esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 1)
|
|
|
|
|
|
|
|
|
|
feed('u')
|
|
|
|
|
feed('0v2lx<esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 0)
|
|
|
|
|
|
|
|
|
|
-- from the other side (nothing should happen)
|
|
|
|
|
feed('$vx')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 0, 0, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks outside of deleted range move with char deletes', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- op_delete in ops.c
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 3)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0x<esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 2)
|
|
|
|
|
|
|
|
|
|
feed('u')
|
|
|
|
|
feed('02x<esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 1)
|
|
|
|
|
|
|
|
|
|
feed('u')
|
|
|
|
|
feed('0v3lx<esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 0)
|
|
|
|
|
|
|
|
|
|
-- from the other side (nothing should happen)
|
|
|
|
|
feed('u')
|
|
|
|
|
feed('$vx')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 3)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with P(backward) paste', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_put in ops.c
|
|
|
|
|
feed('0iabc<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 7)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0veyP')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 7, 0, 15)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with p(forward) paste', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_put in ops.c
|
|
|
|
|
feed('0iabc<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 7)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0veyp')
|
2020-01-14 04:45:09 -07:00
|
|
|
|
check_undo_redo(ns, marks[1], 0, 7, 0, 15)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with blockwise P(backward) paste', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_put in ops.c
|
|
|
|
|
feed('a<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-v>hhkyP<esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 4, 1, 7)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move with blockwise p(forward) paste', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_put in ops.c
|
|
|
|
|
feed('a<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-v>hhkyp<esc>')
|
2020-01-14 04:45:09 -07:00
|
|
|
|
check_undo_redo(ns, marks[1], 1, 4, 1, 7)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
describe('multiline regions', function()
|
|
|
|
|
before_each(function()
|
|
|
|
|
feed('dd')
|
|
|
|
|
-- Achtung: code has been spiced with some unicode,
|
|
|
|
|
-- to make life more interesting.
|
|
|
|
|
-- luacheck whines about TABs inside strings for whatever reason.
|
|
|
|
|
-- luacheck: push ignore 621
|
|
|
|
|
insert([[
|
|
|
|
|
static int nlua_rpcrequest(lua_State *lstate)
|
|
|
|
|
{
|
|
|
|
|
Ïf (!nlua_is_deferred_safe(lstate)) {
|
|
|
|
|
// strictly not allowed
|
|
|
|
|
Яetörn luaL_error(lstate, e_luv_api_disabled, "rpcrequest");
|
|
|
|
|
}
|
|
|
|
|
return nlua_rpc(lstate, true);
|
|
|
|
|
}]])
|
|
|
|
|
-- luacheck: pop
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('delete', function()
|
|
|
|
|
local pos1 = {
|
|
|
|
|
{ 2, 4 },
|
|
|
|
|
{ 2, 12 },
|
|
|
|
|
{ 2, 13 },
|
|
|
|
|
{ 2, 14 },
|
|
|
|
|
{ 2, 25 },
|
|
|
|
|
{ 4, 8 },
|
|
|
|
|
{ 4, 10 },
|
|
|
|
|
{ 4, 20 },
|
|
|
|
|
{ 5, 3 },
|
|
|
|
|
{ 6, 10 },
|
|
|
|
|
}
|
|
|
|
|
local ids = batch_set(ns, pos1)
|
|
|
|
|
batch_check(ns, ids, pos1)
|
|
|
|
|
feed('3Gfiv2+ftd')
|
|
|
|
|
batch_check_undo_redo(ns, ids, pos1, {
|
|
|
|
|
{ 2, 4 },
|
|
|
|
|
{ 2, 12 },
|
|
|
|
|
{ 2, 13 },
|
|
|
|
|
{ 2, 13 },
|
|
|
|
|
{ 2, 13 },
|
2024-01-02 18:09:18 -07:00
|
|
|
|
{ 2, 13 },
|
2020-01-14 04:45:09 -07:00
|
|
|
|
{ 2, 15 },
|
|
|
|
|
{ 2, 25 },
|
|
|
|
|
{ 3, 3 },
|
|
|
|
|
{ 4, 10 },
|
|
|
|
|
})
|
|
|
|
|
end)
|
|
|
|
|
|
feat(extmark): support proper multiline ranges
The removes the previous restriction that nvim_buf_set_extmark()
could not be used to highlight arbitrary multi-line regions
The problem can be summarized as follows: let's assume an extmark with a
hl_group is placed covering the region (5,0) to (50,0) Now, consider
what happens if nvim needs to redraw a window covering the lines 20-30.
It needs to be able to ask the marktree what extmarks cover this region,
even if they don't begin or end here.
Therefore the marktree needs to be augmented with the information covers
a point, not just what marks begin or end there. To do this, we augment
each node with a field "intersect" which is a set the ids of the
marks which overlap this node, but only if it is not part of the set of
any parent. This ensures the number of nodes that need to be explicitly
marked grows only logarithmically with the total number of explicitly
nodes (and thus the number of of overlapping marks).
Thus we can quickly iterate all marks which overlaps any query position
by looking up what leaf node contains that position. Then we only need
to consider all "start" marks within that leaf node, and the "intersect"
set of that node and all its parents.
Now, and the major source of complexity is that the tree restructuring
operations (to ensure that each node has T-1 <= size <= 2*T-1) also need
to update these sets. If a full inner node is split in two, one of the
new parents might start to completely overlap some ranges and its ids
will need to be moved from its children's sets to its own set.
Similarly, if two undersized nodes gets joined into one, it might no
longer completely overlap some ranges, and now the children which do
needs to have the have the ids in its set instead. And then there are
the pivots! Yes the pivot operations when a child gets moved from one
parent to another.
2020-11-22 02:10:37 -07:00
|
|
|
|
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 })
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
feat(extmark): support proper multiline ranges
The removes the previous restriction that nvim_buf_set_extmark()
could not be used to highlight arbitrary multi-line regions
The problem can be summarized as follows: let's assume an extmark with a
hl_group is placed covering the region (5,0) to (50,0) Now, consider
what happens if nvim needs to redraw a window covering the lines 20-30.
It needs to be able to ask the marktree what extmarks cover this region,
even if they don't begin or end here.
Therefore the marktree needs to be augmented with the information covers
a point, not just what marks begin or end there. To do this, we augment
each node with a field "intersect" which is a set the ids of the
marks which overlap this node, but only if it is not part of the set of
any parent. This ensures the number of nodes that need to be explicitly
marked grows only logarithmically with the total number of explicitly
nodes (and thus the number of of overlapping marks).
Thus we can quickly iterate all marks which overlaps any query position
by looking up what leaf node contains that position. Then we only need
to consider all "start" marks within that leaf node, and the "intersect"
set of that node and all its parents.
Now, and the major source of complexity is that the tree restructuring
operations (to ensure that each node has T-1 <= size <= 2*T-1) also need
to update these sets. If a full inner node is split in two, one of the
new parents might start to completely overlap some ranges and its ids
will need to be moved from its children's sets to its own set.
Similarly, if two undersized nodes gets joined into one, it might no
longer completely overlap some ranges, and now the children which do
needs to have the have the ids in its set instead. And then there are
the pivots! Yes the pivot operations when a child gets moved from one
parent to another.
2020-11-22 02:10:37 -07:00
|
|
|
|
end)
|
2020-01-14 04:45:09 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('replace works', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0r2')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('blockwise replace works', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('a<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0<c-v>llkr1<esc>')
|
2020-01-14 04:45:09 -07:00
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 3)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('shift line', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- shift_line in ops.c
|
|
|
|
|
feed(':set shiftwidth=4<cr><esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0>>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 6)
|
2020-01-14 04:45:09 -07:00
|
|
|
|
expect(' 12345')
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
feed('>>')
|
2020-01-14 04:45:09 -07:00
|
|
|
|
-- this is counter-intuitive. But what happens
|
|
|
|
|
-- is that 4 spaces gets extended to one tab (== 8 spaces)
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 6, 0, 3)
|
|
|
|
|
expect('\t12345')
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
feed('<LT><LT>') -- have to escape, same as <<
|
2020-01-14 04:45:09 -07:00
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 6)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('blockwise shift', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- shift_block in ops.c
|
|
|
|
|
feed(':set shiftwidth=4<cr><esc>')
|
|
|
|
|
feed('a<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0<c-v>k>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 2, 1, 6)
|
|
|
|
|
feed('<c-v>j>')
|
2020-01-14 04:45:09 -07:00
|
|
|
|
expect('\t12345\n\t12345')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 6, 1, 3)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
feed('<c-v>j<LT>')
|
2020-01-14 04:45:09 -07:00
|
|
|
|
check_undo_redo(ns, marks[1], 1, 3, 1, 6)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('tab works with expandtab', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- ins_tab in edit.c
|
|
|
|
|
feed(':set expandtab<cr><esc>')
|
|
|
|
|
feed(':set shiftwidth=2<cr><esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0i<tab><tab><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 6)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('tabs work', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- ins_tab in edit.c
|
|
|
|
|
feed(':set noexpandtab<cr><esc>')
|
|
|
|
|
feed(':set shiftwidth=2<cr><esc>')
|
|
|
|
|
feed(':set softtabstop=2<cr><esc>')
|
|
|
|
|
feed(':set tabstop=8<cr><esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0i<tab><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 4)
|
|
|
|
|
feed('0iX<tab><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 4, 0, 6)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move when using :move', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>2<esc>:1move 2<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 0, 1, 0)
|
|
|
|
|
-- test codepath when moving lines up
|
|
|
|
|
feed(':2move 0<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 0, 0, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('marks move when using :move part 2', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- make sure we didn't get lucky with the math...
|
|
|
|
|
feed('A<cr>2<cr>3<cr>4<cr>5<cr>6<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed(':2,3move 5<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 0, 3, 0)
|
|
|
|
|
-- test codepath when moving lines up
|
|
|
|
|
feed(':4,5move 1<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 3, 0, 1, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('undo and redo of set and unset marks', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- Force a new undo head
|
|
|
|
|
feed('o<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('o<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[2], 0, -1)
|
|
|
|
|
set_extmark(ns, marks[3], 0, -1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
feed('u')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(3, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
feed('<c-r>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(3, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
-- Test updates
|
|
|
|
|
feed('o<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], positions[1][1], positions[1][2])
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns, marks[1], marks[1], { limit = 1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(1, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('u')
|
|
|
|
|
feed('<c-r>')
|
2020-01-14 04:45:09 -07:00
|
|
|
|
-- old value is NOT kept in history
|
|
|
|
|
check_undo_redo(
|
|
|
|
|
ns,
|
|
|
|
|
marks[1],
|
|
|
|
|
positions[1][1],
|
|
|
|
|
positions[1][2],
|
|
|
|
|
positions[1][1],
|
|
|
|
|
positions[1][2]
|
|
|
|
|
)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
-- Test unset
|
|
|
|
|
feed('o<esc>')
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_del_extmark(0, ns, marks[3])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('u')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
|
2020-01-14 04:45:09 -07:00
|
|
|
|
-- undo does NOT restore deleted marks
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-r>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('undo and redo of marks deleted during edits', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- test extmark_adjust
|
|
|
|
|
feed('A<cr>12345<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('dd')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 2, 1, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('namespaces work properly', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq(1, rv)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = set_extmark(ns2, marks[1], positions[1][1], positions[1][2])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq(1, rv)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(1, #rv)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns2, { 0, 0 }, { -1, -1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(1, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
-- Set more marks for testing the ranges
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[2], positions[2][1], positions[2][2])
|
|
|
|
|
set_extmark(ns, marks[3], positions[3][1], positions[3][2])
|
|
|
|
|
set_extmark(ns2, marks[2], positions[2][1], positions[2][2])
|
|
|
|
|
set_extmark(ns2, marks[3], positions[3][1], positions[3][2])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
2019-11-25 02:08:02 -07:00
|
|
|
|
-- get_next (limit set)
|
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, positions[2], { limit = 1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(1, #rv)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns2, { 0, 0 }, positions[2], { limit = 1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(1, #rv)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
-- get_prev (limit set)
|
|
|
|
|
rv = get_extmarks(ns, positions[1], { 0, 0 }, { limit = 1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(1, #rv)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
rv = get_extmarks(ns2, positions[1], { 0, 0 }, { limit = 1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(1, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
2019-11-25 02:08:02 -07:00
|
|
|
|
-- get_next (no limit)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, positions[1], positions[2])
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns2, positions[1], positions[2])
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2019-11-25 02:08:02 -07:00
|
|
|
|
-- get_prev (no limit)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, positions[2], positions[1])
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns2, positions[2], positions[1])
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_del_extmark(0, ns, marks[1])
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_del_extmark(0, ns2, marks[1])
|
2019-11-09 04:41:50 -07:00
|
|
|
|
rv = get_extmarks(ns2, { 0, 0 }, { -1, -1 })
|
2020-07-30 22:33:42 -07:00
|
|
|
|
eq(2, #rv)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('mark set can create unique identifiers', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- create mark with id 1
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq(1, set_extmark(ns, 1, positions[1][1], positions[1][2]))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- ask for unique id, it should be the next one, i e 2
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq(2, set_extmark(ns, 0, positions[1][1], positions[1][2]))
|
|
|
|
|
eq(3, set_extmark(ns, 3, positions[2][1], positions[2][2]))
|
|
|
|
|
eq(4, set_extmark(ns, 0, positions[1][1], positions[1][2]))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
|
|
|
|
|
-- mixing manual and allocated id:s are not recommended, but it should
|
|
|
|
|
-- do something reasonable
|
2019-11-09 04:41:50 -07:00
|
|
|
|
eq(6, set_extmark(ns, 6, positions[2][1], positions[2][2]))
|
|
|
|
|
eq(7, set_extmark(ns, 0, positions[1][1], positions[1][2]))
|
|
|
|
|
eq(8, set_extmark(ns, 0, positions[1][1], positions[1][2]))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('auto indenting with enter works', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- op_reindent in ops.c
|
|
|
|
|
feed(':set cindent<cr><esc>')
|
|
|
|
|
feed(':set autoindent<cr><esc>')
|
|
|
|
|
feed(':set shiftwidth=2<cr><esc>')
|
|
|
|
|
feed('0iint <esc>A {1M1<esc>b<esc>')
|
|
|
|
|
-- Set the mark on the M, should move..
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 12)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- Set the mark before the cursor, should stay there
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[2], 0, 10)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('i<cr><esc>')
|
2020-09-04 10:11:26 -07:00
|
|
|
|
local rv = get_extmark_by_id(ns, marks[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ 1, 3 }, rv)
|
2020-09-04 10:11:26 -07:00
|
|
|
|
rv = get_extmark_by_id(ns, marks[2])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ 0, 10 }, rv)
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 12, 1, 3)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('auto indenting entire line works', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed(':set cindent<cr><esc>')
|
|
|
|
|
feed(':set autoindent<cr><esc>')
|
|
|
|
|
feed(':set shiftwidth=2<cr><esc>')
|
|
|
|
|
-- <c-f> will force an indent of 2
|
|
|
|
|
feed('0iint <esc>A {<cr><esc>0i1M1<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('0i<c-f><esc>')
|
2020-09-04 10:11:26 -07:00
|
|
|
|
local rv = get_extmark_by_id(ns, marks[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ 1, 3 }, rv)
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 1, 1, 3)
|
|
|
|
|
-- now check when cursor at eol
|
|
|
|
|
feed('uA<c-f><esc>')
|
2020-09-04 10:11:26 -07:00
|
|
|
|
rv = get_extmark_by_id(ns, marks[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ 1, 3 }, rv)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('removing auto indenting with <C-D> works', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed(':set cindent<cr><esc>')
|
|
|
|
|
feed(':set autoindent<cr><esc>')
|
|
|
|
|
feed(':set shiftwidth=2<cr><esc>')
|
|
|
|
|
feed('0i<tab><esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 3)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('bi<c-d><esc>')
|
2020-09-04 10:11:26 -07:00
|
|
|
|
local rv = get_extmark_by_id(ns, marks[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ 0, 1 }, rv)
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 1)
|
|
|
|
|
-- check when cursor at eol
|
|
|
|
|
feed('uA<c-d><esc>')
|
2020-09-04 10:11:26 -07:00
|
|
|
|
rv = get_extmark_by_id(ns, marks[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ 0, 1 }, rv)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('indenting multiple lines with = works', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed(':set cindent<cr><esc>')
|
|
|
|
|
feed(':set autoindent<cr><esc>')
|
|
|
|
|
feed(':set shiftwidth=2<cr><esc>')
|
|
|
|
|
feed('0iint <esc>A {<cr><bs>1M1<cr><bs>2M2<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 1)
|
|
|
|
|
set_extmark(ns, marks[2], 2, 1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('=gg')
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 1, 1, 3)
|
|
|
|
|
check_undo_redo(ns, marks[2], 2, 1, 2, 5)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes by deleting inside the replace matches', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_sub in ex_cmds.c
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed(':s/34/xx<cr>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 4)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 4)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes when insert text > deleted', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_sub in ex_cmds.c
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed(':s/34/xxx<cr>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 5)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 5)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes when marks around eol', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_sub in ex_cmds.c
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 5)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed(':s/5/xxx<cr>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 4, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 5, 0, 7)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes over range insert text > deleted', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_sub in ex_cmds.c
|
|
|
|
|
feed('A<cr>x34xx<esc>')
|
|
|
|
|
feed('A<cr>xxx34<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 1, 1)
|
|
|
|
|
set_extmark(ns, marks[3], 2, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed(':1,3s/34/xxx<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 5)
|
|
|
|
|
check_undo_redo(ns, marks[2], 1, 1, 1, 4)
|
|
|
|
|
check_undo_redo(ns, marks[3], 2, 4, 2, 6)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes multiple matches in a line', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_sub in ex_cmds.c
|
|
|
|
|
feed('ddi3x3x3<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 0)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed(':s/3/yy/g<cr><esc>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 0, 0, 2)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 2, 0, 5)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 4, 0, 8)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes over multiple lines with newline in pattern', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>67890<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[3], 1, 0)
|
|
|
|
|
set_extmark(ns, marks[4], 1, 5)
|
|
|
|
|
set_extmark(ns, marks[5], 2, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:1,2s:5\n:5 <cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 3)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 4, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[3], 1, 0, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[4], 1, 5, 0, 11)
|
|
|
|
|
check_undo_redo(ns, marks[5], 2, 0, 1, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('inserting', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>67890<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[3], 1, 0)
|
|
|
|
|
set_extmark(ns, marks[4], 1, 5)
|
|
|
|
|
set_extmark(ns, marks[5], 2, 0)
|
|
|
|
|
set_extmark(ns, marks[6], 1, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:1,2s:5\n67:X<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 3)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 4, 0, 5)
|
|
|
|
|
check_undo_redo(ns, marks[3], 1, 0, 0, 5)
|
|
|
|
|
check_undo_redo(ns, marks[4], 1, 5, 0, 8)
|
|
|
|
|
check_undo_redo(ns, marks[5], 2, 0, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[6], 1, 2, 0, 5)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes with multiple newlines in pattern', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>67890<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 5)
|
|
|
|
|
set_extmark(ns, marks[3], 1, 0)
|
|
|
|
|
set_extmark(ns, marks[4], 1, 5)
|
|
|
|
|
set_extmark(ns, marks[5], 2, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:1,2s:\n.*\n:X<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 4, 0, 4)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 5, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[3], 1, 0, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[4], 1, 5, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[5], 2, 0, 0, 6)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes over multiple lines with replace in substitution', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>67890<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 1)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[4], 1, 0)
|
|
|
|
|
set_extmark(ns, marks[5], 2, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:1,2s:3:\r<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 1, 0, 1)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 2, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 4, 1, 1)
|
|
|
|
|
check_undo_redo(ns, marks[4], 1, 0, 2, 0)
|
|
|
|
|
check_undo_redo(ns, marks[5], 2, 0, 3, 0)
|
|
|
|
|
feed('u')
|
|
|
|
|
feed([[:1,2s:3:\rxx<cr>]])
|
2020-09-04 10:11:26 -07:00
|
|
|
|
eq({ 1, 3 }, get_extmark_by_id(ns, marks[3]))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes over multiple lines with replace in substitution', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>x3<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 1, 0)
|
|
|
|
|
set_extmark(ns, marks[2], 1, 1)
|
|
|
|
|
set_extmark(ns, marks[3], 1, 2)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:2,2s:3:\r<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 1, 0, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[2], 1, 1, 2, 0)
|
|
|
|
|
check_undo_redo(ns, marks[3], 1, 2, 2, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes over multiple lines with replace in substitution', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>x3<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 1)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[4], 1, 1)
|
|
|
|
|
set_extmark(ns, marks[5], 2, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:1,2s:3:\r<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 1, 0, 1)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 2, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 4, 1, 1)
|
|
|
|
|
check_undo_redo(ns, marks[4], 1, 1, 3, 0)
|
|
|
|
|
check_undo_redo(ns, marks[5], 2, 0, 4, 0)
|
|
|
|
|
feed('u')
|
|
|
|
|
feed([[:1,2s:3:\rxx<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 4, 1, 3)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes with newline in match and sub, delta is 0', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>67890<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 5)
|
|
|
|
|
set_extmark(ns, marks[4], 1, 0)
|
|
|
|
|
set_extmark(ns, marks[5], 1, 5)
|
|
|
|
|
set_extmark(ns, marks[6], 2, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:1,1s:5\n:\r<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 3)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 4, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 5, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[4], 1, 0, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[5], 1, 5, 1, 5)
|
|
|
|
|
check_undo_redo(ns, marks[6], 2, 0, 2, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes with newline in match and sub, delta > 0', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>67890<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 5)
|
|
|
|
|
set_extmark(ns, marks[4], 1, 0)
|
|
|
|
|
set_extmark(ns, marks[5], 1, 5)
|
|
|
|
|
set_extmark(ns, marks[6], 2, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:1,1s:5\n:\r\r<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 3)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 4, 2, 0)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 5, 2, 0)
|
|
|
|
|
check_undo_redo(ns, marks[4], 1, 0, 2, 0)
|
|
|
|
|
check_undo_redo(ns, marks[5], 1, 5, 2, 5)
|
|
|
|
|
check_undo_redo(ns, marks[6], 2, 0, 3, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes with newline in match and sub, delta < 0', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>67890<cr>xx<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 5)
|
|
|
|
|
set_extmark(ns, marks[4], 1, 0)
|
|
|
|
|
set_extmark(ns, marks[5], 1, 5)
|
|
|
|
|
set_extmark(ns, marks[6], 2, 1)
|
|
|
|
|
set_extmark(ns, marks[7], 3, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:1,2s:5\n.*\n:\r<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 3)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 4, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 5, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[4], 1, 0, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[5], 1, 5, 1, 0)
|
|
|
|
|
check_undo_redo(ns, marks[6], 2, 1, 1, 1)
|
|
|
|
|
check_undo_redo(ns, marks[7], 3, 0, 2, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes with backrefs, newline inserted into sub', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>67890<cr>xx<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 4)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 5)
|
|
|
|
|
set_extmark(ns, marks[4], 1, 0)
|
|
|
|
|
set_extmark(ns, marks[5], 1, 5)
|
|
|
|
|
set_extmark(ns, marks[6], 2, 0)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:1,1s:5\(\n\):\0\1<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 3, 0, 3)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 4, 2, 0)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 5, 2, 0)
|
|
|
|
|
check_undo_redo(ns, marks[4], 1, 0, 2, 0)
|
|
|
|
|
check_undo_redo(ns, marks[5], 1, 5, 2, 5)
|
|
|
|
|
check_undo_redo(ns, marks[6], 2, 0, 3, 0)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('substitutes a ^', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 0)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:s:^:x<cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 0, 0, 1)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 1, 0, 2)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('using <c-a> without increase in order of magnitude', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_addsub in ops.c
|
|
|
|
|
feed('ddiabc998xxx<esc>Tc')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 5)
|
|
|
|
|
set_extmark(ns, marks[4], 0, 6)
|
|
|
|
|
set_extmark(ns, marks[5], 0, 7)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-a>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 5, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[4], 0, 6, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[5], 0, 7, 0, 7)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('using <c-a> when increase in order of magnitude', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_addsub in ops.c
|
|
|
|
|
feed('ddiabc999xxx<esc>Tc')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 5)
|
|
|
|
|
set_extmark(ns, marks[4], 0, 6)
|
|
|
|
|
set_extmark(ns, marks[5], 0, 7)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-a>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 5, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[4], 0, 6, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[5], 0, 7, 0, 8)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('using <c-a> when negative and without decrease in order of magnitude', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('ddiabc-999xxx<esc>T-')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 6)
|
|
|
|
|
set_extmark(ns, marks[4], 0, 7)
|
|
|
|
|
set_extmark(ns, marks[5], 0, 8)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-a>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 6, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[4], 0, 7, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[5], 0, 8, 0, 8)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('using <c-a> when negative and decrease in order of magnitude', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('ddiabc-1000xxx<esc>T-')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 7)
|
|
|
|
|
set_extmark(ns, marks[4], 0, 8)
|
|
|
|
|
set_extmark(ns, marks[5], 0, 9)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-a>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 7, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[4], 0, 8, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[5], 0, 9, 0, 8)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('using <c-x> without decrease in order of magnitude', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_addsub in ops.c
|
|
|
|
|
feed('ddiabc999xxx<esc>Tc')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 5)
|
|
|
|
|
set_extmark(ns, marks[4], 0, 6)
|
|
|
|
|
set_extmark(ns, marks[5], 0, 7)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-x>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 5, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[4], 0, 6, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[5], 0, 7, 0, 7)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('using <c-x> when decrease in order of magnitude', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
-- do_addsub in ops.c
|
|
|
|
|
feed('ddiabc1000xxx<esc>Tc')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 6)
|
|
|
|
|
set_extmark(ns, marks[4], 0, 7)
|
|
|
|
|
set_extmark(ns, marks[5], 0, 8)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-x>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 6, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[4], 0, 7, 0, 6)
|
|
|
|
|
check_undo_redo(ns, marks[5], 0, 8, 0, 7)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('using <c-x> when negative and without increase in order of magnitude', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('ddiabc-998xxx<esc>T-')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 6)
|
|
|
|
|
set_extmark(ns, marks[4], 0, 7)
|
|
|
|
|
set_extmark(ns, marks[5], 0, 8)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-x>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 6, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[4], 0, 7, 0, 7)
|
|
|
|
|
check_undo_redo(ns, marks[5], 0, 8, 0, 8)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('using <c-x> when negative and increase in order of magnitude', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('ddiabc-999xxx<esc>T-')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, 2)
|
|
|
|
|
set_extmark(ns, marks[2], 0, 3)
|
|
|
|
|
set_extmark(ns, marks[3], 0, 6)
|
|
|
|
|
set_extmark(ns, marks[4], 0, 7)
|
|
|
|
|
set_extmark(ns, marks[5], 0, 8)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('<c-x>')
|
|
|
|
|
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
|
|
|
|
|
check_undo_redo(ns, marks[2], 0, 3, 0, 8)
|
|
|
|
|
check_undo_redo(ns, marks[3], 0, 6, 0, 8)
|
|
|
|
|
check_undo_redo(ns, marks[4], 0, 7, 0, 8)
|
|
|
|
|
check_undo_redo(ns, marks[5], 0, 8, 0, 9)
|
|
|
|
|
end)
|
|
|
|
|
|
2019-11-09 04:41:50 -07:00
|
|
|
|
it('throws consistent error codes', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
local ns_invalid = ns2 + 1
|
2023-02-14 12:19:28 -07:00
|
|
|
|
eq(
|
|
|
|
|
"Invalid 'ns_id': 3",
|
|
|
|
|
pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2])
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq("Invalid 'ns_id': 3", pcall_err(api.nvim_buf_del_extmark, 0, ns_invalid, marks[1]))
|
2023-02-14 12:19:28 -07:00
|
|
|
|
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]))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('when col = line-length, set the mark on eol', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, -1)
|
2020-09-04 10:11:26 -07:00
|
|
|
|
local rv = get_extmark_by_id(ns, marks[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ 0, init_text:len() }, rv)
|
|
|
|
|
-- Test another
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 0, -1)
|
2020-09-04 10:11:26 -07:00
|
|
|
|
rv = get_extmark_by_id(ns, marks[1])
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({ 0, init_text:len() }, rv)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('when col = line-length, set the mark on eol', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
local invalid_col = init_text:len() + 1
|
2023-02-14 06:07:38 -07:00
|
|
|
|
eq("Invalid 'col': out of range", pcall_err(set_extmark, ns, marks[1], 0, invalid_col))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('fails when line > line_count', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
local invalid_col = init_text:len() + 1
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local invalid_lnum = 3
|
2023-02-14 06:07:38 -07:00
|
|
|
|
eq(
|
|
|
|
|
"Invalid 'line': out of range",
|
|
|
|
|
pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col)
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2020-09-04 10:11:26 -07:00
|
|
|
|
eq({}, get_extmark_by_id(ns, marks[1]))
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('bug from check_col in extmark_set', function()
|
2019-11-25 02:08:02 -07:00
|
|
|
|
-- This bug was caused by extmark_set always using check_col. check_col
|
|
|
|
|
-- always uses the current buffer. This wasn't working during undo so we
|
|
|
|
|
-- now use check_col and check_lnum only when they are required.
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('A<cr>67890<cr>xx<esc>')
|
|
|
|
|
feed('A<cr>12345<cr>67890<cr>xx<esc>')
|
2019-11-09 04:41:50 -07:00
|
|
|
|
set_extmark(ns, marks[1], 3, 4)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed([[:1,5s:5\n:5 <cr>]])
|
|
|
|
|
check_undo_redo(ns, marks[1], 3, 4, 2, 6)
|
|
|
|
|
end)
|
|
|
|
|
|
2019-11-16 03:05:56 -07:00
|
|
|
|
it('in read-only buffer', function()
|
|
|
|
|
command('view! runtime/doc/help.txt')
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq(true, api.nvim_get_option_value('ro', {}))
|
2019-11-16 03:05:56 -07:00
|
|
|
|
local id = set_extmark(ns, 0, 0, 2)
|
|
|
|
|
eq({ { id, 0, 2 } }, get_extmarks(ns, 0, -1))
|
|
|
|
|
end)
|
2019-11-25 08:50:30 -07:00
|
|
|
|
|
|
|
|
|
it('can set a mark to other buffer', function()
|
|
|
|
|
local buf = request('nvim_create_buf', 0, 1)
|
|
|
|
|
request('nvim_buf_set_lines', buf, 0, -1, 1, { '', '' })
|
2024-01-12 10:59:57 -07:00
|
|
|
|
local id = api.nvim_buf_set_extmark(buf, ns, 1, 0, {})
|
|
|
|
|
eq({ { id, 1, 0 } }, api.nvim_buf_get_extmarks(buf, ns, 0, -1, {}))
|
2019-11-25 08:50:30 -07:00
|
|
|
|
end)
|
2020-01-14 04:45:09 -07:00
|
|
|
|
|
|
|
|
|
it('does not crash with append/delete/undo sequence', function()
|
2023-03-25 19:49:32 -07:00
|
|
|
|
exec([[
|
2020-01-14 04:45:09 -07:00
|
|
|
|
let ns = nvim_create_namespace('myplugin')
|
2020-01-21 06:01:40 -07:00
|
|
|
|
call nvim_buf_set_extmark(0, ns, 0, 0, {})
|
2020-01-14 04:45:09 -07:00
|
|
|
|
call append(0, '')
|
|
|
|
|
%delete
|
2023-03-25 19:49:32 -07:00
|
|
|
|
undo]])
|
2021-09-01 09:42:53 -07:00
|
|
|
|
assert_alive()
|
2020-01-14 04:45:09 -07:00
|
|
|
|
end)
|
2021-01-03 14:59:24 -07:00
|
|
|
|
|
|
|
|
|
it('works with left and right gravity', function()
|
|
|
|
|
-- right gravity should move with inserted text, while
|
|
|
|
|
-- left gravity should stay in place.
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_set_extmark(0, ns, 0, 5, { right_gravity = false })
|
|
|
|
|
api.nvim_buf_set_extmark(0, ns, 0, 5, { right_gravity = true })
|
2021-01-03 14:59:24 -07:00
|
|
|
|
feed([[Aasdfasdf]])
|
|
|
|
|
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq({ { 1, 0, 5 }, { 2, 0, 13 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {}))
|
2021-01-03 14:59:24 -07:00
|
|
|
|
|
|
|
|
|
-- but both move when text is inserted before
|
|
|
|
|
feed([[<esc>Iasdf<esc>]])
|
2024-01-12 10:59:57 -07:00
|
|
|
|
-- eq({}, api.nvim_buf_get_lines(0, 0, -1, true))
|
|
|
|
|
eq({ { 1, 0, 9 }, { 2, 0, 17 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {}))
|
2021-01-03 14:59:24 -07:00
|
|
|
|
|
|
|
|
|
-- clear text
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_set_text(0, 0, 0, 0, 17, {})
|
2021-01-03 14:59:24 -07:00
|
|
|
|
|
|
|
|
|
-- handles set_text correctly as well
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq({ { 1, 0, 0 }, { 2, 0, 0 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {}))
|
|
|
|
|
api.nvim_buf_set_text(0, 0, 0, 0, 0, { 'asdfasdf' })
|
|
|
|
|
eq({ { 1, 0, 0 }, { 2, 0, 8 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {}))
|
2021-01-03 14:59:24 -07:00
|
|
|
|
|
|
|
|
|
feed('u')
|
|
|
|
|
-- handles pasting
|
2023-03-25 19:49:32 -07:00
|
|
|
|
exec([[let @a='asdfasdf']])
|
2021-01-03 14:59:24 -07:00
|
|
|
|
feed([["ap]])
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq({ { 1, 0, 0 }, { 2, 0, 8 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {}))
|
2021-01-03 14:59:24 -07:00
|
|
|
|
end)
|
2021-12-08 08:44:48 -07:00
|
|
|
|
|
|
|
|
|
it('can accept "end_row" or "end_line" #16548', function()
|
|
|
|
|
set_extmark(ns, marks[1], 0, 0, {
|
|
|
|
|
end_col = 0,
|
|
|
|
|
end_line = 1,
|
|
|
|
|
})
|
2022-01-23 17:52:13 -07:00
|
|
|
|
eq({
|
|
|
|
|
{
|
|
|
|
|
1,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
{
|
2023-03-24 18:24:24 -07:00
|
|
|
|
ns_id = 1,
|
2022-01-23 17:52:13 -07:00
|
|
|
|
end_col = 0,
|
|
|
|
|
end_row = 1,
|
|
|
|
|
right_gravity = true,
|
|
|
|
|
end_right_gravity = false,
|
2024-01-02 18:09:18 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
2022-01-23 17:52:13 -07:00
|
|
|
|
}, get_extmarks(ns, 0, -1, { details = true }))
|
2021-12-08 08:44:48 -07:00
|
|
|
|
end)
|
2022-01-13 07:26:57 -07:00
|
|
|
|
|
2022-12-07 10:07:56 -07:00
|
|
|
|
it('in prompt buffer', function()
|
|
|
|
|
feed('dd')
|
|
|
|
|
local id = set_extmark(ns, marks[1], 0, 0, {})
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_set_option_value('buftype', 'prompt', {})
|
2022-12-07 10:07:56 -07:00
|
|
|
|
feed('i<esc>')
|
|
|
|
|
eq({ { id, 0, 2 } }, get_extmarks(ns, 0, -1))
|
|
|
|
|
end)
|
|
|
|
|
|
2022-01-13 07:26:57 -07:00
|
|
|
|
it('can get details', function()
|
|
|
|
|
set_extmark(ns, marks[1], 0, 0, {
|
2023-03-24 18:24:24 -07:00
|
|
|
|
conceal = 'c',
|
|
|
|
|
cursorline_hl_group = 'Statement',
|
2022-01-13 07:26:57 -07:00
|
|
|
|
end_col = 0,
|
2022-01-23 17:52:13 -07:00
|
|
|
|
end_right_gravity = true,
|
2023-03-24 18:24:24 -07:00
|
|
|
|
end_row = 1,
|
2022-01-13 07:26:57 -07:00
|
|
|
|
hl_eol = true,
|
|
|
|
|
hl_group = 'String',
|
2023-03-24 18:24:24 -07:00
|
|
|
|
hl_mode = 'blend',
|
|
|
|
|
line_hl_group = 'Statement',
|
|
|
|
|
number_hl_group = 'Statement',
|
|
|
|
|
priority = 0,
|
|
|
|
|
right_gravity = false,
|
|
|
|
|
sign_hl_group = 'Statement',
|
|
|
|
|
sign_text = '>>',
|
|
|
|
|
spell = true,
|
2023-09-22 02:56:05 -07:00
|
|
|
|
virt_lines = {
|
|
|
|
|
{ { 'lines', 'Macro' }, { '???' } },
|
|
|
|
|
{ { 'stack', { 'Type', 'Search' } }, { '!!!' } },
|
|
|
|
|
},
|
2022-01-13 07:26:57 -07:00
|
|
|
|
virt_lines_above = true,
|
|
|
|
|
virt_lines_leftcol = true,
|
2023-09-22 02:56:05 -07:00
|
|
|
|
virt_text = { { 'text', 'Macro' }, { '???' }, { 'stack', { 'Type', 'Search' } } },
|
2023-03-24 18:24:24 -07:00
|
|
|
|
virt_text_hide = true,
|
|
|
|
|
virt_text_pos = 'right_align',
|
2022-01-13 07:26:57 -07:00
|
|
|
|
})
|
|
|
|
|
set_extmark(ns, marks[2], 0, 0, {
|
|
|
|
|
priority = 0,
|
2023-09-22 02:56:05 -07:00
|
|
|
|
virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } },
|
2022-01-13 07:26:57 -07:00
|
|
|
|
virt_text_win_col = 1,
|
|
|
|
|
})
|
|
|
|
|
eq({
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
{
|
2023-03-24 18:24:24 -07:00
|
|
|
|
conceal = 'c',
|
|
|
|
|
cursorline_hl_group = 'Statement',
|
2022-01-13 07:26:57 -07:00
|
|
|
|
end_col = 0,
|
2022-01-23 17:52:13 -07:00
|
|
|
|
end_right_gravity = true,
|
2023-03-24 18:24:24 -07:00
|
|
|
|
end_row = 1,
|
2022-01-13 07:26:57 -07:00
|
|
|
|
hl_eol = true,
|
|
|
|
|
hl_group = 'String',
|
2023-03-24 18:24:24 -07:00
|
|
|
|
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,
|
2023-09-22 02:56:05 -07:00
|
|
|
|
virt_lines = {
|
|
|
|
|
{ { 'lines', 'Macro' }, { '???' } },
|
|
|
|
|
{ { 'stack', { 'Type', 'Search' } }, { '!!!' } },
|
2024-01-02 18:09:18 -07:00
|
|
|
|
},
|
2022-01-13 07:26:57 -07:00
|
|
|
|
virt_lines_above = true,
|
|
|
|
|
virt_lines_leftcol = true,
|
2023-09-22 02:56:05 -07:00
|
|
|
|
virt_text = { { 'text', 'Macro' }, { '???' }, { 'stack', { 'Type', 'Search' } } },
|
2023-12-25 16:16:03 -07:00
|
|
|
|
virt_text_repeat_linebreak = false,
|
2023-03-24 18:24:24 -07:00
|
|
|
|
virt_text_hide = true,
|
|
|
|
|
virt_text_pos = 'right_align',
|
2023-09-22 02:56:05 -07:00
|
|
|
|
},
|
2022-01-13 07:26:57 -07:00
|
|
|
|
}, get_extmark_by_id(ns, marks[1], { details = true }))
|
|
|
|
|
eq({
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
{
|
2023-03-24 18:24:24 -07:00
|
|
|
|
ns_id = 1,
|
2022-01-23 17:52:13 -07:00
|
|
|
|
right_gravity = true,
|
2022-01-13 07:26:57 -07:00
|
|
|
|
priority = 0,
|
2023-09-22 02:56:05 -07:00
|
|
|
|
virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } },
|
2023-12-25 16:16:03 -07:00
|
|
|
|
virt_text_repeat_linebreak = false,
|
2022-01-13 07:26:57 -07:00
|
|
|
|
virt_text_hide = false,
|
|
|
|
|
virt_text_pos = 'win_col',
|
|
|
|
|
virt_text_win_col = 1,
|
|
|
|
|
},
|
|
|
|
|
}, get_extmark_by_id(ns, marks[2], { details = true }))
|
2023-04-18 06:07:37 -07:00
|
|
|
|
set_extmark(ns, marks[3], 0, 0, { cursorline_hl_group = 'Statement' })
|
|
|
|
|
eq({
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
{
|
|
|
|
|
ns_id = 1,
|
|
|
|
|
cursorline_hl_group = 'Statement',
|
refactor(decorations): break up Decoration struct into smaller pieces
Remove the monolithic Decoration struct. Before this change, each extmark
could either represent just a hl_id + priority value as a inline
decoration, or it would take a pointer to this monolitic 112 byte struct
which has to be allocated.
This change separates the decorations into two pieces: DecorSignHighlight
for signs, highlights and simple set-flag decorations (like spell,
ui-watched), and DecorVirtText for virtual text and lines.
The main separation here is whether they are expected to allocate more
memory. Currently this is not really true as sign text has to be an
allocated string, but the plan is to get rid of this eventually (it can
just be an array of two schar_T:s). Further refactors are expected to
improve the representation of each decoration kind individually. The
goal of this particular PR is to get things started by cutting the
Gordian knot which was the monolithic struct Decoration.
Now, each extmark can either contain chained indicies/pointers to
these kinds of objects, or it can fit a subset of DecorSignHighlight
inline.
The point of this change is not only to make decorations smaller in
memory. In fact, the main motivation is to later allow them to grow
_larger_, but on a dynamic, on demand fashion. As a simple example, it
would be possible to augment highlights to take a list of multiple
`hl_group`:s, which then would trivially map to a chain of multiple
DecorSignHighlight entries.
One small feature improvement included with this refactor itself, is
that the restriction that extmarks cannot be removed inside a decoration
provider has been lifted. These are instead safely lifetime extended
on a "to free" list until the current iteration of screen drawing is done.
NB: flags is a mess. but DecorLevel is useless, this slightly less so
2023-03-08 07:18:02 -07:00
|
|
|
|
priority = 4096,
|
2023-04-18 06:07:37 -07:00
|
|
|
|
right_gravity = true,
|
|
|
|
|
},
|
|
|
|
|
}, get_extmark_by_id(ns, marks[3], { details = true }))
|
2024-01-21 15:25:06 -07:00
|
|
|
|
set_extmark(ns, marks[4], 0, 0, {
|
|
|
|
|
end_col = 1,
|
|
|
|
|
conceal = 'a',
|
|
|
|
|
spell = true,
|
|
|
|
|
})
|
|
|
|
|
eq({
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
{
|
|
|
|
|
conceal = 'a',
|
|
|
|
|
end_col = 1,
|
|
|
|
|
end_right_gravity = false,
|
|
|
|
|
end_row = 0,
|
|
|
|
|
ns_id = 1,
|
|
|
|
|
right_gravity = true,
|
|
|
|
|
spell = true,
|
|
|
|
|
},
|
|
|
|
|
}, get_extmark_by_id(ns, marks[4], { details = true }))
|
|
|
|
|
set_extmark(ns, marks[5], 0, 0, {
|
|
|
|
|
end_col = 1,
|
|
|
|
|
spell = false,
|
|
|
|
|
})
|
|
|
|
|
eq({
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
{
|
|
|
|
|
end_col = 1,
|
|
|
|
|
end_right_gravity = false,
|
|
|
|
|
end_row = 0,
|
|
|
|
|
ns_id = 1,
|
|
|
|
|
right_gravity = true,
|
|
|
|
|
spell = false,
|
|
|
|
|
},
|
|
|
|
|
}, get_extmark_by_id(ns, marks[5], { details = true }))
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
2023-11-18 15:49:11 -07:00
|
|
|
|
-- 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 }))
|
2022-01-13 07:26:57 -07:00
|
|
|
|
end)
|
2023-03-24 18:24:24 -07:00
|
|
|
|
|
|
|
|
|
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' } } } })
|
2023-10-24 04:32:00 -07:00
|
|
|
|
eq(5, #get_extmarks(-1, 0, -1, {}))
|
2023-03-24 18:24:24 -07:00
|
|
|
|
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)
|
2023-10-24 04:32:00 -07:00
|
|
|
|
|
|
|
|
|
it('invalidated marks are deleted', function()
|
|
|
|
|
screen = Screen.new(40, 6)
|
|
|
|
|
screen:attach()
|
|
|
|
|
feed('dd6iaaa bbb ccc<CR><ESC>gg')
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_set_option_value('signcolumn', 'auto:2', {})
|
2023-12-02 03:59:54 -07:00
|
|
|
|
set_extmark(ns, 1, 0, 0, { invalidate = true, sign_text = 'S1', end_row = 1 })
|
|
|
|
|
set_extmark(ns, 2, 1, 0, { invalidate = true, sign_text = 'S2', end_row = 2 })
|
2023-10-24 04:32:00 -07:00
|
|
|
|
-- mark with invalidate is removed
|
2023-12-02 03:59:54 -07:00
|
|
|
|
command('d2')
|
2023-10-24 04:32:00 -07:00
|
|
|
|
screen:expect([[
|
|
|
|
|
S2^aaa bbb ccc |
|
2023-12-09 05:42:00 -07:00
|
|
|
|
aaa bbb ccc |*3
|
|
|
|
|
|*2
|
2023-10-24 04:32:00 -07:00
|
|
|
|
]])
|
|
|
|
|
-- mark is restored with undo_restore == true
|
|
|
|
|
command('silent undo')
|
|
|
|
|
screen:expect([[
|
2023-12-02 03:59:54 -07:00
|
|
|
|
S1 ^aaa bbb ccc |
|
|
|
|
|
S1S2aaa bbb ccc |
|
|
|
|
|
S2 aaa bbb ccc |
|
2023-12-09 05:42:00 -07:00
|
|
|
|
aaa bbb ccc |*2
|
2023-10-24 04:32:00 -07:00
|
|
|
|
|
|
|
|
|
|
]])
|
2024-01-17 05:31:07 -07:00
|
|
|
|
-- decor is not removed twice
|
|
|
|
|
command('d3')
|
|
|
|
|
api.nvim_buf_del_extmark(0, ns, 1)
|
|
|
|
|
command('silent undo')
|
2023-10-24 04:32:00 -07:00
|
|
|
|
-- 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)
|
feat(ui): add support for OSC 8 hyperlinks (#27109)
Extmarks can contain URLs which can then be drawn in any supporting UI.
In the TUI, for example, URLs are "drawn" by emitting the OSC 8 control
sequence to the TTY. On terminals which support the OSC 8 sequence this
will create clickable hyperlinks.
URLs are treated as inline highlights in the decoration subsystem, so
are included in the `DecorSignHighlight` structure. However, unlike
other inline highlights they use allocated memory which must be freed,
so they set the `ext` flag in `DecorInline` so that their lifetimes are
managed along with other allocated memory like virtual text.
The decoration subsystem then adds the URLs as a new highlight
attribute. The highlight subsystem maintains a set of unique URLs to
avoid duplicating allocations for the same string. To attach a URL to an
existing highlight attribute we call `hl_add_url` which finds the URL in
the set (allocating and adding it if it does not exist) and sets the
`url` highlight attribute to the index of the URL in the set (using an
index helps keep the size of the `HlAttrs` struct small).
This has the potential to lead to an increase in highlight attributes
if a URL is used over a range that contains many different highlight
attributes, because now each existing attribute must be combined with
the URL. In practice, however, URLs typically span a range containing a
single highlight (e.g. link text in Markdown), so this is likely just a
pathological edge case.
When a new highlight attribute is defined with a URL it is copied to all
attached UIs with the `hl_attr_define` UI event. The TUI manages its own
set of URLs (just like the highlight subsystem) to minimize allocations.
The TUI keeps track of which URL is "active" for the cell it is
printing. If no URL is active and a cell containing a URL is printed,
the opening OSC 8 sequence is emitted and that URL becomes the actively
tracked URL. If the cursor is moved while in the middle of a URL span,
we emit the terminating OSC sequence to prevent the hyperlink from
spanning multiple lines.
This does not support nested hyperlinks, but that is a rare (and,
frankly, bizarre) use case. If a valid use case for nested hyperlinks
ever presents itself we can address that issue then.
2024-01-24 15:36:25 -07:00
|
|
|
|
|
|
|
|
|
it('can set a URL', function()
|
|
|
|
|
set_extmark(ns, 1, 0, 0, { url = 'https://example.com', end_col = 3 })
|
|
|
|
|
local extmarks = get_extmarks(ns, 0, -1, { details = true })
|
|
|
|
|
eq(1, #extmarks)
|
|
|
|
|
eq('https://example.com', extmarks[1][4].url)
|
|
|
|
|
end)
|
2024-01-28 20:13:58 -07:00
|
|
|
|
|
|
|
|
|
it('respects priority', function()
|
|
|
|
|
screen = Screen.new(15, 10)
|
|
|
|
|
screen:attach()
|
|
|
|
|
|
|
|
|
|
set_extmark(ns, marks[1], 0, 0, {
|
|
|
|
|
hl_group = 'Comment',
|
|
|
|
|
end_col = 2,
|
|
|
|
|
priority = 20,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
-- Extmark defined after first extmark but has lower priority, first extmark "wins"
|
|
|
|
|
set_extmark(ns, marks[2], 0, 0, {
|
|
|
|
|
hl_group = 'String',
|
|
|
|
|
end_col = 2,
|
|
|
|
|
priority = 10,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
screen:expect {
|
|
|
|
|
grid = [[
|
|
|
|
|
{1:12}34^5 |
|
|
|
|
|
{2:~ }|*8
|
|
|
|
|
|
|
|
|
|
|
]],
|
|
|
|
|
attr_ids = {
|
|
|
|
|
[1] = { foreground = Screen.colors.Blue1 },
|
|
|
|
|
[2] = { foreground = Screen.colors.Blue1, bold = true },
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
end)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
describe('Extmarks buffer api with many marks', function()
|
|
|
|
|
local ns1
|
|
|
|
|
local ns2
|
|
|
|
|
local ns_marks = {}
|
|
|
|
|
before_each(function()
|
|
|
|
|
clear()
|
|
|
|
|
ns1 = request('nvim_create_namespace', 'ns1')
|
|
|
|
|
ns2 = request('nvim_create_namespace', 'ns2')
|
|
|
|
|
ns_marks = { [ns1] = {}, [ns2] = {} }
|
|
|
|
|
local lines = {}
|
|
|
|
|
for i = 1, 30 do
|
|
|
|
|
lines[#lines + 1] = string.rep('x ', i)
|
|
|
|
|
end
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_set_lines(0, 0, -1, true, lines)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
local ns = ns1
|
|
|
|
|
local q = 0
|
|
|
|
|
for i = 0, 29 do
|
|
|
|
|
for j = 0, i do
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local id = set_extmark(ns, 0, i, j)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq(nil, ns_marks[ns][id])
|
|
|
|
|
ok(id > 0)
|
|
|
|
|
ns_marks[ns][id] = { i, j }
|
|
|
|
|
ns = ns1 + ns2 - ns
|
|
|
|
|
q = q + 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
eq(233, #ns_marks[ns1])
|
|
|
|
|
eq(232, #ns_marks[ns2])
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
local function get_marks(ns)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
local mark_list = get_extmarks(ns, 0, -1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
local marks = {}
|
|
|
|
|
for _, mark in ipairs(mark_list) do
|
|
|
|
|
local id, row, col = unpack(mark)
|
|
|
|
|
eq(nil, marks[id], 'duplicate mark')
|
|
|
|
|
marks[id] = { row, col }
|
|
|
|
|
end
|
|
|
|
|
return marks
|
|
|
|
|
end
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('can get marks', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq(ns_marks[ns1], get_marks(ns1))
|
|
|
|
|
eq(ns_marks[ns2], get_marks(ns2))
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('can clear all marks in ns', function()
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_clear_namespace(0, ns1, 0, -1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({}, get_marks(ns1))
|
|
|
|
|
eq(ns_marks[ns2], get_marks(ns2))
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_clear_namespace(0, ns2, 0, -1)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
eq({}, get_marks(ns1))
|
|
|
|
|
eq({}, get_marks(ns2))
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('can clear line range', function()
|
2024-01-12 10:59:57 -07:00
|
|
|
|
api.nvim_buf_clear_namespace(0, ns1, 10, 20)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
for id, mark in pairs(ns_marks[ns1]) do
|
|
|
|
|
if 10 <= mark[1] and mark[1] < 20 then
|
|
|
|
|
ns_marks[ns1][id] = nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
eq(ns_marks[ns1], get_marks(ns1))
|
|
|
|
|
eq(ns_marks[ns2], get_marks(ns2))
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('can delete line', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('10Gdd')
|
|
|
|
|
for _, marks in pairs(ns_marks) do
|
|
|
|
|
for id, mark in pairs(marks) do
|
|
|
|
|
if mark[1] == 9 then
|
|
|
|
|
marks[id] = { 9, 0 }
|
|
|
|
|
elseif mark[1] >= 10 then
|
|
|
|
|
mark[1] = mark[1] - 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
eq(ns_marks[ns1], get_marks(ns1))
|
|
|
|
|
eq(ns_marks[ns2], get_marks(ns2))
|
|
|
|
|
end)
|
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('can delete lines', function()
|
2017-01-18 05:20:07 -07:00
|
|
|
|
feed('10G10dd')
|
|
|
|
|
for _, marks in pairs(ns_marks) do
|
|
|
|
|
for id, mark in pairs(marks) do
|
|
|
|
|
if 9 <= mark[1] and mark[1] < 19 then
|
|
|
|
|
marks[id] = { 9, 0 }
|
|
|
|
|
elseif mark[1] >= 19 then
|
|
|
|
|
mark[1] = mark[1] - 10
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
eq(ns_marks[ns1], get_marks(ns1))
|
|
|
|
|
eq(ns_marks[ns2], get_marks(ns2))
|
|
|
|
|
end)
|
2019-11-09 04:41:50 -07:00
|
|
|
|
|
2020-01-14 04:45:09 -07:00
|
|
|
|
it('can wipe buffer', function()
|
2019-11-09 04:41:50 -07:00
|
|
|
|
command('bwipe!')
|
|
|
|
|
eq({}, get_marks(ns1))
|
|
|
|
|
eq({}, get_marks(ns2))
|
|
|
|
|
end)
|
2017-01-18 05:20:07 -07:00
|
|
|
|
end)
|
2021-09-15 16:53:56 -07:00
|
|
|
|
|
|
|
|
|
describe('API/win_extmark', function()
|
|
|
|
|
local screen
|
|
|
|
|
local marks, line1, line2
|
|
|
|
|
local ns
|
|
|
|
|
|
|
|
|
|
before_each(function()
|
|
|
|
|
-- Initialize some namespaces and insert text into a buffer
|
|
|
|
|
marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
|
|
|
|
|
|
|
|
|
|
line1 = 'non ui-watched line'
|
|
|
|
|
line2 = 'ui-watched line'
|
|
|
|
|
|
|
|
|
|
clear()
|
|
|
|
|
|
|
|
|
|
insert(line1)
|
|
|
|
|
feed('o<esc>')
|
|
|
|
|
insert(line2)
|
|
|
|
|
ns = request('nvim_create_namespace', 'extmark-ui')
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('sends and only sends ui-watched marks to ui', function()
|
|
|
|
|
screen = Screen.new(20, 4)
|
|
|
|
|
screen:attach()
|
|
|
|
|
-- should send this
|
|
|
|
|
set_extmark(ns, marks[1], 1, 0, { ui_watched = true })
|
|
|
|
|
-- should not send this
|
|
|
|
|
set_extmark(ns, marks[2], 0, 0, { ui_watched = false })
|
|
|
|
|
screen:expect({
|
|
|
|
|
grid = [[
|
|
|
|
|
non ui-watched line |
|
|
|
|
|
ui-watched lin^e |
|
|
|
|
|
~ |
|
|
|
|
|
|
|
|
|
|
|
]],
|
|
|
|
|
extmarks = {
|
|
|
|
|
[2] = {
|
|
|
|
|
-- positioned at the end of the 2nd line
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 16 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('sends multiple ui-watched marks to ui', function()
|
|
|
|
|
screen = Screen.new(20, 4)
|
|
|
|
|
screen:attach()
|
2023-12-25 00:50:58 -07:00
|
|
|
|
feed('15A!<Esc>')
|
2021-09-15 16:53:56 -07:00
|
|
|
|
-- should send all of these
|
|
|
|
|
set_extmark(ns, marks[1], 1, 0, { ui_watched = true, virt_text_pos = 'overlay' })
|
|
|
|
|
set_extmark(ns, marks[2], 1, 2, { ui_watched = true, virt_text_pos = 'overlay' })
|
|
|
|
|
set_extmark(ns, marks[3], 1, 4, { ui_watched = true, virt_text_pos = 'overlay' })
|
|
|
|
|
set_extmark(ns, marks[4], 1, 6, { ui_watched = true, virt_text_pos = 'overlay' })
|
|
|
|
|
set_extmark(ns, marks[5], 1, 8, { ui_watched = true })
|
|
|
|
|
screen:expect({
|
|
|
|
|
grid = [[
|
|
|
|
|
non ui-watched line |
|
2023-12-25 00:50:58 -07:00
|
|
|
|
ui-watched line!!!!!|
|
|
|
|
|
!!!!!!!!!^! |
|
2021-09-15 16:53:56 -07:00
|
|
|
|
|
|
|
|
|
|
]],
|
|
|
|
|
extmarks = {
|
|
|
|
|
[2] = {
|
2023-12-25 00:50:58 -07:00
|
|
|
|
-- notification from 1st call
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 0 },
|
2023-12-25 00:50:58 -07:00
|
|
|
|
-- notifications from 2nd call
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 0 },
|
|
|
|
|
{ 1000, ns, marks[2], 1, 2 },
|
2023-12-25 03:57:55 -07:00
|
|
|
|
-- notifications from 3rd call
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 0 },
|
|
|
|
|
{ 1000, ns, marks[2], 1, 2 },
|
|
|
|
|
{ 1000, ns, marks[3], 1, 4 },
|
2023-12-25 00:50:58 -07:00
|
|
|
|
-- notifications from 4th call
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 0 },
|
|
|
|
|
{ 1000, ns, marks[2], 1, 2 },
|
|
|
|
|
{ 1000, ns, marks[3], 1, 4 },
|
|
|
|
|
{ 1000, ns, marks[4], 1, 6 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
-- final
|
|
|
|
|
-- overlay
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 0 },
|
|
|
|
|
{ 1000, ns, marks[2], 1, 2 },
|
|
|
|
|
{ 1000, ns, marks[3], 1, 4 },
|
|
|
|
|
{ 1000, ns, marks[4], 1, 6 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
-- eol
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[5], 2, 11 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('updates ui-watched marks', function()
|
|
|
|
|
screen = Screen.new(20, 4)
|
|
|
|
|
screen:attach()
|
|
|
|
|
-- should send this
|
|
|
|
|
set_extmark(ns, marks[1], 1, 0, { ui_watched = true })
|
|
|
|
|
-- should not send this
|
|
|
|
|
set_extmark(ns, marks[2], 0, 0, { ui_watched = false })
|
|
|
|
|
-- make some changes
|
|
|
|
|
insert(' update')
|
|
|
|
|
screen:expect({
|
|
|
|
|
grid = [[
|
|
|
|
|
non ui-watched line |
|
|
|
|
|
ui-watched linupdat^e|
|
|
|
|
|
e |
|
|
|
|
|
|
|
|
|
|
|
]],
|
|
|
|
|
extmarks = {
|
|
|
|
|
[2] = {
|
|
|
|
|
-- positioned at the end of the 2nd line
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 16 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
-- updated and wrapped to 3rd line
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 2, 2 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
feed('<c-e>')
|
|
|
|
|
screen:expect({
|
|
|
|
|
grid = [[
|
|
|
|
|
ui-watched linupdat^e|
|
|
|
|
|
e |
|
|
|
|
|
~ |
|
|
|
|
|
|
|
|
|
|
|
]],
|
|
|
|
|
extmarks = {
|
|
|
|
|
[2] = {
|
|
|
|
|
-- positioned at the end of the 2nd line
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 16 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
-- updated and wrapped to 3rd line
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 2, 2 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
-- scrolled up one line, should be handled by grid scroll
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('sends ui-watched to splits', function()
|
|
|
|
|
screen = Screen.new(20, 8)
|
|
|
|
|
screen:attach({ ext_multigrid = true })
|
|
|
|
|
-- should send this
|
|
|
|
|
set_extmark(ns, marks[1], 1, 0, { ui_watched = true })
|
|
|
|
|
-- should not send this
|
|
|
|
|
set_extmark(ns, marks[2], 0, 0, { ui_watched = false })
|
|
|
|
|
command('split')
|
|
|
|
|
screen:expect({
|
|
|
|
|
grid = [[
|
|
|
|
|
## grid 1
|
2023-12-09 05:42:00 -07:00
|
|
|
|
[4:--------------------]|*3
|
2021-09-15 16:53:56 -07:00
|
|
|
|
[No Name] [+] |
|
2023-12-09 05:42:00 -07:00
|
|
|
|
[2:--------------------]|*2
|
2021-09-15 16:53:56 -07:00
|
|
|
|
[No Name] [+] |
|
|
|
|
|
[3:--------------------]|
|
|
|
|
|
## grid 2
|
|
|
|
|
non ui-watched line |
|
|
|
|
|
ui-watched line |
|
|
|
|
|
## grid 3
|
|
|
|
|
|
|
|
|
|
|
## grid 4
|
|
|
|
|
non ui-watched line |
|
|
|
|
|
ui-watched lin^e |
|
|
|
|
|
~ |
|
|
|
|
|
]],
|
|
|
|
|
extmarks = {
|
|
|
|
|
[2] = {
|
|
|
|
|
-- positioned at the end of the 2nd line
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 16 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
-- updated after split
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 16 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
},
|
|
|
|
|
[4] = {
|
|
|
|
|
-- only after split
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1001, ns, marks[1], 1, 16 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
-- make some changes
|
|
|
|
|
insert(' update')
|
|
|
|
|
screen:expect({
|
|
|
|
|
grid = [[
|
|
|
|
|
## grid 1
|
2023-12-09 05:42:00 -07:00
|
|
|
|
[4:--------------------]|*3
|
2021-09-15 16:53:56 -07:00
|
|
|
|
[No Name] [+] |
|
2023-12-09 05:42:00 -07:00
|
|
|
|
[2:--------------------]|*2
|
2021-09-15 16:53:56 -07:00
|
|
|
|
[No Name] [+] |
|
|
|
|
|
[3:--------------------]|
|
|
|
|
|
## grid 2
|
|
|
|
|
non ui-watched line |
|
|
|
|
|
ui-watched linupd@@@|
|
|
|
|
|
## grid 3
|
|
|
|
|
|
|
|
|
|
|
## grid 4
|
|
|
|
|
non ui-watched line |
|
|
|
|
|
ui-watched linupdat^e|
|
|
|
|
|
e |
|
|
|
|
|
]],
|
|
|
|
|
extmarks = {
|
|
|
|
|
[2] = {
|
|
|
|
|
-- positioned at the end of the 2nd line
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 16 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
-- updated after split
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1000, ns, marks[1], 1, 16 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
},
|
|
|
|
|
[4] = {
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1001, ns, marks[1], 1, 16 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
-- updated
|
2024-01-16 06:26:21 -07:00
|
|
|
|
{ 1001, ns, marks[1], 2, 2 },
|
2021-09-15 16:53:56 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
end)
|
|
|
|
|
end)
|