aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/sign.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/sign.c')
-rw-r--r--src/nvim/sign.c113
1 files changed, 70 insertions, 43 deletions
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index 0136937ad2..9a48b1b1a5 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -71,9 +71,9 @@ static int64_t group_get_ns(const char *group)
return ns ? ns : -1;
}
-static const char *sign_get_name(MTKey mark)
+static const char *sign_get_name(DecorSignHighlight *sh)
{
- char *name = mark.decor_full->sign_name;
+ char *name = sh->sign_name;
return !name ? "" : map_has(cstr_t, &sign_map, name) ? name : "[Deleted]";
}
@@ -92,15 +92,24 @@ static void buf_set_sign(buf_T *buf, uint32_t *id, char *group, int prio, linenr
}
uint32_t ns = group ? (uint32_t)nvim_create_namespace(cstr_as_string(group)) : 0;
- Decoration decor = DECORATION_INIT;
- decor.sign_text = sp->sn_text ? xstrdup(sp->sn_text) : NULL;
- decor.sign_name = xstrdup(sp->sn_name);
- decor.sign_hl_id = sp->sn_text_hl;
- decor.line_hl_id = sp->sn_line_hl;
- decor.number_hl_id = sp->sn_num_hl;
- decor.cursorline_hl_id = sp->sn_cul_hl;
- decor.priority = (DecorPriority)prio;
- extmark_set(buf, ns, id, lnum - 1, 0, -1, -1, &decor, true, false, true, true, NULL);
+ DecorSignHighlight sign = DECOR_SIGN_HIGHLIGHT_INIT;
+
+ sign.flags |= kSHIsSign;
+ sign.text.ptr = sp->sn_text ? xstrdup(sp->sn_text) : NULL;
+ sign.sign_name = xstrdup(sp->sn_name);
+ sign.hl_id = sp->sn_text_hl;
+ sign.line_hl_id = sp->sn_line_hl;
+ sign.number_hl_id = sp->sn_num_hl;
+ sign.cursorline_hl_id = sp->sn_cul_hl;
+ sign.priority = (DecorPriority)prio;
+
+ bool has_hl = (sp->sn_line_hl || sp->sn_num_hl || sp->sn_cul_hl);
+ uint16_t decor_flags = (sp->sn_text ? MT_FLAG_DECOR_SIGNTEXT : 0)
+ | (has_hl ? MT_FLAG_DECOR_SIGNHL : 0);
+
+ DecorInline decor = { .ext = true, .data.ext = { .vt = NULL, .sh_idx = decor_put_sh(sign) } };
+ extmark_set(buf, ns, id, lnum - 1, 0, -1, -1, decor, decor_flags, true,
+ false, true, true, NULL);
}
/// For an existing, placed sign with "id", modify the sign, group or priority.
@@ -148,9 +157,18 @@ int sign_cmp(const void *p1, const void *p2)
const MTKey *s2 = (MTKey *)p2;
int n = s1->pos.row - s2->pos.row;
- return n ? n : (n = s2->decor_full->priority - s1->decor_full->priority)
- ? n : (n = (int)(s2->id - s1->id))
- ? n : (s2->decor_full->sign_add_id - s1->decor_full->sign_add_id);
+ if (n) {
+ return n;
+ }
+
+ DecorSignHighlight *sh1 = decor_find_sign(mt_decor(*s1));
+ DecorSignHighlight *sh2 = decor_find_sign(mt_decor(*s2));
+ assert(sh1 && sh2);
+
+ n = sh2->priority - sh1->priority;
+
+ return n ? n : (n = (int)(s2->id - s1->id))
+ ? n : (sh2->sign_add_id - sh1->sign_add_id);
}
/// Delete the specified signs
@@ -177,8 +195,7 @@ static int buf_delete_signs(buf_T *buf, char *group, int id, linenr_T atlnum)
MTPair pair;
while (marktree_itr_step_overlap(buf->b_marktree, itr, &pair)) {
- if ((ns == UINT32_MAX || ns == pair.start.ns)
- && pair.start.decor_full && decor_has_sign(pair.start.decor_full)) {
+ if ((ns == UINT32_MAX || ns == pair.start.ns) && mt_decor_sign(pair.start)) {
kv_push(signs, pair.start);
}
}
@@ -191,7 +208,7 @@ static int buf_delete_signs(buf_T *buf, char *group, int id, linenr_T atlnum)
if (row && mark.pos.row > row) {
break;
}
- if (!mt_end(mark) && mark.decor_full && decor_has_sign(mark.decor_full)
+ if (!mt_end(mark) && mt_decor_sign(mark)
&& (id == 0 || (int)mark.id == id)
&& (ns == UINT32_MAX || ns == mark.ns)) {
if (atlnum > 0) {
@@ -248,7 +265,7 @@ static void sign_list_placed(buf_T *rbuf, char *group)
while (itr->x) {
MTKey mark = marktree_itr_current(itr);
- if (!mt_end(mark) && mark.decor_full && decor_has_sign(mark.decor_full)
+ if (!mt_end(mark) && mt_decor_sign(mark)
&& (ns == UINT32_MAX || ns == mark.ns)) {
kv_push(signs, mark);
}
@@ -262,14 +279,16 @@ static void sign_list_placed(buf_T *rbuf, char *group)
namebuf[0] = '\0';
groupbuf[0] = '\0';
MTKey mark = kv_A(signs, i);
- if (mark.decor_full->sign_name != NULL) {
- vim_snprintf(namebuf, MSG_BUF_LEN, _(" name=%s"), sign_get_name(mark));
+
+ DecorSignHighlight *sh = decor_find_sign(mt_decor(mark));
+ if (sh->sign_name != NULL) {
+ vim_snprintf(namebuf, MSG_BUF_LEN, _(" name=%s"), sign_get_name(sh));
}
if (mark.ns != 0) {
vim_snprintf(groupbuf, MSG_BUF_LEN, _(" group=%s"), describe_ns((int)mark.ns, ""));
}
vim_snprintf(lbuf, MSG_BUF_LEN, _(" line=%" PRIdLINENR " id=%u%s%s priority=%d"),
- mark.pos.row + 1, mark.id, groupbuf, namebuf, mark.decor_full->priority);
+ mark.pos.row + 1, mark.id, groupbuf, namebuf, sh->priority);
msg_puts(lbuf);
msg_putchar('\n');
}
@@ -841,21 +860,12 @@ void ex_sign(exarg_T *eap)
}
}
-/// Append dictionary of information for a defined sign "sp", or placed
-/// sign "mark" to "retlist". Either "sp", or "mark" is NULL.
-static void sign_list_append_info(sign_T *sp, MTKey *mark, list_T *retlist)
+/// Get dictionary of information for a defined sign "sp"
+static dict_T *sign_get_info_dict(sign_T *sp)
{
dict_T *d = tv_dict_alloc();
- tv_list_append_dict(retlist, d);
- tv_dict_add_str(d, S_LEN("name"), sp ? sp->sn_name : sign_get_name(*mark));
- if (mark != NULL) {
- tv_dict_add_nr(d, S_LEN("id"), (int)mark->id);
- tv_dict_add_str(d, S_LEN("group"), describe_ns((int)mark->ns, ""));
- tv_dict_add_nr(d, S_LEN("lnum"), mark->pos.row + 1);
- tv_dict_add_nr(d, S_LEN("priority"), mark->decor_full->priority);
- return;
- }
+ tv_dict_add_str(d, S_LEN("name"), sp->sn_name);
if (sp->sn_icon != NULL) {
tv_dict_add_str(d, S_LEN("icon"), sp->sn_icon);
@@ -871,6 +881,22 @@ static void sign_list_append_info(sign_T *sp, MTKey *mark, list_T *retlist)
tv_dict_add_str(d, arg[i], strlen(arg[i]), p ? p : "NONE");
}
}
+ return d;
+}
+
+/// Get dictionary of information for placed sign "mark"
+static dict_T *sign_get_placed_info_dict(MTKey mark)
+{
+ dict_T *d = tv_dict_alloc();
+
+ DecorSignHighlight *sh = decor_find_sign(mt_decor(mark));
+
+ tv_dict_add_str(d, S_LEN("name"), sign_get_name(sh));
+ tv_dict_add_nr(d, S_LEN("id"), (int)mark.id);
+ tv_dict_add_str(d, S_LEN("group"), describe_ns((int)mark.ns, ""));
+ tv_dict_add_nr(d, S_LEN("lnum"), mark.pos.row + 1);
+ tv_dict_add_nr(d, S_LEN("priority"), sh->priority);
+ return d;
}
/// Returns information about signs placed in a buffer as list of dicts.
@@ -883,8 +909,8 @@ list_T *get_buffer_signs(buf_T *buf)
while (itr->x) {
MTKey mark = marktree_itr_current(itr);
- if (!mt_end(mark) && mark.decor_full && decor_has_sign(mark.decor_full)) {
- sign_list_append_info(NULL, &mark, l);
+ if (!mt_end(mark) && mt_decor_sign(mark)) {
+ tv_list_append_dict(l, sign_get_placed_info_dict(mark));
}
marktree_itr_next(buf->b_marktree, itr);
}
@@ -918,13 +944,15 @@ static void sign_get_placed_in_buf(buf_T *buf, linenr_T lnum, int sign_id, const
if (lnum && mark.pos.row >= lnum) {
break;
}
- if (!mt_end(mark) && mark.decor_full && decor_has_sign(mark.decor_full)
+ if (!mt_end(mark)
&& (ns == UINT32_MAX || ns == mark.ns)
&& ((lnum == 0 && sign_id == 0)
|| (sign_id == 0 && lnum == mark.pos.row + 1)
|| (lnum == 0 && sign_id == (int)mark.id)
|| (lnum == mark.pos.row + 1 && sign_id == (int)mark.id))) {
- kv_push(signs, mark);
+ if (mt_decor_sign(mark)) {
+ kv_push(signs, mark);
+ }
}
marktree_itr_next(buf->b_marktree, itr);
}
@@ -932,7 +960,7 @@ static void sign_get_placed_in_buf(buf_T *buf, linenr_T lnum, int sign_id, const
if (kv_size(signs)) {
qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp);
for (size_t i = 0; i < kv_size(signs); i++) {
- sign_list_append_info(NULL, &kv_A(signs, i), l);
+ tv_list_append_dict(l, sign_get_placed_info_dict(kv_A(signs, i)));
}
kv_destroy(signs);
}
@@ -1222,18 +1250,17 @@ void f_sign_define(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "sign_getdefined()" function
void f_sign_getdefined(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- sign_T *sp;
-
tv_list_alloc_ret(rettv, 0);
if (argvars[0].v_type == VAR_UNKNOWN) {
+ sign_T *sp;
map_foreach_value(&sign_map, sp, {
- sign_list_append_info(sp, NULL, rettv->vval.v_list);
+ tv_list_append_dict(rettv->vval.v_list, sign_get_info_dict(sp));
});
} else {
- sp = pmap_get(cstr_t)(&sign_map, tv_get_string(&argvars[0]));
+ sign_T *sp = pmap_get(cstr_t)(&sign_map, tv_get_string(&argvars[0]));
if (sp != NULL) {
- sign_list_append_info(sp, NULL, rettv->vval.v_list);
+ tv_list_append_dict(rettv->vval.v_list, sign_get_info_dict(sp));
}
}
}