aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-07-03 22:57:45 +0800
committerGitHub <noreply@github.com>2023-07-03 22:57:45 +0800
commit35c3275b4896a65d67caf2a4355d7516b6ddec29 (patch)
tree8bb3cd8103bf0146af1cb83a2f5c98db3a83977c
parent6da110d617dba6378f770c5d66d523df92f2d355 (diff)
downloadrneovim-35c3275b4896a65d67caf2a4355d7516b6ddec29.tar.gz
rneovim-35c3275b4896a65d67caf2a4355d7516b6ddec29.tar.bz2
rneovim-35c3275b4896a65d67caf2a4355d7516b6ddec29.zip
fix(plines): handle inline virtual text after last char (#24241)
Also remove dead code in win_lbr_chartabsize().
-rw-r--r--src/nvim/plines.c11
-rw-r--r--src/nvim/plines.h14
-rw-r--r--test/functional/ui/decorations_spec.lua36
3 files changed, 47 insertions, 14 deletions
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index 523b85fd32..eb1ae540a4 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -287,7 +287,7 @@ unsigned win_linetabsize(win_T *wp, linenr_T lnum, char *line, colnr_T len)
/// Return the number of cells line "lnum" of window "wp" will take on the
/// screen, taking into account the size of a tab and text properties.
-unsigned linetabsize(win_T *wp, linenr_T lnum)
+unsigned linetabsize(win_T *wp, linenr_T lnum)
{
return win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum, false), (colnr_T)MAXCOL);
}
@@ -298,9 +298,8 @@ void win_linetabsize_cts(chartabsize_T *cts, colnr_T len)
MB_PTR_ADV(cts->cts_ptr)) {
cts->cts_vcol += win_lbr_chartabsize(cts, NULL);
}
- // check for a virtual text on an empty line
- if (cts->cts_has_virt_text && *cts->cts_ptr == NUL
- && cts->cts_ptr == cts->cts_line) {
+ // check for a virtual text after the end of the line
+ if (len == MAXCOL && cts->cts_has_virt_text && *cts->cts_ptr == NUL) {
(void)win_lbr_chartabsize(cts, NULL);
cts->cts_vcol += cts->cts_cur_text_width_left + cts->cts_cur_text_width_right;
}
@@ -406,15 +405,15 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
// First get normal size, without 'linebreak' or virtual text
int size = win_chartabsize(wp, s, vcol);
+
if (cts->cts_has_virt_text) {
int tab_size = size;
- int charlen = *s == NUL ? 1 : utf_ptr2len(s);
int col = (int)(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 && mark.pos.col < col + charlen) {
+ } else if (mark.pos.col == col) {
if (!mt_end(mark)) {
Decoration decor = get_decor(mark);
if (decor.virt_text_pos == kVTInline) {
diff --git a/src/nvim/plines.h b/src/nvim/plines.h
index 2ce7133705..d89dc7b6f6 100644
--- a/src/nvim/plines.h
+++ b/src/nvim/plines.h
@@ -6,19 +6,19 @@
#include "nvim/buffer_defs.h"
#include "nvim/vim.h"
-// Argument for lbr_chartabsize().
+/// Argument for lbr_chartabsize().
typedef struct {
win_T *cts_win;
- char *cts_line; // start of the line
- char *cts_ptr; // current position in line
+ 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_left; // width of virtual text left of cursor
- int cts_cur_text_width_right; // width of virtual text right of cursor
+ bool cts_has_virt_text; ///< true if if there is inline virtual text
+ int cts_cur_text_width_left; ///< width of virtual text left of cursor
+ int cts_cur_text_width_right; ///< width of virtual text right of cursor
MarkTreeIter cts_iter[1];
- int cts_vcol; // virtual column at current position
+ int cts_vcol; ///< virtual column at current position
} chartabsize_T;
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 4c04bad3a0..8070ac550d 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -1835,7 +1835,7 @@ describe('decorations: inline virtual text', function()
]]}
end)
- it('text is drawn correctly when inserting a wrapping virtual text on an empty line', function()
+ it('text is drawn correctly with a wrapping virtual text', function()
feed('o<esc>')
insert([[aaaaaaa
@@ -1899,6 +1899,40 @@ bbbbbbb]])
{1:~ }|
|
]]}
+
+ feed('ggic')
+ screen:expect { grid = [[
+ c{10:^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ {10:XX} |
+ aaaaaaa |
+ {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ bbbbbbb |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {8:-- INSERT --} |
+ ]]}
+ end)
+
+ it('regexp \\%V does not count trailing virtual text', function()
+ screen:try_resize(50, 4)
+ meths.buf_set_lines(0, 0, -1, true, {'foofoo', '', 'foofoo'})
+ meths.buf_set_extmark(0, ns, 1, 0, { virt_text = {{'barbarbar', 'Special'}}, virt_text_pos = 'inline' })
+ feed([[<C-V>G5l<Esc>/foo\n\%V<CR>]])
+ screen:expect{grid=[[
+ foo{12:^foo } |
+ {10:barbarbar} |
+ foofoo |
+ {16:search hit BOTTOM, continuing at TOP} |
+ ]]}
+ feed([[jIbaz<Esc>/foo\nbaz\%V<CR>]])
+ screen:expect{grid=[[
+ foo{12:^foo } |
+ {12:baz}{10:barbarbar} |
+ foofoo |
+ {16:search hit BOTTOM, continuing at TOP} |
+ ]]}
end)
it('cursor position is correct with virtual text attached to hard tabs', function()