treesitter: use internal "decorations" buffer

This commit is contained in:
Björn Linse 2020-01-17 22:27:17 +01:00
parent 6c5bbf07d9
commit 95fd28f4a1
5 changed files with 49 additions and 81 deletions

View File

@ -85,7 +85,6 @@ end
function TSHighlighter:on_window(_, _win, _buf, _topline, botline)
self.iter = nil
self.active_nodes = {}
self.nextrow = 0
self.botline = botline
self.redraw_count = self.redraw_count + 1
@ -107,34 +106,13 @@ function TSHighlighter:on_line(_, _win, buf, line)
end
local start_row, start_col, end_row, end_col = node:range()
local hl = self.id_map[capture]
if hl > 0 and active then
if start_row == line and end_row == line then
a.nvim__put_attr(hl, start_col, end_col)
elseif end_row >= line then
-- TODO(bfredl): this is quite messy. Togheter with multiline bufhl we should support
-- luahl generating multiline highlights (and other kinds of annotations)
self.active_nodes[{hl=hl, start_row=start_row, start_col=start_col, end_row=end_row, end_col=end_col}] = true
end
if hl > 0 and active and end_row >= line then
a.nvim__put_attr(hl, start_row, start_col, end_row, end_col)
end
if start_row > line then
self.nextrow = start_row
end
end
for node,_ in pairs(self.active_nodes) do
if node.start_row <= line and node.end_row >= line then
local start_col, end_col = node.start_col, node.end_col
if node.start_row < line then
start_col = 0
end
if node.end_row > line then
end_col = 9000
end
a.nvim__put_attr(node.hl, start_col, end_col)
end
if node.end_row <= line then
self.active_nodes[node] = nil
end
end
self.line_count[line] = (self.line_count[line] or 0) + 1
--return tostring(self.line_count[line])
end

View File

