refactor(extmarks): extmark_del() with MarkTreeIter

This commit is contained in:
Luuk van Baal
2023-10-31 23:53:52 +01:00
parent 746a153bc1
commit 14c7bf3916
2 changed files with 23 additions and 59 deletions

View File

@@ -862,7 +862,7 @@ Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *er
return false; return false;
} }
return extmark_del(buf, (uint32_t)ns_id, (uint32_t)id); return extmark_del_id(buf, (uint32_t)ns_id, (uint32_t)id);
} }
uint32_t src2ns(Integer *src_id) uint32_t src2ns(Integer *src_id)

View File

@@ -93,7 +93,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
goto error; goto error;
} }
if (mt_paired(old_mark) || end_row > -1) { if (mt_paired(old_mark) || end_row > -1) {
extmark_del(buf, ns_id, id); extmark_del_id(buf, ns_id, id);
} else { } else {
// TODO(bfredl): we need to do more if "revising" a decoration mark. // TODO(bfredl): we need to do more if "revising" a decoration mark.
assert(marktree_itr_valid(itr)); assert(marktree_itr_valid(itr));
@@ -194,25 +194,33 @@ static bool extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col)
return true; return true;
} }
/// Remove an extmark linenr_T extmark_del_id(buf_T *buf, uint32_t ns_id, uint32_t id)
///
/// @return 0 on missing id
bool extmark_del(buf_T *buf, uint32_t ns_id, uint32_t id)
{ {
MarkTreeIter itr[1] = { 0 }; MarkTreeIter it[1] = { 0 };
MTKey key = marktree_lookup_ns(buf->b_marktree, ns_id, id, false, itr); MTKey key = marktree_lookup_ns(buf->b_marktree, ns_id, id, false, it);
if (!key.id) { if (!key.id) {
return false; return 0;
} }
return extmark_del(buf, it, key, false);
}
/// Remove a (paired) extmark "key" pointed to by "itr"
///
/// @return line number of the deleted mark
linenr_T extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
{
assert(key.pos.row >= 0); assert(key.pos.row >= 0);
uint64_t other = marktree_del_itr(buf->b_marktree, itr, false);
MTKey key2 = key; MTKey key2 = key;
uint64_t other = marktree_del_itr(buf->b_marktree, itr, false);
if (other) { if (other) {
key2 = marktree_lookup(buf->b_marktree, other, itr); key2 = marktree_lookup(buf->b_marktree, other, itr);
assert(key2.pos.row >= 0); assert(key2.pos.row >= 0);
marktree_del_itr(buf->b_marktree, itr, false); marktree_del_itr(buf->b_marktree, itr, false);
if (restore) {
marktree_itr_get(buf->b_marktree, key.pos.row, key.pos.col, itr);
}
} }
if (marktree_decor_level(key) > kDecorLevelNone) { if (marktree_decor_level(key) > kDecorLevelNone) {
@@ -220,7 +228,7 @@ bool extmark_del(buf_T *buf, uint32_t ns_id, uint32_t id)
} }
// TODO(bfredl): delete it from current undo header, opportunistically? // TODO(bfredl): delete it from current undo header, opportunistically?
return true; return key.pos.row + 1;
} }
/// Free extmarks in a ns between lines /// Free extmarks in a ns between lines
@@ -231,8 +239,6 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
return false; return false;
} }
bool marks_cleared = false;
bool all_ns = (ns_id == 0); bool all_ns = (ns_id == 0);
uint32_t *ns = NULL; uint32_t *ns = NULL;
if (!all_ns) { if (!all_ns) {
@@ -243,11 +249,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
} }
} }
// the value is either zero or the lnum (row+1) if highlight was present. bool marks_cleared = false;
static Map(uint64_t, ssize_t) delete_set = MAP_INIT;
typedef struct { int row1; } DecorItem;
static kvec_t(DecorItem) decors;
MarkTreeIter itr[1] = { 0 }; MarkTreeIter itr[1] = { 0 };
marktree_itr_get(buf->b_marktree, l_row, l_col, itr); marktree_itr_get(buf->b_marktree, l_row, l_col, itr);
while (true) { while (true) {
@@ -257,52 +259,14 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
|| (mark.pos.row == u_row && mark.pos.col > u_col)) { || (mark.pos.row == u_row && mark.pos.col > u_col)) {
break; break;
} }
ssize_t *del_status = map_ref(uint64_t, ssize_t)(&delete_set, mt_lookup_key(mark), NULL);
if (del_status) {
marktree_del_itr(buf->b_marktree, itr, false);
if (*del_status >= 0) { // we had a decor_id
DecorItem it = kv_A(decors, *del_status);
decor_remove(buf, it.row1, mark.pos.row, mark.decor_full);
}
map_del(uint64_t, ssize_t)(&delete_set, mt_lookup_key(mark), NULL);
continue;
}
assert(mark.ns > 0 && mark.id > 0);
if (mark.ns == ns_id || all_ns) { if (mark.ns == ns_id || all_ns) {
marks_cleared = true; marks_cleared = true;
if (mark.decor_full && !mt_paired(mark)) { // if paired: deal with it later extmark_del(buf, itr, mark, true);
decor_remove(buf, mark.pos.row, mark.pos.row, mark.decor_full);
}
uint64_t other = marktree_del_itr(buf->b_marktree, itr, false);
if (mt_paired(mark)) {
ssize_t decor_id = -1;
if (marktree_decor_level(mark) > kDecorLevelNone) {
// Save the decoration and the first pos. Clear the decoration
// later when we know the full range.
decor_id = (ssize_t)kv_size(decors);
kv_push(decors,
((DecorItem) { .row1 = mark.pos.row }));
}
map_put(uint64_t, ssize_t)(&delete_set, other, decor_id);
}
} else { } else {
marktree_itr_next(buf->b_marktree, itr); marktree_itr_next(buf->b_marktree, itr);
} }
} }
uint64_t id;
ssize_t decor_id;
map_foreach(&delete_set, id, decor_id, {
MTKey mark = marktree_lookup(buf->b_marktree, id, itr);
assert(marktree_itr_valid(itr));
marktree_del_itr(buf->b_marktree, itr, false);
if (decor_id >= 0) {
DecorItem it = kv_A(decors, decor_id);
decor_remove(buf, it.row1, mark.pos.row, mark.decor_full);
}
});
map_clear(uint64_t, &delete_set);
kv_size(decors) = 0;
return marks_cleared; return marks_cleared;
} }