aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/lua.txt6
-rw-r--r--runtime/lua/vim/_editor.lua5
-rw-r--r--runtime/lua/vim/lsp/client.lua2
-rw-r--r--src/mpack/lmpack.c4
-rw-r--r--src/nvim/api/ui.c101
-rw-r--r--src/nvim/extmark.c6
-rw-r--r--src/nvim/ui_defs.h1
-rw-r--r--src/nvim/undo.c4
-rw-r--r--test/functional/api/buffer_updates_spec.lua14
-rw-r--r--test/functional/api/server_notifications_spec.lua2
-rw-r--r--test/functional/api/server_requests_spec.lua14
-rw-r--r--test/functional/autocmd/cmdline_spec.lua2
-rw-r--r--test/functional/core/exit_spec.lua2
-rw-r--r--test/functional/core/job_spec.lua2
-rw-r--r--test/functional/ex_cmds/dict_notifications_spec.lua2
-rw-r--r--test/functional/lua/vim_spec.lua2
-rw-r--r--test/functional/provider/define_spec.lua2
-rw-r--r--test/functional/ui/decorations_spec.lua38
-rw-r--r--test/functional/ui/hlstate_spec.lua279
-rw-r--r--test/functional/vimscript/wait_spec.lua2
20 files changed, 410 insertions, 80 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index c2f5941a5c..6a1d94d34b 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1622,9 +1622,9 @@ vim.on_key({fn}, {ns_id}) *vim.on_key()*
• {fn} will receive the keys after mappings have been evaluated
Parameters: ~
- • {fn} (`fun(key: string)`) Function invoked on every key press.
- |i_CTRL-V| Returning nil removes the callback associated with
- namespace {ns_id}.
+ • {fn} (`fun(key: string)?`) Function invoked on every key press.
+ |i_CTRL-V| Passing in nil when {ns_id} is specified removes
+ the callback associated with namespace {ns_id}.
• {ns_id} (`integer?`) Namespace ID. If nil or 0, generates and returns
a new |nvim_create_namespace()| id.
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index c130eb1958..c5a6e65e86 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -652,8 +652,9 @@ local on_key_cbs = {}
---@note {fn} will not be cleared by |nvim_buf_clear_namespace()|
---@note {fn} will receive the keys after mappings have been evaluated
---
----@param fn fun(key: string) Function invoked on every key press. |i_CTRL-V|
---- Returning nil removes the callback associated with namespace {ns_id}.
+---@param fn fun(key: string)? Function invoked on every key press. |i_CTRL-V|
+--- Passing in nil when {ns_id} is specified removes the
+--- callback associated with namespace {ns_id}.
---@param ns_id integer? Namespace ID. If nil or 0, generates and returns a
--- new |nvim_create_namespace()| id.
---
diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua
index 58db4387b6..a279be55e9 100644
--- a/runtime/lua/vim/lsp/client.lua
+++ b/runtime/lua/vim/lsp/client.lua
@@ -79,6 +79,7 @@ local validate = vim.validate
--- Track this so that we can escalate automatically if we've already tried a
--- graceful shutdown
--- @field private _graceful_shutdown_failed true?
+--- @field private commands table
---
--- @field dynamic_capabilities lsp.DynamicCapabilities
---
@@ -270,6 +271,7 @@ function Client.start(config)
attached_buffers = {},
server_capabilities = {},
dynamic_capabilities = vim.lsp._dynamic.new(id),
+ commands = config.commands, -- Remove in Nvim 0.11
--- Contains $/progress report messages.
--- They have the format {token: integer|string, value: any}
diff --git a/src/mpack/lmpack.c b/src/mpack/lmpack.c
index ff21e29789..4ce4b5f3e5 100644
--- a/src/mpack/lmpack.c
+++ b/src/mpack/lmpack.c
@@ -882,7 +882,9 @@ static int lmpack_session_receive(lua_State *L)
luaL_argcheck(L, (size_t)startpos <= len, 3,
"start position must be less than or equal to the input string length");
- str += (size_t)startpos - 1;
+ size_t offset = (size_t)startpos - 1 ;
+ str += offset;
+ len -= offset;
if (session->unpacker != LUA_REFNIL) {
lmpack_geti(L, session->reg, session->unpacker);
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 5c8ebfb861..c7280253c2 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -584,7 +584,6 @@ static inline int write_cb(void *vdata, const char *buf, size_t len)
data->pack_totlen += len;
if (!data->temp_buf && UI_BUF_SIZE - BUF_POS(data) < len) {
- data->buf_overflow = true;
return 0;
}
@@ -594,14 +593,42 @@ static inline int write_cb(void *vdata, const char *buf, size_t len)
return 0;
}
-static bool prepare_call(UI *ui, const char *name)
+static inline int size_cb(void *vdata, const char *buf, size_t len)
+{
+ UIData *data = (UIData *)vdata;
+ if (!buf) {
+ return 0;
+ }
+
+ data->pack_totlen += len;
+ return 0;
+}
+
+static void prepare_call(UI *ui, const char *name, size_t size_needed)
{
UIData *data = ui->data;
+ size_t name_len = strlen(name);
+ const size_t overhead = name_len + 20;
+ bool oversized_message = size_needed + overhead > UI_BUF_SIZE;
- if (BUF_POS(data) > UI_BUF_SIZE - EVENT_BUF_SIZE) {
+ if (oversized_message || BUF_POS(data) > UI_BUF_SIZE - size_needed - overhead) {
remote_ui_flush_buf(ui);
}
+ if (oversized_message) {
+ // TODO(bfredl): manually testable by setting UI_BUF_SIZE to 1024 (mode_info_set)
+ data->temp_buf = xmalloc(20 + name_len + size_needed);
+ data->buf_wptr = data->temp_buf;
+ char **buf = &data->buf_wptr;
+ mpack_array(buf, 3);
+ mpack_uint(buf, 2);
+ mpack_str(buf, S_LEN("redraw"));
+ mpack_array(buf, 1);
+ mpack_array(buf, 2);
+ mpack_str(buf, name, name_len);
+ return;
+ }
+
// To optimize data transfer(especially for "grid_line"), we bundle adjacent
// calls to same method together, so only add a new call entry if the last
// method call is different from "name"
@@ -614,64 +641,42 @@ static bool prepare_call(UI *ui, const char *name)
mpack_str(buf, name, strlen(name));
data->nevents++;
data->ncalls = 1;
- return true;
+ return;
}
+}
- return false;
+static void send_oversized_message(UIData *data)
+{
+ if (data->temp_buf) {
+ size_t size = (size_t)(data->buf_wptr - data->temp_buf);
+ WBuffer *buf = wstream_new_buffer(data->temp_buf, size, 1, xfree);
+ rpc_write_raw(data->channel_id, buf);
+ data->temp_buf = NULL;
+ data->buf_wptr = data->buf;
+ data->nevents_pos = NULL;
+ }
}
/// Pushes data into UI.UIData, to be consumed later by remote_ui_flush().
static void push_call(UI *ui, const char *name, Array args)
{
UIData *data = ui->data;
- bool pending = data->nevents_pos;
- char *buf_pos_save = data->buf_wptr;
-
- bool new_event = prepare_call(ui, name);
msgpack_packer pac;
data->pack_totlen = 0;
- data->buf_overflow = false;
+ // First determine the needed size
+ msgpack_packer_init(&pac, data, size_cb);
+ msgpack_rpc_from_array(args, &pac);
+ // Then send the actual message
+ prepare_call(ui, name, data->pack_totlen);
msgpack_packer_init(&pac, data, write_cb);
msgpack_rpc_from_array(args, &pac);
- if (data->buf_overflow) {
- data->buf_wptr = buf_pos_save;
- if (new_event) {
- data->cur_event = NULL;
- data->nevents--;
- }
- if (pending) {
- remote_ui_flush_buf(ui);
- }
- size_t name_len = strlen(name);
- if (data->pack_totlen > UI_BUF_SIZE - name_len - 20) {
- // TODO(bfredl): manually testable by setting UI_BUF_SIZE to 1024 (mode_info_set)
- data->temp_buf = xmalloc(20 + name_len + data->pack_totlen);
- data->buf_wptr = data->temp_buf;
- char **buf = &data->buf_wptr;
- mpack_array(buf, 3);
- mpack_uint(buf, 2);
- mpack_str(buf, S_LEN("redraw"));
- mpack_array(buf, 1);
- mpack_array(buf, 2);
- mpack_str(buf, name, name_len);
- } else {
- prepare_call(ui, name);
- }
- data->pack_totlen = 0;
- data->buf_overflow = false;
- msgpack_rpc_from_array(args, &pac);
-
- if (data->temp_buf) {
- size_t size = (size_t)(data->buf_wptr - data->temp_buf);
- WBuffer *buf = wstream_new_buffer(data->temp_buf, size, 1, xfree);
- rpc_write_raw(data->channel_id, buf);
- data->temp_buf = NULL;
- data->buf_wptr = data->buf;
- data->nevents_pos = NULL;
- }
+ // Oversized messages need to be sent immediately
+ if (data->temp_buf) {
+ send_oversized_message(data);
}
+
data->ncalls++;
}
@@ -866,7 +871,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
{
UIData *data = ui->data;
if (ui->ui_ext[kUILinegrid]) {
- prepare_call(ui, "grid_line");
+ prepare_call(ui, "grid_line", EVENT_BUF_SIZE);
data->ncalls++;
char **buf = &data->buf_wptr;
@@ -895,7 +900,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
mpack_bool(buf, false);
remote_ui_flush_buf(ui);
- prepare_call(ui, "grid_line");
+ prepare_call(ui, "grid_line", EVENT_BUF_SIZE);
data->ncalls++;
mpack_array(buf, 5);
mpack_uint(buf, (uint32_t)grid);
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 0f9e7749f1..e753ad199a 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -116,6 +116,12 @@ static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool
return;
}
+ // Only the position before undo needs to be redrawn here,
+ // as the position after undo should be marked as changed.
+ if (!invalid && mt_decor_any(key) && key.pos.row != row) {
+ decor_redraw(buf, key.pos.row, key.pos.row, key.pos.col, mt_decor(key));
+ }
+
int row1 = 0;
int row2 = 0;
if (invalid) {
diff --git a/src/nvim/ui_defs.h b/src/nvim/ui_defs.h
index 2245575306..a2071782b6 100644
--- a/src/nvim/ui_defs.h
+++ b/src/nvim/ui_defs.h
@@ -46,7 +46,6 @@ typedef struct {
// state for write_cb, while packing a single arglist to msgpack. This
// might fail due to buffer overflow.
size_t pack_totlen;
- bool buf_overflow;
char *temp_buf;
// We start packing the two outermost msgpack arrays before knowing the total
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 547ac605e7..6081268e53 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -2390,9 +2390,7 @@ static void u_undoredo(bool undo, bool do_buf_event)
// When text has been changed, possibly the start of the next line
// may have SpellCap that should be removed or it needs to be
// displayed. Schedule the next line for redrawing just in case.
- // Also just in case the line had a sign which needs to be removed.
- if ((spell_check_window(curwin) || buf_meta_total(curbuf, kMTMetaSignText))
- && bot <= curbuf->b_ml.ml_line_count) {
+ if (spell_check_window(curwin) && bot <= curbuf->b_ml.ml_line_count) {
redrawWinline(curwin, bot);
}
diff --git a/test/functional/api/buffer_updates_spec.lua b/test/functional/api/buffer_updates_spec.lua
index d68c60e54c..262ca40e28 100644
--- a/test/functional/api/buffer_updates_spec.lua
+++ b/test/functional/api/buffer_updates_spec.lua
@@ -482,7 +482,7 @@ describe('API: buffer events:', function()
end)
it('does not get confused if enabled/disabled many times', function()
- local channel = api.nvim_get_api_info()[1]
+ local channel = api.nvim_get_chan_info(0).id
local b, tick = editoriginal(false)
-- Enable buffer events many times.
@@ -564,7 +564,7 @@ describe('API: buffer events:', function()
-- make sure there are no other pending nvim_buf_lines_event messages going to
-- channel 1
- local channel1 = request(1, 'nvim_get_api_info')[1]
+ local channel1 = request(1, 'nvim_get_chan_info', 0).id
eval('rpcnotify(' .. channel1 .. ', "Hello")')
wantn(1, 'Hello', {})
@@ -576,14 +576,14 @@ describe('API: buffer events:', function()
-- make sure there are no other pending nvim_buf_lines_event messages going to
-- channel 1
- channel1 = request(1, 'nvim_get_api_info')[1]
+ channel1 = request(1, 'nvim_get_chan_info', 0).id
eval('rpcnotify(' .. channel1 .. ', "Hello Again")')
wantn(1, 'Hello Again', {})
end)
it('works with :diffput and :diffget', function()
local b1, tick1 = editoriginal(true, { 'AAA', 'BBB' })
- local channel = api.nvim_get_api_info()[1]
+ local channel = api.nvim_get_chan_info(0).id
command('diffthis')
command('rightbelow vsplit')
local b2, tick2 = open(true, { 'BBB', 'CCC' })
@@ -700,7 +700,7 @@ describe('API: buffer events:', function()
it('detaches if the buffer is closed', function()
local b, tick = editoriginal(true, { 'AAA' })
- local channel = api.nvim_get_api_info()[1]
+ local channel = api.nvim_get_chan_info(0).id
-- Test that buffer events are working.
command('normal! x')
@@ -739,7 +739,7 @@ describe('API: buffer events:', function()
it(':enew! does not detach hidden buffer', function()
local b, tick = editoriginal(true, { 'AAA', 'BBB' })
- local channel = api.nvim_get_api_info()[1]
+ local channel = api.nvim_get_chan_info(0).id
command('set undoreload=1 hidden')
command('normal! x')
@@ -753,7 +753,7 @@ describe('API: buffer events:', function()
it('stays attached if the buffer is hidden', function()
local b, tick = editoriginal(true, { 'AAA' })
- local channel = api.nvim_get_api_info()[1]
+ local channel = api.nvim_get_chan_info(0).id
-- Test that buffer events are working.
command('normal! x')
diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua
index f6058b14ee..d1608a951c 100644
--- a/test/functional/api/server_notifications_spec.lua
+++ b/test/functional/api/server_notifications_spec.lua
@@ -14,7 +14,7 @@ describe('notify', function()
before_each(function()
clear()
- channel = api.nvim_get_api_info()[1]
+ channel = api.nvim_get_chan_info(0).id
end)
after_each(function()
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index 5e508e7513..298dbac217 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -18,18 +18,18 @@ describe('server -> client', function()
before_each(function()
clear()
- cid = api.nvim_get_api_info()[1]
+ cid = api.nvim_get_chan_info(0).id
end)
it('handles unexpected closed stream while preparing RPC response', function()
source([[
let g:_nvim_args = [v:progpath, '--embed', '--headless', '-n', '-u', 'NONE', '-i', 'NONE', ]
let ch1 = jobstart(g:_nvim_args, {'rpc': v:true})
- let child1_ch = rpcrequest(ch1, "nvim_get_api_info")[0]
+ let child1_ch = rpcrequest(ch1, "nvim_get_chan_info", 0).id
call rpcnotify(ch1, 'nvim_eval', 'rpcrequest('.child1_ch.', "nvim_get_api_info")')
let ch2 = jobstart(g:_nvim_args, {'rpc': v:true})
- let child2_ch = rpcrequest(ch2, "nvim_get_api_info")[0]
+ let child2_ch = rpcrequest(ch2, "nvim_get_chan_info", 0).id
call rpcnotify(ch2, 'nvim_eval', 'rpcrequest('.child2_ch.', "nvim_get_api_info")')
call jobstop(ch1)
@@ -231,7 +231,7 @@ describe('server -> client', function()
describe('jobstart()', function()
local jobid
before_each(function()
- local channel = api.nvim_get_api_info()[1]
+ local channel = api.nvim_get_chan_info(0).id
api.nvim_set_var('channel', channel)
source([[
function! s:OnEvent(id, data, event)
@@ -292,7 +292,7 @@ describe('server -> client', function()
ok(id > 0)
fn.rpcrequest(id, 'nvim_set_current_line', 'hello')
- local client_id = fn.rpcrequest(id, 'nvim_get_api_info')[1]
+ local client_id = fn.rpcrequest(id, 'nvim_get_chan_info', 0).id
set_session(server)
eq(serverpid, fn.getpid())
@@ -300,7 +300,7 @@ describe('server -> client', function()
-- method calls work both ways
fn.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!')
- eq(id, fn.rpcrequest(client_id, 'nvim_get_api_info')[1])
+ eq(id, fn.rpcrequest(client_id, 'nvim_get_chan_info', 0).id)
set_session(client)
eq(clientpid, fn.getpid())
@@ -378,7 +378,7 @@ describe('server -> client', function()
eq('hello', api.nvim_get_current_line())
eq(serverpid, fn.rpcrequest(id, 'nvim_eval', 'getpid()'))
- eq(id, fn.rpcrequest(id, 'nvim_get_api_info')[1])
+ eq(id, fn.rpcrequest(id, 'nvim_get_chan_info', 0).id)
end)
end)
end)
diff --git a/test/functional/autocmd/cmdline_spec.lua b/test/functional/autocmd/cmdline_spec.lua
index 5a5b16b438..7428456656 100644
--- a/test/functional/autocmd/cmdline_spec.lua
+++ b/test/functional/autocmd/cmdline_spec.lua
@@ -14,7 +14,7 @@ describe('cmdline autocommands', function()
local channel
before_each(function()
clear()
- channel = api.nvim_get_api_info()[1]
+ channel = api.nvim_get_chan_info(0).id
api.nvim_set_var('channel', channel)
command("autocmd CmdlineEnter * call rpcnotify(g:channel, 'CmdlineEnter', v:event)")
command("autocmd CmdlineLeave * call rpcnotify(g:channel, 'CmdlineLeave', v:event)")
diff --git a/test/functional/core/exit_spec.lua b/test/functional/core/exit_spec.lua
index b74ebb2367..d9e3cc3f31 100644
--- a/test/functional/core/exit_spec.lua
+++ b/test/functional/core/exit_spec.lua
@@ -18,7 +18,7 @@ describe('v:exiting', function()
before_each(function()
helpers.clear()
- cid = helpers.api.nvim_get_api_info()[1]
+ cid = helpers.api.nvim_get_chan_info(0).id
end)
it('defaults to v:null', function()
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index c6885d0b7c..318730fbb1 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -42,7 +42,7 @@ describe('jobs', function()
before_each(function()
clear()
- channel = api.nvim_get_api_info()[1]
+ channel = api.nvim_get_chan_info(0).id
api.nvim_set_var('channel', channel)
source([[
function! Normalize(data) abort
diff --git a/test/functional/ex_cmds/dict_notifications_spec.lua b/test/functional/ex_cmds/dict_notifications_spec.lua
index 15fbb750f6..fc7714d16b 100644
--- a/test/functional/ex_cmds/dict_notifications_spec.lua
+++ b/test/functional/ex_cmds/dict_notifications_spec.lua
@@ -14,7 +14,7 @@ describe('Vimscript dictionary notifications', function()
before_each(function()
clear()
- channel = api.nvim_get_api_info()[1]
+ channel = api.nvim_get_chan_info(0).id
api.nvim_set_var('channel', channel)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 10a2437ba2..c7490756d4 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -3363,7 +3363,7 @@ describe('lua stdlib', function()
describe('returns -2 when interrupted', function()
before_each(function()
- local channel = api.nvim_get_api_info()[1]
+ local channel = api.nvim_get_chan_info(0).id
api.nvim_set_var('channel', channel)
end)
diff --git a/test/functional/provider/define_spec.lua b/test/functional/provider/define_spec.lua
index a1109935d2..657f1a0d8a 100644
--- a/test/functional/provider/define_spec.lua
+++ b/test/functional/provider/define_spec.lua
@@ -362,7 +362,7 @@ local function function_specs_for(fn, sync, first_arg_factory, init)
end
local function channel()
- return api.nvim_get_api_info()[1]
+ return api.nvim_get_chan_info(0).id
end
local function host()
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 9f38c05757..951188614b 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -2230,6 +2230,44 @@ describe('extmark decorations', function()
]]}
end)
+ it('virtual text is drawn correctly after delete and undo #27368', function()
+ insert('aaa\nbbb\nccc\nddd\neee')
+ command('vsplit')
+ api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = {{'EOL'}} })
+ feed('3gg')
+ screen:expect{grid=[[
+ aaa │aaa |
+ bbb │bbb |
+ ^ccc EOL │ccc EOL |
+ ddd │ddd |
+ eee │eee |
+ {1:~ }│{1:~ }|*8
+ {41:[No Name] [+] }{40:[No Name] [+] }|
+ |
+ ]]}
+ feed('dd')
+ screen:expect{grid=[[
+ aaa │aaa |
+ bbb │bbb |
+ ^ddd EOL │ddd EOL |
+ eee │eee |
+ {1:~ }│{1:~ }|*9
+ {41:[No Name] [+] }{40:[No Name] [+] }|
+ |
+ ]]}
+ command('silent undo')
+ screen:expect{grid=[[
+ aaa │aaa |
+ bbb │bbb |
+ ^ccc EOL │ccc EOL |
+ ddd │ddd |
+ eee │eee |
+ {1:~ }│{1:~ }|*8
+ {41:[No Name] [+] }{40:[No Name] [+] }|
+ |
+ ]]}
+ end)
+
it('works with both hl_group and sign_hl_group', function()
screen:try_resize(screen._width, 3)
insert('abcdefghijklmn')
diff --git a/test/functional/ui/hlstate_spec.lua b/test/functional/ui/hlstate_spec.lua
index 278e6e5272..8b36ad5431 100644
--- a/test/functional/ui/hlstate_spec.lua
+++ b/test/functional/ui/hlstate_spec.lua
@@ -309,4 +309,283 @@ describe('ext_hlstate detailed highlights', function()
{3: }|
]])
end)
+
+ it('combines deleted extmark highlights', function()
+ insert([[
+ line1
+ line2
+ line3
+ line4
+ line5
+ line6]])
+
+ screen:expect {
+ grid = [[
+ line1 |
+ line2 |
+ line3 |
+ line4 |
+ line5 |
+ line^6 |
+ {1:~ }|
+ {2: }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.Blue, bold = true },
+ { { ui_name = 'EndOfBuffer', hi_name = 'NonText', kind = 'ui' } },
+ },
+ [2] = { {}, { { ui_name = 'MsgArea', hi_name = 'MsgArea', kind = 'ui' } } },
+ },
+ }
+
+ local ns = api.nvim_create_namespace('test')
+
+ local add_indicator = function(line, col)
+ api.nvim_buf_set_extmark(0, ns, line, col, {
+ hl_mode = 'combine',
+ priority = 2,
+ right_gravity = false,
+ virt_text = { { '|', 'Delimiter' } },
+ virt_text_win_col = 0,
+ virt_text_pos = 'overlay',
+ })
+ end
+
+ add_indicator(1, 0)
+ add_indicator(2, 0)
+ add_indicator(3, 0)
+ add_indicator(4, 0)
+
+ screen:expect {
+ grid = [[
+ line1 |
+ {1:|} line2 |
+ {1:|} line3 |
+ {1:|} line4 |
+ {1:|} line5 |
+ line^6 |
+ {2:~ }|
+ {3: }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { hi_name = 'Special', kind = 'syntax' } },
+ },
+ [2] = {
+ { bold = true, foreground = Screen.colors.Blue },
+ { { ui_name = 'EndOfBuffer', kind = 'ui', hi_name = 'NonText' } },
+ },
+ [3] = { {}, { { ui_name = 'MsgArea', kind = 'ui', hi_name = 'MsgArea' } } },
+ },
+ }
+
+ helpers.feed('3ggV2jd')
+ --screen:redraw_debug()
+ screen:expect {
+ grid = [[
+ line1 |
+ {1:|} line2 |
+ {2:^|}ine6 |
+ {3:~ }|*4
+ {4:3 fewer lines }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { kind = 'syntax', hi_name = 'Special' } },
+ },
+ [2] = { { foreground = Screen.colors.SlateBlue }, { 1, 1, 1 } },
+ [3] = {
+ { bold = true, foreground = Screen.colors.Blue },
+ { { kind = 'ui', ui_name = 'EndOfBuffer', hi_name = 'NonText' } },
+ },
+ [4] = { {}, { { kind = 'ui', ui_name = 'MsgArea', hi_name = 'MsgArea' } } },
+ },
+ }
+ end)
+
+ it('removes deleted extmark highlights with invalidate', function()
+ insert([[
+ line1
+ line2
+ line3
+ line4
+ line5
+ line6]])
+
+ screen:expect {
+ grid = [[
+ line1 |
+ line2 |
+ line3 |
+ line4 |
+ line5 |
+ line^6 |
+ {1:~ }|
+ {2: }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.Blue, bold = true },
+ { { ui_name = 'EndOfBuffer', hi_name = 'NonText', kind = 'ui' } },
+ },
+ [2] = { {}, { { ui_name = 'MsgArea', hi_name = 'MsgArea', kind = 'ui' } } },
+ },
+ }
+
+ local ns = api.nvim_create_namespace('test')
+
+ local add_indicator = function(line, col)
+ api.nvim_buf_set_extmark(0, ns, line, col, {
+ hl_mode = 'combine',
+ priority = 2,
+ right_gravity = false,
+ virt_text = { { '|', 'Delimiter' } },
+ virt_text_win_col = 0,
+ virt_text_pos = 'overlay',
+ invalidate = true,
+ })
+ end
+
+ add_indicator(1, 0)
+ add_indicator(2, 0)
+ add_indicator(3, 0)
+ add_indicator(4, 0)
+
+ screen:expect {
+ grid = [[
+ line1 |
+ {1:|} line2 |
+ {1:|} line3 |
+ {1:|} line4 |
+ {1:|} line5 |
+ line^6 |
+ {2:~ }|
+ {3: }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { hi_name = 'Special', kind = 'syntax' } },
+ },
+ [2] = {
+ { bold = true, foreground = Screen.colors.Blue },
+ { { ui_name = 'EndOfBuffer', kind = 'ui', hi_name = 'NonText' } },
+ },
+ [3] = { {}, { { ui_name = 'MsgArea', kind = 'ui', hi_name = 'MsgArea' } } },
+ },
+ }
+
+ helpers.feed('3ggV2jd')
+ --screen:redraw_debug()
+ screen:expect {
+ grid = [[
+ line1 |
+ {1:|} line2 |
+ ^line6 |
+ {2:~ }|*4
+ {3:3 fewer lines }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { kind = 'syntax', hi_name = 'Special' } },
+ },
+ [2] = {
+ { foreground = Screen.colors.Blue, bold = true },
+ { { kind = 'ui', ui_name = 'EndOfBuffer', hi_name = 'NonText' } },
+ },
+ [3] = { {}, { { kind = 'ui', ui_name = 'MsgArea', hi_name = 'MsgArea' } } },
+ },
+ }
+ end)
+
+ it('does not hang when combining too many highlights', function()
+ local num_lines = 500
+ insert('first line\n')
+ for _ = 1, num_lines do
+ insert([[
+ line
+ ]])
+ end
+ insert('last line')
+
+ helpers.feed('gg')
+ screen:expect {
+ grid = [[
+ ^first line |
+ line |*6
+ {1: }|
+ ]],
+ attr_ids = {
+ [1] = { {}, { { kind = 'ui', hi_name = 'MsgArea', ui_name = 'MsgArea' } } },
+ },
+ }
+ local ns = api.nvim_create_namespace('test')
+
+ local add_indicator = function(line, col)
+ api.nvim_buf_set_extmark(0, ns, line, col, {
+ hl_mode = 'combine',
+ priority = 2,
+ right_gravity = false,
+ virt_text = { { '|', 'Delimiter' } },
+ virt_text_win_col = 0,
+ virt_text_pos = 'overlay',
+ })
+ end
+
+ for i = 1, num_lines do
+ add_indicator(i, 0)
+ end
+
+ screen:expect {
+ grid = [[
+ ^first line |
+ {1:|} line |*6
+ {2: }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { kind = 'syntax', hi_name = 'Special' } },
+ },
+ [2] = { {}, { { kind = 'ui', ui_name = 'MsgArea', hi_name = 'MsgArea' } } },
+ },
+ }
+
+ helpers.feed(string.format('3ggV%ijd', num_lines - 2))
+ --screen:redraw_debug(nil, nil, 100000)
+
+ local expected_ids = {}
+ for i = 1, num_lines - 1 do
+ expected_ids[i] = 1
+ end
+ screen:expect {
+ grid = string.format(
+ [[
+ first line |
+ {1:|} line |
+ {2:^|}ast line |
+ {3:~ }|*4
+ {4:%-40s}|
+ ]],
+ tostring(num_lines - 1) .. ' fewer lines'
+ ),
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { kind = 'syntax', hi_name = 'Special' } },
+ },
+ [2] = { { foreground = Screen.colors.SlateBlue }, expected_ids },
+ [3] = {
+ { foreground = Screen.colors.Blue, bold = true },
+ { { kind = 'ui', hi_name = 'NonText', ui_name = 'EndOfBuffer' } },
+ },
+ [4] = { {}, { { kind = 'ui', hi_name = 'MsgArea', ui_name = 'MsgArea' } } },
+ },
+ timeout = 100000,
+ }
+ end)
end)
diff --git a/test/functional/vimscript/wait_spec.lua b/test/functional/vimscript/wait_spec.lua
index 4ee3b183b3..50cdb2cfb4 100644
--- a/test/functional/vimscript/wait_spec.lua
+++ b/test/functional/vimscript/wait_spec.lua
@@ -13,7 +13,7 @@ local pcall_err = helpers.pcall_err
before_each(function()
clear()
- local channel = api.nvim_get_api_info()[1]
+ local channel = api.nvim_get_chan_info(0).id
api.nvim_set_var('channel', channel)
end)