diff options
-rw-r--r-- | src/nvim/api/buffer.c | 42 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 3 | ||||
-rw-r--r-- | src/nvim/decoration.c | 2 | ||||
-rw-r--r-- | src/nvim/extmark.c | 9 | ||||
-rw-r--r-- | src/nvim/lua/vim.lua | 11 | ||||
-rw-r--r-- | test/functional/api/extmark_spec.lua | 34 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 14 |
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=[[ |