aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-03-17 17:24:03 +0800
committerGitHub <noreply@github.com>2024-03-17 17:24:03 +0800
commit54db75e995f82a11f5d2a223d816d2ea0bd0467e (patch)
treeb6413e4394c5b96a380fd1860de09f71396bace2
parentc52dfb6e840827a2de713e40ea8506491ec7ce0b (diff)
downloadrneovim-54db75e995f82a11f5d2a223d816d2ea0bd0467e.tar.gz
rneovim-54db75e995f82a11f5d2a223d816d2ea0bd0467e.tar.bz2
rneovim-54db75e995f82a11f5d2a223d816d2ea0bd0467e.zip
refactor(drawline): integrate terminal hl with eol loop (#27893)
There is no test for using 'cursorline' in Normal mode in a terminal buffer, so add a test and fix 'cursorcolumn' remaining when entering Terminal mode. Also move synIDattr() tests to ui/highlight_spec.lua.
-rw-r--r--src/nvim/drawline.c21
-rw-r--r--src/nvim/terminal.c3
-rw-r--r--test/functional/terminal/buffer_spec.lua2
-rw-r--r--test/functional/terminal/highlight_spec.lua172
-rw-r--r--test/functional/ui/highlight_spec.lua112
5 files changed, 181 insertions, 129 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 816eb8a674..a6f3f0c4b3 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -2576,7 +2576,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
&& wp->w_virtcol < grid->cols * (ptrdiff_t)(wlv.row - startrow + 1) + start_col
&& lnum != wp->w_cursor.lnum)
|| wlv.color_cols || wlv.line_attr_lowprio || wlv.line_attr
- || wlv.diff_hlf != 0)) {
+ || wlv.diff_hlf != 0 || wp->w_buffer->terminal)) {
int rightmost_vcol = get_rightmost_vcol(wp, wlv.color_cols);
const int cuc_attr = win_hl_attr(wp, HLF_CUC);
const int mc_attr = win_hl_attr(wp, HLF_MC);
@@ -2590,7 +2590,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
: 0;
const int base_attr = hl_combine_attr(wlv.line_attr_lowprio, diff_attr);
- if (base_attr || wlv.line_attr) {
+ if (base_attr || wlv.line_attr || wp->w_buffer->terminal) {
rightmost_vcol = INT_MAX;
}
@@ -2609,6 +2609,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
col_attr = hl_combine_attr(col_attr, mc_attr);
}
+ if (wp->w_buffer->terminal && wlv.vcol < TERM_ATTRS_MAX) {
+ col_attr = hl_combine_attr(col_attr, term_attrs[wlv.vcol]);
+ }
+
col_attr = hl_combine_attr(col_attr, wlv.line_attr);
linebuf_attr[wlv.off] = col_attr;
@@ -2622,19 +2626,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
}
}
- // TODO(bfredl): integrate with the common beyond-the-end-loop
- if (wp->w_buffer->terminal) {
- // terminal buffers may need to highlight beyond the end of the logical line
- while (wlv.col >= 0 && wlv.col < grid->cols) {
- linebuf_char[wlv.off] = schar_from_ascii(' ');
- linebuf_attr[wlv.off] = wlv.vcol >= TERM_ATTRS_MAX ? 0 : term_attrs[wlv.vcol];
- linebuf_vcol[wlv.off] = wlv.vcol;
- wlv.off++;
- wlv.vcol++;
- wlv.col++;
- }
- }
-
if (kv_size(fold_vt) > 0) {
draw_virt_text_item(buf, win_col_offset, fold_vt, kHlModeCombine, grid->cols, 0);
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index edde7ff57a..3734d55a5b 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -543,6 +543,9 @@ bool terminal_enter(void)
} else {
curwin->w_p_cul = false;
}
+ if (curwin->w_p_cuc) {
+ redraw_later(curwin, UPD_SOME_VALID);
+ }
curwin->w_p_cuc = false;
curwin->w_p_so = 0;
curwin->w_p_siso = 0;
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 376b7b849e..ea9d974dc3 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -54,7 +54,7 @@ describe(':terminal buffer', function()
eq({ 0, 'both' }, eval('[&l:cursorline, &l:cursorlineopt]'))
end)
- it('terminal-mode disables cursorline when cursorlineopt is only set to "line', function()
+ it('terminal-mode disables cursorline when cursorlineopt is only set to "line"', function()
feed([[<C-\><C-N>]])
command('setlocal cursorline cursorlineopt=line')
feed('i')
diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua
index ec057c6766..98d760d1ee 100644
--- a/test/functional/terminal/highlight_spec.lua
+++ b/test/functional/terminal/highlight_spec.lua
@@ -5,7 +5,6 @@ local feed, clear = helpers.feed, helpers.clear
local api = helpers.api
local testprg, command = helpers.testprg, helpers.command
local nvim_prog_abs = helpers.nvim_prog_abs
-local eq, eval = helpers.eq, helpers.eval
local fn = helpers.fn
local nvim_set = helpers.nvim_set
local is_os = helpers.is_os
@@ -191,6 +190,65 @@ it(':terminal highlight has lower precedence than editor #9964', function()
]])
end)
+it('CursorLine and CursorColumn work in :terminal buffer in Normal mode', function()
+ clear()
+ local screen = Screen.new(50, 7)
+ screen:set_default_attr_ids({
+ [1] = { background = Screen.colors.Grey90 }, -- CursorLine, CursorColumn
+ [2] = { reverse = true }, -- TermCursor
+ [3] = { bold = true }, -- ModeMsg
+ })
+ screen:attach()
+ command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
+ screen:expect([[
+ ^tty ready |
+ |*6
+ ]])
+ thelpers.feed_data((' foobar'):rep(30))
+ screen:expect([[
+ ^tty ready |
+ foobar foobar foobar foobar foobar foobar foobar |
+ foobar foobar foobar foobar foobar foobar foobar f|
+ oobar foobar foobar foobar foobar foobar foobar fo|
+ obar foobar foobar foobar foobar foobar foobar foo|
+ bar foobar |
+ |
+ ]])
+ command('set cursorline cursorcolumn')
+ feed('j10w')
+ screen:expect([[
+ tty ready {1: } |
+ foobar foobar{1: }foobar foobar foobar foobar foobar |
+ {1:foobar foobar ^foobar foobar foobar foobar foobar f}|
+ oobar foobar f{1:o}obar foobar foobar foobar foobar fo|
+ obar foobar fo{1:o}bar foobar foobar foobar foobar foo|
+ bar foobar {1: } |
+ |
+ ]])
+ -- Entering terminal mode disables 'cursorline' and 'cursorcolumn'.
+ feed('i')
+ screen:expect([[
+ tty ready |
+ foobar foobar foobar foobar foobar foobar foobar |
+ foobar foobar foobar foobar foobar foobar foobar f|
+ oobar foobar foobar foobar foobar foobar foobar fo|
+ obar foobar foobar foobar foobar foobar foobar foo|
+ bar foobar{2: } |
+ {3:-- TERMINAL --} |
+ ]])
+ -- Leaving terminal mode restores old values.
+ feed([[<C-\><C-N>]])
+ screen:expect([[
+ tty ready{1: } |
+ foobar f{1:o}obar foobar foobar foobar foobar foobar |
+ foobar fo{1:o}bar foobar foobar foobar foobar foobar f|
+ oobar foo{1:b}ar foobar foobar foobar foobar foobar fo|
+ obar foob{1:a}r foobar foobar foobar foobar foobar foo|
+ {1:bar fooba^r }|
+ |
+ ]])
+end)
+
describe(':terminal highlight forwarding', function()
local screen
@@ -276,115 +334,3 @@ describe(':terminal highlight with custom palette', function()
]])
end)
end)
-
-describe('synIDattr()', function()
- local screen
- before_each(function()
- clear()
- screen = Screen.new(50, 7)
- command('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black')
- -- Salmon #fa8072 Maroon #800000
- command(
- 'highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon cterm=strikethrough gui=strikethrough'
- )
- end)
-
- it('returns cterm-color if RGB-capable UI is _not_ attached', function()
- eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
- eq('252', eval('synIDattr(hlID("Normal"), "fg#")'))
- eq('', eval('synIDattr(hlID("Normal"), "bg")'))
- eq('', eval('synIDattr(hlID("Normal"), "bg#")'))
- eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
- eq('79', eval('synIDattr(hlID("Keyword"), "fg#")'))
- eq('', eval('synIDattr(hlID("Keyword"), "sp")'))
- eq('', eval('synIDattr(hlID("Keyword"), "sp#")'))
- end)
-
- it('returns gui-color if "gui" arg is passed', function()
- eq('Black', eval('synIDattr(hlID("Normal"), "bg", "gui")'))
- eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp", "gui")'))
- end)
-
- it('returns gui-color if RGB-capable UI is attached', function()
- screen:attach({ rgb = true })
- eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg")'))
- eq('Black', eval('synIDattr(hlID("Normal"), "bg")'))
- eq('Salmon', eval('synIDattr(hlID("Keyword"), "fg")'))
- eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp")'))
- end)
-
- it('returns #RRGGBB value for fg#/bg#/sp#', function()
- screen:attach({ rgb = true })
- eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg#")'))
- eq('#000000', eval('synIDattr(hlID("Normal"), "bg#")'))
- eq('#fa8072', eval('synIDattr(hlID("Keyword"), "fg#")'))
- eq('#800000', eval('synIDattr(hlID("Keyword"), "sp#")'))
- end)
-
- it('returns color number if non-GUI', function()
- screen:attach({ rgb = false })
- eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
- eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
- end)
-
- it('returns "1" if group has given highlight attribute', function()
- local hl_attrs = {
- 'underline',
- 'undercurl',
- 'underdouble',
- 'underdotted',
- 'underdashed',
- 'strikethrough',
- }
- for _, hl_attr in ipairs(hl_attrs) do
- local context = 'using ' .. hl_attr .. ' attr'
- command('highlight Keyword cterm=' .. hl_attr .. ' gui=' .. hl_attr)
- eq('', eval('synIDattr(hlID("Normal"), "' .. hl_attr .. '")'), context)
- eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '")'), context)
- eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '", "gui")'), context)
- end
- end)
-end)
-
-describe('fg/bg special colors', function()
- local screen
- before_each(function()
- clear()
- screen = Screen.new(50, 7)
- command('highlight Normal ctermfg=145 ctermbg=16 guifg=#ff0000 guibg=Black')
- command('highlight Visual ctermfg=bg ctermbg=fg guifg=bg guibg=fg guisp=bg')
- end)
-
- it('resolve to "Normal" values', function()
- eq(eval('synIDattr(hlID("Normal"), "bg")'), eval('synIDattr(hlID("Visual"), "fg")'))
- eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")'))
- eq(eval('synIDattr(hlID("Normal"), "fg")'), eval('synIDattr(hlID("Visual"), "bg")'))
- eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")'))
- eq('bg', eval('synIDattr(hlID("Visual"), "fg", "gui")'))
- eq('bg', eval('synIDattr(hlID("Visual"), "fg#", "gui")'))
- eq('fg', eval('synIDattr(hlID("Visual"), "bg", "gui")'))
- eq('fg', eval('synIDattr(hlID("Visual"), "bg#", "gui")'))
- eq('bg', eval('synIDattr(hlID("Visual"), "sp", "gui")'))
- eq('bg', eval('synIDattr(hlID("Visual"), "sp#", "gui")'))
- end)
-
- it('resolve to "Normal" values in RGB-capable UI', function()
- screen:attach({ rgb = true })
- eq('bg', eval('synIDattr(hlID("Visual"), "fg")'))
- eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")'))
- eq('fg', eval('synIDattr(hlID("Visual"), "bg")'))
- eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")'))
- eq('bg', eval('synIDattr(hlID("Visual"), "sp")'))
- eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "sp#")'))
- end)
-
- it('resolve after the "Normal" group is modified', function()
- screen:attach({ rgb = true })
- local new_guibg = '#282c34'
- local new_guifg = '#abb2bf'
- command('highlight Normal guifg=' .. new_guifg .. ' guibg=' .. new_guibg)
- eq(new_guibg, eval('synIDattr(hlID("Visual"), "fg#")'))
- eq(new_guifg, eval('synIDattr(hlID("Visual"), "bg#")'))
- eq(new_guibg, eval('synIDattr(hlID("Visual"), "sp#")'))
- end)
-end)
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index f6d262c6fd..34a7bc19c6 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -2537,3 +2537,115 @@ describe('highlight namespaces', function()
}
end)
end)
+
+describe('synIDattr()', function()
+ local screen
+ before_each(function()
+ clear()
+ screen = Screen.new(50, 7)
+ command('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black')
+ -- Salmon #fa8072 Maroon #800000
+ command(
+ 'highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon cterm=strikethrough gui=strikethrough'
+ )
+ end)
+
+ it('returns cterm-color if RGB-capable UI is _not_ attached', function()
+ eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
+ eq('252', eval('synIDattr(hlID("Normal"), "fg#")'))
+ eq('', eval('synIDattr(hlID("Normal"), "bg")'))
+ eq('', eval('synIDattr(hlID("Normal"), "bg#")'))
+ eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
+ eq('79', eval('synIDattr(hlID("Keyword"), "fg#")'))
+ eq('', eval('synIDattr(hlID("Keyword"), "sp")'))
+ eq('', eval('synIDattr(hlID("Keyword"), "sp#")'))
+ end)
+
+ it('returns gui-color if "gui" arg is passed', function()
+ eq('Black', eval('synIDattr(hlID("Normal"), "bg", "gui")'))
+ eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp", "gui")'))
+ end)
+
+ it('returns gui-color if RGB-capable UI is attached', function()
+ screen:attach({ rgb = true })
+ eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg")'))
+ eq('Black', eval('synIDattr(hlID("Normal"), "bg")'))
+ eq('Salmon', eval('synIDattr(hlID("Keyword"), "fg")'))
+ eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp")'))
+ end)
+
+ it('returns #RRGGBB value for fg#/bg#/sp#', function()
+ screen:attach({ rgb = true })
+ eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg#")'))
+ eq('#000000', eval('synIDattr(hlID("Normal"), "bg#")'))
+ eq('#fa8072', eval('synIDattr(hlID("Keyword"), "fg#")'))
+ eq('#800000', eval('synIDattr(hlID("Keyword"), "sp#")'))
+ end)
+
+ it('returns color number if non-GUI', function()
+ screen:attach({ rgb = false })
+ eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
+ eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
+ end)
+
+ it('returns "1" if group has given highlight attribute', function()
+ local hl_attrs = {
+ 'underline',
+ 'undercurl',
+ 'underdouble',
+ 'underdotted',
+ 'underdashed',
+ 'strikethrough',
+ }
+ for _, hl_attr in ipairs(hl_attrs) do
+ local context = 'using ' .. hl_attr .. ' attr'
+ command('highlight Keyword cterm=' .. hl_attr .. ' gui=' .. hl_attr)
+ eq('', eval('synIDattr(hlID("Normal"), "' .. hl_attr .. '")'), context)
+ eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '")'), context)
+ eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '", "gui")'), context)
+ end
+ end)
+end)
+
+describe('fg/bg special colors', function()
+ local screen
+ before_each(function()
+ clear()
+ screen = Screen.new(50, 7)
+ command('highlight Normal ctermfg=145 ctermbg=16 guifg=#ff0000 guibg=Black')
+ command('highlight Visual ctermfg=bg ctermbg=fg guifg=bg guibg=fg guisp=bg')
+ end)
+
+ it('resolve to "Normal" values', function()
+ eq(eval('synIDattr(hlID("Normal"), "bg")'), eval('synIDattr(hlID("Visual"), "fg")'))
+ eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")'))
+ eq(eval('synIDattr(hlID("Normal"), "fg")'), eval('synIDattr(hlID("Visual"), "bg")'))
+ eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")'))
+ eq('bg', eval('synIDattr(hlID("Visual"), "fg", "gui")'))
+ eq('bg', eval('synIDattr(hlID("Visual"), "fg#", "gui")'))
+ eq('fg', eval('synIDattr(hlID("Visual"), "bg", "gui")'))
+ eq('fg', eval('synIDattr(hlID("Visual"), "bg#", "gui")'))
+ eq('bg', eval('synIDattr(hlID("Visual"), "sp", "gui")'))
+ eq('bg', eval('synIDattr(hlID("Visual"), "sp#", "gui")'))
+ end)
+
+ it('resolve to "Normal" values in RGB-capable UI', function()
+ screen:attach({ rgb = true })
+ eq('bg', eval('synIDattr(hlID("Visual"), "fg")'))
+ eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")'))
+ eq('fg', eval('synIDattr(hlID("Visual"), "bg")'))
+ eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")'))
+ eq('bg', eval('synIDattr(hlID("Visual"), "sp")'))
+ eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "sp#")'))
+ end)
+
+ it('resolve after the "Normal" group is modified', function()
+ screen:attach({ rgb = true })
+ local new_guibg = '#282c34'
+ local new_guifg = '#abb2bf'
+ command('highlight Normal guifg=' .. new_guifg .. ' guibg=' .. new_guibg)
+ eq(new_guibg, eval('synIDattr(hlID("Visual"), "fg#")'))
+ eq(new_guifg, eval('synIDattr(hlID("Visual"), "bg#")'))
+ eq(new_guibg, eval('synIDattr(hlID("Visual"), "sp#")'))
+ end)
+end)