mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
kbtree: allow iterators to start at arbitrary position
This commit is contained in:
parent
1eff241ec6
commit
6712e08bba
@ -74,6 +74,12 @@
|
|||||||
#include "nvim/os/time.h"
|
#include "nvim/os/time.h"
|
||||||
#include "nvim/os/input.h"
|
#include "nvim/os/input.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
kBLSUnchanged = 0,
|
||||||
|
kBLSChanged = 1,
|
||||||
|
kBLSDeleted = 2,
|
||||||
|
} BufhlLineStatus;
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "buffer.c.generated.h"
|
# include "buffer.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
@ -5228,21 +5234,21 @@ void bufhl_clear_line_range(buf_T *buf,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
linenr_T first_changed = MAXLNUM, last_changed = -1;
|
linenr_T first_changed = MAXLNUM, last_changed = -1;
|
||||||
// TODO: implement kb_itr_interval and jump directly to the first line
|
|
||||||
kbitr_t itr;
|
kbitr_t itr;
|
||||||
BufhlLine *l;
|
BufhlLine *l, t = {line_start};
|
||||||
for (kb_itr_first(bufhl, buf->b_bufhl_info, &itr);
|
if (!kb_itr_get(bufhl, buf->b_bufhl_info, &t, &itr)) {
|
||||||
kb_itr_valid(&itr);
|
kb_itr_next(bufhl, buf->b_bufhl_info, &itr);
|
||||||
kb_itr_next(bufhl, buf->b_bufhl_info, &itr)) {
|
}
|
||||||
|
for (; kb_itr_valid(&itr); kb_itr_next(bufhl, buf->b_bufhl_info, &itr)) {
|
||||||
l = kb_itr_key(BufhlLine *, &itr);
|
l = kb_itr_key(BufhlLine *, &itr);
|
||||||
linenr_T line = l->line;
|
linenr_T line = l->line;
|
||||||
if (line < line_start) {
|
if (line > line_end) {
|
||||||
continue;
|
|
||||||
} else if (line > line_end) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (line_start <= line && line <= line_end) {
|
if (line_start <= line && line <= line_end) {
|
||||||
if (bufhl_clear_line(buf->b_bufhl_info, src_id, line)) {
|
BufhlLineStatus status = bufhl_clear_line(buf->b_bufhl_info, src_id, line);
|
||||||
|
if (status != kBLSUnchanged) {
|
||||||
if (line > last_changed) {
|
if (line > last_changed) {
|
||||||
last_changed = line;
|
last_changed = line;
|
||||||
}
|
}
|
||||||
@ -5250,6 +5256,9 @@ void bufhl_clear_line_range(buf_T *buf,
|
|||||||
first_changed = line;
|
first_changed = line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (status == kBLSDeleted) {
|
||||||
|
kb_del_itr(bufhl, buf->b_bufhl_info, &itr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5264,8 +5273,8 @@ void bufhl_clear_line_range(buf_T *buf,
|
|||||||
/// @param bufhl_info The highlight info for the buffer
|
/// @param bufhl_info The highlight info for the buffer
|
||||||
/// @param src_id Highlight source group to clear, or -1 to clear all groups.
|
/// @param src_id Highlight source group to clear, or -1 to clear all groups.
|
||||||
/// @param lnum Linenr where the highlight should be cleared
|
/// @param lnum Linenr where the highlight should be cleared
|
||||||
static bool bufhl_clear_line(bufhl_info_T *bufhl_info, int src_id,
|
static BufhlLineStatus bufhl_clear_line(bufhl_info_T *bufhl_info, int src_id,
|
||||||
linenr_T lnum)
|
linenr_T lnum)
|
||||||
{
|
{
|
||||||
BufhlLine *lineinfo = bufhl_tree_ref(bufhl_info, lnum, false);
|
BufhlLine *lineinfo = bufhl_tree_ref(bufhl_info, lnum, false);
|
||||||
size_t oldsize = kv_size(lineinfo->items);
|
size_t oldsize = kv_size(lineinfo->items);
|
||||||
@ -5286,9 +5295,9 @@ static bool bufhl_clear_line(bufhl_info_T *bufhl_info, int src_id,
|
|||||||
|
|
||||||
if (kv_size(lineinfo->items) == 0) {
|
if (kv_size(lineinfo->items) == 0) {
|
||||||
kv_destroy(lineinfo->items);
|
kv_destroy(lineinfo->items);
|
||||||
kb_del(bufhl, bufhl_info, lineinfo);
|
return kBLSDeleted;
|
||||||
}
|
}
|
||||||
return kv_size(lineinfo->items) != oldsize;
|
return kv_size(lineinfo->items) != oldsize ? kBLSChanged : kBLSUnchanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove all highlights and free the highlight data
|
/// Remove all highlights and free the highlight data
|
||||||
@ -5315,15 +5324,19 @@ void bufhl_mark_adjust(buf_T* buf,
|
|||||||
// we need to detect this case and
|
// we need to detect this case and
|
||||||
|
|
||||||
kbitr_t itr;
|
kbitr_t itr;
|
||||||
BufhlLine *l;
|
BufhlLine *l, t = {line1};
|
||||||
for (kb_itr_first(bufhl, buf->b_bufhl_info, &itr);
|
if (!kb_itr_get(bufhl, buf->b_bufhl_info, &t, &itr)) {
|
||||||
kb_itr_valid(&itr);
|
kb_itr_next(bufhl, buf->b_bufhl_info, &itr);
|
||||||
kb_itr_next(bufhl, buf->b_bufhl_info, &itr)) {
|
}
|
||||||
|
for (; kb_itr_valid(&itr); kb_itr_next(bufhl, buf->b_bufhl_info, &itr)) {
|
||||||
l = kb_itr_key(BufhlLine *, &itr);
|
l = kb_itr_key(BufhlLine *, &itr);
|
||||||
if (l->line >= line1 && l->line <= line2) {
|
if (l->line >= line1 && l->line <= line2) {
|
||||||
if (amount == MAXLNUM) {
|
if (amount == MAXLNUM) {
|
||||||
bufhl_clear_line(buf->b_bufhl_info, -1, l->line);
|
if (bufhl_clear_line(buf->b_bufhl_info, -1, l->line) == kBLSDeleted) {
|
||||||
continue;
|
kb_del_itr(bufhl, buf->b_bufhl_info, &itr);
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
l->line += amount;
|
l->line += amount;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ typedef struct {
|
|||||||
colnr_T valid_to;
|
colnr_T valid_to;
|
||||||
} bufhl_lineinfo_T;
|
} bufhl_lineinfo_T;
|
||||||
|
|
||||||
#define BUFHL_CMP(a, b) (((b)->line - (a)->line))
|
#define BUFHL_CMP(a, b) (((a)->line - (b)->line))
|
||||||
KBTREE_INIT(bufhl, BufhlLine *, BUFHL_CMP)
|
KBTREE_INIT(bufhl, BufhlLine *, BUFHL_CMP)
|
||||||
typedef kbtree_t(bufhl) bufhl_info_T;
|
typedef kbtree_t(bufhl) bufhl_info_T;
|
||||||
#endif // NVIM_BUFHL_DEFS_H
|
#endif // NVIM_BUFHL_DEFS_H
|
||||||
|
@ -57,7 +57,9 @@ typedef struct {
|
|||||||
int off_key, off_ptr, ilen, elen; \
|
int off_key, off_ptr, ilen, elen; \
|
||||||
int n, t; \
|
int n, t; \
|
||||||
int n_keys, n_nodes; \
|
int n_keys, n_nodes; \
|
||||||
} kbtree_##name##_t;
|
} kbtree_##name##_t; \
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define __KB_INIT(name, key_t) \
|
#define __KB_INIT(name, key_t) \
|
||||||
static inline kbtree_##name##_t *kb_init_##name(unsigned int size) \
|
static inline kbtree_##name##_t *kb_init_##name(unsigned int size) \
|
||||||
@ -75,7 +77,7 @@ typedef struct {
|
|||||||
b->root = (kbnode_t*)calloc(1, (unsigned int)b->ilen); \
|
b->root = (kbnode_t*)calloc(1, (unsigned int)b->ilen); \
|
||||||
++b->n_nodes; \
|
++b->n_nodes; \
|
||||||
return b; \
|
return b; \
|
||||||
}
|
} \
|
||||||
|
|
||||||
#define __kb_destroy(b) do { \
|
#define __kb_destroy(b) do { \
|
||||||
int i; \
|
int i; \
|
||||||
@ -346,7 +348,48 @@ typedef struct {
|
|||||||
if (itr->p < itr->stack) return 0; \
|
if (itr->p < itr->stack) return 0; \
|
||||||
if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \
|
if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \
|
||||||
} \
|
} \
|
||||||
}
|
} \
|
||||||
|
static inline int kb_itr_prev_##name(kbtree_##name##_t *b, kbitr_t *itr) \
|
||||||
|
{ \
|
||||||
|
if (itr->p < itr->stack) return 0; \
|
||||||
|
for (;;) { \
|
||||||
|
while (itr->p->x && itr->p->i >= 0) { \
|
||||||
|
itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \
|
||||||
|
itr->p[1].i = itr->p[1].x ? itr->p[1].x->n : -1; \
|
||||||
|
++itr->p; \
|
||||||
|
} \
|
||||||
|
--itr->p; \
|
||||||
|
if (itr->p < itr->stack) return 0; \
|
||||||
|
--itr->p->i; \
|
||||||
|
if (itr->p->x && itr->p->i >= 0) return 1; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
static int kb_itr_getp_##name(kbtree_##name##_t *b, const key_t * __restrict k, kbitr_t *itr) \
|
||||||
|
{ \
|
||||||
|
int i, r = 0; \
|
||||||
|
itr->p = itr->stack; \
|
||||||
|
itr->p->x = b->root; \
|
||||||
|
while (itr->p->x) { \
|
||||||
|
i = __kb_getp_aux_##name(itr->p->x, k, &r); \
|
||||||
|
itr->p->i = i; \
|
||||||
|
if (i >= 0 && r == 0) return 1; \
|
||||||
|
++itr->p->i; \
|
||||||
|
itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[i + 1] : 0; \
|
||||||
|
++itr->p; \
|
||||||
|
} \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
static int kb_itr_get_##name(kbtree_##name##_t *b, const key_t k, kbitr_t *itr) \
|
||||||
|
{ \
|
||||||
|
return kb_itr_getp_##name(b,&k,itr); \
|
||||||
|
} \
|
||||||
|
static inline void kb_del_itr_##name(kbtree_##name##_t *b, kbitr_t *itr) \
|
||||||
|
{ \
|
||||||
|
key_t k = kb_itr_key(key_t, itr); \
|
||||||
|
kb_delp_##name(b, &k); \
|
||||||
|
kb_itr_getp_##name(b, &k, itr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define KBTREE_INIT(name, key_t, __cmp) \
|
#define KBTREE_INIT(name, key_t, __cmp) \
|
||||||
__KB_TREE_T(name) \
|
__KB_TREE_T(name) \
|
||||||
@ -373,7 +416,11 @@ typedef struct {
|
|||||||
#define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u)
|
#define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u)
|
||||||
|
|
||||||
#define kb_itr_first(name, b, i) kb_itr_first_##name(b, i)
|
#define kb_itr_first(name, b, i) kb_itr_first_##name(b, i)
|
||||||
|
#define kb_itr_get(name, b, k, i) kb_itr_get_##name(b, k, i)
|
||||||
|
#define kb_itr_getp(name, b, k, i) kb_itr_getp_##name(b, k, i)
|
||||||
#define kb_itr_next(name, b, i) kb_itr_next_##name(b, i)
|
#define kb_itr_next(name, b, i) kb_itr_next_##name(b, i)
|
||||||
|
#define kb_itr_prev(name, b, i) kb_itr_prev_##name(b, i)
|
||||||
|
#define kb_del_itr(name, b, i) kb_del_itr_##name(b, i)
|
||||||
#define kb_itr_key(type, itr) __KB_KEY(type, (itr)->p->x)[(itr)->p->i]
|
#define kb_itr_key(type, itr) __KB_KEY(type, (itr)->p->x)[(itr)->p->i]
|
||||||
#define kb_itr_valid(itr) ((itr)->p >= (itr)->stack)
|
#define kb_itr_valid(itr) ((itr)->p >= (itr)->stack)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user