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
This commit is contained in:
Luuk van Baal 2023-11-18 23:49:11 +01:00
parent 34fa1e1ca4
commit c249058758
5 changed files with 35 additions and 17 deletions

View File

@ -6998,11 +6998,11 @@ sign_place({id}, {group}, {name}, {buf} [, {dict}]) *sign_place()*
similar to the |:sign-place| command. similar to the |:sign-place| command.
If the sign identifier {id} is zero, then a new identifier is If the sign identifier {id} is zero, then a new identifier is
allocated. Otherwise the specified number is used. {group} is allocated (first available id in a buffer). Otherwise the
the sign group name. To use the global sign group, use an specified number is used. {group} is the sign group name. To use
empty string. {group} functions as a namespace for {id}, thus the global sign group, use an empty string. {group} functions
two groups can use the same IDs. Refer to |sign-identifier| as a namespace for {id}, thus two groups can use the same IDs.
and |sign-group| for more information. Refer to |sign-identifier| and |sign-group| for more information.
{name} refers to a defined sign. {name} refers to a defined sign.
{buf} refers to a buffer name or number. For the accepted {buf} refers to a buffer name or number. For the accepted

View File

@ -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 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 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 is assigned when placing the sign using the |:sign-place| command or the
|sign_place()| function. Each sign identifier should be a unique number. |sign_place()| function. Each sign identifier should be a unique number (per
Placing the same identifier twice will move the previously placed sign. The buffer). Placing the same identifier twice will move the previously placed sign.
|sign_place()| function can be called with a zero sign identifier to allocate The |sign_place()| function can be called with a zero sign identifier to allocate
the next available identifier. the next available identifier.
*sign-group* *sign-group*

View File

@ -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)); 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 // uncrustify:off
struct { char *name; const int val; } hls[] = { struct { char *name; const int val; } hls[] = {

View File

@ -171,12 +171,12 @@ int sign_cmp(const void *p1, const void *p2)
? n : (sh2->sign_add_id - sh1->sign_add_id); ? 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 buf buffer sign is stored in or NULL for all buffers
/// @param group sign group /// @param group sign group
/// @param id sign id /// @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) static int buf_delete_signs(buf_T *buf, char *group, int id, linenr_T atlnum)
{ {
int64_t ns = group_get_ns(group); 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]; MarkTreeIter itr[1];
int row = atlnum > 0 ? atlnum - 1 : 0; int row = atlnum > 0 ? atlnum - 1 : 0;
kvec_t(MTKey) signs = KV_INITIAL_VALUE; 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 (atlnum > 0) {
if (!marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) { if (!marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) {
return FAIL; 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)) { if (kv_size(signs)) {
qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp); 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); 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); numhl = tv_dict_get_string(dict, "numhl", false);
} }
if (sign_define_by_name(name, icon, text, linehl, texthl, culhl, numhl) == OK) { return sign_define_by_name(name, icon, text, linehl, texthl, culhl, numhl) - 1;
return 0;
}
return -1;
} }
/// Define multiple signs using attributes from list 'l' and store the return /// 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 /// "sign_unplace()" function

View File

@ -1582,6 +1582,23 @@ describe('API/extmarks', function()
priority = 4096, priority = 4096,
right_gravity = true, right_gravity = true,
} }, get_extmark_by_id(ns, marks[3], { details = 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) end)
it('can get marks from anonymous namespaces', function() it('can get marks from anonymous namespaces', function()