From c249058758af6919f718750b2f4acb96bafeb2dd Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Sat, 18 Nov 2023 23:49:11 +0100 Subject: [PATCH] feat(extmarks): add sign name to extmark "details" array Problem: Unable to identify legacy signs when fetching extmarks with `nvim_buf_get_extmarks()`. Solution: Add "sign_name" to the extmark detail array. Add some misc. changes as follow-up to #25724 --- runtime/doc/builtin.txt | 10 +++++----- runtime/doc/sign.txt | 6 +++--- src/nvim/decoration.c | 4 ++++ src/nvim/sign.c | 15 ++++++--------- test/functional/api/extmark_spec.lua | 17 +++++++++++++++++ 5 files changed, 35 insertions(+), 17 deletions(-) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 860372767a..5d70c42157 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -6998,11 +6998,11 @@ sign_place({id}, {group}, {name}, {buf} [, {dict}]) *sign_place()* similar to the |:sign-place| command. If the sign identifier {id} is zero, then a new identifier is - allocated. Otherwise the specified number is used. {group} is - the sign group name. To use the global sign group, use an - empty string. {group} functions as a namespace for {id}, thus - two groups can use the same IDs. Refer to |sign-identifier| - and |sign-group| for more information. + allocated (first available id in a buffer). Otherwise the + specified number is used. {group} is the sign group name. To use + the global sign group, use an empty string. {group} functions + as a namespace for {id}, thus two groups can use the same IDs. + Refer to |sign-identifier| and |sign-group| for more information. {name} refers to a defined sign. {buf} refers to a buffer name or number. For the accepted diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index 733b0fe212..30fa7eee0b 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -53,9 +53,9 @@ If 'cursorline' is enabled, then the CursorLineSign highlight group is used Each placed sign is identified by a number called the sign identifier. This identifier is used to jump to the sign or to remove the sign. The identifier is assigned when placing the sign using the |:sign-place| command or the -|sign_place()| function. Each sign identifier should be a unique number. -Placing the same identifier twice will move the previously placed sign. The -|sign_place()| function can be called with a zero sign identifier to allocate +|sign_place()| function. Each sign identifier should be a unique number (per +buffer). Placing the same identifier twice will move the previously placed sign. +The |sign_place()| function can be called with a zero sign identifier to allocate the next available identifier. *sign-group* diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 2ef689680d..0f4bbaaac7 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -1022,6 +1022,10 @@ void decor_to_dict_legacy(Dictionary *dict, DecorInline decor, bool hl_name) PUT(*dict, "sign_text", CSTR_TO_OBJ(sh_sign.text.ptr)); } + if (sh_sign.sign_name) { + PUT(*dict, "sign_name", CSTR_TO_OBJ(sh_sign.sign_name)); + } + // uncrustify:off struct { char *name; const int val; } hls[] = { diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 9a48b1b1a5..243e9e57cf 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -171,12 +171,12 @@ int sign_cmp(const void *p1, const void *p2) ? n : (sh2->sign_add_id - sh1->sign_add_id); } -/// Delete the specified signs +/// Delete the specified sign(s) /// /// @param buf buffer sign is stored in or NULL for all buffers /// @param group sign group /// @param id sign id -/// @param atlnum sign at this line, -1 at any line +/// @param atlnum single sign at this line, specified signs at any line when -1 static int buf_delete_signs(buf_T *buf, char *group, int id, linenr_T atlnum) { int64_t ns = group_get_ns(group); @@ -187,7 +187,7 @@ static int buf_delete_signs(buf_T *buf, char *group, int id, linenr_T atlnum) MarkTreeIter itr[1]; int row = atlnum > 0 ? atlnum - 1 : 0; kvec_t(MTKey) signs = KV_INITIAL_VALUE; - // Store and sort when removing a single sign at a specific line number. + // Store signs at a specific line number to remove one later. if (atlnum > 0) { if (!marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) { return FAIL; @@ -222,6 +222,7 @@ static int buf_delete_signs(buf_T *buf, char *group, int id, linenr_T atlnum) } } + // Sort to remove the highest priority sign at a specific line number. if (kv_size(signs)) { qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp); extmark_del_id(buf, kv_A(signs, 0).ns, kv_A(signs, 0).id); @@ -1198,11 +1199,7 @@ static int sign_define_from_dict(char *name, dict_T *dict) numhl = tv_dict_get_string(dict, "numhl", false); } - if (sign_define_by_name(name, icon, text, linehl, texthl, culhl, numhl) == OK) { - return 0; - } - - return -1; + return sign_define_by_name(name, icon, text, linehl, texthl, culhl, numhl) - 1; } /// Define multiple signs using attributes from list 'l' and store the return @@ -1563,7 +1560,7 @@ static int sign_unplace_from_dict(typval_T *group_tv, dict_T *dict) } } - return sign_unplace(buf, id, group, 0) ? 0 : -1; + return sign_unplace(buf, id, group, 0) - 1; } /// "sign_unplace()" function diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua index 2115c7c244..44a151cf6a 100644 --- a/test/functional/api/extmark_spec.lua +++ b/test/functional/api/extmark_spec.lua @@ -1582,6 +1582,23 @@ describe('API/extmarks', function() priority = 4096, right_gravity = true, } }, get_extmark_by_id(ns, marks[3], { details = true })) + curbufmeths.clear_namespace(ns, 0, -1) + -- 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 })) end) it('can get marks from anonymous namespaces', function()