diff options
-rw-r--r-- | src/nvim/api/buffer.c | 23 | ||||
-rw-r--r-- | src/nvim/decoration.c | 2 | ||||
-rw-r--r-- | src/nvim/extmark.c | 6 | ||||
-rw-r--r-- | test/functional/api/extmark_spec.lua | 34 |
4 files changed, 58 insertions, 7 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 8d82d22040..7c381ac1ed 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1400,6 +1400,9 @@ 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. +/// - gravity : the direction the extmark will be shifted in +/// when new text is inserted. Must be either 'left' or +/// 'right'. /// @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 +1443,7 @@ 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; for (size_t i = 0; i < opts.size; i++) { String k = opts.items[i].key; Object *v = &opts.items[i].value; @@ -1522,6 +1526,19 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, goto error; } priority = (DecorPriority)v->data.integer; + } else if (strequal("gravity", k.data)) { + if (v->type != kObjectTypeString) { + api_set_error(err, kErrorTypeValidation, + "gravity must be a string"); + goto error; + } + if (strequal("left", v->data.string.data)) { + right_gravity = false; + } else if (!strequal("right", v->data.string.data)) { + api_set_error(err, kErrorTypeValidation, + "invalid option for gravity: must be 'left' or 'right'"); + goto error; + } } else { api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); goto error; @@ -1572,7 +1589,7 @@ 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, kExtmarkNoUndo); } return (Integer)id; @@ -1687,7 +1704,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, kExtmarkNoUndo); return src_id; } @@ -1796,7 +1813,7 @@ 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, kExtmarkNoUndo); return src_id; } diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index e6a616c927..0a096bec9e 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, kExtmarkNoUndo); } } diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index b2d8532cd7..3f3b8c76f3 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -71,7 +71,7 @@ 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, ExtmarkOp op) { ExtmarkNs *ns = buf_ns_ref(buf, ns_id, true); assert(ns != NULL); @@ -109,10 +109,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, + row, col, right_gravity, end_row, end_col, false); } else { - mark = marktree_put(buf->b_marktree, row, col, true); + mark = marktree_put(buf->b_marktree, row, col, right_gravity); } revised: diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua index ab913ba4a4..159b8f7a58 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, {gravity = 'left'}) + curbufmeths.set_extmark(ns, 0, 5, {gravity = 'right'}) + 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() |