refactor(decorations): move provider code

Move decoration provider code to a separate file.
This commit is contained in:
Lewis Russell
2022-03-10 15:17:06 +00:00
parent 9e9322b222
commit 1b054119ec
10 changed files with 285 additions and 198 deletions

View File

@@ -75,6 +75,7 @@
#include "nvim/cursor.h"
#include "nvim/cursor_shape.h"
#include "nvim/decoration.h"
#include "nvim/decoration_provider.h"
#include "nvim/diff.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
@@ -126,8 +127,6 @@
#define MB_FILLER_CHAR '<' /* character used when a double-width character
* doesn't fit. */
typedef kvec_withinit_t(DecorProvider *, 4) Providers;
// temporary buffer for rendering a single screenline, so it can be
// compared with previous contents to calculate smallest delta.
// Per-cell attributes
@@ -168,36 +167,6 @@ static bool resizing = false;
static char *provider_err = NULL;
static bool provider_invoke(NS ns_id, const char *name, LuaRef ref, Array args, bool default_true)
{
Error err = ERROR_INIT;
textlock++;
provider_active = true;
Object ret = nlua_call_ref(ref, name, args, true, &err);
provider_active = false;
textlock--;
if (!ERROR_SET(&err)
&& api_object_to_bool(ret, "provider %s retval", default_true, &err)) {
return true;
}
if (ERROR_SET(&err)) {
const char *ns_name = describe_ns(ns_id);
ELOG("error in provider %s:%s: %s", ns_name, name, err.msg);
bool verbose_errs = true; // TODO(bfredl):
if (verbose_errs && provider_err == NULL) {
static char errbuf[IOSIZE];
snprintf(errbuf, sizeof errbuf, "%s: %s", ns_name, err.msg);
provider_err = xstrdup(errbuf);
}
}
api_free_object(ret);
return false;
}
/// Redraw a window later, with update_screen(type).
///
/// Set must_redraw only if not already set to a higher value.
@@ -501,28 +470,8 @@ int update_screen(int type)
ui_comp_set_screen_valid(true);
Providers providers;
kvi_init(providers);
for (size_t i = 0; i < kv_size(decor_providers); i++) {
DecorProvider *p = &kv_A(decor_providers, i);
if (!p->active) {
continue;
}
bool active;
if (p->redraw_start != LUA_NOREF) {
FIXED_TEMP_ARRAY(args, 2);
args.items[0] = INTEGER_OBJ(display_tick);
args.items[1] = INTEGER_OBJ(type);
active = provider_invoke(p->ns_id, "start", p->redraw_start, args, true);
} else {
active = true;
}
if (active) {
kvi_push(providers, p);
}
}
DecorProviders providers;
decor_providers_start(&providers, type, &provider_err);
// "start" callback could have changed highlights for global elements
if (win_check_ns_hl(NULL)) {
@@ -591,14 +540,7 @@ int update_screen(int type)
}
if (buf->b_mod_tick_decor < display_tick) {
for (size_t i = 0; i < kv_size(providers); i++) {
DecorProvider *p = kv_A(providers, i);
if (p && p->redraw_buf != LUA_NOREF) {
FIXED_TEMP_ARRAY(args, 1);
args.items[0] = BUFFER_OBJ(buf->handle);
provider_invoke(p->ns_id, "buf", p->redraw_buf, args, true);
}
}
decor_providers_invoke_buf(buf, &providers, &provider_err);
buf->b_mod_tick_decor = display_tick;
}
}
@@ -668,18 +610,7 @@ int update_screen(int type)
}
did_intro = true;
for (size_t i = 0; i < kv_size(providers); i++) {
DecorProvider *p = kv_A(providers, i);
if (!p->active) {
continue;
}
if (p->redraw_end != LUA_NOREF) {
FIXED_TEMP_ARRAY(args, 1);
args.items[0] = INTEGER_OBJ(display_tick);
provider_invoke(p->ns_id, "end", p->redraw_end, args, true);
}
}
decor_providers_invoke_end(&providers, &provider_err);
kvi_destroy(providers);
@@ -766,7 +697,7 @@ bool win_cursorline_standout(const win_T *wp)
* mid: from mid_start to mid_end (update inversion or changed text)
* bot: from bot_start to last row (when scrolled up)
*/
static void win_update(win_T *wp, Providers *providers)
static void win_update(win_T *wp, DecorProviders *providers)
{
buf_T *buf = wp->w_buffer;
int type;
@@ -1377,30 +1308,8 @@ static void win_update(win_T *wp, Providers *providers)
decor_redraw_reset(buf, &decor_state);
Providers line_providers;
kvi_init(line_providers);
linenr_T knownmax = ((wp->w_valid & VALID_BOTLINE)
? wp->w_botline
: (wp->w_topline + wp->w_height_inner));
for (size_t k = 0; k < kv_size(*providers); k++) {
DecorProvider *p = kv_A(*providers, k);
if (p && p->redraw_win != LUA_NOREF) {
FIXED_TEMP_ARRAY(args, 4);
args.items[0] = WINDOW_OBJ(wp->handle);
args.items[1] = BUFFER_OBJ(buf->handle);
// TODO(bfredl): we are not using this, but should be first drawn line?
args.items[2] = INTEGER_OBJ(wp->w_topline-1);
args.items[3] = INTEGER_OBJ(knownmax);
if (provider_invoke(p->ns_id, "win", p->redraw_win, args, true)) {
kvi_push(line_providers, p);
}
}
}
win_check_ns_hl(wp);
DecorProviders line_providers;
decor_providers_invoke_win(wp, providers, &line_providers, &provider_err);
for (;;) {
/* stop updating when reached the end of the window (check for _past_
@@ -2028,6 +1937,17 @@ static size_t fill_foldcolumn(char_u *p, win_T *wp, foldinfo_T foldinfo, linenr_
return MAX(char_counter + (fdc-i), (size_t)fdc);
}
static inline void provider_err_virt_text(linenr_T lnum, char *err)
{
Decoration err_decor = DECORATION_INIT;
int hl_err = syn_check_group(S_LEN("ErrorMsg"));
kv_push(err_decor.virt_text,
((VirtTextChunk){ .text = provider_err,
.hl_id = hl_err }));
err_decor.virt_text_width = mb_string2cells((char_u *)err);
decor_add_ephemeral(lnum-1, 0, lnum-1, 0, &err_decor);
}
/// Display line "lnum" of window 'wp' on the screen.
/// wp->w_virtcol needs to be valid.
///
@@ -2043,7 +1963,7 @@ static size_t fill_foldcolumn(char_u *p, win_T *wp, foldinfo_T foldinfo, linenr_
///
/// @return the number of last row the line occupies.
static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
bool number_only, foldinfo_T foldinfo, Providers *providers)
bool number_only, foldinfo_T foldinfo, DecorProviders *providers)
{
int c = 0; // init for GCC
long vcol = 0; // virtual column (for tabs)
@@ -2231,34 +2151,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
has_decor = decor_redraw_line(buf, lnum-1, &decor_state);
for (size_t k = 0; k < kv_size(*providers); k++) {
DecorProvider *p = kv_A(*providers, k);
if (p && p->redraw_line != LUA_NOREF) {
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);
if (provider_invoke(p->ns_id, "line", p->redraw_line, args, true)) {
has_decor = true;
} else {
// return 'false' or error: skip rest of this window
kv_A(*providers, k) = NULL;
}
win_check_ns_hl(wp);
}
}
providers_invoke_line(wp, providers, lnum-1, &has_decor, &provider_err);
if (provider_err) {
Decoration err_decor = DECORATION_INIT;
int hl_err = syn_check_group(S_LEN("ErrorMsg"));
kv_push(err_decor.virt_text,
((VirtTextChunk){ .text = provider_err,
.hl_id = hl_err }));
err_decor.virt_text_width = mb_string2cells((char_u *)provider_err);
decor_add_ephemeral(lnum-1, 0, lnum-1, 0, &err_decor);
provider_err = NULL;
provider_err_virt_text(lnum, provider_err);
has_decor = true;
provider_err = NULL;
}
if (has_decor) {