aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/decoration.c18
-rw-r--r--src/nvim/decoration.h3
-rw-r--r--src/nvim/drawline.c18
-rw-r--r--test/functional/ui/decorations_spec.lua103
4 files changed, 92 insertions, 50 deletions
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 265bc11661..0181cc8983 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -348,18 +348,12 @@ next_mark:
if (active && item.decor.spell != kNone) {
spell = item.decor.spell;
}
- if (item.start_row == state->row && decor_virt_pos(&item.decor)
- && item.draw_col != INT_MIN) {
- if (item.start_col <= col) {
- if (item.decor.virt_text_pos == kVTOverlay && item.draw_col == -1) {
- item.draw_col = (item.decor.virt_text_hide && hidden) ? INT_MIN : win_col;
- } else if (item.draw_col == -3) {
- item.draw_col = -1;
- }
- } else if (wp->w_p_wrap
- && (item.decor.virt_text_pos == kVTRightAlign
- || item.decor.virt_text_pos == kVTWinCol)) {
- item.draw_col = -3;
+ if (item.start_row == state->row && item.start_col <= col
+ && decor_virt_pos(&item.decor) && item.draw_col == -1) {
+ if (item.decor.virt_text_pos == kVTOverlay) {
+ item.draw_col = (item.decor.virt_text_hide && hidden) ? INT_MIN : win_col;
+ } else if (win_col < 0 && item.decor.virt_text_pos != kVTInline) {
+ item.draw_col = win_col;
}
}
if (keep) {
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index 3d16aa803e..dfd26294f3 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -84,7 +84,8 @@ typedef struct {
bool virt_text_owned;
/// 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 a later screen line.
+ /// When -2, the virtual text should be drawn at the start of the screen line.
+ /// When -3, the virtual text should be drawn on the next screen line.
/// When INT_MIN, the virtual text should no longer be drawn.
int draw_col;
uint64_t ns_id;
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index d0e31b41c3..b22699231d 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -282,6 +282,10 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int
} else if (item->decor.virt_text_pos == kVTWinCol) {
item->draw_col = MAX(item->decor.col + col_off, 0);
}
+ } else if (item->draw_col == -2) {
+ item->draw_col = col_off;
+ } else if (item->draw_col == -3) {
+ item->draw_col = item->decor.virt_text_pos == kVTOverlay ? -2 : -1;
}
if (item->draw_col < 0) {
continue;
@@ -3080,10 +3084,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
if (has_decor && (wp->w_p_rl ? (wlv.col < 0) : (wlv.col >= grid->cols))) {
// At the end of screen line: might need to peek for decorations just after
- // this position. Without wrapping, we might need to display win_col overlays
- // from the entire text line.
- colnr_T nextpos = wp->w_p_wrap ? (colnr_T)(ptr - line) : (colnr_T)strlen(line);
- decor_redraw_col(wp, nextpos, wlv.off, true, &decor_state);
+ // this position.
+ if (wp->w_p_wrap) {
+ // FIXME: virt_text_hide doesn't work for overlay virt_text at the next char
+ // as it's not easy to check if the next char is inside Visual selection.
+ decor_redraw_col(wp, (int)(ptr - line), -3, false, &decor_state);
+ } else {
+ // Without wrapping, we might need to display right_align and win_col
+ // virt_text for the entire text line.
+ decor_redraw_col(wp, MAXCOL, -1, true, &decor_state);
+ }
}
// At end of screen line and there is more to come: Display the line
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 4262f7ce77..8a94eaef1b 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -859,6 +859,43 @@ describe('extmark decorations', function()
]]}
end)
+ it('overlay virtual text works with wrapped lines #25158', function()
+ screen:try_resize(50, 6)
+ insert(('ab'):rep(100))
+ for i = 0, 9 do
+ meths.buf_set_extmark(0, ns, 0, 42 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay'})
+ meths.buf_set_extmark(0, ns, 0, 91 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide = true})
+ end
+ screen:expect{grid=[[
+ ababababababababababababababababababababab{4:01234567}|
+ {4:89}abababababababababababababababababababa{4:012345678}|
+ {4:9}babababababababababababababababababababababababab|
+ ababababababababababababababababababababababababa^b|
+ {1:~ }|
+ |
+ ]]}
+
+ command('set number')
+ screen:expect{grid=[[
+ {2: 1 }ababababababababababababababababababababab{4:0123}|
+ {2: }{4:456789}abababababababababababababababababababa{4:0}|
+ {2: }{4:123456789}babababababababababababababababababab|
+ {2: }ababababababababababababababababababababababab|
+ {2: }abababababababa^b |
+ |
+ ]]}
+
+ command('set cpoptions+=n')
+ screen:expect{grid=[[
+ {2: 1 }ababababababababababababababababababababab{4:0123}|
+ {4:456789}abababababababababababababababababababa{4:01234}|
+ {4:56789}babababababababababababababababababababababab|
+ ababababababababababababababababababababababababab|
+ aba^b |
+ |
+ ]]}
+ end)
+
it('virt_text_hide hides overlay virtual text when extmark is off-screen', function()
screen:try_resize(50, 3)
command('set nowrap')
@@ -1028,12 +1065,12 @@ describe('extmark decorations', function()
it('can have virtual text of right_align and fixed win_col position', function()
insert(example_text)
feed 'gg'
- meths.buf_set_extmark(0, ns, 1, 0, { virt_text={{'Very', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
+ meths.buf_set_extmark(0, ns, 1, 0, { virt_text={{'Very', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
meths.buf_set_extmark(0, ns, 1, 0, { virt_text={{'VERY', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 2, 10, { virt_text={{'Much', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
+ meths.buf_set_extmark(0, ns, 2, 10, { virt_text={{'Much', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
meths.buf_set_extmark(0, ns, 2, 10, { virt_text={{'MUCH', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 3, 15, { virt_text={{'Error', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 3, 15, { virt_text={{'ERROR', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
+ meths.buf_set_extmark(0, ns, 3, 14, { virt_text={{'Error', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
+ meths.buf_set_extmark(0, ns, 3, 14, { virt_text={{'ERROR', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
meths.buf_set_extmark(0, ns, 7, 21, { virt_text={{'-', 'NonText'}}, virt_text_win_col=4, hl_mode='blend'})
meths.buf_set_extmark(0, ns, 7, 21, { virt_text={{'-', 'NonText'}}, virt_text_pos='right_align', hl_mode='blend'})
-- empty virt_text should not change anything
@@ -1191,40 +1228,40 @@ describe('extmark decorations', function()
|
]]}
- command 'set cpoptions-=n nonumber nowrap'
+ command 'set cpoptions-=n nowrap'
screen:expect{grid=[[
- for _,item in ipairs(items) do |
- local text, hl_id_cell, cou{4:Very} unpack(ite{4:VERY}|
- if |
- hl_id_cell ~= nil then {4:Much} {4:MUCH}|
- --^ -- -- -- -- -- -- --{4:Error}- -- -- h{4:ERROR}|
- end |
- for _ = 1, (count or 1) do |
- local cell = line[colpos] |
- {1:-} cell.text = text {1:-}|
- cell.hl_id = hl_id |
- colpos = colpos+1 |
- end |
- end |
+ {2: 1 }for _,item in ipairs(items) do |
+ {2: 2 } local text, hl_id_cell, cou{4:Very} unpack{4:VERY}|
+ {2: 3 } if |
+ {2: 4 }hl_id_cell ~= nil then {4:Much} {4:MUCH}|
+ {2: 5 } --^ -- -- -- -- -- -- --{4:Error}- -- {4:ERROR}|
+ {2: 6 } end |
+ {2: 7 } for _ = 1, (count or 1) do |
+ {2: 8 } local cell = line[colpos] |
+ {2: 9 } {1:-} cell.text = text {1:-}|
+ {2: 10 } cell.hl_id = hl_id |
+ {2: 11 } colpos = colpos+1 |
+ {2: 12 } end |
+ {2: 13 }end |
{1:~ }|
|
]]}
- feed '8zl'
+ feed '12zl'
screen:expect{grid=[[
- em in ipairs(items) do |
- l text, hl_id_cell, count = unp{4:Very}item) {4:VERY}|
- |
- ll ~= nil then {4:Much} {4:MUCH}|
- --^ -- -- -- -- -- -- -- -- -- -{4:Error}hl_id = h{4:ERROR}|
- |
- _ = 1, (count or 1) do |
- local cell = line[colpos] |
- cell{1:-}text = text {1:-}|
- cell.hl_id = hl_id |
- colpos = colpos+1 |
- |
- |
+ {2: 1 }n ipairs(items) do |
+ {2: 2 }xt, hl_id_cell, count = unpack({4:Very}) {4:VERY}|
+ {2: 3 } |
+ {2: 4 }= nil then {4:Much} {4:MUCH}|
+ {2: 5 }^- -- -- -- -- -- -- -- -- -- --{4:Error}d = h{4:ERROR}|
+ {2: 6 } |
+ {2: 7 }1, (count or 1) do |
+ {2: 8 }l cell = line[colpos] |
+ {2: 9 }.tex{1:-} = text {1:-}|
+ {2: 10 }.hl_id = hl_id |
+ {2: 11 }os = colpos+1 |
+ {2: 12 } |
+ {2: 13 } |
{1:~ }|
|
]]}
@@ -1243,7 +1280,7 @@ describe('extmark decorations', function()
-- 1. With 'wrap' it is never shown.
-- 2. With 'nowrap' it is shown only if the extmark is hidden before leftcol.
meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'AA', 'Underlined'}}, hl_mode = 'combine', virt_text_pos = 'overlay' })
- meths.buf_set_extmark(0, ns, 0, 1, { virt_text = {{'BB', 'Underlined'}}, hl_mode = 'combine', virt_text_win_col = 10 })
+ meths.buf_set_extmark(0, ns, 0, 5, { virt_text = {{'BB', 'Underlined'}}, hl_mode = 'combine', virt_text_win_col = 10 })
meths.buf_set_extmark(0, ns, 0, 2, { virt_text = {{'CC', 'Underlined'}}, hl_mode = 'combine', virt_text_pos = 'right_align' })
screen:expect{grid=[[
{29:AA}{33:- 2 lin}{29:BB}{33:: 11111·····························}{29:CC}|