@ -2598,7 +2598,8 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Error *err)
/// interface should probably be derived from a reformed
/// bufhl/virttext interface with full support for multi-line
/// ranges etc
void nvim__put_attr(Integer id, Integer c0, Integer c1)
void nvim__put_attr(Integer id, Integer start_row, Integer start_col,
Integer end_row, Integer end_col)
FUNC_API_LUA_ONLY
{
if (!lua_attr_active) {
@ -2608,10 +2609,8 @@ void nvim__put_attr(Integer id, Integer c0, Integer c1)
return;
}
int attr = syn_id2attr((int)id);
c0 = MAX(c0, 0);
c1 = MIN(c1, (Integer)lua_attr_bufsize);
for (Integer c = c0; c < c1; c++) {
lua_attr_buf[c] = (sattr_T)hl_combine_attr(lua_attr_buf[c], (int)attr);
if (attr == 0) {
return;
}
return;
decoration_state_add_tmp(attr, start_row, start_col, end_row, end_col);
}

View File

@ -756,17 +756,18 @@ VirtText *extmark_find_virttext(buf_T *buf, int row, uint64_t ns_id)
return NULL;
}
// TODO: use decoration_state prefix
bool extmark_decorations_reset(buf_T *buf, DecorationState *state)
{
state->row = -1;
return buf->b_extmark_index;
kv_size(state->active) = 0;
// TODO: for tmp decorations!
return buf->b_extmark_index || true;
}
bool extmark_decorations_start(buf_T *buf, int top_row, DecorationState *state)
{
kv_size(state->active) = 0;
state->top_row = top_row;
marktree_itr_get(buf->b_marktree, top_row, 0, state->itr);
if (!state->itr->node) {

View File

@ -127,10 +127,6 @@ typedef off_t off_T;
EXTERN int mod_mask INIT(= 0x0); /* current key modifiers */
// TODO(bfredl): for the final interface this should find a more suitable
// location.
EXTERN sattr_T *lua_attr_buf INIT(= NULL);
EXTERN size_t lua_attr_bufsize INIT(= 0);
EXTERN bool lua_attr_active INIT(= false);
/*

View File

@ -637,6 +637,15 @@ bool win_cursorline_standout(const win_T *wp)
static DecorationState decorations;
bool decorations_active = false;
// VERY ad-hoc, should be in mark_extended.c?
void decoration_state_add_tmp(int attr_id,
int start_row, int start_col,
int end_row, int end_col)
{
kv_push(decorations.active,
((HlRange){ start_row, start_col, end_row, end_col, attr_id, NULL }));
}
/*
* Update a single window.
*
@ -2311,6 +2320,8 @@ win_line (
char *luatext = NULL;
buf_T *buf = wp->w_buffer;
if (!number_only) {
// To speed up the loop below, set extra_check when there is linebreak,
// trailing white space and/or syntax processing to be done.
@ -2332,6 +2343,33 @@ win_line (
}
}
if (buf->b_luahl && buf->b_luahl_line != LUA_NOREF) {
Error err = ERROR_INIT;
// TODO(bfredl): build a macro for the "static array" pattern
// in buf_updates_send_changes?
FIXED_TEMP_ARRAY(args, 3);
args.items[0] = WINDOW_OBJ(wp->handle);
args.items[1] = BUFFER_OBJ(buf->handle);
args.items[2] = INTEGER_OBJ(lnum-1);
lua_attr_active = true;
extra_check = true;
Object o = executor_exec_lua_cb(buf->b_luahl_line, "line",
args, true, &err);
lua_attr_active = false;
if (o.type == kObjectTypeString) {
// TODO(bfredl): this is a bit of a hack. A final API should use an
// "unified" interface where luahl can add both bufhl and virttext
luatext = o.data.string.data;
do_virttext = true;
} else if (ERROR_SET(&err)) {
ELOG("error in luahl line: %s", err.msg);
luatext = err.msg;
do_virttext = true;
}
decorations_active = true; // TODO: huff!
}
if (decorations_active) {
has_decorations = extmark_decorations_line(wp->w_buffer, lnum-1,
&decorations);
@ -2532,41 +2570,6 @@ win_line (
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
ptr = line;
buf_T *buf = wp->w_buffer;
if (buf->b_luahl && buf->b_luahl_line != LUA_NOREF) {
size_t size = STRLEN(line);
if (lua_attr_bufsize < size) {
xfree(lua_attr_buf);
lua_attr_buf = xcalloc(size, sizeof(*lua_attr_buf));
lua_attr_bufsize = size;
} else if (lua_attr_buf) {
memset(lua_attr_buf, 0, size * sizeof(*lua_attr_buf));
}
Error err = ERROR_INIT;
// TODO(bfredl): build a macro for the "static array" pattern
// in buf_updates_send_changes?
FIXED_TEMP_ARRAY(args, 3);
args.items[0] = WINDOW_OBJ(wp->handle);
args.items[1] = BUFFER_OBJ(buf->handle);
args.items[2] = INTEGER_OBJ(lnum-1);
lua_attr_active = true;
extra_check = true;
Object o = executor_exec_lua_cb(buf->b_luahl_line, "line",
args, true, &err);
lua_attr_active = false;
if (o.type == kObjectTypeString) {
// TODO(bfredl): this is a bit of a hack. A final API should use an
// "unified" interface where luahl can add both bufhl and virttext
luatext = o.data.string.data;
do_virttext = true;
} else if (ERROR_SET(&err)) {
ELOG("error in luahl line: %s", err.msg);
luatext = err.msg;
do_virttext = true;
api_clear_error(&err);
}
}
if (has_spell && !number_only) {
// For checking first word with a capital skip white space.
if (cap_col == 0) {
@ -3549,15 +3552,6 @@ win_line (
}
}
// TODO(bfredl): luahl should reuse the "active decorations" buffer
if (buf->b_luahl && v > 0 && v < (long)lua_attr_bufsize+1) {
if (!attr_pri) {
char_attr = hl_combine_attr(char_attr, lua_attr_buf[v-1]);
} else {
char_attr = hl_combine_attr(lua_attr_buf[v-1], char_attr);
}
}
if (wp->w_buffer->terminal) {
char_attr = hl_combine_attr(term_attrs[vcol], char_attr);
}