screen: fix glitches with nvim_buf_set_virtual_text

- virtual text disappeared when 'cursorline' was set
- virtual text was shifted when emtpy line was visually selected.
This commit is contained in:
Björn Linse
2018-10-23 10:10:23 +02:00
parent c03a0f5fc8
commit 662abd8451
2 changed files with 244 additions and 187 deletions

View File

@@ -2199,7 +2199,6 @@ win_line (
// of the matches // of the matches
int prev_c = 0; // previous Arabic character int prev_c = 0; // previous Arabic character
int prev_c1 = 0; // first composing char for prev_c int prev_c1 = 0; // first composing char for prev_c
int did_line_attr = 0;
bool search_attr_from_match = false; // if search_attr is from :match bool search_attr_from_match = false; // if search_attr is from :match
BufhlLineInfo bufhl_info; // bufhl data for this line BufhlLineInfo bufhl_info; // bufhl data for this line
@@ -3041,8 +3040,7 @@ win_line (
} }
// Only highlight one character after the last column. // Only highlight one character after the last column.
if (*ptr == NUL if (*ptr == NUL
&& (did_line_attr >= 1 && (wp->w_p_list && lcs_eol_one == -1)) {
|| (wp->w_p_list && lcs_eol_one == -1))) {
search_attr = 0; search_attr = 0;
} }
} }
@@ -3680,34 +3678,6 @@ win_line (
(col < wp->w_width))) { (col < wp->w_width))) {
c = ' '; c = ' ';
ptr--; // put it back at the NUL ptr--; // put it back at the NUL
} else if ((diff_hlf != (hlf_T)0 || line_attr_lowprio || line_attr)
&& (wp->w_p_rl
? (col >= 0)
: (col - boguscols < wp->w_width))) {
// Highlight until the right side of the window
c = ' ';
ptr--; // put it back at the NUL
// Remember we do the char for line highlighting.
did_line_attr++;
// don't do search HL for the rest of the line
if ((line_attr_lowprio || line_attr)
&& char_attr == search_attr
&& (did_line_attr > 1
|| (wp->w_p_list && lcs_eol > 0))) {
char_attr = line_attr;
}
if (diff_hlf == HLF_TXD) {
diff_hlf = HLF_CHD;
if (attr == 0 || char_attr != attr) {
char_attr = win_hl_attr(wp, diff_hlf);
if (wp->w_p_cul && lnum == wp->w_cursor.lnum) {
char_attr = hl_combine_attr(char_attr,
win_hl_attr(wp, HLF_CUL));
}
}
}
} }
} }
@@ -3824,7 +3794,7 @@ win_line (
/* /*
* At end of the text line or just after the last character. * At end of the text line or just after the last character.
*/ */
if (c == NUL || did_line_attr == 1) { if (c == NUL) {
long prevcol = (long)(ptr - line) - (c == NUL); long prevcol = (long)(ptr - line) - (c == NUL);
/* we're not really at that column when skipping some text */ /* we're not really at that column when skipping some text */
@@ -3855,11 +3825,7 @@ win_line (
|| lnum == curwin->w_cursor.lnum) || lnum == curwin->w_cursor.lnum)
&& c == NUL) && c == NUL)
// highlight 'hlsearch' match at end of line // highlight 'hlsearch' match at end of line
|| (prevcol_hl_flag || prevcol_hl_flag)) {
&& !(wp->w_p_cul && lnum == wp->w_cursor.lnum
&& !(wp == curwin && VIsual_active))
&& diff_hlf == (hlf_T)0
&& did_line_attr <= 1))) {
int n = 0; int n = 0;
if (wp->w_p_rl) { if (wp->w_p_rl) {
@@ -3903,10 +3869,11 @@ win_line (
} }
} }
if (wp->w_hl_attr_normal != 0) { int eol_attr = char_attr;
char_attr = hl_combine_attr(wp->w_hl_attr_normal, char_attr); if (wp->w_p_cul && lnum == wp->w_cursor.lnum) {
eol_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUL), eol_attr);
} }
ScreenAttrs[off] = char_attr; ScreenAttrs[off] = eol_attr;
if (wp->w_p_rl) { if (wp->w_p_rl) {
--col; --col;
--off; --off;
@@ -3917,12 +3884,6 @@ win_line (
++vcol; ++vcol;
eol_hl_off = 1; eol_hl_off = 1;
} }
}
//
// At end of the text line.
//
if (c == NUL) {
// Highlight 'cursorcolumn' & 'colorcolumn' past end of the line. // Highlight 'cursorcolumn' & 'colorcolumn' past end of the line.
if (wp->w_p_wrap) { if (wp->w_p_wrap) {
v = wp->w_skipcol; v = wp->w_skipcol;
@@ -3946,8 +3907,8 @@ win_line (
&& (int)wp->w_virtcol < && (int)wp->w_virtcol <
wp->w_width * (row - startrow + 1) + v wp->w_width * (row - startrow + 1) + v
&& lnum != wp->w_cursor.lnum) && lnum != wp->w_cursor.lnum)
|| draw_color_col || do_virttext) || draw_color_col || line_attr_lowprio || line_attr
&& !wp->w_p_rl) { || diff_hlf != (hlf_T)0 || do_virttext)) {
int rightmost_vcol = 0; int rightmost_vcol = 0;
int i; int i;
@@ -3959,7 +3920,7 @@ win_line (
// Make sure alignment is the same regardless // Make sure alignment is the same regardless
// if listchars=eol:X is used or not. // if listchars=eol:X is used or not.
bool delay_virttext = lcs_eol <= 0; bool delay_virttext = lcs_eol == lcs_eol_one && eol_hl_off == 0;
if (wp->w_p_cuc) { if (wp->w_p_cuc) {
rightmost_vcol = wp->w_virtcol; rightmost_vcol = wp->w_virtcol;
@@ -3977,7 +3938,22 @@ win_line (
int cuc_attr = win_hl_attr(wp, HLF_CUC); int cuc_attr = win_hl_attr(wp, HLF_CUC);
int mc_attr = win_hl_attr(wp, HLF_MC); int mc_attr = win_hl_attr(wp, HLF_MC);
while (col < wp->w_width) { int diff_attr = 0;
if (diff_hlf == HLF_TXD) {
diff_hlf = HLF_CHD;
}
if (diff_hlf != 0) {
diff_attr = win_hl_attr(wp, diff_hlf);
}
int base_attr = hl_combine_attr(line_attr_lowprio, diff_attr);
if (base_attr || line_attr) {
rightmost_vcol = INT_MAX;
}
int col_stride = wp->w_p_rl ? -1 : 1;
while (wp->w_p_rl ? col >= 0 : col < wp->w_width) {
int cells = -1; int cells = -1;
if (do_virttext && !delay_virttext) { if (do_virttext && !delay_virttext) {
if (*s.p == NUL) { if (*s.p == NUL) {
@@ -4001,12 +3977,13 @@ win_line (
schar_from_ascii(ScreenLines[off], ' '); schar_from_ascii(ScreenLines[off], ' ');
cells = 1; cells = 1;
} }
col += cells; col += cells * col_stride;
if (draw_color_col) { if (draw_color_col) {
draw_color_col = advance_color_col(VCOL_HLC, &color_cols); draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
} }
int attr = 0; int attr = base_attr;
if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) { if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) {
attr = cuc_attr; attr = cuc_attr;
} else if (draw_color_col && VCOL_HLC == *color_cols) { } else if (draw_color_col && VCOL_HLC == *color_cols) {
@@ -4017,11 +3994,13 @@ win_line (
attr = hl_combine_attr(attr, virt_attr); attr = hl_combine_attr(attr, virt_attr);
} }
attr = hl_combine_attr(attr, line_attr);
ScreenAttrs[off] = attr; ScreenAttrs[off] = attr;
if (cells == 2) { if (cells == 2) {
ScreenAttrs[off+1] = attr; ScreenAttrs[off+1] = attr;
} }
off += cells; off += cells * col_stride;
if (VCOL_HLC >= rightmost_vcol && *s.p == NUL if (VCOL_HLC >= rightmost_vcol && *s.p == NUL
&& virt_pos >= virt_text.size) { && virt_pos >= virt_text.size) {

View File

@@ -3,7 +3,7 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command, neq = helpers.command, helpers.neq local command, neq = helpers.command, helpers.neq
local curbufmeths = helpers.curbufmeths local curbufmeths, eq = helpers.curbufmeths, helpers.eq
describe('Buffer highlighting', function() describe('Buffer highlighting', function()
local screen local screen
@@ -27,6 +27,9 @@ describe('Buffer highlighting', function()
[11] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, [11] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
[12] = {foreground = Screen.colors.Blue1}, [12] = {foreground = Screen.colors.Blue1},
[13] = {background = Screen.colors.LightGrey}, [13] = {background = Screen.colors.LightGrey},
[14] = {background = Screen.colors.Gray90},
[15] = {background = Screen.colors.Gray90, bold = true, foreground = Screen.colors.Brown},
[16] = {foreground = Screen.colors.Magenta, background = Screen.colors.Gray90},
}) })
end) end)
@@ -279,150 +282,225 @@ describe('Buffer highlighting', function()
]]) ]])
end) end)
it('supports virtual text annotations', function() describe('virtual text annotations', function()
local set_virtual_text = curbufmeths.set_virtual_text local set_virtual_text = curbufmeths.set_virtual_text
insert([[ local id1, id2
1 + 2 before_each(function()
3 + insert([[
x = 4]]) 1 + 2
feed('O<esc>20A5, <esc>gg') 3 +
screen:expect([[ x = 4]])
^1 + 2 | feed('O<esc>20A5, <esc>gg')
3 + | screen:expect([[
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5| ^1 + 2 |
, 5, 5, 5, 5, 5, 5, | 3 + |
x = 4 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
{1:~ }| , 5, 5, 5, 5, 5, 5, |
{1:~ }| x = 4 |
| {1:~ }|
]]) {1:~ }|
|
]])
local id1 = set_virtual_text(0, 0, {{"=", "Statement"}, {" 3", "Number"}}, {}) id1 = set_virtual_text(0, 0, {{"=", "Statement"}, {" 3", "Number"}}, {})
set_virtual_text(id1, 1, {{"ERROR:", "ErrorMsg"}, {" invalid syntax"}}, {}) set_virtual_text(id1, 1, {{"ERROR:", "ErrorMsg"}, {" invalid syntax"}}, {})
local id2 = set_virtual_text(0, 2, {{"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."}}, {}) id2 = set_virtual_text(0, 2, {{"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."}}, {})
neq(id2, id1) neq(id2, id1)
screen:expect([[ end)
^1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
{1:~ }|
{1:~ }|
|
]])
clear_hl(id1, 0, -1) it('works', function()
screen:expect([[ screen:expect([[
^1 + 2 | ^1 + 2 {3:=}{2: 3} |
3 + | 3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s| , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 | x = 4 |
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
| |
]]) ]])
-- Handles doublewidth chars, leaving a space if truncating clear_hl(id1, 0, -1)
-- in the middle of a char screen:expect([[
set_virtual_text(id1, 1, {{"暗x事zz速野谷質結育副住新覚丸活解終事", "Comment"}}, {}) ^1 + 2 |
screen:expect([[ 3 + |
^1 + 2 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
3 + {12:暗x事zz速野谷質結育副住新覚丸活解終 }| , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5| x = 4 |
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s| {1:~ }|
x = 4 | {1:~ }|
{1:~ }| |
{1:~ }| ]])
|
]])
feed("2Gx") -- Handles doublewidth chars, leaving a space if truncating
screen:expect([[ -- in the middle of a char
1 + 2 | eq(-1, set_virtual_text(-1, 1, {{"暗x事zz速野谷質結育副住新覚丸活解終事", "Comment"}}, {}))
^ + {12:暗x事zz速野谷質結育副住新覚丸活解終事}| screen:expect([[
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5| ^1 + 2 |
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s| 3 + {12:暗x事zz速野谷質結育副住新覚丸活解終 }|
x = 4 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
{1:~ }| , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
{1:~ }| x = 4 |
| {1:~ }|
]]) {1:~ }|
|
]])
-- visual selection doesn't highlight virtual text feed("2Gx")
feed("ggVG") screen:expect([[
screen:expect([[ 1 + 2 |
{13:1 + 2} | ^ + {12:暗x事zz速野谷質結育副住新覚丸活解終事}|
{13: +} {12:暗x事zz速野谷質結育副住新覚丸活解終事}| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
{13:5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}| , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
{13:, 5, 5, 5, 5, 5, 5, } Lorem ipsum dolor s| x = 4 |
^x{13: = 4} | {1:~ }|
{1:~ }| {1:~ }|
{1:~ }| |
{7:-- VISUAL LINE --} | ]])
]])
feed("<esc>") feed("2Gdd")
screen:expect([[ screen:expect([[
1 + 2 | 1 + 2 |
+ {12:暗x事zz速野谷質結育副住新覚丸活解終事}| ^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5| , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s| x = 4 |
^x = 4 | {1:~ }|
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
| |
]]) ]])
end)
feed("2Gdd") it('is not highlighted by visual selection', function()
screen:expect([[ feed("ggVG")
1 + 2 | screen:expect([[
^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5| {13:1 + 2} {3:=}{2: 3} |
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s| {13:3 +} {11:ERROR:} invalid syntax |
x = 4 | {13:5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
{1:~ }| {13:, 5, 5, 5, 5, 5, 5, } Lorem ipsum dolor s|
{1:~ }| ^x{13: = 4} |
{1:~ }| {1:~ }|
| {1:~ }|
]]) {7:-- VISUAL LINE --} |
]])
-- listchars=eol:- works, and doesn't shift virtual text feed("<esc>")
command("set list") screen:expect([[
screen:expect([[ 1 + 2 {3:=}{2: 3} |
1 + 2 | 3 + {11:ERROR:} invalid syntax |
^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5,{1:-} Lorem ipsum dolor s| , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 | ^x = 4 |
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
{1:~ }| |
| ]])
]])
clear_hl(-1, 0, -1) -- special case: empty line has extra eol highlight
screen:expect([[ feed("ggd$")
1 + 2 | screen:expect([[
^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5| ^ {3:=}{2: 3} |
, 5, 5, 5, 5, 5, 5,{1:-} | 3 + {11:ERROR:} invalid syntax |
x = 4 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
{1:~ }| , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
{1:~ }| x = 4 |
{1:~ }| {1:~ }|
| {1:~ }|
]]) |
]])
set_virtual_text(0, 0, {{"x\tx\ny\ry", "Statement"}, {"aa\000bb", "Number"}}, {}) feed("jvk")
screen:expect([[ screen:expect([[
1 + 2 {3:x^Ix^@y^My}{2:aa} | ^ {3:=}{2: 3} |
^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5| {13:3} + {11:ERROR:} invalid syntax |
, 5, 5, 5, 5, 5, 5,{1:-} | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
x = 4 | , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
{1:~ }| x = 4 |
{1:~ }| {1:~ }|
{1:~ }| {1:~ }|
| {7:-- VISUAL --} |
]]) ]])
feed("o")
screen:expect([[
{13: }{3:=}{2: 3} |
^3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
{1:~ }|
{1:~ }|
{7:-- VISUAL --} |
]])
end)
it('works with listchars', function()
command("set list listchars+=eol:$")
screen:expect([[
^1 + 2{1:$}{3:=}{2: 3} |
3 +{1:$}{11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5,{1:-$}Lorem ipsum dolor s|
x = 4{1:$} |
{1:~ }|
{1:~ }|
|
]])
clear_hl(-1, 0, -1)
screen:expect([[
^1 + 2{1:$} |
3 +{1:$} |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5,{1:-$} |
x = 4{1:$} |
{1:~ }|
{1:~ }|
|
]])
end)
it('works with cursorline', function()
command("set cursorline")
screen:expect([[
{14:^1 + 2 }{15:=}{16: 3}{14: }|
3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
{1:~ }|
{1:~ }|
|
]])
feed('j')
screen:expect([[
1 + 2 {3:=}{2: 3} |
{14:^3 + }{11:ERROR:}{14: invalid syntax }|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
{1:~ }|
{1:~ }|
|
]])
feed('j')
screen:expect([[
1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
{14:^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
{14:, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s}|
x = 4 |
{1:~ }|
{1:~ }|
|
]])
end)
end) end)
end) end)