diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/extmark.c | 1 | ||||
-rw-r--r-- | src/nvim/api/keysets_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 23 | ||||
-rw-r--r-- | src/nvim/decoration.c | 29 | ||||
-rw-r--r-- | src/nvim/decoration_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/decoration_provider.c | 25 |
6 files changed, 61 insertions, 19 deletions
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index e4bb9d6953..a6aadc2430 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -1049,6 +1049,7 @@ void nvim_set_decoration_provider(Integer ns_id, Dict(set_decoration_provider) * { "on_end", &opts->on_end, &p->redraw_end }, { "_on_hl_def", &opts->_on_hl_def, &p->hl_def }, { "_on_spell_nav", &opts->_on_spell_nav, &p->spell_nav }, + { "_on_conceal_line", &opts->_on_conceal_line, &p->conceal_line }, { NULL, NULL, NULL }, }; diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h index b9bd8ea286..1ab1fe340f 100644 --- a/src/nvim/api/keysets_defs.h +++ b/src/nvim/api/keysets_defs.h @@ -21,6 +21,7 @@ typedef struct { LuaRefOf(("end" _, Integer tick)) on_end; LuaRefOf(("hl_def" _)) _on_hl_def; LuaRefOf(("spell_nav" _)) _on_spell_nav; + LuaRefOf(("conceal_line" _)) _on_conceal_line; } Dict(set_decoration_provider); typedef struct { diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 7f0768ec60..dd98a1eb9f 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1313,23 +1313,18 @@ struct window_S { linenr_T w_statuscol_line_count; // line count when 'statuscolumn' width was computed. int w_nrwidth_width; // nr of chars to print line count. - qf_info_T *w_llist; // Location list for this window + qf_info_T *w_llist; // Location list for this window // Location list reference used in the location list window. // In a non-location list window, w_llist_ref is NULL. qf_info_T *w_llist_ref; - // Status line click definitions - StlClickDefinition *w_status_click_defs; - // Size of the w_status_click_defs array - size_t w_status_click_defs_size; + StlClickDefinition *w_status_click_defs; // Status line click definitions + size_t w_status_click_defs_size; // Size of the w_status_click_defs array + StlClickDefinition *w_winbar_click_defs; // Window bar click definitions + size_t w_winbar_click_defs_size; // Size of the w_winbar_click_defs array + StlClickDefinition *w_statuscol_click_defs; // Status column click definitions + size_t w_statuscol_click_defs_size; // Size of the w_statuscol_click_defs array - // Window bar click definitions - StlClickDefinition *w_winbar_click_defs; - // Size of the w_winbar_click_defs array - size_t w_winbar_click_defs_size; - - // Status column click definitions - StlClickDefinition *w_statuscol_click_defs; - // Size of the w_statuscol_click_defs array - size_t w_statuscol_click_defs_size; + buf_T *w_conceal_line_buf; // buffer in win when first invoked + bool w_conceal_line_provider; // whether conceal_line provider is active }; diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index f13e91ee0f..326589c36e 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -12,6 +12,7 @@ #include "nvim/buffer_defs.h" #include "nvim/change.h" #include "nvim/decoration.h" +#include "nvim/decoration_provider.h" #include "nvim/drawscreen.h" #include "nvim/extmark.h" #include "nvim/fold.h" @@ -843,7 +844,8 @@ next_mark: static const uint32_t conceal_filter[kMTMetaCount] = {[kMTMetaConcealLines] = kMTFilterSelect }; /// Called by draw, move and plines code to determine whether a line is concealed. -/// Scans the marktree for conceal_line marks on "row", if necessary. +/// Scans the marktree for conceal_line marks on "row" and invokes any +/// _on_conceal_line decoration provider callbacks, if necessary. /// /// @param check_cursor If true, avoid an early return for an unconcealed cursorline. /// Depending on the callsite, we still want to know whether the @@ -852,12 +854,25 @@ static const uint32_t conceal_filter[kMTMetaCount] = {[kMTMetaConcealLines] = kM /// @return whether "row" is concealed bool decor_conceal_line(win_T *wp, int row, bool check_cursor) { - if (wp->w_p_cole < 2 || !buf_meta_total(wp->w_buffer, kMTMetaConcealLines) + if (wp->w_p_cole < 2 || (!check_cursor && wp == curwin && row + 1 == wp->w_cursor.lnum && !conceal_cursor_line(wp))) { return false; } + // No need to scan the marktree if there are no conceal_line marks. + if (!buf_meta_total(wp->w_buffer, kMTMetaConcealLines)) { + // Only invoke callback when a decor provider has indicated that it may + // conceal lines in a certain buffer (the callback's return value). + if (wp->w_conceal_line_buf != wp->w_buffer) { + wp->w_conceal_line_provider = false; + } + if (wp->w_conceal_line_provider || wp->w_conceal_line_buf != wp->w_buffer) { + goto invoke; + } + return false; + } + // Scan the marktree for any conceal_line marks on this row. MTPair pair; MarkTreeIter itr[1]; @@ -880,14 +895,20 @@ bool decor_conceal_line(win_T *wp, int row, bool check_cursor) } marktree_itr_next_filter(wp->w_buffer->b_marktree, itr, row + 1, 0, conceal_filter); } - return false; + +invoke:; + // Interpret increase in keys to mean this row is concealed by a callback. + size_t keys = wp->w_buffer->b_marktree->n_keys; + decor_providers_invoke_conceal_line(wp, row); + return wp->w_buffer->b_marktree->n_keys > keys; } /// @return whether a window may have folded or concealed lines bool win_lines_concealed(win_T *wp) { return hasAnyFolding(wp) - || (wp->w_p_cole >= 2 && buf_meta_total(wp->w_buffer, kMTMetaConcealLines)); + || (wp->w_p_cole >= 2 + && (wp->w_conceal_line_provider || buf_meta_total(wp->w_buffer, kMTMetaConcealLines))); } int sign_item_cmp(const void *p1, const void *p2) diff --git a/src/nvim/decoration_defs.h b/src/nvim/decoration_defs.h index f84952a0e7..06013e1b0a 100644 --- a/src/nvim/decoration_defs.h +++ b/src/nvim/decoration_defs.h @@ -152,6 +152,7 @@ typedef struct { LuaRef redraw_end; LuaRef hl_def; LuaRef spell_nav; + LuaRef conceal_line; int hl_valid; bool hl_cached; diff --git a/src/nvim/decoration_provider.c b/src/nvim/decoration_provider.c index 7c99fbf889..f5ff8be416 100644 --- a/src/nvim/decoration_provider.c +++ b/src/nvim/decoration_provider.c @@ -30,7 +30,7 @@ static kvec_t(DecorProvider) decor_providers = KV_INITIAL_VALUE; #define DECORATION_PROVIDER_INIT(ns_id) (DecorProvider) \ { ns_id, kDecorProviderDisabled, LUA_NOREF, LUA_NOREF, \ LUA_NOREF, LUA_NOREF, LUA_NOREF, \ - LUA_NOREF, -1, false, false, 0 } + LUA_NOREF, LUA_NOREF, -1, false, false, 0 } static void decor_provider_error(DecorProvider *provider, const char *name, const char *msg) { @@ -92,6 +92,23 @@ void decor_providers_invoke_spell(win_T *wp, int start_row, int start_col, int e } } +void decor_providers_invoke_conceal_line(win_T *wp, int row) +{ + wp->w_conceal_line_buf = wp->w_buffer; + for (size_t i = 0; i < kv_size(decor_providers); i++) { + DecorProvider *p = &kv_A(decor_providers, i); + if (p->state != kDecorProviderDisabled && p->conceal_line != LUA_NOREF) { + MAXSIZE_TEMP_ARRAY(args, 4); + ADD_C(args, INTEGER_OBJ(wp->handle)); + ADD_C(args, INTEGER_OBJ(wp->w_buffer->handle)); + ADD_C(args, INTEGER_OBJ(row)); + if (decor_provider_invoke((int)i, "conceal_line", p->conceal_line, args, false)) { + wp->w_conceal_line_provider = true; + } + } + } +} + /// For each provider invoke the 'start' callback /// /// @param[out] providers Decoration providers @@ -262,6 +279,12 @@ void decor_provider_clear(DecorProvider *p) NLUA_CLEAR_REF(p->redraw_line); NLUA_CLEAR_REF(p->redraw_end); NLUA_CLEAR_REF(p->spell_nav); + if (p->conceal_line != LUA_NOREF) { + NLUA_CLEAR_REF(p->conceal_line); + FOR_ALL_TAB_WINDOWS(tp, wp) { + wp->w_conceal_line_buf = NULL; // invoke at least once + } + } p->state = kDecorProviderDisabled; } |