diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-02-20 19:53:49 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-20 19:53:49 +0800 |
commit | a0790558c3097f2813c56e404af30c3e2d8b8983 (patch) | |
tree | e68f996439184015a2de06b6f72ff2fbe95fe842 /src | |
parent | 69bdcc68234e7f228b667f95b0e65d4ebe8d1f80 (diff) | |
download | rneovim-a0790558c3097f2813c56e404af30c3e2d8b8983.tar.gz rneovim-a0790558c3097f2813c56e404af30c3e2d8b8983.tar.bz2 rneovim-a0790558c3097f2813c56e404af30c3e2d8b8983.zip |
fix(extmarks): priority order of inline and non-inline virt_text (#27532)
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/extmark.c | 7 | ||||
-rw-r--r-- | src/nvim/decoration.c | 2 | ||||
-rw-r--r-- | src/nvim/decoration.h | 8 | ||||
-rw-r--r-- | src/nvim/drawline.c | 32 |
4 files changed, 31 insertions, 18 deletions
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index f6f7d332ec..0b5f3471fb 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -452,9 +452,10 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// hidden marks, an "invalid" key is added to the "details" /// array of |nvim_buf_get_extmarks()| and family. If /// "undo_restore" is false, the extmark is deleted instead. -/// - priority: a priority value for the highlight group or sign -/// attribute. For example treesitter highlighting uses a -/// value of 100. +/// - priority: a priority value for the highlight group, sign +/// attribute or virtual text. For virtual text, item with +/// highest priority is drawn last. For example treesitter +/// highlighting uses a value of 100. /// - strict: boolean that indicates extmark should not be placed /// if the line or column value is past the end of the /// buffer or end of the line respectively. Defaults to true. diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 792204bdbc..aaa435fb45 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -541,7 +541,7 @@ void decor_range_add_sh(DecorState *state, int start_row, int start_col, int end } /// Initialize the draw_col of a newly-added virtual text item. -static void decor_init_draw_col(int win_col, bool hidden, DecorRange *item) +void decor_init_draw_col(int win_col, bool hidden, DecorRange *item) { DecorVirtText *vt = item->kind == kDecorKindVirtText ? item->data.vt : NULL; VirtTextPos pos = decor_virt_pos_kind(item); diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h index e70c588806..a63cc7afc0 100644 --- a/src/nvim/decoration.h +++ b/src/nvim/decoration.h @@ -52,10 +52,10 @@ typedef struct { ///< Reflects the order of patterns/captures in the query file. DecorRangeKind kind; /// Screen column to draw the virtual text. - /// When -1, the virtual text may be drawn after deciding where. - /// When -3, the virtual text should be drawn on the next screen line. - /// When -10, the virtual text has just been added. - /// When INT_MIN, the virtual text should no longer be drawn. + /// When -1, it should be drawn on the current screen line after deciding where. + /// When -3, it may be drawn at a position yet to be assigned. + /// When -10, it has just been added. + /// When INT_MIN, it should no longer be drawn. int draw_col; } DecorRange; diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index c275fcd7d4..d7c8110d6d 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -769,7 +769,7 @@ static bool has_more_inline_virt(winlinevars_T *wlv, ptrdiff_t v) return false; } -static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t v) +static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t v, bool selected) { while (wlv->n_extra == 0) { if (wlv->virt_inline_i >= kv_size(wlv->virt_inline)) { @@ -779,6 +779,11 @@ static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t DecorState *state = &decor_state; for (size_t i = 0; i < kv_size(state->active); i++) { DecorRange *item = &kv_A(state->active, i); + if (item->draw_col == -3) { + // No more inline virtual text before this non-inline virtual text item, + // so its position can be decided now. + decor_init_draw_col(wlv->off, selected, item); + } if (item->start_row != state->row || item->kind != kDecorKindVirtText || item->data.vt->pos != kVPosInline @@ -1493,6 +1498,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s extra_check = true; } + const bool may_have_inline_virt + = !has_foldtext && buf_meta_total(wp->w_buffer, kMTMetaInline) > 0; int virt_line_index; int virt_line_offset = -1; // Repeat for the whole displayed line. @@ -1656,17 +1663,21 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s bool selected = (area_active || (area_highlighting && noinvcur && wlv.vcol == wp->w_virtcol)); + // When there may be inline virtual text, position of non-inline virtual text + // can only be decided after drawing inline virtual text with lower priority. if (decor_need_recheck) { - decor_recheck_draw_col(wlv.off, selected, &decor_state); + if (!may_have_inline_virt) { + decor_recheck_draw_col(wlv.off, selected, &decor_state); + } decor_need_recheck = false; } if (wlv.filler_todo <= 0) { - extmark_attr = decor_redraw_col(wp, (colnr_T)(ptr - line), wlv.off, selected, - &decor_state); + extmark_attr = decor_redraw_col(wp, (colnr_T)(ptr - line), + may_have_inline_virt ? -3 : wlv.off, + selected, &decor_state); } - - if (!has_foldtext && buf_meta_total(wp->w_buffer, kMTMetaInline) > 0) { - handle_inline_virtual_text(wp, &wlv, ptr - line); + if (may_have_inline_virt) { + handle_inline_virtual_text(wp, &wlv, ptr - line, selected); if (wlv.n_extra > 0 && wlv.virt_inline_hl_mode <= kHlModeReplace) { // restore search_attr and area_attr when n_extra is down to zero // TODO(bfredl): this is ugly as fuck. look if we can do this some other way. @@ -2665,12 +2676,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s && !has_foldtext) { if (has_decor && *ptr == NUL && lcs_eol == 0 && lcs_eol_todo) { // Tricky: there might be a virtual text just _after_ the last char - decor_redraw_col(wp, (colnr_T)(ptr - line), wlv.off, false, &decor_state); + decor_redraw_col(wp, (colnr_T)(ptr - line), -1, false, &decor_state); } if (*ptr != NUL || (lcs_eol > 0 && lcs_eol_todo) || (wlv.n_extra > 0 && (wlv.sc_extra != NUL || *wlv.p_extra != NUL)) - || has_more_inline_virt(&wlv, ptr - line)) { + || (may_have_inline_virt && has_more_inline_virt(&wlv, ptr - line))) { mb_schar = wp->w_p_lcs_chars.ext; wlv.char_attr = win_hl_attr(wp, HLF_AT); mb_c = schar_get_first_codepoint(mb_schar); @@ -2819,6 +2830,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s } else if (!is_wrapped) { // Without wrapping, we might need to display right_align and win_col // virt_text for the entire text line. + decor_recheck_draw_col(-1, true, &decor_state); decor_redraw_col(wp, MAXCOL, -1, true, &decor_state); } } @@ -2831,7 +2843,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s || (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL && wlv.p_extra != at_end_str) || (wlv.n_extra != 0 && (wlv.sc_extra != NUL || *wlv.p_extra != NUL)) - || has_more_inline_virt(&wlv, ptr - line))) { + || (may_have_inline_virt && has_more_inline_virt(&wlv, ptr - line)))) { const bool wrap = is_wrapped // Wrapping enabled (not a folded line). && wlv.filler_todo <= 0 // Not drawing diff filler lines. && lcs_eol_todo // Haven't printed the lcs_eol character. |