Merge pull request #22687 from bfredl/intermarks

refactor(extmarks): some minor internal API changes
This commit is contained in:
bfredl 2023-03-16 14:23:09 +01:00 committed by GitHub
commit 995196c614
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 53 additions and 40 deletions

View File

@ -793,7 +793,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
// TODO(bfredl): synergize these two branches even more
if (ephemeral && decor_state.buf == buf) {
if (ephemeral && decor_state.win && decor_state.win->w_buffer == buf) {
decor_add_ephemeral((int)line, (int)col, line2, col2, &decor, (uint64_t)ns_id, id);
} else {
if (ephemeral) {

View File

@ -166,10 +166,10 @@ next_mark:
return NULL;
}
bool decor_redraw_reset(buf_T *buf, DecorState *state)
bool decor_redraw_reset(win_T *wp, DecorState *state)
{
state->row = -1;
state->buf = buf;
state->win = wp;
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange item = kv_A(state->active, i);
if (item.virt_text_owned) {
@ -177,7 +177,7 @@ bool decor_redraw_reset(buf_T *buf, DecorState *state)
}
}
kv_size(state->active) = 0;
return buf->b_marktree->n_keys;
return wp->w_buffer->b_marktree->n_keys;
}
Decoration get_decor(mtkey_t mark)
@ -198,8 +198,9 @@ static bool decor_virt_pos(Decoration decor)
return kv_size(decor.virt_text) || decor.ui_watched;
}
bool decor_redraw_start(buf_T *buf, int top_row, DecorState *state)
bool decor_redraw_start(win_T *wp, int top_row, DecorState *state)
{
buf_T *buf = wp->w_buffer;
state->top_row = top_row;
marktree_itr_get(buf->b_marktree, top_row, 0, state->itr);
if (!state->itr->node) {
@ -250,10 +251,10 @@ next_mark:
return true; // TODO(bfredl): check if available in the region
}
bool decor_redraw_line(buf_T *buf, int row, DecorState *state)
bool decor_redraw_line(win_T *wp, int row, DecorState *state)
{
if (state->row == -1) {
decor_redraw_start(buf, row, state);
decor_redraw_start(wp, row, state);
}
state->row = row;
state->col_until = -1;
@ -282,8 +283,9 @@ static void decor_add(DecorState *state, int start_row, int start_col, int end_r
kv_A(state->active, index) = range;
}
int decor_redraw_col(buf_T *buf, int col, int win_col, bool hidden, DecorState *state)
int decor_redraw_col(win_T *wp, int col, int win_col, bool hidden, DecorState *state)
{
buf_T *buf = wp->w_buffer;
if (col <= state->col_until) {
return state->current;
}
@ -529,12 +531,12 @@ next_mark:
void decor_redraw_end(DecorState *state)
{
state->buf = NULL;
state->win = NULL;
}
bool decor_redraw_eol(buf_T *buf, DecorState *state, int *eol_attr, int eol_col)
bool decor_redraw_eol(win_T *wp, DecorState *state, int *eol_attr, int eol_col)
{
decor_redraw_col(buf, MAXCOL, MAXCOL, false, state);
decor_redraw_col(wp, MAXCOL, MAXCOL, false, state);
state->eol_col = eol_col;
bool has_virttext = false;
for (size_t i = 0; i < kv_size(state->active); i++) {

View File

@ -88,7 +88,7 @@ typedef struct {
typedef struct {
MarkTreeIter itr[1];
kvec_t(DecorRange) active;
buf_T *buf;
win_T *win;
int top_row;
int row;
int col_until;

View File

@ -1096,7 +1096,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
}
has_decor = decor_redraw_line(buf, lnum - 1, &decor_state);
has_decor = decor_redraw_line(wp, lnum - 1, &decor_state);
decor_providers_invoke_line(wp, providers, lnum - 1, &has_decor, provider_err);
@ -1619,7 +1619,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.draw_state = WL_LINE;
if (has_decor && wlv.row == startrow + wlv.filler_lines) {
// hide virt_text on text hidden by 'nowrap'
decor_redraw_col(wp->w_buffer, wlv.vcol, wlv.off, true, &decor_state);
decor_redraw_col(wp, wlv.vcol, wlv.off, true, &decor_state);
}
win_line_continue(&wlv); // use wlv.saved_ values
}
@ -2011,7 +2011,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (has_decor && v > 0) {
bool selected = (area_active || (area_highlighting && noinvcur
&& wlv.vcol == wp->w_virtcol));
int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, wlv.off,
int extmark_attr = decor_redraw_col(wp, (colnr_T)v - 1, wlv.off,
selected, &decor_state);
if (extmark_attr != 0) {
if (!attr_pri) {
@ -2615,7 +2615,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
? 1 : 0);
if (has_decor) {
has_virttext = decor_redraw_eol(wp->w_buffer, &decor_state, &wlv.line_attr,
has_virttext = decor_redraw_eol(wp, &decor_state, &wlv.line_attr,
wlv.col + eol_skip);
}

View File

@ -1427,7 +1427,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
win_extmark_arr.size = 0;
decor_redraw_reset(buf, &decor_state);
decor_redraw_reset(wp, &decor_state);
DecorProviders line_providers;
decor_providers_invoke_win(wp, providers, &line_providers, &provider_err);

View File

@ -92,7 +92,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
extmark_del(buf, ns_id, id);
} else {
// TODO(bfredl): we need to do more if "revising" a decoration mark.
assert(itr->node);
assert(marktree_itr_valid(itr));
if (old_mark.pos.row == row && old_mark.pos.col == col) {
if (marktree_decor_level(old_mark) > kDecorLevelNone) {
decor_remove(buf, row, row, old_mark.decor_full);
@ -191,12 +191,12 @@ bool extmark_del(buf_T *buf, uint32_t ns_id, uint32_t id)
return false;
}
assert(key.pos.row >= 0);
marktree_del_itr(buf->b_marktree, itr, false);
uint64_t other = marktree_del_itr(buf->b_marktree, itr, false);
mtkey_t key2 = key;
if (mt_paired(key)) {
key2 = marktree_lookup_ns(buf->b_marktree, ns_id, id, true, itr);
if (other) {
key2 = marktree_lookup(buf->b_marktree, other, itr);
assert(key2.pos.row >= 0);
marktree_del_itr(buf->b_marktree, itr, false);
}
@ -258,8 +258,11 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
assert(mark.ns > 0 && mark.id > 0);
if (mark.ns == ns_id || all_ns) {
marks_cleared = true;
if (mark.decor_full && !mt_paired(mark)) { // if paired: deal with it later
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)) {
uint64_t other = mt_lookup_id(mark.ns, mark.id, !mt_end(mark));
ssize_t decor_id = -1;
if (marktree_decor_level(mark) > kDecorLevelNone) {
// Save the decoration and the first pos. Clear the decoration
@ -269,10 +272,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
((DecorItem) { .row1 = mark.pos.row }));
}
map_put(uint64_t, ssize_t)(&delete_set, other, decor_id);
} else if (mark.decor_full) {
decor_remove(buf, mark.pos.row, mark.pos.row, mark.decor_full);
}
marktree_del_itr(buf->b_marktree, itr, false);
} else {
marktree_itr_next(buf->b_marktree, itr);
}
@ -281,7 +281,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
ssize_t decor_id;
map_foreach(&delete_set, id, decor_id, {
mtkey_t mark = marktree_lookup(buf->b_marktree, id, itr);
assert(itr->node);
assert(marktree_itr_valid(itr));
marktree_del_itr(buf->b_marktree, itr, false);
if (decor_id >= 0) {
DecorItem it = kv_A(decors, decor_id);
@ -306,7 +306,7 @@ ExtmarkInfoArray extmark_get(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_co
ExtmarkInfoArray array = KV_INITIAL_VALUE;
MarkTreeIter itr[1];
// Find all the marks
marktree_itr_get_ext(buf->b_marktree, (mtpos_t){ l_row, l_col },
marktree_itr_get_ext(buf->b_marktree, mtpos_t(l_row, l_col),
itr, reverse, false, NULL);
int order = reverse ? -1 : 1;
while ((int64_t)kv_size(array) < amount) {

View File

@ -279,13 +279,13 @@ void marktree_put_key(MarkTree *b, mtkey_t k)
/// 6. If 4 went all the way to the root node. The root node
/// might have ended up with size 0. Delete it then.
///
/// NB: ideally keeps the iterator valid. Like point to the key after this
/// if present.
/// The iterator remains valid, and now points at the key _after_ the deleted
/// one.
///
/// @param rev should be true if we plan to iterate _backwards_ and delete
/// stuff before this key. Most of the time this is false (the
/// recommended strategy is to always iterate forward)
void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
{
int adjustment = 0;
@ -294,6 +294,12 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
uint64_t id = mt_lookup_key(cur->key[curi]);
// fprintf(stderr, "\nDELET %lu\n", id);
mtkey_t raw = rawkey(itr);
uint64_t other = 0;
if (mt_paired(raw)) {
other = mt_lookup_id(raw.ns, raw.id, !mt_end(raw));
}
if (itr->node->level) {
if (rev) {
abort();
@ -442,6 +448,8 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
marktree_itr_next(b, itr);
}
}
return other;
}
static mtnode_t *merge_node(MarkTree *b, mtnode_t *p, int i)

View File

@ -22,21 +22,26 @@ typedef struct {
int32_t row;
int32_t col;
} mtpos_t;
#define mtpos_t(r, c) ((mtpos_t){ .row = (r), .col = (c) })
typedef struct mtnode_s mtnode_t;
typedef struct {
int oldcol;
int i;
} iterstate_t;
typedef struct {
mtpos_t pos;
int lvl;
mtnode_t *node;
int i;
iterstate_t s[MT_MAX_DEPTH];
struct {
int oldcol;
int i;
} s[MT_MAX_DEPTH];
size_t intersect_idx;
mtpos_t intersect_pos;
} MarkTreeIter;
#define marktree_itr_valid(itr) ((itr)->node != NULL)
// Internal storage
//
// NB: actual marks have flags > 0, so we can use (row,col,0) pseudo-key for
@ -123,8 +128,6 @@ struct mtnode_s {
mtnode_t *ptr[];
};
// TODO(bfredl): the iterator is pretty much everpresent, make it part of the
// tree struct itself?
typedef struct {
mtnode_t *root;
size_t n_keys, n_nodes;

View File

@ -1203,7 +1203,7 @@ bool no_spell_checking(win_T *wp)
static void decor_spell_nav_start(win_T *wp)
{
decor_state = (DecorState){ 0 };
decor_redraw_reset(wp->w_buffer, &decor_state);
decor_redraw_reset(wp, &decor_state);
}
static bool decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_lnum, int col,
@ -1211,10 +1211,10 @@ static bool decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_lnum,
{
if (*decor_lnum != lnum) {
decor_providers_invoke_spell(wp, lnum - 1, col, lnum - 1, -1, decor_error);
decor_redraw_line(wp->w_buffer, lnum - 1, &decor_state);
decor_redraw_line(wp, lnum - 1, &decor_state);
*decor_lnum = lnum;
}
decor_redraw_col(wp->w_buffer, col, col, false, &decor_state);
decor_redraw_col(wp, col, col, false, &decor_state);
return decor_state.spell == kTrue;
}