aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/extmark.c7
-rw-r--r--src/nvim/decoration.c2
-rw-r--r--src/nvim/decoration.h8
-rw-r--r--src/nvim/drawline.c32
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.