Created
November 2, 2022 19:00
-
-
Save qRoC/31ffa9b9431e63dd4cddd82b82d5813d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 26641de736600618efbb99ee31c4ffec522433d2 Mon Sep 17 00:00:00 2001 | |
From: Andrii Savytskyi <[email protected]> | |
Date: Wed, 2 Nov 2022 20:58:03 +0200 | |
Subject: [PATCH] 20130 | |
--- | |
src/nvim/api/extmark.c | 4 ++++ | |
src/nvim/decoration.h | 3 ++- | |
src/nvim/drawline.c | 48 +++++++++++++++++++++++++++++++++++++----- | |
src/nvim/plines.c | 27 ++++++++++++++++++++++-- | |
src/nvim/plines.h | 2 ++ | |
5 files changed, 76 insertions(+), 8 deletions(-) | |
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c | |
index 3b1b47062..f5806c043 100644 | |
--- a/src/nvim/api/extmark.c | |
+++ b/src/nvim/api/extmark.c | |
@@ -399,6 +399,8 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e | |
/// - "overlay": display over the specified column, without | |
/// shifting the underlying text. | |
/// - "right_align": display right aligned in the window. | |
+/// - "inline": display at the specified column, and | |
+/// shift the buffer text to the right as needed | |
/// - virt_text_win_col : position the virtual text at a fixed | |
/// window column (starting from the first | |
/// text column) | |
@@ -613,6 +615,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer | |
decor.virt_text_pos = kVTOverlay; | |
} else if (strequal("right_align", str.data)) { | |
decor.virt_text_pos = kVTRightAlign; | |
+ } else if (strequal("inline", str.data)) { | |
+ decor.virt_text_pos = kVTInline; | |
} else { | |
api_set_error(err, kErrorTypeValidation, "virt_text_pos: invalid value"); | |
goto error; | |
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h | |
index bdbfd72a8..2dd7912a3 100644 | |
--- a/src/nvim/decoration.h | |
+++ b/src/nvim/decoration.h | |
@@ -15,9 +15,10 @@ typedef enum { | |
kVTOverlay, | |
kVTWinCol, | |
kVTRightAlign, | |
+ kVTInline, | |
} VirtTextPos; | |
-EXTERN const char *const virt_text_pos_str[] INIT(= { "eol", "overlay", "win_col", "right_align" }); | |
+EXTERN const char *const virt_text_pos_str[] INIT(= { "eol", "overlay", "win_col", "right_align", "inline" }); | |
typedef enum { | |
kHlModeUnknown, | |
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c | |
index 08b6fd89a..c8d52c105 100644 | |
--- a/src/nvim/drawline.c | |
+++ b/src/nvim/drawline.c | |
@@ -590,6 +590,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, | |
int left_curline_col = 0; | |
int right_curline_col = 0; | |
+ VirtText virt_inline = KV_INITIAL_VALUE; | |
+ size_t virt_inline_i = 0; | |
+ | |
// draw_state: items that are drawn in sequence: | |
#define WL_START 0 // nothing done yet | |
#define WL_CMDLINE (WL_START + 1) // cmdline window column | |
@@ -1384,7 +1387,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, | |
n_extra = 0; | |
} | |
- if (draw_state == WL_LINE && (area_highlighting || has_spell)) { | |
+ int extmark_attr = 0; | |
+ if (draw_state == WL_LINE && (area_highlighting || has_spell || extra_check)) { | |
// handle Visual or match highlighting in this line | |
if (vcol == fromcol | |
|| (vcol + 1 == fromcol && n_extra == 0 | |
@@ -1439,6 +1443,44 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, | |
} | |
} | |
+ if (has_decor && v >= 0) { | |
+ bool selected = (area_active || (area_highlighting && noinvcur | |
+ && (colnr_T)vcol == wp->w_virtcol)); | |
+ extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v, off, | |
+ selected, &decor_state); | |
+ | |
+ // we could already be inside an existing virt_line with multiple chunks | |
+ if (!(virt_inline_i < kv_size(virt_inline))) { | |
+ DecorState *state = &decor_state; | |
+ for (size_t i = 0; i < kv_size(state->active); i++) { | |
+ DecorRange *item = &kv_A(state->active, i); | |
+ if (!(item->start_row == state->row | |
+ && kv_size(item->decor.virt_text) | |
+ && item->decor.virt_text_pos == kVTInline)) { | |
+ continue; | |
+ } | |
+ if (item->win_col >= -1 && item->start_col <= v) { | |
+ virt_inline = item->decor.virt_text; | |
+ virt_inline_i = 0; | |
+ item->win_col = -2; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
+ if (n_extra <= 0 && virt_inline_i < kv_size(virt_inline)) { | |
+ VirtTextChunk vtc = kv_A(virt_inline, virt_inline_i); | |
+ p_extra = (char_u *)vtc.text; | |
+ n_extra = (int)STRLEN(p_extra); | |
+ c_extra = NUL; | |
+ c_final = NUL; | |
+ extra_attr = vtc.hl_id ? syn_id2attr(vtc.hl_id) : 0; | |
+ n_attr = n_extra; | |
+ extmark_attr = 0; | |
+ virt_inline_i++; | |
+ } | |
+ } | |
+ | |
// Decide which of the highlight attributes to use. | |
attr_pri = true; | |
@@ -1702,10 +1744,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, | |
} | |
if (has_decor && v > 0) { | |
- bool selected = (area_active || (area_highlighting && noinvcur | |
- && (colnr_T)vcol == wp->w_virtcol)); | |
- int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, off, | |
- selected, &decor_state); | |
if (extmark_attr != 0) { | |
if (!attr_pri) { | |
char_attr = hl_combine_attr(char_attr, extmark_attr); | |
diff --git a/src/nvim/plines.c b/src/nvim/plines.c | |
index 42218ac84..0c8b69395 100644 | |
--- a/src/nvim/plines.c | |
+++ b/src/nvim/plines.c | |
@@ -302,8 +302,16 @@ void init_chartabsize_arg(chartabsize_T *cts, win_T *wp, linenr_T lnum FUNC_ATTR | |
cts->cts_line = line; | |
cts->cts_ptr = ptr; | |
cts->cts_cur_text_width = 0; | |
- // TODO(bfredl): actually lookup inline virtual text here | |
cts->cts_has_virt_text = false; | |
+ cts->cts_row = lnum - 1; | |
+ | |
+ if (cts->cts_row >= 0) { | |
+ marktree_itr_get(wp->w_buffer->b_marktree, cts->cts_row, 0, cts->cts_iter); | |
+ mtkey_t mark = marktree_itr_current(cts->cts_iter); | |
+ if (mark.pos.row == lnum - 1) { | |
+ cts->cts_has_virt_text = true; | |
+ } | |
+ } | |
} | |
/// Free any allocated item in "cts". | |
@@ -385,7 +393,22 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp) | |
// First get normal size, without 'linebreak' or virtual text | |
int size = win_chartabsize(wp, (char *)s, vcol); | |
if (cts->cts_has_virt_text) { | |
- // TODO(bfredl): inline virtual text | |
+ int col = (int)((char *)s - line); | |
+ while (true) { | |
+ mtkey_t mark = marktree_itr_current(cts->cts_iter); | |
+ if (mark.pos.row != cts->cts_row || mark.pos.col > col) { | |
+ break; | |
+ } else if (mark.pos.col == col) { // TODO: or maybe unconditionally, what if byte-misaligned? | |
+ if (!mt_end(mark)) { | |
+ Decoration decor = get_decor(mark); | |
+ if (decor.virt_text_pos == kVTInline) { | |
+ cts->cts_cur_text_width = decor.virt_text_width; | |
+ size += cts->cts_cur_text_width; | |
+ } | |
+ } | |
+ } | |
+ marktree_itr_next(wp->w_buffer->b_marktree, cts->cts_iter); | |
+ } | |
} | |
int c = *s; | |
diff --git a/src/nvim/plines.h b/src/nvim/plines.h | |
index f463d82f1..05f91fc07 100644 | |
--- a/src/nvim/plines.h | |
+++ b/src/nvim/plines.h | |
@@ -8,9 +8,11 @@ typedef struct { | |
win_T *cts_win; | |
char *cts_line; // start of the line | |
char *cts_ptr; // current position in line | |
+ int cts_row; | |
bool cts_has_virt_text; // true if if a property inserts text | |
int cts_cur_text_width; // width of current inserted text | |
+ MarkTreeIter cts_iter[1]; | |
// TODO(bfredl): iterator in to the marktree for scanning virt text | |
int cts_vcol; // virtual column at current position | |
-- | |
2.38.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
brew edit nvim