mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			391 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			391 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local helpers = require('test.functional.helpers')(after_each)
 | |
| local Screen = require('test.functional.ui.screen')
 | |
| local thelpers = require('test.functional.terminal.helpers')
 | |
| 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
 | |
| local skip = helpers.skip
 | |
| 
 | |
| describe(':terminal highlight', function()
 | |
|   local screen
 | |
| 
 | |
|   before_each(function()
 | |
|     clear()
 | |
|     screen = Screen.new(50, 7)
 | |
|     screen:set_default_attr_ids({
 | |
|       [1] = { foreground = 45 },
 | |
|       [2] = { background = 46 },
 | |
|       [3] = { foreground = 45, background = 46 },
 | |
|       [4] = { bold = true, italic = true, underline = true, strikethrough = true },
 | |
|       [5] = { bold = true },
 | |
|       [6] = { foreground = 12 },
 | |
|       [7] = { bold = true, reverse = true },
 | |
|       [8] = { background = 11 },
 | |
|       [9] = { foreground = 130 },
 | |
|       [10] = { reverse = true },
 | |
|       [11] = { background = 11 },
 | |
|       [12] = { bold = true, underdouble = true },
 | |
|       [13] = { italic = true, undercurl = true },
 | |
|     })
 | |
|     screen:attach({ rgb = false })
 | |
|     command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
 | |
|     feed('i')
 | |
|     screen:expect([[
 | |
|       tty ready                                         |
 | |
|       {10: }                                                 |
 | |
|                                                         |*4
 | |
|       {5:-- TERMINAL --}                                    |
 | |
|     ]])
 | |
|   end)
 | |
| 
 | |
|   local function descr(title, attr_num, set_attrs_fn)
 | |
|     local function sub(s)
 | |
|       local str = s:gsub('NUM', attr_num)
 | |
|       return str
 | |
|     end
 | |
| 
 | |
|     describe(title, function()
 | |
|       before_each(function()
 | |
|         set_attrs_fn()
 | |
|         thelpers.feed_data('text')
 | |
|         thelpers.clear_attrs()
 | |
|         thelpers.feed_data('text')
 | |
|       end)
 | |
| 
 | |
|       local function pass_attrs()
 | |
|         skip(is_os('win'))
 | |
|         screen:expect(sub([[
 | |
|           tty ready                                         |
 | |
|           {NUM:text}text{10: }                                         |
 | |
|                                                             |*4
 | |
|           {5:-- TERMINAL --}                                    |
 | |
|         ]]))
 | |
|       end
 | |
| 
 | |
|       it('will pass the corresponding attributes', pass_attrs)
 | |
| 
 | |
|       it('will pass the corresponding attributes on scrollback', function()
 | |
|         skip(is_os('win'))
 | |
|         pass_attrs()
 | |
|         local lines = {}
 | |
|         for i = 1, 8 do
 | |
|           table.insert(lines, 'line' .. tostring(i))
 | |
|         end
 | |
|         table.insert(lines, '')
 | |
|         thelpers.feed_data(lines)
 | |
|         screen:expect([[
 | |
|           line4                                             |
 | |
|           line5                                             |
 | |
|           line6                                             |
 | |
|           line7                                             |
 | |
|           line8                                             |
 | |
|           {10: }                                                 |
 | |
|           {5:-- TERMINAL --}                                    |
 | |
|         ]])
 | |
|         feed('<c-\\><c-n>gg')
 | |
|         screen:expect(sub([[
 | |
|           ^tty ready                                         |
 | |
|           {NUM:text}textline1                                     |
 | |
|           line2                                             |
 | |
|           line3                                             |
 | |
|           line4                                             |
 | |
|           line5                                             |
 | |
|                                                             |
 | |
|         ]]))
 | |
|       end)
 | |
|     end)
 | |
|   end
 | |
| 
 | |
|   descr('foreground', 1, function()
 | |
|     thelpers.set_fg(45)
 | |
|   end)
 | |
|   descr('background', 2, function()
 | |
|     thelpers.set_bg(46)
 | |
|   end)
 | |
|   descr('foreground and background', 3, function()
 | |
|     thelpers.set_fg(45)
 | |
|     thelpers.set_bg(46)
 | |
|   end)
 | |
|   descr('bold, italics, underline and strikethrough', 4, function()
 | |
|     thelpers.set_bold()
 | |
|     thelpers.set_italic()
 | |
|     thelpers.set_underline()
 | |
|     thelpers.set_strikethrough()
 | |
|   end)
 | |
|   descr('bold and underdouble', 12, function()
 | |
|     thelpers.set_bold()
 | |
|     thelpers.set_underdouble()
 | |
|   end)
 | |
|   descr('italics and undercurl', 13, function()
 | |
|     thelpers.set_italic()
 | |
|     thelpers.set_undercurl()
 | |
|   end)
 | |
| end)
 | |
| 
 | |
