aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/api/buffer.c42
-rw-r--r--src/nvim/api/vim.c3
-rw-r--r--src/nvim/decoration.c2
-rw-r--r--src/nvim/extmark.c9
-rw-r--r--src/nvim/lua/vim.lua11
-rw-r--r--test/functional/api/extmark_spec.lua34
-rw-r--r--test/functional/api/vim_spec.lua14
7 files changed, 104 insertions, 11 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 8d82d22040..2890d89bc0 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -1400,6 +1400,13 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
/// callbacks. The mark will only be used for the current
/// redraw cycle, and not be permantently stored in the
/// buffer.
+/// - right_gravity : boolean that indicates the direction
+/// the extmark will be shifted in when new text is inserted
+/// (true for right, false for left). defaults to true.
+/// - end_right_gravity : boolean that indicates the direction
+/// the extmark end position (if it exists) will be shifted
+/// in when new text is inserted (true for right, false
+/// for left). Defaults to false.
/// @param[out] err Error details, if any
/// @return Id of the created/updated extmark
Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
@@ -1440,6 +1447,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
DecorPriority priority = DECOR_PRIORITY_BASE;
colnr_T col2 = 0;
VirtText virt_text = KV_INITIAL_VALUE;
+ bool right_gravity = true;
+ bool end_right_gravity = false;
+ bool end_gravity_set = false;
+
for (size_t i = 0; i < opts.size; i++) {
String k = opts.items[i].key;
Object *v = &opts.items[i].value;
@@ -1522,12 +1533,35 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
goto error;
}
priority = (DecorPriority)v->data.integer;
+ } else if (strequal("right_gravity", k.data)) {
+ if (v->type != kObjectTypeBoolean) {
+ api_set_error(err, kErrorTypeValidation,
+ "right_gravity must be a boolean");
+ goto error;
+ }
+ right_gravity = v->data.boolean;
+ } else if (strequal("end_right_gravity", k.data)) {
+ if (v->type != kObjectTypeBoolean) {
+ api_set_error(err, kErrorTypeValidation,
+ "end_right_gravity must be a boolean");
+ goto error;
+ }
+ end_right_gravity = v->data.boolean;
+ end_gravity_set = true;
} else {
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
goto error;
}
}
+ // Only error out if they try to set end_right_gravity without
+ // setting end_col or end_line
+ if (line2 == -1 && col2 == 0 && end_gravity_set) {
+ api_set_error(err, kErrorTypeValidation,
+ "cannot set end_right_gravity "
+ "without setting end_line or end_col");
+ }
+
if (col2 >= 0) {
if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) {
len = STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false));
@@ -1572,7 +1606,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
}
id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
- line2, col2, decor, kExtmarkNoUndo);
+ line2, col2, decor, right_gravity,
+ end_right_gravity, kExtmarkNoUndo);
}
return (Integer)id;
@@ -1687,7 +1722,7 @@ Integer nvim_buf_add_highlight(Buffer buffer,
extmark_set(buf, ns_id, 0,
(int)line, (colnr_T)col_start,
end_line, (colnr_T)col_end,
- decor_hl(hl_id), kExtmarkNoUndo);
+ decor_hl(hl_id), true, false, kExtmarkNoUndo);
return src_id;
}
@@ -1796,7 +1831,8 @@ Integer nvim_buf_set_virtual_text(Buffer buffer,
Decoration *decor = xcalloc(1, sizeof(*decor));
decor->virt_text = virt_text;
- extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, kExtmarkNoUndo);
+ extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, true,
+ false, kExtmarkNoUndo);
return src_id;
}
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 9e2fb6da6f..09895a2119 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1011,8 +1011,9 @@ void nvim_echo(Array chunks, Boolean history, Dictionary opts, Error *err)
}
no_wait_return++;
- bool need_clear = true;
msg_start();
+ msg_clr_eos();
+ bool need_clear = false;
for (uint32_t i = 0; i < kv_size(hl_msg); i++) {
HlMessageChunk chunk = kv_A(hl_msg, i);
msg_multiline_attr((const char *)chunk.text.data, chunk.attr,
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index e6a616c927..f3ee42fab1 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -69,7 +69,7 @@ void bufhl_add_hl_pos_offset(buf_T *buf,
}
(void)extmark_set(buf, (uint64_t)src_id, 0,
(int)lnum-1, hl_start, (int)lnum-1+end_off, hl_end,
- decor, kExtmarkNoUndo);
+ decor, true, false, kExtmarkNoUndo);
}
}
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index b2d8532cd7..cacbeddb32 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -71,7 +71,8 @@ static ExtmarkNs *buf_ns_ref(buf_T *buf, uint64_t ns_id, bool put) {
/// @returns the mark id
uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id,
int row, colnr_T col, int end_row, colnr_T end_col,
- Decoration *decor, ExtmarkOp op)
+ Decoration *decor, bool right_gravity,
+ bool end_right_gravity, ExtmarkOp op)
{
ExtmarkNs *ns = buf_ns_ref(buf, ns_id, true);
assert(ns != NULL);
@@ -109,10 +110,10 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id,
if (end_row > -1) {
mark = marktree_put_pair(buf->b_marktree,
- row, col, true,
- end_row, end_col, false);
+ row, col, right_gravity,
+ end_row, end_col, end_right_gravity);
} else {
- mark = marktree_put(buf->b_marktree, row, col, true);
+ mark = marktree_put(buf->b_marktree, row, col, right_gravity);
}
revised:
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index b20fbbf038..80b311de2c 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -121,10 +121,17 @@ function vim._load_package(name)
end
for _,trail in ipairs(vim._so_trails) do
- local path = "lua/"..trail:gsub('?',basename)
+ local path = "lua"..trail:gsub('?', basename) -- so_trails contains a leading slash
local found = vim.api.nvim_get_runtime_file(path, false)
if #found > 0 then
- local f, err = package.loadlib(found[1])
+ -- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is
+ -- a) strip prefix up to and including the first dash, if any
+ -- b) replace all dots by underscores
+ -- c) prepend "luaopen_"
+ -- So "foo-bar.baz" should result in "luaopen_bar_baz"
+ local dash = name:find("-", 1, true)
+ local modname = dash and name:sub(dash + 1) or name
+ local f, err = package.loadlib(found[1], "luaopen_"..modname:gsub("%.", "_"))
return f or error(err)
end
end
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua
index ab913ba4a4..d2b555ee5b 100644
--- a/test/functional/api/extmark_spec.lua
+++ b/test/functional/api/extmark_spec.lua
@@ -1389,6 +1389,40 @@ describe('API/extmarks', function()
undo]],false)
eq(2, meths.eval('1+1')) -- did not crash
end)
+
+ it('works with left and right gravity', function()
+ -- right gravity should move with inserted text, while
+ -- left gravity should stay in place.
+ curbufmeths.set_extmark(ns, 0, 5, {right_gravity = false})
+ curbufmeths.set_extmark(ns, 0, 5, {right_gravity = true})
+ feed([[Aasdfasdf]])
+
+ eq({ {1, 0, 5}, {2, 0, 13} },
+ curbufmeths.get_extmarks(ns, 0, -1, {}))
+
+ -- but both move when text is inserted before
+ feed([[<esc>Iasdf<esc>]])
+ -- eq({}, curbufmeths.get_lines(0, -1, true))
+ eq({ {1, 0, 9}, {2, 0, 17} },
+ curbufmeths.get_extmarks(ns, 0, -1, {}))
+
+ -- clear text
+ curbufmeths.set_text(0, 0, 0, 17, {})
+
+ -- handles set_text correctly as well
+ eq({ {1, 0, 0}, {2, 0, 0} },
+ meths.buf_get_extmarks(0, ns, 0, -1, {}))
+ curbufmeths.set_text(0, 0, 0, 0, {'asdfasdf'})
+ eq({ {1, 0, 0}, {2, 0, 8} },
+ curbufmeths.get_extmarks(ns, 0, -1, {}))
+
+ feed('u')
+ -- handles pasting
+ meths.exec([[let @a='asdfasdf']], false)
+ feed([["ap]])
+ eq({ {1, 0, 0}, {2, 0, 8} },
+ meths.buf_get_extmarks(0, ns, 0, -1, {}))
+ end)
end)
describe('Extmarks buffer api with many marks', function()
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 1d8ffc2087..3ff3efb8c9 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -2021,6 +2021,20 @@ describe('API', function()
command('highlight Special guifg=SlateBlue')
end)
+ it('should clear cmdline message before echo', function()
+ feed(':call nvim_echo([["msg"]], v:false, {})<CR>')
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ msg |
+ ]]}
+ end)
+
it('can show highlighted line', function()
nvim_async("echo", {{"msg_a"}, {"msg_b", "Statement"}, {"msg_c", "Special"}}, true, {})
screen:expect{grid=[[