mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
refactor(extmarks): some minor internal API changes
extranges and a bunch of other improvements are coming for 0.10 This gets in some minor surrounding API changes to avoid rebase conflicts until then. - decorations will be able to be specific to windows - adjust deletion API to fit with extranges
This commit is contained in:
parent
320cb344c1
commit
8021300806
@ -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) {
|
||||
|
@ -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++) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user