| it(':terminal highlight has lower precedence than editor #9964', function()
 | |
|   clear()
 | |
|   local screen = Screen.new(30, 4)
 | |
|   screen:set_default_attr_ids({
 | |
|     -- "Normal" highlight emitted by the child nvim process.
 | |
|     N_child = {
 | |
|       foreground = tonumber('0x4040ff'),
 | |
|       background = tonumber('0xffff40'),
 | |
|       fg_indexed = true,
 | |
|       bg_indexed = true,
 | |
|     },
 | |
|     -- "Search" highlight in the parent nvim process.
 | |
|     S = { background = Screen.colors.Green, italic = true, foreground = Screen.colors.Red },
 | |
|     -- "Question" highlight in the parent nvim process.
 | |
|     -- note: bg is indexed as it comes from the (cterm) child, while fg isn't as it comes from (rgb) parent
 | |
|     Q = {
 | |
|       background = tonumber('0xffff40'),
 | |
|       bold = true,
 | |
|       foreground = Screen.colors.SeaGreen4,
 | |
|       bg_indexed = true,
 | |
|     },
 | |
|   })
 | |
|   screen:attach({ rgb = true })
 | |
|   -- Child nvim process in :terminal (with cterm colors).
 | |
|   fn.termopen({
 | |
|     nvim_prog_abs(),
 | |
|     '-n',
 | |
|     '-u',
 | |
|     'NORC',
 | |
|     '-i',
 | |
|     'NONE',
 | |
|     '--cmd',
 | |
|     nvim_set .. ' notermguicolors',
 | |
|     '+hi Normal ctermfg=Blue ctermbg=Yellow',
 | |
|     '+norm! ichild nvim',
 | |
|     '+norm! oline 2',
 | |
|   }, {
 | |
|     env = {
 | |
|       VIMRUNTIME = os.getenv('VIMRUNTIME'),
 | |
|     },
 | |
|   })
 | |
|   screen:expect([[
 | |
|     {N_child:^child nvim                    }|
 | |
|     {N_child:line 2                        }|
 | |
|     {N_child:                              }|
 | |
|                                   |
 | |
|   ]])
 | |
|   command('hi Search gui=italic guifg=Red guibg=Green cterm=italic ctermfg=Red ctermbg=Green')
 | |
|   feed('/nvim<cr>')
 | |
|   screen:expect([[
 | |
|     {N_child:child }{S:^nvim}{N_child:                    }|
 | |
|     {N_child:line 2                        }|
 | |
|     {N_child:                              }|
 | |
|     /nvim                         |
 | |
|   ]])
 | |
|   command('syntax keyword Question line')
 | |
|   screen:expect([[
 | |
|     {N_child:child }{S:^nvim}{N_child:                    }|
 | |
|     {Q:line}{N_child: 2                        }|
 | |
|     {N_child:                              }|
 | |
|     /nvim                         |
 | |
|   ]])
 | |
| end)
 | |
| 
 | |
| describe(':terminal highlight forwarding', function()
 | |
|   local screen
 | |
| 
 | |
|   before_each(function()
 | |
|     clear()
 | |
|     screen = Screen.new(50, 7)
 | |
|     screen:set_rgb_cterm(true)
 | |
|     screen:set_default_attr_ids({
 | |
|       [1] = { { reverse = true }, { reverse = true } },
 | |
|       [2] = { { bold = true }, { bold = true } },
 | |
|       [3] = { { fg_indexed = true, foreground = tonumber('0xe0e000') }, { foreground = 3 } },
 | |
|       [4] = { { foreground = tonumber('0xff8000') }, {} },
 | |
|     })
 | |
|     screen:attach()
 | |
|     command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
 | |
|     feed('i')
 | |
|     screen:expect([[
 | |
|       tty ready                                         |
 | |
|       {1: }                                                 |
 | |
|                                                         |*4
 | |
|       {2:-- TERMINAL --}                                    |
 | |
|     ]])
 | |
|   end)
 | |
| 
 | |
|   it('will handle cterm and rgb attributes', function()
 | |
|     skip(is_os('win'))
 | |
|     thelpers.set_fg(3)
 | |
|     thelpers.feed_data('text')
 | |
|     thelpers.feed_termcode('[38:2:255:128:0m')
 | |
|     thelpers.feed_data('color')
 | |
|     thelpers.clear_attrs()
 | |
|     thelpers.feed_data('text')
 | |
|     screen:expect {
 | |
|       grid = [[
 | |
|       tty ready                                         |
 | |
|       {3:text}{4:color}text{1: }                                    |
 | |
|                                                         |*4
 | |
|       {2:-- TERMINAL --}                                    |
 | |
|     ]],
 | |
|     }
 | |
|   end)
 | |
| end)
 | |
| 
 | |
| describe(':terminal highlight with custom palette', function()
 | |
|   local screen
 | |
| 
 | |
|   before_each(function()
 | |
|     clear()
 | |
|     screen = Screen.new(50, 7)
 | |
|     screen:set_default_attr_ids({
 | |
|       [1] = { foreground = tonumber('0x123456') }, -- no fg_indexed when overridden
 | |
|       [2] = { foreground = 12 },
 | |
|       [3] = { bold = true, reverse = true },
 | |
|       [5] = { background = 11 },
 | |
|       [6] = { foreground = 130 },
 | |
|       [7] = { reverse = true },
 | |
|       [8] = { background = 11 },
 | |
|       [9] = { bold = true },
 | |
|     })
 | |
|     screen:attach({ rgb = true })
 | |
|     api.nvim_set_var('terminal_color_3', '#123456')
 | |
|     command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
 | |
|     feed('i')
 | |
|     screen:expect([[
 | |
|       tty ready                                         |
 | |
|       {7: }                                                 |
 | |
|                                                         |*4
 | |
|       {9:-- TERMINAL --}                                    |
 | |
|     ]])
 | |
|   end)
 | |
| 
 | |
|   it('will use the custom color', function()
 | |
|     skip(is_os('win'))
 | |
|     thelpers.set_fg(3)
 | |
|     thelpers.feed_data('text')
 | |
|     thelpers.clear_attrs()
 | |
|     thelpers.feed_data('text')
 | |
|     screen:expect([[
 | |
|       tty ready                                         |
 | |
|       {1:text}text{7: }                                         |
 | |
|                                                         |*4
 | |
|       {9:-- TERMINAL --}                                    |
 | |
|     ]])
 | |
|   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)
 | 
