neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

highlight_spec.lua (93999B)


      1 local t = require('test.testutil')
      2 local n = require('test.functional.testnvim')()
      3 local Screen = require('test.functional.ui.screen')
      4 local os = require('os')
      5 
      6 local clear, feed, insert = n.clear, n.feed, n.insert
      7 local command, exec = n.command, n.exec
      8 local eval = n.eval
      9 local feed_command, eq = n.feed_command, t.eq
     10 local fn = n.fn
     11 local api = n.api
     12 local exec_lua = n.exec_lua
     13 
     14 describe('colorscheme compatibility', function()
     15  before_each(function()
     16    clear()
     17  end)
     18 
     19  it('&t_Co exists and is set to 256 by default', function()
     20    eq(1, fn.exists('&t_Co'))
     21    eq(1, fn.exists('+t_Co'))
     22    eq('256', eval('&t_Co'))
     23  end)
     24 end)
     25 
     26 describe('highlight: `:syntax manual`', function()
     27  -- When using manual syntax highlighting, it should be preserved even when
     28  -- switching buffers... bug did only occur without :set hidden
     29  -- Ref: vim patch 7.4.1236
     30  local screen
     31 
     32  before_each(function()
     33    clear()
     34    screen = Screen.new(20, 5)
     35    -- syntax highlight for vimscript's "echo"
     36  end)
     37 
     38  after_each(function()
     39    os.remove('Xtest-functional-ui-highlight.tmp.vim')
     40  end)
     41 
     42  it("works with buffer switch and 'hidden'", function()
     43    command('e tmp1.vim')
     44    command('e Xtest-functional-ui-highlight.tmp.vim')
     45    command('filetype on')
     46    command('syntax manual')
     47    command('set ft=vim')
     48    command('set syntax=ON')
     49    feed('iecho 1<esc>0')
     50 
     51    command('set hidden')
     52    command('w')
     53    command('bn')
     54    feed_command('bp')
     55    screen:expect([[
     56      {15:^echo} {26:1}              |
     57      {1:~                   }|*3
     58      :bp                 |
     59    ]])
     60  end)
     61 
     62  it("works with buffer switch and 'nohidden'", function()
     63    command('e tmp1.vim')
     64    command('e Xtest-functional-ui-highlight.tmp.vim')
     65    command('filetype on')
     66    command('syntax manual')
     67    command('set filetype=vim fileformat=unix')
     68    command('set syntax=ON')
     69    feed('iecho 1<esc>0')
     70 
     71    command('set nohidden')
     72    command('w')
     73    command('silent bn')
     74    eq('tmp1.vim', eval("fnamemodify(bufname('%'), ':t')"))
     75    feed_command('silent bp')
     76    eq('Xtest-functional-ui-highlight.tmp.vim', eval("fnamemodify(bufname('%'), ':t')"))
     77    screen:expect([[
     78      {15:^echo} {26:1}              |
     79      {1:~                   }|*3
     80      :silent bp          |
     81    ]])
     82  end)
     83 end)
     84 
     85 describe('highlight defaults', function()
     86  local screen
     87 
     88  before_each(function()
     89    clear()
     90    screen = Screen.new()
     91    screen:add_extra_attr_ids {
     92      [100] = { foreground = Screen.colors.Red, background = Screen.colors.WebGreen },
     93      [101] = { italic = true },
     94    }
     95  end)
     96 
     97  it('window status bar', function()
     98    feed_command('sp', 'vsp', 'vsp')
     99    screen:expect([[
    100      ^                                                   |
    101      {1:~                   }{1:~               }{1:~              }|*5
    102      {3:[No Name]            }{2:[No Name]        [No Name]      }|
    103                                                           |
    104      {1:~                                                    }|*4
    105      {2:[No Name]                                            }|
    106      :vsp                                                 |
    107    ]])
    108    -- navigate to verify that the attributes are properly moved
    109    feed('<c-w>j')
    110    screen:expect([[
    111                                                         |
    112      {1:~                   }{1:~               }{1:~              }|*5
    113      {2:[No Name]            [No Name]        [No Name]      }|
    114      ^                                                     |
    115      {1:~                                                    }|*4
    116      {3:[No Name]                                            }|
    117      :vsp                                                 |
    118    ]])
    119    -- note that when moving to a window with small width nvim will increase
    120    -- the width of the new active window at the expense of a inactive window
    121    -- (upstream vim has the same behavior)
    122    feed('<c-w>k<c-w>l')
    123    screen:expect([[
    124                          ^                               |
    125      {1:~                   }{1:~                   }{1:~          }|*5
    126      {2:[No Name]            }{3:[No Name]            }{2:[No Name]  }|
    127                                                           |
    128      {1:~                                                    }|*4
    129      {2:[No Name]                                            }|
    130      :vsp                                                 |
    131    ]])
    132    feed('<c-w>l')
    133    screen:expect([[
    134                                     ^                    |
    135      {1:~                   }{1:~          }{1:~                   }|*5
    136      {2:[No Name]            [No Name]   }{3:[No Name]           }|
    137                                                           |
    138      {1:~                                                    }|*4
    139      {2:[No Name]                                            }|
    140      :vsp                                                 |
    141    ]])
    142    feed('<c-w>h<c-w>h')
    143    screen:expect([[
    144      ^                                                   |
    145      {1:~                   }{1:~                   }{1:~          }|*5
    146      {3:[No Name]            }{2:[No Name]            [No Name]  }|
    147                                                           |
    148      {1:~                                                    }|*4
    149      {2:[No Name]                                            }|
    150      :vsp                                                 |
    151    ]])
    152  end)
    153 
    154  it('insert mode text', function()
    155    feed('i')
    156    screen:try_resize(53, 4)
    157    screen:expect([[
    158      ^                                                     |
    159      {1:~                                                    }|*2
    160      {5:-- INSERT --}                                         |
    161    ]])
    162  end)
    163 
    164  it('end of file markers', function()
    165    screen:try_resize(53, 4)
    166    screen:expect([[
    167      ^                                                     |
    168      {1:~                                                    }|*2
    169                                                           |
    170    ]])
    171  end)
    172 
    173  it('"wait return" text', function()
    174    screen:try_resize(53, 4)
    175    feed(':ls<cr>')
    176    screen:expect([[
    177      {3:                                                     }|
    178      :ls                                                  |
    179        1 %a   "[No Name]"                    line 1       |
    180      {6:Press ENTER or type command to continue}^              |
    181    ]])
    182    feed('<cr>') --  skip the "Press ENTER..." state or tests will hang
    183  end)
    184 
    185  it('can be cleared and linked to other highlight groups', function()
    186    screen:try_resize(53, 4)
    187    feed_command('highlight clear ModeMsg')
    188    feed('i')
    189    screen:expect([[
    190      ^                                                     |
    191      {1:~                                                    }|*2
    192      -- INSERT --                                         |
    193    ]])
    194    feed('<esc>')
    195    feed_command('highlight CustomHLGroup guifg=red guibg=green')
    196    feed_command('highlight link ModeMsg CustomHLGroup')
    197    feed('i')
    198    screen:expect([[
    199      ^                                                     |
    200      {1:~                                                    }|*2
    201      {100:-- INSERT --}                                         |
    202    ]])
    203  end)
    204 
    205  it('can be cleared by assigning NONE', function()
    206    screen:try_resize(53, 4)
    207    feed_command('syn keyword TmpKeyword neovim')
    208    feed_command('hi link TmpKeyword ErrorMsg')
    209    insert('neovim')
    210    screen:expect([[
    211      {9:neovi^m}                                               |
    212      {1:~                                                    }|*2
    213                                                           |
    214    ]])
    215    feed_command(
    216      'hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE'
    217        .. ' gui=NONE guifg=NONE guibg=NONE guisp=NONE'
    218    )
    219    screen:expect([[
    220      neovi^m                                               |
    221      {1:~                                                    }|*2
    222                                                           |
    223    ]])
    224  end)
    225 
    226  it('linking updates window highlight immediately #16552', function()
    227    screen:try_resize(53, 4)
    228    screen:expect([[
    229      ^                                                     |
    230      {1:~                                                    }|*2
    231                                                           |
    232    ]])
    233    feed_command('hi NonTextAlt guifg=Red')
    234    feed_command('hi! link NonText NonTextAlt')
    235    screen:expect([[
    236      ^                                                     |
    237      {19:~                                                    }|*2
    238      :hi! link NonText NonTextAlt                         |
    239    ]])
    240  end)
    241 
    242  it('Cursor after `:hi clear|syntax reset` #6508', function()
    243    command('highlight clear|syntax reset')
    244    eq('guifg=bg guibg=fg', eval([[matchstr(execute('hi Cursor'), '\v(gui|cterm).*$')]]))
    245  end)
    246 
    247  it('Whitespace highlight', function()
    248    screen:try_resize(53, 4)
    249    feed_command('highlight NonText gui=NONE guifg=#FF0000')
    250    feed_command('set listchars=space:.,tab:>-,trail:*,eol:¬ list')
    251    insert('   ne \t o\tv  im  ')
    252    screen:expect([[
    253      ne{19:.>----.}o{19:>-----}v{19:..}im{19:*^*¬}                             |
    254      {19:~                                                    }|*2
    255                                                           |
    256    ]])
    257    feed_command('highlight Whitespace gui=NONE guifg=#0000FF')
    258    screen:expect([[
    259      ne{18:.>----.}o{18:>-----}v{18:..}im{18:*^*}{19:¬}                             |
    260      {19:~                                                    }|*2
    261      :highlight Whitespace gui=NONE guifg=#0000FF         |
    262    ]])
    263  end)
    264 
    265  it('are sent to UIs', function()
    266    screen:try_resize(53, 4)
    267 
    268    screen:expect {
    269      grid = [[
    270      ^                                                     |
    271      {1:~                                                    }|*2
    272                                                           |
    273    ]],
    274      hl_groups = { EndOfBuffer = 1, MsgSeparator = 3 },
    275    }
    276 
    277    command('highlight EndOfBuffer gui=italic')
    278    screen:expect {
    279      grid = [[
    280      ^                                                     |
    281      {101:~                                                    }|*2
    282                                                           |
    283    ]],
    284      hl_groups = { EndOfBuffer = 101, MsgSeparator = 3 },
    285    }
    286 
    287    command('highlight clear EndOfBuffer')
    288    screen:expect {
    289      grid = [[
    290      ^                                                     |
    291      {1:~                                                    }|*2
    292                                                           |
    293    ]],
    294      hl_groups = { EndOfBuffer = 1, MsgSeparator = 3 },
    295    }
    296  end)
    297 end)
    298 
    299 describe('highlight', function()
    300  before_each(clear)
    301 
    302  it('Visual', function()
    303    local screen = Screen.new(45, 5)
    304    insert([[
    305      line1 foo bar
    306    abcdefghijklmnopqrs
    307    ABCDEFGHIJKLMNOPQRS
    308    ]])
    309    feed('gg')
    310    command('vsplit')
    311 
    312    -- Non-blinking block cursor: does NOT highlight char-at-cursor.
    313    command('set guicursor=a:block-blinkon0')
    314    feed('V')
    315    screen:expect([[
    316      {17:  }^l{17:ine1 foo bar}       {17:  line1 foo bar}       |
    317      abcdefghijklmnopqrs   abcdefghijklmnopqrs   |
    318      ABCDEFGHIJKLMNOPQRS   ABCDEFGHIJKLMNOPQRS   |
    319      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    320      {5:-- VISUAL LINE --}                            |
    321    ]])
    322 
    323    feed('<Esc>$vhhh')
    324    screen:expect([[
    325        line1 foo^ {17:bar}         line1 foo{17: bar}       |
    326      abcdefghijklmnopqrs   abcdefghijklmnopqrs   |
    327      ABCDEFGHIJKLMNOPQRS   ABCDEFGHIJKLMNOPQRS   |
    328      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    329      {5:-- VISUAL --}                                 |
    330    ]])
    331 
    332    -- Vertical cursor: highlights char-at-cursor. #8983
    333    command('set guicursor=a:block-blinkon175')
    334    screen:expect([[
    335        line1 foo{17:^ bar}         line1 foo{17: bar}       |
    336      abcdefghijklmnopqrs   abcdefghijklmnopqrs   |
    337      ABCDEFGHIJKLMNOPQRS   ABCDEFGHIJKLMNOPQRS   |
    338      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    339      {5:-- VISUAL --}                                 |
    340    ]])
    341 
    342    command('set selection=exclusive')
    343    screen:expect([[
    344        line1 foo{17:^ ba}r         line1 foo{17: ba}r       |
    345      abcdefghijklmnopqrs   abcdefghijklmnopqrs   |
    346      ABCDEFGHIJKLMNOPQRS   ABCDEFGHIJKLMNOPQRS   |
    347      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    348      {5:-- VISUAL --}                                 |
    349    ]])
    350 
    351    feed('o')
    352    screen:expect([[
    353        line1 foo{17: ba}^r         line1 foo{17: ba}r       |
    354      abcdefghijklmnopqrs   abcdefghijklmnopqrs   |
    355      ABCDEFGHIJKLMNOPQRS   ABCDEFGHIJKLMNOPQRS   |
    356      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    357      {5:-- VISUAL --}                                 |
    358    ]])
    359 
    360    feed('V')
    361    screen:expect([[
    362      {17:  line1 foo ba^r}       {17:  line1 foo bar}       |
    363      abcdefghijklmnopqrs   abcdefghijklmnopqrs   |
    364      ABCDEFGHIJKLMNOPQRS   ABCDEFGHIJKLMNOPQRS   |
    365      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    366      {5:-- VISUAL LINE --}                            |
    367    ]])
    368 
    369    command('set cursorcolumn')
    370    feed('<C-V>')
    371    screen:expect([[
    372        line1 foo{17: ba}^r         line1 foo{17: ba}r       |
    373      abcdefghijklmn{21:o}pqrs   abcdefghijklmnopqrs   |
    374      ABCDEFGHIJKLMN{21:O}PQRS   ABCDEFGHIJKLMNOPQRS   |
    375      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    376      {5:-- VISUAL BLOCK --}                           |
    377    ]])
    378 
    379    command('set selection&')
    380    screen:expect([[
    381        line1 foo{17: ba^r}         line1 foo{17: bar}       |
    382      abcdefghijklmn{21:o}pqrs   abcdefghijklmnopqrs   |
    383      ABCDEFGHIJKLMN{21:O}PQRS   ABCDEFGHIJKLMNOPQRS   |
    384      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    385      {5:-- VISUAL BLOCK --}                           |
    386    ]])
    387 
    388    feed('^')
    389    screen:expect([[
    390        {17:^line1 foo }bar         {17:line1 foo }bar       |
    391      ab{21:c}defghijklmnopqrs   abcdefghijklmnopqrs   |
    392      AB{21:C}DEFGHIJKLMNOPQRS   ABCDEFGHIJKLMNOPQRS   |
    393      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    394      {5:-- VISUAL BLOCK --}                           |
    395    ]])
    396 
    397    feed('2j')
    398    screen:expect([[
    399        {17:line1 foo }bar         {17:line1 foo }bar       |
    400      ab{17:cdefghijkl}mnopqrs   ab{17:cdefghijkl}mnopqrs   |
    401      AB{17:^CDEFGHIJKL}MNOPQRS   AB{17:CDEFGHIJKL}MNOPQRS   |
    402      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    403      {5:-- VISUAL BLOCK --}                           |
    404    ]])
    405 
    406    command('set nocursorcolumn')
    407    feed('O')
    408    screen:expect([[
    409        {17:line1 foo }bar         {17:line1 foo }bar       |
    410      ab{17:cdefghijkl}mnopqrs   ab{17:cdefghijkl}mnopqrs   |
    411      AB{17:CDEFGHIJK^L}MNOPQRS   AB{17:CDEFGHIJKL}MNOPQRS   |
    412      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    413      {5:-- VISUAL BLOCK --}                           |
    414    ]])
    415 
    416    command('set selection=exclusive')
    417    screen:expect([[
    418        {17:line1 foo} bar         {17:line1 foo} bar       |
    419      ab{17:cdefghijk}lmnopqrs   ab{17:cdefghijk}lmnopqrs   |
    420      AB{17:CDEFGHIJK}^LMNOPQRS   AB{17:CDEFGHIJK}LMNOPQRS   |
    421      {3:[No Name] [+]          }{2:[No Name] [+]         }|
    422      {5:-- VISUAL BLOCK --}                           |
    423    ]])
    424  end)
    425 
    426  it('blockwise Visual highlight with virtualedit=block #34235', function()
    427    local screen = Screen.new(45, 5)
    428    command('set virtualedit=block')
    429    insert('foobar\nfoo')
    430    feed('0<C-V>k$')
    431    screen:expect([[
    432      {17:foobar}^                                       |
    433      {17:foo    }                                      |
    434      {1:~                                            }|*2
    435      {5:-- VISUAL BLOCK --}                           |
    436    ]])
    437    feed('10l')
    438    screen:expect([[
    439      {17:foobar          }^                             |
    440      {17:foo              }                            |
    441      {1:~                                            }|*2
    442      {5:-- VISUAL BLOCK --}                           |
    443    ]])
    444  end)
    445 
    446  it("is updated with H/L and 'scrolloff' #36059", function()
    447    local screen = Screen.new(40, 10)
    448    exec([[
    449      call setline(1, map(range(1, 100), "'line ' .. v:val"))
    450      set scrolloff=2 nostartofline
    451      call cursor(50, 1)
    452    ]])
    453    feed('z<CR>V')
    454    screen:expect([[
    455      line 48                                 |
    456      line 49                                 |
    457      ^l{17:ine 50}                                 |
    458      line 51                                 |
    459      line 52                                 |
    460      line 53                                 |
    461      line 54                                 |
    462      line 55                                 |
    463      line 56                                 |
    464      {5:-- VISUAL LINE --}                       |
    465    ]])
    466    feed('L')
    467    screen:expect([[
    468      line 48                                 |
    469      line 49                                 |
    470      {17:line 50}                                 |
    471      {17:line 51}                                 |
    472      {17:line 52}                                 |
    473      {17:line 53}                                 |
    474      ^l{17:ine 54}                                 |
    475      line 55                                 |
    476      line 56                                 |
    477      {5:-- VISUAL LINE --}                       |
    478    ]])
    479    feed('<Esc>V')
    480    screen:expect([[
    481      line 48                                 |
    482      line 49                                 |
    483      line 50                                 |
    484      line 51                                 |
    485      line 52                                 |
    486      line 53                                 |
    487      ^l{17:ine 54}                                 |
    488      line 55                                 |
    489      line 56                                 |
    490      {5:-- VISUAL LINE --}                       |
    491    ]])
    492    feed('H')
    493    screen:expect([[
    494      line 48                                 |
    495      line 49                                 |
    496      ^l{17:ine 50}                                 |
    497      {17:line 51}                                 |
    498      {17:line 52}                                 |
    499      {17:line 53}                                 |
    500      {17:line 54}                                 |
    501      line 55                                 |
    502      line 56                                 |
    503      {5:-- VISUAL LINE --}                       |
    504    ]])
    505  end)
    506 
    507  it('cterm=standout gui=standout', function()
    508    local screen = Screen.new(20, 5)
    509    screen:add_extra_attr_ids {
    510      [100] = {
    511        foreground = Screen.colors.Blue1,
    512        bold = true,
    513        background = Screen.colors.Grey90,
    514        underline = true,
    515        standout = true,
    516      },
    517      [101] = { underline = true, standout = true, background = Screen.colors.Grey90 },
    518    }
    519    feed_command('hi CursorLine cterm=standout,underline gui=standout,underline')
    520    feed_command('set cursorline')
    521    feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
    522    feed('i\t abcd <cr>\t abcd <cr><esc>k')
    523    screen:expect([[
    524    {1:>-------.}abcd{1:*¬}     |
    525    {100:^>-------.}{101:abcd}{100:*¬}{101:     }|
    526    {1:¬}                   |
    527    {1:~                   }|
    528                        |
    529    ]])
    530  end)
    531 
    532  it('strikethrough', function()
    533    local screen = Screen.new(25, 6)
    534    feed_command('syntax on')
    535    feed_command('syn keyword TmpKeyword foo')
    536    feed_command('hi! Awesome cterm=strikethrough gui=strikethrough')
    537    feed_command('hi link TmpKeyword Awesome')
    538    insert([[
    539      foo
    540      foo bar
    541      foobarfoobar
    542      ]])
    543    screen:expect(
    544      [[
    545      {1:foo}                      |
    546      {1:foo} bar                  |
    547      foobarfoobar             |
    548      ^                         |
    549      {2:~                        }|
    550                               |
    551    ]],
    552      {
    553        [1] = { strikethrough = true },
    554        [2] = { bold = true, foreground = Screen.colors.Blue1 },
    555      }
    556    )
    557  end)
    558 
    559  it('nocombine', function()
    560    local screen = Screen.new(25, 6)
    561    screen:add_extra_attr_ids {
    562      [100] = { underline = true, reverse = true, foreground = Screen.colors.SlateBlue },
    563      [101] = {
    564        foreground = Screen.colors.SlateBlue,
    565        reverse = true,
    566        background = Screen.colors.Yellow,
    567      },
    568    }
    569    feed_command('syntax on')
    570    feed_command('hi! Underlined cterm=underline gui=underline')
    571    feed_command('syn keyword Underlined foobar')
    572    feed_command('hi Search cterm=inverse,nocombine gui=inverse,nocombine')
    573    insert([[
    574      foobar
    575      foobar
    576      ]])
    577    screen:expect {
    578      grid = [[
    579      {28:foobar}                   |*2
    580      ^                         |
    581      {1:~                        }|*2
    582                               |
    583    ]],
    584    }
    585 
    586    feed('/foo')
    587    screen:expect {
    588      grid = [[
    589      {100:foo}{28:bar}                   |
    590      {101:foo}{28:bar}                   |
    591                               |
    592      {1:~                        }|*2
    593      /foo^                     |
    594    ]],
    595    }
    596    feed('<cr>')
    597    screen:expect {
    598      grid = [[
    599      {101:^foo}{28:bar}                   |
    600      {101:foo}{28:bar}                   |
    601                               |
    602      {1:~                        }|*2
    603      {19:search hit...uing at TOP} |
    604    ]],
    605    }
    606  end)
    607 
    608  it('guisp (special/undercurl)', function()
    609    local screen = Screen.new(25, 10)
    610    feed_command('syntax on')
    611    feed_command('syn keyword TmpKeyword neovim')
    612    feed_command('syn keyword TmpKeyword1 special')
    613    feed_command('syn keyword TmpKeyword2 specialwithbg')
    614    feed_command('syn keyword TmpKeyword3 specialwithfg')
    615    feed_command('hi! Awesome guifg=red guibg=yellow guisp=red')
    616    feed_command('hi! Awesome1 guisp=red')
    617    feed_command('hi! Awesome2 guibg=yellow guisp=red')
    618    feed_command('hi! Awesome3 guifg=red guisp=red')
    619    feed_command('hi link TmpKeyword Awesome')
    620    feed_command('hi link TmpKeyword1 Awesome1')
    621    feed_command('hi link TmpKeyword2 Awesome2')
    622    feed_command('hi link TmpKeyword3 Awesome3')
    623    insert([[
    624      neovim
    625      awesome neovim
    626      wordcontainingneovim
    627      special
    628      specialwithbg
    629      specialwithfg
    630      ]])
    631    feed('Go<tab>neovim tabbed')
    632    screen:expect(
    633      [[
    634      {1:neovim}                   |
    635      awesome {1:neovim}           |
    636      wordcontainingneovim     |
    637      {2:special}                  |
    638      {3:specialwithbg}            |
    639      {4:specialwithfg}            |
    640                               |
    641              {1:neovim} tabbed^    |
    642      {0:~                        }|
    643      {5:-- INSERT --}             |
    644    ]],
    645      {
    646        [0] = { bold = true, foreground = Screen.colors.Blue },
    647        [1] = {
    648          background = Screen.colors.Yellow,
    649          foreground = Screen.colors.Red,
    650          special = Screen.colors.Red,
    651        },
    652        [2] = { special = Screen.colors.Red },
    653        [3] = { special = Screen.colors.Red, background = Screen.colors.Yellow },
    654        [4] = { foreground = Screen.colors.Red, special = Screen.colors.Red },
    655        [5] = { bold = true },
    656      }
    657    )
    658  end)
    659 
    660  it("'diff', syntax and extmark #23722", function()
    661    local screen = Screen.new(25, 10)
    662    exec([[
    663      new
    664      call setline(1, ['', '01234 6789'])
    665      windo diffthis
    666      wincmd w
    667      syn match WarningMsg "^.*$"
    668      call nvim_buf_add_highlight(0, -1, 'ErrorMsg', 1, 2, 8)
    669    ]])
    670    screen:expect(
    671      [[
    672      {1:  }{5:^                       }|
    673      {1:  }{2:01}{3:234 67}{2:89}{5:             }|
    674      {4:~                        }|*2
    675      {7:[No Name] [+]            }|
    676      {1:  }{6:-----------------------}|*2
    677      {1:  }                       |
    678      {8:[No Name]                }|
    679                               |
    680    ]],
    681      {
    682        [0] = { Screen.colors.WebGray, foreground = Screen.colors.DarkBlue },
    683        [1] = { background = Screen.colors.Grey, foreground = Screen.colors.Blue4 },
    684        [2] = { foreground = Screen.colors.Red, background = Screen.colors.LightBlue },
    685        [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.LightBlue },
    686        [4] = { bold = true, foreground = Screen.colors.Blue },
    687        [5] = { background = Screen.colors.LightBlue },
    688        [6] = {
    689          bold = true,
    690          background = Screen.colors.LightCyan,
    691          foreground = Screen.colors.Blue1,
    692        },
    693        [7] = { reverse = true, bold = true },
    694        [8] = { reverse = true },
    695      }
    696    )
    697  end)
    698 end)
    699 
    700 describe("'listchars' highlight", function()
    701  local screen
    702 
    703  before_each(function()
    704    clear()
    705    screen = Screen.new(20, 5)
    706  end)
    707 
    708  it("'cursorline' and 'cursorcolumn'", function()
    709    feed_command('highlight clear ModeMsg')
    710    feed_command('set cursorline')
    711    feed('i')
    712    screen:expect([[
    713      {21:^                    }|
    714      {1:~                   }|*3
    715      -- INSERT --        |
    716    ]])
    717    feed('abcdefg<cr>kkasdf')
    718    screen:expect([[
    719      abcdefg             |
    720      {21:kkasdf^              }|
    721      {1:~                   }|*2
    722      -- INSERT --        |
    723    ]])
    724    feed('<esc>')
    725    screen:expect([[
    726      abcdefg             |
    727      {21:kkasd^f              }|
    728      {1:~                   }|*2
    729                          |
    730    ]])
    731    feed_command('set nocursorline')
    732    screen:expect([[
    733      abcdefg             |
    734      kkasd^f              |
    735      {1:~                   }|*2
    736      :set nocursorline   |
    737    ]])
    738    feed('k')
    739    screen:expect([[
    740      abcde^fg             |
    741      kkasdf              |
    742      {1:~                   }|*2
    743      :set nocursorline   |
    744    ]])
    745    feed('jjji<cr><cr><cr><esc>')
    746    screen:expect([[
    747      kkasd               |
    748                          |*2
    749      ^f                   |
    750                          |
    751    ]])
    752    feed_command('set cursorline')
    753    feed_command('set cursorcolumn')
    754    feed('kkiabcdefghijk<esc>hh')
    755    screen:expect([[
    756      kkasd   {21: }           |
    757      {21:abcdefgh^ijk         }|
    758              {21: }           |
    759      f       {21: }           |
    760                          |
    761    ]])
    762    feed('khh')
    763    screen:expect([[
    764      {21:kk^asd               }|
    765      ab{21:c}defghijk         |
    766        {21: }                 |
    767      f {21: }                 |
    768                          |
    769    ]])
    770  end)
    771 
    772  it("'cursorline' and with 'listchars' option", function()
    773    screen:add_extra_attr_ids {
    774      [100] = { foreground = Screen.colors.Red, background = Screen.colors.Grey90 },
    775      [101] = { foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.Grey90 },
    776    }
    777    feed_command('highlight clear ModeMsg')
    778    feed_command('highlight Whitespace guifg=#FF0000')
    779    feed_command('set cursorline')
    780    feed_command('set tabstop=8')
    781    feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
    782    feed('i\t abcd <cr>\t abcd <cr><esc>k')
    783    screen:expect([[
    784      {19:>-------.}abcd{19:*}{1:¬}     |
    785      {100:^>-------.}{21:abcd}{100:*}{101:¬}{21:     }|
    786      {1:¬}                   |
    787      {1:~                   }|
    788                          |
    789    ]])
    790    feed('k')
    791    screen:expect([[
    792      {100:^>-------.}{21:abcd}{100:*}{101:¬}{21:     }|
    793      {19:>-------.}abcd{19:*}{1:¬}     |
    794      {1:¬}                   |
    795      {1:~                   }|
    796                          |
    797    ]])
    798    feed_command('set nocursorline')
    799    screen:expect([[
    800      {19:^>-------.}abcd{19:*}{1:¬}     |
    801      {19:>-------.}abcd{19:*}{1:¬}     |
    802      {1:¬}                   |
    803      {1:~                   }|
    804      :set nocursorline   |
    805    ]])
    806    feed_command('set nowrap')
    807    feed('ALorem ipsum dolor sit amet<ESC>0')
    808    screen:expect([[
    809      {19:^>-------.}abcd{19:.}Lorem{1:>}|
    810      {19:>-------.}abcd{19:*}{1:¬}     |
    811      {1:¬}                   |
    812      {1:~                   }|
    813                          |
    814    ]])
    815    feed_command('set cursorline')
    816    screen:expect([[
    817      {100:^>-------.}{21:abcd}{100:.}{21:Lorem}{101:>}|
    818      {19:>-------.}abcd{19:*}{1:¬}     |
    819      {1:¬}                   |
    820      {1:~                   }|
    821      :set cursorline     |
    822    ]])
    823    feed('$')
    824    screen:expect([[
    825      {101:<}{21:r}{100:.}{21:sit}{100:.}{21:ame^t}{101:¬}{21:        }|
    826      {1:<}                   |*2
    827      {1:~                   }|
    828      :set cursorline     |
    829    ]])
    830    feed('G')
    831    screen:expect([[
    832      {19:>-------.}abcd{19:.}Lorem{1:>}|
    833      {19:>-------.}abcd{19:*}{1:¬}     |
    834      {101:^¬}{21:                   }|
    835      {1:~                   }|
    836      :set cursorline     |
    837    ]])
    838  end)
    839 
    840  it("'listchar' with wrap", function()
    841    feed_command('set wrap')
    842    feed_command('set listchars=eol:¬,precedes:< list')
    843    feed('90ia<esc>')
    844    screen:expect([[
    845      {1:<}aaaaaaaaaaaaaaaaaaa|
    846      aaaaaaaaaaaaaaaaaaaa|*2
    847      aaaaaaaaa^a{1:¬}         |
    848                          |
    849    ]])
    850    feed('0')
    851    screen:expect([[
    852      ^aaaaaaaaaaaaaaaaaaaa|
    853      aaaaaaaaaaaaaaaaaaaa|*3
    854                          |
    855    ]])
    856  end)
    857 
    858  it("'listchar' in visual mode", function()
    859    screen:add_extra_attr_ids {
    860      [100] = {
    861        foreground = Screen.colors.Blue1,
    862        bold = true,
    863        background = Screen.colors.LightGray,
    864      },
    865      [101] = { foreground = Screen.colors.Red, background = Screen.colors.Grey90 },
    866      [102] = { foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.Grey90 },
    867      [103] = { foreground = Screen.colors.Red, background = Screen.colors.LightGray },
    868    }
    869    command('highlight clear ModeMsg')
    870    command('highlight Whitespace guifg=#FF0000')
    871    command('set cursorline')
    872    command('set tabstop=8')
    873    command('set nowrap')
    874    command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
    875    feed('i\t abcd <cr>\t abcd Lorem ipsum dolor sit amet<cr><esc>kkk0')
    876    screen:expect([[
    877      {101:^>-------.}{21:abcd}{101:*}{102:¬}{21:     }|
    878      {19:>-------.}abcd{19:.}Lorem{1:>}|
    879      {1:¬}                   |
    880      {1:~                   }|
    881                          |
    882    ]])
    883    feed('lllvj')
    884    screen:expect([[
    885      {19:>-------.}a{17:bcd}{103:*}{100:¬}     |
    886      {103:>-------.}{17:a}^bcd{19:.}Lorem{1:>}|
    887      {1:¬}                   |
    888      {1:~                   }|
    889      -- VISUAL --        |
    890    ]])
    891    feed('<esc>V')
    892    screen:expect([[
    893      {19:>-------.}abcd{19:*}{1:¬}     |
    894      {103:>-------.}{17:a}^b{17:cd}{103:.}{17:Lorem}{1:>}|
    895      {1:¬}                   |
    896      {1:~                   }|
    897      -- VISUAL LINE --   |
    898    ]])
    899    feed('<esc>$')
    900    screen:expect([[
    901      {1:<}                   |
    902      {102:<}{21:r}{101:.}{21:sit}{101:.}{21:ame^t}{102:¬}{21:        }|
    903      {1:<}                   |
    904      {1:~                   }|
    905                          |
    906    ]])
    907  end)
    908 
    909  it("'cursorline' with :match", function()
    910    screen:add_extra_attr_ids {
    911      [100] = { foreground = Screen.colors.Lime, background = Screen.colors.Red },
    912    }
    913    feed_command('highlight clear ModeMsg')
    914    feed_command('highlight Whitespace guifg=#FF0000')
    915    feed_command('highlight Error guifg=#00FF00')
    916    feed_command('set nowrap')
    917    feed('ia \t bc \t  <esc>')
    918    screen:expect([[
    919      a        bc      ^   |
    920      {1:~                   }|*3
    921                          |
    922    ]])
    923    feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
    924    screen:expect([[
    925      a{19:.>-----.}bc{19:*>---*^*}{1:¬} |
    926      {1:~                   }|*3
    927                          |
    928    ]])
    929    feed_command('match Error /\\s\\+$/')
    930    screen:expect([[
    931      a{19:.>-----.}bc{100:*>---*^*}{1:¬} |
    932      {1:~                   }|*3
    933                          |
    934    ]])
    935  end)
    936 end)
    937 
    938 describe('CursorLine and CursorLineNr highlights', function()
    939  before_each(clear)
    940 
    941  it('overridden by Error, ColorColumn if fg not set', function()
    942    local screen = Screen.new(50, 5)
    943    screen:add_extra_attr_ids {
    944      [100] = { background = Screen.colors.LightRed },
    945      [101] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Grey90 },
    946    }
    947 
    948    command('filetype on')
    949    command('syntax on')
    950    command('set cursorline ft=json')
    951    feed('i{<cr>"a" : abc // 10;<cr>}<cr><esc>')
    952    screen:expect([[
    953      {16:{}                                                 |
    954      "{15:a}" : {9:abc} {9:// 10;}                                  |
    955      {16:}}                                                 |
    956      {21:^                                                  }|
    957                                                        |
    958    ]])
    959 
    960    command('set colorcolumn=3')
    961    feed('i  <esc>')
    962    screen:expect([[
    963      {16:{} {100: }                                               |
    964      "{15:a}{100:"} : {9:abc} {9:// 10;}                                  |
    965      {16:}} {100: }                                               |
    966      {21: ^ }{100: }{21:                                               }|
    967                                                        |
    968    ]])
    969  end)
    970 
    971  it("overridden by NonText in 'showbreak' characters", function()
    972    local screen = Screen.new(20, 5)
    973    screen:add_extra_attr_ids {
    974      [100] = { foreground = Screen.colors.Yellow1 },
    975      [101] = { foreground = Screen.colors.Yellow1, background = Screen.colors.Blue },
    976      [102] = { foreground = Screen.colors.Grey0, background = Screen.colors.Grey100 },
    977      [103] = { foreground = Screen.colors.Yellow1, background = Screen.colors.Grey100 },
    978    }
    979 
    980    feed_command('set wrap cursorline')
    981    feed_command('set showbreak=>>>')
    982    feed_command('highlight clear NonText')
    983    feed_command('highlight clear CursorLine')
    984    feed_command('highlight NonText guifg=Yellow guibg=Blue gui=NONE')
    985    feed_command('highlight CursorLine guifg=Black guibg=White gui=NONE')
    986 
    987    feed('30iø<esc>o<esc>30ia<esc>')
    988    screen:expect([[
    989      øøøøøøøøøøøøøøøøøøøø|
    990      {101:>>>}øøøøøøøøøø       |
    991      {102:aaaaaaaaaaaaaaaaaaaa}|
    992      {101:>>>}{102:aaaaaaaaa^a       }|
    993                          |
    994    ]])
    995    feed('k')
    996    screen:expect([[
    997      {102:øøøøøøøøøøøøøøøøøøøø}|
    998      {101:>>>}{102:øøøøøøøøø^ø       }|
    999      aaaaaaaaaaaaaaaaaaaa|
   1000      {101:>>>}aaaaaaaaaa       |
   1001                          |
   1002    ]])
   1003    feed_command('highlight NonText guibg=NONE')
   1004    screen:expect([[
   1005      {102:øøøøøøøøøøøøøøøøøøøø}|
   1006      {103:>>>}{102:øøøøøøøøø^ø       }|
   1007      aaaaaaaaaaaaaaaaaaaa|
   1008      {100:>>>}aaaaaaaaaa       |
   1009                          |
   1010    ]])
   1011    feed_command('set nocursorline')
   1012    screen:expect([[
   1013      øøøøøøøøøøøøøøøøøøøø|
   1014      {100:>>>}øøøøøøøøø^ø       |
   1015      aaaaaaaaaaaaaaaaaaaa|
   1016      {100:>>>}aaaaaaaaaa       |
   1017      :set nocursorline   |
   1018    ]])
   1019  end)
   1020 
   1021  it("'cursorlineopt' screenline", function()
   1022    local screen = Screen.new(20, 5)
   1023    screen:add_extra_attr_ids {
   1024      [100] = { foreground = Screen.colors.Yellow },
   1025      [101] = { foreground = Screen.colors.Red, background = Screen.colors.WebGreen },
   1026      [102] = { foreground = Screen.colors.Black, background = Screen.colors.Grey100 },
   1027      [103] = { foreground = Screen.colors.WebGreen, background = Screen.colors.Red },
   1028    }
   1029 
   1030    command('set wrap cursorline cursorlineopt=screenline')
   1031    command('set showbreak=>>>')
   1032    command('highlight clear NonText')
   1033    command('highlight clear CursorLine')
   1034    command('highlight NonText guifg=Yellow gui=NONE')
   1035    command('highlight LineNr guifg=Red guibg=Green gui=NONE')
   1036    command('highlight CursorLine guifg=Black guibg=White gui=NONE')
   1037    command('highlight CursorLineNr guifg=Green guibg=Red gui=NONE')
   1038 
   1039    feed('30iø<esc>o<esc>30ia<esc>')
   1040 
   1041    -- CursorLine should not apply to 'showbreak' when 'cursorlineopt' contains "screenline"
   1042    screen:expect([[
   1043      øøøøøøøøøøøøøøøøøøøø|
   1044      {100:>>>}øøøøøøøøøø       |
   1045      aaaaaaaaaaaaaaaaaaaa|
   1046      {100:>>>}{102:aaaaaaaaa^a       }|
   1047                          |
   1048    ]])
   1049    feed('gk')
   1050    screen:expect([[
   1051      øøøøøøøøøøøøøøøøøøøø|
   1052      {100:>>>}øøøøøøøøøø       |
   1053      {102:aaaaaaaaaaaa^aaaaaaaa}|
   1054      {100:>>>}aaaaaaaaaa       |
   1055                          |
   1056    ]])
   1057    feed('k')
   1058    screen:expect([[
   1059      {102:øøøøøøøøøøøø^øøøøøøøø}|
   1060      {100:>>>}øøøøøøøøøø       |
   1061      aaaaaaaaaaaaaaaaaaaa|
   1062      {100:>>>}aaaaaaaaaa       |
   1063                          |
   1064    ]])
   1065 
   1066    -- CursorLineNr should not apply to line number when 'cursorlineopt' does not contain "number"
   1067    command('set relativenumber numberwidth=2')
   1068    screen:expect([[
   1069      {101:0 }{102:øøøøøøøøøøøø^øøøøøø}|
   1070      {101:  }{100:>>>}øøøøøøøøøøøø   |
   1071      {101:1 }aaaaaaaaaaaaaaaaaa|
   1072      {101:  }{100:>>>}aaaaaaaaaaaa   |
   1073                          |
   1074    ]])
   1075 
   1076    -- CursorLineNr should apply to line number when 'cursorlineopt' contains "number"
   1077    command('set cursorlineopt+=number')
   1078    screen:expect([[
   1079      {103:0 }{102:øøøøøøøøøøøø^øøøøøø}|
   1080      {101:  }{100:>>>}øøøøøøøøøøøø   |
   1081      {101:1 }aaaaaaaaaaaaaaaaaa|
   1082      {101:  }{100:>>>}aaaaaaaaaaaa   |
   1083                          |
   1084    ]])
   1085    feed('gj')
   1086    screen:expect([[
   1087      {103:0 }øøøøøøøøøøøøøøøøøø|
   1088      {101:  }{100:>>>}{102:øøøøøøøøø^øøø   }|
   1089      {101:1 }aaaaaaaaaaaaaaaaaa|
   1090      {101:  }{100:>>>}aaaaaaaaaaaa   |
   1091                          |
   1092    ]])
   1093    feed('gj')
   1094    screen:expect([[
   1095      {101:1 }øøøøøøøøøøøøøøøøøø|
   1096      {101:  }{100:>>>}øøøøøøøøøøøø   |
   1097      {103:0 }{102:aaaaaaaaaaaa^aaaaaa}|
   1098      {101:  }{100:>>>}aaaaaaaaaaaa   |
   1099                          |
   1100    ]])
   1101    feed('gj')
   1102    screen:expect([[
   1103      {101:1 }øøøøøøøøøøøøøøøøøø|
   1104      {101:  }{100:>>>}øøøøøøøøøøøø   |
   1105      {103:0 }aaaaaaaaaaaaaaaaaa|
   1106      {101:  }{100:>>>}{102:aaaaaaaaa^aaa   }|
   1107                          |
   1108    ]])
   1109 
   1110    -- updated in Insert mode
   1111    feed('I')
   1112    screen:expect([[
   1113      {101:1 }øøøøøøøøøøøøøøøøøø|
   1114      {101:  }{100:>>>}øøøøøøøøøøøø   |
   1115      {103:0 }{102:^aaaaaaaaaaaaaaaaaa}|
   1116      {101:  }{100:>>>}aaaaaaaaaaaa   |
   1117      {5:-- INSERT --}        |
   1118    ]])
   1119 
   1120    feed('<Esc>gg')
   1121    screen:expect([[
   1122      {103:0 }{102:^øøøøøøøøøøøøøøøøøø}|
   1123      {101:  }{100:>>>}øøøøøøøøøøøø   |
   1124      {101:1 }aaaaaaaaaaaaaaaaaa|
   1125      {101:  }{100:>>>}aaaaaaaaaaaa   |
   1126                          |
   1127    ]])
   1128  end)
   1129 
   1130  -- oldtest: Test_cursorline_screenline_resize()
   1131  it("'cursorlineopt' screenline is updated on window resize", function()
   1132    local screen = Screen.new(75, 8)
   1133    exec([[
   1134      50vnew
   1135      call setline(1, repeat('xyz ', 30))
   1136      setlocal number cursorline cursorlineopt=screenline
   1137      normal! $
   1138    ]])
   1139    screen:expect([[
   1140      {8:  1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xy                        |
   1141      {8:    }z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz {1:~                       }|
   1142      {8:    }{21:xyz xyz xyz xyz xyz xyz xyz^                   }{1:~                       }|
   1143      {1:~                                                 }{1:~                       }|*3
   1144      {3:[No Name] [+]                                      }{2:[No Name]               }|
   1145                                                                                 |
   1146    ]])
   1147    command('vertical resize -4')
   1148    screen:expect([[
   1149      {8:  1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xy                            |
   1150      {8:    }z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz {1:~                           }|
   1151      {8:    }{21:xyz xyz xyz xyz xyz xyz xyz xyz xyz^       }{1:~                           }|
   1152      {1:~                                             }{1:~                           }|*3
   1153      {3:[No Name] [+]                                  }{2:[No Name]                   }|
   1154                                                                                 |
   1155    ]])
   1156    command('set cpoptions+=n')
   1157    screen:expect([[
   1158      {8:  1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xy                            |
   1159      z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz {1:~                           }|
   1160      {21:xyz xyz xyz xyz xyz xyz xyz xyz^               }{1:~                           }|
   1161      {1:~                                             }{1:~                           }|*3
   1162      {3:[No Name] [+]                                  }{2:[No Name]                   }|
   1163                                                                                 |
   1164    ]])
   1165  end)
   1166 
   1167  -- oldtest: Test_cursorline_screenline_update()
   1168  it("'cursorlineopt' screenline is updated on various movements", function()
   1169    local screen = Screen.new(75, 8)
   1170    exec([[
   1171      func TestRetab()
   1172        let w = winwidth(0)
   1173        call cursor([1, w + 1, 0, w + 1])
   1174        call line('w0')
   1175        retab 8
   1176      endfunc
   1177 
   1178      call setline(1, repeat('xyz ', 30))
   1179      set cursorline cursorlineopt=screenline tabstop=8
   1180      inoremap <F2> <Cmd>call cursor(1, 1)<CR>
   1181      inoremap <F3> <Cmd>call TestRetab()<CR>
   1182    ]])
   1183 
   1184    feed('A')
   1185    screen:expect([[
   1186      xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz|
   1187      {21: xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz ^                              }|
   1188      {1:~                                                                          }|*5
   1189      {5:-- INSERT --}                                                               |
   1190    ]])
   1191    feed('<F2>')
   1192    screen:expect([[
   1193      {21:^xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz}|
   1194       xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz                               |
   1195      {1:~                                                                          }|*5
   1196      {5:-- INSERT --}                                                               |
   1197    ]])
   1198    feed('<F3>')
   1199    screen:expect([[
   1200      xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz|
   1201      {21:^ xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz                               }|
   1202      {1:~                                                                          }|*5
   1203      {5:-- INSERT --}                                                               |
   1204    ]])
   1205    feed('<Esc>')
   1206  end)
   1207 
   1208  -- oldtest: Test_cursorline_after_yank()
   1209  it('always updated. vim-patch:8.1.0849', function()
   1210    local screen = Screen.new(50, 5)
   1211    screen:add_extra_attr_ids {
   1212      [100] = { background = Screen.colors.LightRed },
   1213      [101] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Grey90 },
   1214    }
   1215    command('set cursorline relativenumber')
   1216    command('call setline(1, ["","1","2","3",""])')
   1217    feed('Gy3k')
   1218    screen:expect([[
   1219      {15:  0 }{21:^1                                             }|
   1220      {8:  1 }2                                             |
   1221      {8:  2 }3                                             |
   1222      {8:  3 }                                              |
   1223      4 lines yanked                                    |
   1224    ]])
   1225    feed('jj')
   1226    screen:expect([[
   1227      {8:  2 }1                                             |
   1228      {8:  1 }2                                             |
   1229      {15:  0 }{21:^3                                             }|
   1230      {8:  1 }                                              |
   1231      4 lines yanked                                    |
   1232    ]])
   1233  end)
   1234 
   1235  -- oldtest: Test_cursorline_with_visualmode()
   1236  it('with visual area. vim-patch:8.1.1001', function()
   1237    local screen = Screen.new(50, 5)
   1238    screen:add_extra_attr_ids {
   1239      [100] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Grey90 },
   1240      [101] = { background = Screen.colors.LightRed },
   1241    }
   1242    command('set cursorline')
   1243    command('call setline(1, repeat(["abc"], 50))')
   1244    feed('V<C-f>zbkkjk')
   1245    screen:expect([[
   1246      {17:abc}                                               |
   1247      ^a{17:bc}                                               |
   1248      abc                                               |*2
   1249      {5:-- VISUAL LINE --}                                 |
   1250    ]])
   1251  end)
   1252 
   1253  -- oldtest: Test_cursorline_callback()
   1254  it('is updated if cursor is moved up from timer vim-patch:8.2.4591', function()
   1255    local screen = Screen.new(50, 8)
   1256    exec([[
   1257      call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd'])
   1258      set cursorline
   1259      call cursor(4, 1)
   1260 
   1261      func Func(timer)
   1262        call cursor(2, 1)
   1263      endfunc
   1264    ]])
   1265    screen:expect([[
   1266      aaaaa                                             |
   1267      bbbbb                                             |
   1268      ccccc                                             |
   1269      {21:^ddddd                                             }|
   1270      {1:~                                                 }|*3
   1271                                                        |
   1272    ]])
   1273    command([[call timer_start(300, 'Func')]])
   1274    screen:expect_unchanged(false, 100)
   1275    screen:expect([[
   1276      aaaaa                                             |
   1277      {21:^bbbbb                                             }|
   1278      ccccc                                             |
   1279      ddddd                                             |
   1280      {1:~                                                 }|*3
   1281                                                        |
   1282    ]])
   1283  end)
   1284 
   1285  it('with split windows in diff mode', function()
   1286    local screen = Screen.new(50, 12)
   1287    screen:add_extra_attr_ids {
   1288      [100] = { background = Screen.colors.Plum1, underline = true },
   1289      [101] = { background = Screen.colors.Red1, bold = true, underline = true },
   1290    }
   1291 
   1292    command('hi CursorLine ctermbg=red ctermfg=white guibg=red guifg=white')
   1293    command('set cursorline')
   1294    feed('iline 1 some text<cr>line 2 more text<cr>extra line!<cr>extra line!<cr>last line ...<cr>')
   1295    feed('<esc>gg')
   1296    command('vsplit')
   1297    command('enew')
   1298    feed(
   1299      'iline 1 some text<cr>line 2 moRe text!<cr>extra line!<cr>extra line!<cr>extra line!<cr>last line ...<cr>'
   1300    )
   1301    feed('<esc>gg')
   1302    command('windo diffthis')
   1303    screen:expect([[
   1304      {7:  }{9:line 1 some text       }{7:  }{9:^line 1 some text      }|
   1305      {7:  }{4:line 2 mo}{27:R}{4:e text}{27:!}{4:      }{7:  }{4:line 2 mo}{27:r}{4:e text      }|
   1306      {7:  }{22:extra line!            }{7:  }{23:----------------------}|
   1307      {7:  }extra line!            {7:  }extra line!           |*2
   1308      {7:  }last line ...          {7:  }last line ...         |
   1309      {7:  }                       {7:  }                      |
   1310      {1:~                        }{1:~                       }|*3
   1311      {2:[No Name] [+]             }{3:[No Name] [+]           }|
   1312                                                        |
   1313    ]])
   1314    feed('jjjjj')
   1315    screen:expect([[
   1316      {7:  }line 1 some text       {7:  }line 1 some text      |
   1317      {7:  }{4:line 2 mo}{27:R}{4:e text}{27:!}{4:      }{7:  }{4:line 2 mo}{27:r}{4:e text      }|
   1318      {7:  }{22:extra line!            }{7:  }{23:----------------------}|
   1319      {7:  }extra line!            {7:  }extra line!           |*2
   1320      {7:  }last line ...          {7:  }last line ...         |
   1321      {7:  }{9:                       }{7:  }{9:^                      }|
   1322      {1:~                        }{1:~                       }|*3
   1323      {2:[No Name] [+]             }{3:[No Name] [+]           }|
   1324                                                        |
   1325    ]])
   1326 
   1327    -- CursorLine with fg=NONE is "low-priority".
   1328    -- Rendered as underline in a diff-line. #9028
   1329    command('hi CursorLine ctermbg=red ctermfg=NONE guibg=red guifg=NONE')
   1330    feed('kkkk')
   1331    screen:expect([[
   1332      {7:  }line 1 some text       {7:  }line 1 some text      |
   1333      {7:  }{100:line 2 mo}{101:R}{100:e text}{101:!}{100:      }{7:  }{100:^line 2 mo}{101:r}{100:e text      }|
   1334      {7:  }{22:extra line!            }{7:  }{23:----------------------}|
   1335      {7:  }extra line!            {7:  }extra line!           |*2
   1336      {7:  }last line ...          {7:  }last line ...         |
   1337      {7:  }                       {7:  }                      |
   1338      {1:~                        }{1:~                       }|*3
   1339      {2:[No Name] [+]             }{3:[No Name] [+]           }|
   1340                                                        |
   1341    ]])
   1342  end)
   1343 
   1344  -- oldtest: Test_diff_with_cursorline_number()
   1345  it('CursorLineNr shows correctly just below filler lines', function()
   1346    local screen = Screen.new(50, 12)
   1347    screen:add_extra_attr_ids {
   1348      [100] = { foreground = Screen.colors.Black, bold = true, background = Screen.colors.Grey100 },
   1349    }
   1350 
   1351    command('hi CursorLine guibg=red guifg=white')
   1352    command('hi CursorLineNr guibg=white guifg=black gui=bold')
   1353    command('set cursorline number')
   1354    command('call setline(1, ["baz", "foo", "foo", "bar"])')
   1355    feed('2gg0')
   1356    command('vnew')
   1357    command('call setline(1, ["foo", "foo", "bar"])')
   1358    command('windo diffthis')
   1359    command('1wincmd w')
   1360    screen:expect([[
   1361      {7:  }{8:    }{23:-------------------}│{7:  }{8:  1 }{22:baz               }|
   1362      {7:  }{100:  1 }{9:^foo                }{7:  }{100:  2 }{9:foo               }|
   1363      {7:  }{8:  2 }foo                {7:  }{8:  3 }foo               |
   1364      {7:  }{8:  3 }bar                {7:  }{8:  4 }bar               |
   1365      {1:~                        }{1:~                       }|*6
   1366      {3:[No Name] [+]             }{2:[No Name] [+]           }|
   1367                                                        |
   1368    ]])
   1369    command('set cursorlineopt=number')
   1370    screen:expect([[
   1371      {7:  }{8:    }{23:-------------------}│{7:  }{8:  1 }{22:baz               }|
   1372      {7:  }{100:  1 }^foo                {7:  }{100:  2 }{9:foo               }|
   1373      {7:  }{8:  2 }foo                {7:  }{8:  3 }foo               |
   1374      {7:  }{8:  3 }bar                {7:  }{8:  4 }bar               |
   1375      {1:~                        }{1:~                       }|*6
   1376      {3:[No Name] [+]             }{2:[No Name] [+]           }|
   1377                                                        |
   1378    ]])
   1379  end)
   1380 
   1381  it('CursorLine overlays hl group linked to Normal', function()
   1382    local screen = Screen.new(50, 12)
   1383    screen:add_extra_attr_ids({
   1384      [101] = { background = Screen.colors.Grey90, foreground = Screen.colors.Grey100 },
   1385      [102] = { background = Screen.colors.DarkGray, foreground = Screen.colors.WebGreen },
   1386    })
   1387    command('hi Normal guibg=black guifg=white')
   1388    command('hi def link Test Normal')
   1389    feed('ifoo bar<ESC>')
   1390    feed(':call matchadd("Test", "bar")<cr>')
   1391    command('set cursorline')
   1392    screen:expect([[
   1393      {21:foo }{101:ba^r}{21:                                           }|
   1394      {1:~                                                 }|*10
   1395      :call matchadd("Test", "bar")                     |
   1396    ]])
   1397    api.nvim_buf_set_lines(0, 0, -1, false, { 'aaaaa', 'bbbbb' })
   1398    command('hi AAA guifg=Green guibg=DarkGrey ctermfg=Green ctermbg=DarkGrey')
   1399    fn.matchadd('AAA', 'aaaaa')
   1400    command('setlocal winhighlight=Normal:NormalFloat')
   1401    screen:expect([[
   1402      {102:aaaa^a}{21:                                             }|
   1403      {4:bbbbb                                             }|
   1404      {11:~                                                 }|*9
   1405      :call matchadd("Test", "bar")                     |
   1406    ]])
   1407  end)
   1408 end)
   1409 
   1410 describe('CursorColumn highlight', function()
   1411  local screen
   1412  before_each(function()
   1413    clear()
   1414    screen = Screen.new(50, 8)
   1415    screen:add_extra_attr_ids {
   1416      [100] = { background = Screen.colors.Blue1 },
   1417    }
   1418  end)
   1419 
   1420  it('is updated when pressing "i" on a TAB character', function()
   1421    exec([[
   1422      call setline(1, ['123456789', "a\tb"])
   1423      set cursorcolumn
   1424      call cursor(2, 2)
   1425    ]])
   1426    screen:expect([[
   1427      1234567{21:8}9                                         |
   1428      a      ^ b                                         |
   1429      {1:~                                                 }|*5
   1430                                                        |
   1431    ]])
   1432    feed('i')
   1433    screen:expect([[
   1434      1{21:2}3456789                                         |
   1435      a^       b                                         |
   1436      {1:~                                                 }|*5
   1437      {5:-- INSERT --}                                      |
   1438    ]])
   1439    feed('<C-O>')
   1440    screen:expect([[
   1441      1234567{21:8}9                                         |
   1442      a      ^ b                                         |
   1443      {1:~                                                 }|*5
   1444      {5:-- (insert) --}                                    |
   1445    ]])
   1446    feed('i')
   1447    screen:expect([[
   1448      1{21:2}3456789                                         |
   1449      a^       b                                         |
   1450      {1:~                                                 }|*5
   1451      {5:-- INSERT --}                                      |
   1452    ]])
   1453  end)
   1454 
   1455  -- oldtest: Test_cursorcolumn_callback()
   1456  it('is updated if cursor is moved from timer', function()
   1457    exec([[
   1458      call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd'])
   1459      set cursorcolumn
   1460      call cursor(4, 5)
   1461 
   1462      func Func(timer)
   1463        call cursor(1, 1)
   1464      endfunc
   1465    ]])
   1466    screen:expect([[
   1467      aaaa{21:a}                                             |
   1468      bbbb{21:b}                                             |
   1469      cccc{21:c}                                             |
   1470      dddd^d                                             |
   1471      {1:~                                                 }|*3
   1472                                                        |
   1473    ]])
   1474    command([[call timer_start(300, 'Func')]])
   1475    screen:expect_unchanged(false, 100)
   1476    screen:expect([[
   1477      ^aaaaa                                             |
   1478      {21:b}bbbb                                             |
   1479      {21:c}cccc                                             |
   1480      {21:d}dddd                                             |
   1481      {1:~                                                 }|*3
   1482                                                        |
   1483    ]])
   1484  end)
   1485 
   1486  it('is not shown on current line with virtualedit', function()
   1487    exec([[
   1488      hi! CursorColumn guibg=Red
   1489      hi! CursorLine guibg=Blue
   1490      set virtualedit=all cursorline cursorcolumn
   1491    ]])
   1492    insert('line 1\nline 2\nline 3')
   1493    feed('k')
   1494    screen:expect([[
   1495      line {30:1}                                            |
   1496      {100:line ^2                                            }|
   1497      line {30:3}                                            |
   1498      {1:~                                                 }|*4
   1499                                                        |
   1500    ]])
   1501    feed('l')
   1502    screen:expect([[
   1503      line 1{30: }                                           |
   1504      {100:line 2^                                            }|
   1505      line 3{30: }                                           |
   1506      {1:~                                                 }|*4
   1507                                                        |
   1508    ]])
   1509    feed('l')
   1510    screen:expect([[
   1511      line 1 {30: }                                          |
   1512      {100:line 2 ^                                           }|
   1513      line 3 {30: }                                          |
   1514      {1:~                                                 }|*4
   1515                                                        |
   1516    ]])
   1517    feed('l')
   1518    screen:expect([[
   1519      line 1  {30: }                                         |
   1520      {100:line 2  ^                                          }|
   1521      line 3  {30: }                                         |
   1522      {1:~                                                 }|*4
   1523                                                        |
   1524    ]])
   1525  end)
   1526 end)
   1527 
   1528 describe('ColorColumn highlight', function()
   1529  local screen
   1530 
   1531  before_each(function()
   1532    clear()
   1533    screen = Screen.new(40, 15)
   1534    screen:add_extra_attr_ids {
   1535      [100] = { foreground = Screen.colors.Red, background = Screen.colors.Grey90 },
   1536      [101] = { background = Screen.colors.LightRed },
   1537      [102] = { foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.LightRed },
   1538    }
   1539  end)
   1540 
   1541  -- oldtest: Test_colorcolumn()
   1542  it('when entering a buffer vim-patch:8.1.2073', function()
   1543    exec([[
   1544      set nohidden
   1545      split
   1546      edit X
   1547      call setline(1, ["1111111111","22222222222","3333333333"])
   1548      set nomodified
   1549      set colorcolumn=3,9
   1550      set number cursorline cursorlineopt=number
   1551      wincmd w
   1552      buf X
   1553    ]])
   1554    screen:expect([[
   1555      {15:  1 }11{101:1}11111{101:1}1                          |
   1556      {8:  2 }22{101:2}22222{101:2}22                         |
   1557      {8:  3 }33{101:3}33333{101:3}3                          |
   1558      {1:~                                       }|*3
   1559      {2:X                                       }|
   1560      {15:  1 }^11{101:1}11111{101:1}1                          |
   1561      {8:  2 }22{101:2}22222{101:2}22                         |
   1562      {8:  3 }33{101:3}33333{101:3}3                          |
   1563      {1:~                                       }|*3
   1564      {3:X                                       }|
   1565                                              |
   1566    ]])
   1567  end)
   1568 
   1569  -- oldtest: Test_colorcolumn_bri()
   1570  it("in 'breakindent' vim-patch:8.2.1689", function()
   1571    exec([[
   1572      call setline(1, 'The quick brown fox jumped over the lazy dogs')
   1573      set co=40 linebreak bri briopt=shift:2 cc=40,41,43
   1574    ]])
   1575    screen:expect([[
   1576      ^The quick brown fox jumped over the    {101: }|
   1577      {101: } {101:l}azy dogs                             |
   1578      {1:~                                       }|*12
   1579                                              |
   1580    ]])
   1581  end)
   1582 
   1583  -- oldtest: Test_colorcolumn_sbr()
   1584  it("in 'showbreak' vim-patch:8.2.1689", function()
   1585    exec([[
   1586      call setline(1, 'The quick brown fox jumped over the lazy dogs')
   1587      set co=40 showbreak=+++>\\  cc=40,41,43
   1588    ]])
   1589    screen:expect([[
   1590      ^The quick brown fox jumped over the laz{101:y}|
   1591      {102:+}{1:+}{102:+}{1:>\} dogs                              |
   1592      {1:~                                       }|*12
   1593                                              |
   1594    ]])
   1595  end)
   1596 
   1597  it('is combined with low-priority CursorLine highlight #23016', function()
   1598    screen:try_resize(40, 2)
   1599    command('set colorcolumn=30 cursorline')
   1600    screen:expect([[
   1601      {21:^                             }{101: }{21:          }|
   1602                                              |
   1603    ]])
   1604    command('hi clear ColorColumn')
   1605    screen:expect([[
   1606      {21:^                                        }|
   1607                                              |
   1608    ]])
   1609    command('hi ColorColumn guifg=Red')
   1610    screen:expect([[
   1611      {21:^                             }{100: }{21:          }|
   1612                                              |
   1613    ]])
   1614  end)
   1615 end)
   1616 
   1617 describe('MsgSeparator highlight and msgsep fillchar', function()
   1618  local screen
   1619  before_each(function()
   1620    clear()
   1621    screen = Screen.new(50, 5)
   1622    screen:set_default_attr_ids({
   1623      [1] = { bold = true, foreground = Screen.colors.Blue },
   1624      [2] = { bold = true, reverse = true },
   1625      [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
   1626      [4] = { background = Screen.colors.Cyan, bold = true, reverse = true },
   1627      [5] = { bold = true, background = Screen.colors.Magenta },
   1628      [6] = { background = Screen.colors.WebGray },
   1629      [7] = {
   1630        background = Screen.colors.WebGray,
   1631        bold = true,
   1632        foreground = Screen.colors.SeaGreen4,
   1633      },
   1634      [8] = { foreground = Screen.colors.Grey0, background = Screen.colors.Gray60 },
   1635      [9] = { foreground = Screen.colors.Grey40, background = Screen.colors.Gray60 },
   1636      [10] = { foreground = tonumber('0x000019'), background = Screen.colors.Gray60 },
   1637      [11] = { background = Screen.colors.Gray60, bold = true, foreground = tonumber('0x666699') },
   1638      [12] = { background = Screen.colors.Gray60, bold = true, foreground = tonumber('0x297d4e') },
   1639      [13] = { background = tonumber('0xff4cff'), bold = true, foreground = tonumber('0xb200ff') },
   1640    })
   1641  end)
   1642 
   1643  it('works', function()
   1644    -- defaults
   1645    feed_command('ls')
   1646    screen:expect([[
   1647                                                        |
   1648      {2:                                                  }|
   1649      :ls                                               |
   1650        1 %a   "[No Name]"                    line 1    |
   1651      {3:Press ENTER or type command to continue}^           |
   1652    ]])
   1653    feed('<cr>')
   1654 
   1655    feed_command('set fillchars+=msgsep:-')
   1656    feed_command('ls')
   1657    screen:expect([[
   1658                                                        |
   1659      {2:--------------------------------------------------}|
   1660      :ls                                               |
   1661        1 %a   "[No Name]"                    line 1    |
   1662      {3:Press ENTER or type command to continue}^           |
   1663    ]])
   1664 
   1665    -- linked to StatusLine per default
   1666    feed_command('hi StatusLine guibg=Cyan')
   1667    feed_command('ls')
   1668    screen:expect([[
   1669                                                        |
   1670      {4:--------------------------------------------------}|
   1671      :ls                                               |
   1672        1 %a   "[No Name]"                    line 1    |
   1673      {3:Press ENTER or type command to continue}^           |
   1674    ]])
   1675 
   1676    -- but can be unlinked
   1677    feed_command('hi clear MsgSeparator')
   1678    feed_command('hi MsgSeparator guibg=Magenta gui=bold')
   1679    feed_command('ls')
   1680    screen:expect([[
   1681                                                        |
   1682      {5:--------------------------------------------------}|
   1683      :ls                                               |
   1684        1 %a   "[No Name]"                    line 1    |
   1685      {3:Press ENTER or type command to continue}^           |
   1686    ]])
   1687  end)
   1688 
   1689  it('and MsgArea', function()
   1690    feed_command('hi MsgArea guibg=Gray')
   1691    screen:expect {
   1692      grid = [[
   1693      ^                                                  |
   1694      {1:~                                                 }|*3
   1695      {6:                                                  }|
   1696    ]],
   1697    }
   1698    feed(':ls')
   1699    screen:expect {
   1700      grid = [[
   1701                                                        |
   1702      {1:~                                                 }|*3
   1703      {6::ls^                                               }|
   1704    ]],
   1705    }
   1706    feed(':<cr>')
   1707    screen:expect {
   1708      grid = [[
   1709                                                        |
   1710      {2:                                                  }|
   1711      {6::ls:                                              }|
   1712      {6:  1 %a   "[No Name]"                    line 1    }|
   1713      {7:Press ENTER or type command to continue}{6:^           }|
   1714    ]],
   1715    }
   1716 
   1717    -- support madness^Wblending of message "overlay"
   1718    feed_command('hi MsgArea blend=20')
   1719    feed_command('hi clear MsgSeparator')
   1720    feed_command('hi MsgSeparator blend=30 guibg=Magenta')
   1721    screen:expect {
   1722      grid = [[
   1723      ^                                                  |
   1724      {1:~                                                 }|*3
   1725      {8::hi}{9: }{8:MsgSeparator}{9: }{8:blend=30}{9: }{8:guibg=Magenta}{9:           }|
   1726    ]],
   1727    }
   1728    feed(':ls')
   1729    screen:expect {
   1730      grid = [[
   1731                                                        |
   1732      {1:~                                                 }|*3
   1733      {8::ls}{9:^                                               }|
   1734    ]],
   1735    }
   1736    feed('<cr>')
   1737    screen:expect {
   1738      grid = [[
   1739                                                        |
   1740      {13:~                                                 }|
   1741      {10::ls}{11:                                               }|
   1742      {11:~ }{10:1}{11: }{10:%a}{11:   }{10:"[No}{11: }{10:Name]"}{11:                    }{10:line}{11: }{10:1}{11:    }|
   1743      {12:Press}{9: }{12:ENTER}{9: }{12:or}{9: }{12:type}{9: }{12:command}{9: }{12:to}{9: }{12:continue}{9:^           }|
   1744    ]],
   1745    }
   1746  end)
   1747 end)
   1748 
   1749 describe("'winhighlight' highlight", function()
   1750  local screen
   1751 
   1752  before_each(function()
   1753    clear()
   1754    screen = Screen.new(20, 8)
   1755    screen:set_default_attr_ids {
   1756      [0] = { bold = true, foreground = Screen.colors.Blue },
   1757      [1] = { background = Screen.colors.DarkBlue },
   1758      [2] = { background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Blue1 },
   1759      [3] = { bold = true, reverse = true },
   1760      [4] = { reverse = true },
   1761      [5] = { background = Screen.colors.DarkGreen },
   1762      [6] = { background = Screen.colors.DarkGreen, bold = true, foreground = Screen.colors.Blue1 },
   1763      [7] = { background = Screen.colors.DarkMagenta },
   1764      [8] = {
   1765        background = Screen.colors.DarkMagenta,
   1766        bold = true,
   1767        foreground = Screen.colors.Blue1,
   1768      },
   1769      [9] = { foreground = Screen.colors.Brown },
   1770      [10] = { foreground = Screen.colors.Brown, background = Screen.colors.DarkBlue },
   1771      [11] = { background = Screen.colors.DarkBlue, bold = true, reverse = true },
   1772      [12] = { background = Screen.colors.DarkGreen, reverse = true },
   1773      [13] = { background = Screen.colors.Magenta4, reverse = true },
   1774      [14] = { background = Screen.colors.DarkBlue, reverse = true },
   1775      [15] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
   1776      [16] = { foreground = Screen.colors.Blue1 },
   1777      [17] = { background = Screen.colors.LightRed },
   1778      [18] = { background = Screen.colors.Gray90 },
   1779      [19] = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray },
   1780      [20] = { background = Screen.colors.LightGrey, underline = true },
   1781      [21] = { bold = true },
   1782      [22] = { bold = true, foreground = Screen.colors.SeaGreen4 },
   1783      [23] = { background = Screen.colors.LightMagenta },
   1784      [24] = { background = Screen.colors.WebGray },
   1785      [25] = { bold = true, foreground = Screen.colors.Green1 },
   1786      [26] = { background = Screen.colors.Red },
   1787      [27] = { background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Green1 },
   1788      [28] = { bold = true, foreground = Screen.colors.Brown },
   1789      [29] = { foreground = Screen.colors.Blue1, background = Screen.colors.Red, bold = true },
   1790      [30] = { background = tonumber('0xff8800') },
   1791      [31] = { background = tonumber('0xff8800'), bold = true, foreground = Screen.colors.Blue },
   1792      [32] = { bold = true, reverse = true, background = Screen.colors.DarkGreen },
   1793    }
   1794    command('hi Background1 guibg=DarkBlue')
   1795    command('hi Background2 guibg=DarkGreen')
   1796  end)
   1797 
   1798  it('works for background color', function()
   1799    insert('aa')
   1800    command('split')
   1801    command('set winhl=Normal:Background1')
   1802    screen:expect([[
   1803      {1:a^a                  }|
   1804      {2:~                   }|*2
   1805      {3:[No Name] [+]       }|
   1806      aa                  |
   1807      {0:~                   }|
   1808      {4:[No Name] [+]       }|
   1809                          |
   1810    ]])
   1811 
   1812    command('enew')
   1813    screen:expect([[
   1814      {1:^                    }|
   1815      {2:~                   }|*2
   1816      {3:[No Name]           }|
   1817      aa                  |
   1818      {0:~                   }|
   1819      {4:[No Name] [+]       }|
   1820                          |
   1821    ]])
   1822  end)
   1823 
   1824  it('works for background color in rightleft window #22640', function()
   1825    -- Use a wide screen to also check that this doesn't overflow linebuf_attr.
   1826    screen:try_resize(80, 6)
   1827    insert('aa')
   1828    command('setlocal rightleft')
   1829    command('setlocal winhl=Normal:Background1')
   1830    screen:expect([[
   1831      {1:                                                                              ^aa}|
   1832      {2:                                                                               ~}|*4
   1833                                                                                      |
   1834    ]])
   1835    command('botright vsplit')
   1836    screen:expect([[
   1837      {1:                                     aa                                      ^aa}|
   1838      {2:                                      ~}{1:}{2:                                       ~}|*3
   1839      {4:[No Name] [+]                           }{3:[No Name] [+]                           }|
   1840                                                                                      |
   1841    ]])
   1842  end)
   1843 
   1844  it('handles undefined groups', function()
   1845    command('set winhl=Normal:Background1')
   1846    screen:expect([[
   1847      {1:^                    }|
   1848      {2:~                   }|*6
   1849                          |
   1850    ]])
   1851 
   1852    command('set winhl=xxx:yyy')
   1853    eq('xxx:yyy', eval('&winhl'))
   1854    screen:expect {
   1855      grid = [[
   1856      ^                    |
   1857      {0:~                   }|*6
   1858                          |
   1859    ]],
   1860    }
   1861  end)
   1862 
   1863  it('can be changed to define different groups', function()
   1864    command('set winhl=EndOfBuffer:Background1')
   1865    screen:expect {
   1866      grid = [[
   1867      ^                    |
   1868      {1:~                   }|*6
   1869                          |
   1870    ]],
   1871    }
   1872 
   1873    command('set winhl=Normal:ErrorMsg')
   1874    screen:expect {
   1875      grid = [[
   1876      {15:^                    }|
   1877      {29:~                   }|*6
   1878                          |
   1879    ]],
   1880    }
   1881  end)
   1882 
   1883  it('works local to the window', function()
   1884    insert('aa')
   1885    command('split')
   1886    command('setlocal winhl=Normal:Background1')
   1887    screen:expect([[
   1888      {1:a^a                  }|
   1889      {2:~                   }|*2
   1890      {3:[No Name] [+]       }|
   1891      aa                  |
   1892      {0:~                   }|
   1893      {4:[No Name] [+]       }|
   1894                          |
   1895    ]])
   1896 
   1897    command('enew')
   1898    screen:expect([[
   1899      ^                    |
   1900      {0:~                   }|*2
   1901      {3:[No Name]           }|
   1902      aa                  |
   1903      {0:~                   }|
   1904      {4:[No Name] [+]       }|
   1905                          |
   1906    ]])
   1907 
   1908    command('bnext')
   1909    screen:expect([[
   1910      {1:^aa                  }|
   1911      {2:~                   }|*2
   1912      {3:[No Name] [+]       }|
   1913      aa                  |
   1914      {0:~                   }|
   1915      {4:[No Name] [+]       }|
   1916                          |
   1917    ]])
   1918  end)
   1919 
   1920  it('for inactive window background works', function()
   1921    command('set winhl=Normal:Background1,NormalNC:Background2')
   1922    -- tests global value is copied across split
   1923    command('split')
   1924    screen:expect([[
   1925      {1:^                    }|
   1926      {2:~                   }|*2
   1927      {3:[No Name]           }|
   1928      {5:                    }|
   1929      {6:~                   }|
   1930      {4:[No Name]           }|
   1931                          |
   1932    ]])
   1933 
   1934    feed('<c-w><c-w>')
   1935    screen:expect([[
   1936      {5:                    }|
   1937      {6:~                   }|*2
   1938      {4:[No Name]           }|
   1939      {1:^                    }|
   1940      {2:~                   }|
   1941      {3:[No Name]           }|
   1942                          |
   1943    ]])
   1944 
   1945    feed('<c-w><c-w>')
   1946    screen:expect([[
   1947      {1:^                    }|
   1948      {2:~                   }|*2
   1949      {3:[No Name]           }|
   1950      {5:                    }|
   1951      {6:~                   }|
   1952      {4:[No Name]           }|
   1953                          |
   1954    ]])
   1955  end)
   1956 
   1957  it('works with NormalNC', function()
   1958    command('hi NormalNC guibg=DarkMagenta')
   1959    -- tests global value is copied across split
   1960    command('split')
   1961    screen:expect([[
   1962      ^                    |
   1963      {0:~                   }|*2
   1964      {3:[No Name]           }|
   1965      {7:                    }|
   1966      {8:~                   }|
   1967      {4:[No Name]           }|
   1968                          |
   1969    ]])
   1970 
   1971    command('wincmd w')
   1972    screen:expect([[
   1973      {7:                    }|
   1974      {8:~                   }|*2
   1975      {4:[No Name]           }|
   1976      ^                    |
   1977      {0:~                   }|
   1978      {3:[No Name]           }|
   1979                          |
   1980    ]])
   1981 
   1982    -- winbg=Normal:... overrides global NormalNC
   1983    command('set winhl=Normal:Background1')
   1984    screen:expect([[
   1985      {7:                    }|
   1986      {8:~                   }|*2
   1987      {4:[No Name]           }|
   1988      {1:^                    }|
   1989      {2:~                   }|
   1990      {3:[No Name]           }|
   1991                          |
   1992    ]])
   1993 
   1994    command('wincmd w')
   1995    screen:expect([[
   1996      ^                    |
   1997      {0:~                   }|*2
   1998      {3:[No Name]           }|
   1999      {1:                    }|
   2000      {2:~                   }|
   2001      {4:[No Name]           }|
   2002                          |
   2003    ]])
   2004 
   2005    command('wincmd w')
   2006    command('set winhl=Normal:Background1,NormalNC:Background2')
   2007    screen:expect([[
   2008      {7:                    }|
   2009      {8:~                   }|*2
   2010      {4:[No Name]           }|
   2011      {1:^                    }|
   2012      {2:~                   }|
   2013      {3:[No Name]           }|
   2014                          |
   2015    ]])
   2016 
   2017    command('wincmd w')
   2018    screen:expect([[
   2019      ^                    |
   2020      {0:~                   }|*2
   2021      {3:[No Name]           }|
   2022      {5:                    }|
   2023      {6:~                   }|
   2024      {4:[No Name]           }|
   2025                          |
   2026    ]])
   2027  end)
   2028 
   2029  it('updates background to changed linked group', function()
   2030    command('split')
   2031    command('setlocal winhl=Normal:FancyGroup') -- does not yet exist
   2032    screen:expect {
   2033      grid = [[
   2034      ^                    |
   2035      {0:~                   }|*2
   2036      {3:[No Name]           }|
   2037                          |
   2038      {0:~                   }|
   2039      {4:[No Name]           }|
   2040                          |
   2041    ]],
   2042    }
   2043 
   2044    command('hi FancyGroup guibg=#FF8800') -- nice orange
   2045    screen:expect {
   2046      grid = [[
   2047      {30:^                    }|
   2048      {31:~                   }|*2
   2049      {3:[No Name]           }|
   2050                          |
   2051      {0:~                   }|
   2052      {4:[No Name]           }|
   2053                          |
   2054    ]],
   2055    }
   2056  end)
   2057 
   2058  it('background applies also to non-text', function()
   2059    command('set sidescroll=0')
   2060    insert('Lorem ipsum dolor sit amet ')
   2061    command('set shiftwidth=2')
   2062    feed('>>')
   2063    command('set number')
   2064    command('set breakindent')
   2065    command('set briopt=shift:5,min:0')
   2066    command('set list')
   2067    command('set showbreak=↪')
   2068    screen:expect([[
   2069      {9:  1 }  ^Lorem ipsum do|
   2070      {9:    }       {0:}lor sit |
   2071      {9:    }       {0:}amet{0:-}   |
   2072      {0:~                   }|*4
   2073                          |
   2074    ]])
   2075 
   2076    command('set winhl=Normal:Background1')
   2077    screen:expect([[
   2078      {10:  1 }{1:  ^Lorem ipsum do}|
   2079      {10:    }{1:       }{2:}{1:lor sit }|
   2080      {10:    }{1:       }{2:}{1:amet}{2:-}{1:   }|
   2081      {2:~                   }|*4
   2082                          |
   2083    ]])
   2084 
   2085    command('set nowrap')
   2086    command('set listchars+=extends:❯,precedes:❮')
   2087    feed('3w')
   2088    screen:expect([[
   2089      {10:  1 }{2:}{1: dolor ^sit ame}{2:}|
   2090      {2:~                   }|*6
   2091                          |
   2092    ]])
   2093  end)
   2094 
   2095  it("background doesn't override syntax background", function()
   2096    command('syntax on')
   2097    command('syntax keyword Foobar foobar')
   2098    command('syntax keyword Article the')
   2099    command('hi Foobar guibg=#FF0000')
   2100    command('hi Article guifg=#00FF00 gui=bold')
   2101    insert('the foobar was foobar')
   2102    screen:expect([[
   2103      {25:the} {26:foobar} was {26:fooba}|
   2104      {26:^r}                   |
   2105      {0:~                   }|*5
   2106                          |
   2107    ]])
   2108 
   2109    -- winhl=Normal:Group with background doesn't override syntax background,
   2110    -- but does combine with syntax foreground.
   2111    command('set winhl=Normal:Background1')
   2112    screen:expect([[
   2113      {27:the}{1: }{26:foobar}{1: was }{26:fooba}|
   2114      {26:^r}{1:                   }|
   2115      {2:~                   }|*5
   2116                          |
   2117    ]])
   2118  end)
   2119 
   2120  it('can override NonText, Conceal and EndOfBuffer', function()
   2121    api.nvim_buf_set_lines(0, 0, -1, true, { 'raa\000' })
   2122    command('call matchaddpos("Conceal", [[1,2]], 0, -1, {"conceal": "#"})')
   2123    command('set cole=2 cocu=nvic')
   2124    command('split')
   2125    command('call matchaddpos("Conceal", [[1,2]], 0, -1, {"conceal": "#"})')
   2126    command('set winhl=SpecialKey:ErrorMsg,EndOfBuffer:Background1,' .. 'Conceal:Background2')
   2127 
   2128    screen:expect([[
   2129      ^r{5:#}a{15:^@}               |
   2130      {1:~                   }|*2
   2131      {3:[No Name] [+]       }|
   2132      r{19:#}a{16:^@}               |
   2133      {0:~                   }|
   2134      {4:[No Name] [+]       }|
   2135                          |
   2136    ]])
   2137  end)
   2138 
   2139  it('can override LineNr, CursorColumn and ColorColumn', function()
   2140    insert('very text\nmore text')
   2141    command('set number')
   2142    command('set colorcolumn=2')
   2143    command('set cursorcolumn')
   2144    feed('k')
   2145 
   2146    command('split')
   2147    command('set winhl=LineNr:Background1,CursorColumn:Background2,' .. 'ColorColumn:ErrorMsg')
   2148    screen:expect([[
   2149      {1:  1 }v{15:e}ry tex^t       |
   2150      {1:  2 }m{15:o}re tex{5:t}       |
   2151      {0:~                   }|
   2152      {3:[No Name] [+]       }|
   2153      {9:  1 }v{17:e}ry text       |
   2154      {9:  2 }m{17:o}re tex{18:t}       |
   2155      {4:[No Name] [+]       }|
   2156                          |
   2157    ]])
   2158  end)
   2159 
   2160  it('can override Tabline', function()
   2161    command('tabnew')
   2162    command('set winhl=TabLine:Background1,TabLineSel:ErrorMsg')
   2163 
   2164    screen:expect([[
   2165      {20: No Name] }{15: No Name]}{20:X}|
   2166      ^                    |
   2167      {0:~                   }|*5
   2168                          |
   2169    ]])
   2170    command('tabnext')
   2171    screen:expect([[
   2172      {21: No Name] }{1: No Name]}{20:X}|
   2173      ^                    |
   2174      {0:~                   }|*5
   2175                          |
   2176    ]])
   2177  end)
   2178 
   2179  it('can override popupmenu', function()
   2180    insert('word wording wordy')
   2181    command('split')
   2182    command(
   2183      'set winhl=Pmenu:Background1,PmenuSel:Background2,' .. 'PmenuSbar:ErrorMsg,PmenuThumb:Normal'
   2184    )
   2185    screen:expect([[
   2186      word wording word^y  |
   2187      {0:~                   }|*2
   2188      {3:[No Name] [+]       }|
   2189      word wording wordy  |
   2190      {0:~                   }|
   2191      {4:[No Name] [+]       }|
   2192                          |
   2193    ]])
   2194 
   2195    feed('oword<c-x><c-p>')
   2196    screen:expect([[
   2197      word wording wordy  |
   2198      wordy^               |
   2199      {1:word           }{0:     }|
   2200      {1:wording        }{3:     }|
   2201      {5:wordy          }rdy  |
   2202      wordy               |
   2203      {4:[No Name] [+]       }|
   2204      {21:-- }{22:match 1 of 3}     |
   2205    ]])
   2206 
   2207    feed('<esc>u<c-w><c-w>oword<c-x><c-p>')
   2208    screen:expect([[
   2209      word wording wordy  |
   2210      wordy               |
   2211      {23:word           }{0:     }|
   2212      {23:wording        }{4:     }|
   2213      {24:wordy          }rdy  |
   2214      wordy^               |
   2215      {3:[No Name] [+]       }|
   2216      {21:-- }{22:match 1 of 3}     |
   2217    ]])
   2218  end)
   2219 
   2220  it('can override CursorLine and CursorLineNr', function()
   2221    -- CursorLine used to be parsed as CursorLineNr, because strncmp
   2222    command('set cursorline number')
   2223    command('split')
   2224    command('set winhl=CursorLine:Background1')
   2225    screen:expect {
   2226      grid = [[
   2227      {28:  1 }{1:^                }|
   2228      {0:~                   }|*2
   2229      {3:[No Name]           }|
   2230      {28:  1 }{18:                }|
   2231      {0:~                   }|
   2232      {4:[No Name]           }|
   2233                          |
   2234    ]],
   2235    }
   2236 
   2237    command('set winhl=CursorLineNr:Background2,CursorLine:Background1')
   2238    screen:expect {
   2239      grid = [[
   2240      {5:  1 }{1:^                }|
   2241      {0:~                   }|*2
   2242      {3:[No Name]           }|
   2243      {28:  1 }{18:                }|
   2244      {0:~                   }|
   2245      {4:[No Name]           }|
   2246                          |
   2247    ]],
   2248    }
   2249 
   2250    feed('<c-w>w')
   2251    screen:expect {
   2252      grid = [[
   2253      {5:  1 }{1:                }|
   2254      {0:~                   }|*2
   2255      {4:[No Name]           }|
   2256      {28:  1 }{18:^                }|
   2257      {0:~                   }|
   2258      {3:[No Name]           }|
   2259                          |
   2260    ]],
   2261    }
   2262  end)
   2263 
   2264  it('can override StatusLine and StatusLineNC', function()
   2265    command('set winhighlight=StatusLine:Background1,StatusLineNC:Background2')
   2266    command('split')
   2267    screen:expect([[
   2268      ^                    |
   2269      {0:~                   }|*2
   2270      {1:[No Name]           }|
   2271                          |
   2272      {0:~                   }|
   2273      {5:[No Name]           }|
   2274                          |
   2275    ]])
   2276  end)
   2277 
   2278  it('can override WinBar and WinBarNC #19345', function()
   2279    command('setlocal winbar=foobar')
   2280    command('set winhighlight=WinBar:Background1,WinBarNC:Background2')
   2281    command('split')
   2282    screen:expect([[
   2283      {1:foobar              }|
   2284      ^                    |
   2285      {0:~                   }|
   2286      {3:[No Name]           }|
   2287      {5:foobar              }|
   2288                          |
   2289      {4:[No Name]           }|
   2290                          |
   2291    ]])
   2292  end)
   2293 
   2294  it('can override syntax groups', function()
   2295    command('syntax on')
   2296    command('syntax keyword Foobar foobar')
   2297    command('syntax keyword Article the')
   2298    command('hi Foobar guibg=#FF0000')
   2299    command('hi Article guifg=#00FF00 gui=bold')
   2300    insert('the foobar was foobar')
   2301    screen:expect([[
   2302      {25:the} {26:foobar} was {26:fooba}|
   2303      {26:^r}                   |
   2304      {0:~                   }|*5
   2305                          |
   2306    ]])
   2307 
   2308    command('split')
   2309    command('set winhl=Foobar:Background1,Article:ErrorMsg')
   2310    screen:expect {
   2311      grid = [[
   2312      {15:the} {1:foobar} was {1:fooba}|
   2313      {1:^r}                   |
   2314      {0:~                   }|
   2315      {3:[No Name] [+]       }|
   2316      {25:the} {26:foobar} was {26:fooba}|
   2317      {26:r}                   |
   2318      {4:[No Name] [+]       }|
   2319                          |
   2320    ]],
   2321    }
   2322  end)
   2323 
   2324  it('can be disabled in newly opened window #19823', function()
   2325    command('split | set winhl=Normal:ErrorMsg | set winhl=')
   2326    screen:expect {
   2327      grid = [[
   2328      ^                    |
   2329      {0:~                   }|*2
   2330      {3:[No Name]           }|
   2331                          |
   2332      {0:~                   }|
   2333      {4:[No Name]           }|
   2334                          |
   2335    ]],
   2336    }
   2337 
   2338    n.assert_alive()
   2339  end)
   2340 
   2341  it('can redraw statusline on cursor movement', function()
   2342    screen:try_resize(40, 8)
   2343    exec [[
   2344      set statusline=%f%=%#Background1#%l,%c%V\ %P
   2345      split
   2346    ]]
   2347    insert [[
   2348      some text
   2349      more text]]
   2350    screen:expect {
   2351      grid = [[
   2352      some text                               |
   2353      more tex^t                               |
   2354      {0:~                                       }|
   2355      {3:[No Name]                        }{11:2,9 All}|
   2356      some text                               |
   2357      more text                               |
   2358      {4:[No Name]                        }{14:1,1 All}|
   2359                                              |
   2360    ]],
   2361    }
   2362 
   2363    command 'set winhl=Background1:Background2'
   2364    screen:expect {
   2365      grid = [[
   2366      some text                               |
   2367      more tex^t                               |
   2368      {0:~                                       }|
   2369      {3:[No Name]                        }{32:2,9 All}|
   2370      some text                               |
   2371      more text                               |
   2372      {4:[No Name]                        }{14:1,1 All}|
   2373                                              |
   2374    ]],
   2375    }
   2376 
   2377    feed 'k'
   2378    screen:expect {
   2379      grid = [[
   2380      some tex^t                               |
   2381      more text                               |
   2382      {0:~                                       }|
   2383      {3:[No Name]                        }{32:1,9 All}|
   2384      some text                               |
   2385      more text                               |
   2386      {4:[No Name]                        }{14:1,1 All}|
   2387                                              |
   2388    ]],
   2389    }
   2390  end)
   2391 
   2392  it('can link to empty highlight group', function()
   2393    command 'hi NormalNC guibg=Red' -- czerwone time
   2394    command 'set winhl=NormalNC:Normal'
   2395    command 'split'
   2396 
   2397    screen:expect {
   2398      grid = [[
   2399      ^                    |
   2400      {0:~                   }|*2
   2401      {3:[No Name]           }|
   2402                          |
   2403      {0:~                   }|
   2404      {4:[No Name]           }|
   2405                          |
   2406    ]],
   2407    }
   2408  end)
   2409 end)
   2410 
   2411 describe('highlight namespaces', function()
   2412  local screen
   2413  local ns1, ns2
   2414 
   2415  before_each(function()
   2416    clear()
   2417    screen = Screen.new(25, 10)
   2418    screen:set_default_attr_ids {
   2419      [1] = { foreground = Screen.colors.Blue, bold = true },
   2420      [2] = { background = Screen.colors.DarkGrey },
   2421      [3] = {
   2422        italic = true,
   2423        foreground = Screen.colors.DarkCyan,
   2424        background = Screen.colors.DarkOrange4,
   2425      },
   2426      [4] = { background = Screen.colors.Magenta4 },
   2427      [5] = { background = Screen.colors.Magenta4, foreground = Screen.colors.Crimson },
   2428      [6] = { bold = true, reverse = true },
   2429      [7] = { reverse = true },
   2430      [8] = { foreground = Screen.colors.Gray20 },
   2431      [9] = { foreground = Screen.colors.Blue },
   2432      [10] = { bold = true, foreground = Screen.colors.SeaGreen },
   2433    }
   2434 
   2435    ns1 = api.nvim_create_namespace 'grungy'
   2436    ns2 = api.nvim_create_namespace 'ultrared'
   2437 
   2438    api.nvim_set_hl(ns1, 'Normal', { bg = 'DarkGrey' })
   2439    api.nvim_set_hl(ns1, 'NonText', { bg = 'DarkOrange4', fg = 'DarkCyan', italic = true })
   2440    api.nvim_set_hl(ns2, 'Normal', { bg = 'DarkMagenta' })
   2441    api.nvim_set_hl(ns2, 'NonText', { fg = 'Crimson' })
   2442  end)
   2443 
   2444  it('can be used globally', function()
   2445    screen:expect {
   2446      grid = [[
   2447      ^                         |
   2448      {1:~                        }|*8
   2449                               |
   2450    ]],
   2451    }
   2452 
   2453    api.nvim_set_hl_ns(ns1)
   2454    screen:expect {
   2455      grid = [[
   2456      {2:^                         }|
   2457      {3:~                        }|*8
   2458                               |
   2459    ]],
   2460    }
   2461 
   2462    api.nvim_set_hl_ns(ns2)
   2463    screen:expect {
   2464      grid = [[
   2465      {4:^                         }|
   2466      {5:~                        }|*8
   2467                               |
   2468    ]],
   2469    }
   2470 
   2471    api.nvim_set_hl_ns(0)
   2472    screen:expect {
   2473      grid = [[
   2474      ^                         |
   2475      {1:~                        }|*8
   2476                               |
   2477    ]],
   2478    }
   2479  end)
   2480 
   2481  it('can be used per window', function()
   2482    local win1 = api.nvim_get_current_win()
   2483    command 'split'
   2484    local win2 = api.nvim_get_current_win()
   2485    command 'split'
   2486 
   2487    api.nvim_win_set_hl_ns(win1, ns1)
   2488    api.nvim_win_set_hl_ns(win2, ns2)
   2489 
   2490    screen:expect {
   2491      grid = [[
   2492      ^                         |
   2493      {1:~                        }|
   2494      {6:[No Name]                }|
   2495      {4:                         }|
   2496      {5:~                        }|
   2497      {7:[No Name]                }|
   2498      {2:                         }|
   2499      {3:~                        }|
   2500      {7:[No Name]                }|
   2501                               |
   2502    ]],
   2503    }
   2504  end)
   2505 
   2506  it('redraws correctly when ns=0', function()
   2507    screen:expect {
   2508      grid = [[
   2509      ^                         |
   2510      {1:~                        }|*8
   2511                               |
   2512    ]],
   2513    }
   2514 
   2515    api.nvim_set_hl(0, 'EndOfBuffer', { fg = '#333333' })
   2516    screen:expect {
   2517      grid = [[
   2518      ^                         |
   2519      {8:~                        }|*8
   2520                               |
   2521    ]],
   2522    }
   2523  end)
   2524 
   2525  it('winhl does not accept invalid value #24586', function()
   2526    command('set winhl=Normal:Visual')
   2527    for _, cmd in ipairs({
   2528      [[set winhl='Normal:Wrong']],
   2529      [[set winhl=Normal:Wrong']],
   2530      [[set winhl='Normal:Wrong]],
   2531    }) do
   2532      local res = exec_lua(
   2533        [[
   2534          local _, msg = pcall(vim.api.nvim_command, ...)
   2535          return { msg, vim.wo.winhl }
   2536        ]],
   2537        cmd
   2538      )
   2539      eq({
   2540        'Vim(set):E5248: Invalid character in group name',
   2541        'Normal:Visual',
   2542      }, res)
   2543    end
   2544  end)
   2545 
   2546  it('Normal in set_hl #25474', function()
   2547    command('highlight Ignore guifg=bg ctermfg=White')
   2548    api.nvim_set_hl(0, 'Normal', { bg = '#333333' })
   2549    command('highlight Ignore')
   2550    screen:expect {
   2551      grid = [[
   2552                               |
   2553      {1:~                        }|*2
   2554      {6:                         }|
   2555                               |
   2556      Ignore         {8:xxx} {9:ctermf}|
   2557      {9:g=}15               {9:guifg=}|
   2558      bg                       |
   2559      {10:Press ENTER or type comma}|
   2560      {10:nd to continue}^           |
   2561    ]],
   2562    }
   2563  end)
   2564 end)
   2565 
   2566 describe('synIDattr()', function()
   2567  before_each(function()
   2568    clear()
   2569    command('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black')
   2570    -- Salmon #fa8072 Maroon #800000
   2571    command(
   2572      'highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon cterm=strikethrough gui=strikethrough'
   2573    )
   2574  end)
   2575 
   2576  it('returns cterm-color if RGB-capable UI is _not_ attached', function()
   2577    eq('252', eval('synIDattr(hlID("Normal"),  "fg")'))
   2578    eq('252', eval('synIDattr(hlID("Normal"),  "fg#")'))
   2579    eq('', eval('synIDattr(hlID("Normal"),  "bg")'))
   2580    eq('', eval('synIDattr(hlID("Normal"),  "bg#")'))
   2581    eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
   2582    eq('79', eval('synIDattr(hlID("Keyword"), "fg#")'))
   2583    eq('', eval('synIDattr(hlID("Keyword"), "sp")'))
   2584    eq('', eval('synIDattr(hlID("Keyword"), "sp#")'))
   2585  end)
   2586 
   2587  it('returns gui-color if "gui" arg is passed', function()
   2588    eq('Black', eval('synIDattr(hlID("Normal"),  "bg", "gui")'))
   2589    eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp", "gui")'))
   2590  end)
   2591 
   2592  it('returns gui-color if RGB-capable UI is attached', function()
   2593    local _ = Screen.new(50, 7, { rgb = true })
   2594    eq('#ff0000', eval('synIDattr(hlID("Normal"),  "fg")'))
   2595    eq('Black', eval('synIDattr(hlID("Normal"),  "bg")'))
   2596    eq('Salmon', eval('synIDattr(hlID("Keyword"), "fg")'))
   2597    eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp")'))
   2598  end)
   2599 
   2600  it('returns #RRGGBB value for fg#/bg#/sp#', function()
   2601    local _ = Screen.new(50, 7, { rgb = true })
   2602    eq('#ff0000', eval('synIDattr(hlID("Normal"),  "fg#")'))
   2603    eq('#000000', eval('synIDattr(hlID("Normal"),  "bg#")'))
   2604    eq('#fa8072', eval('synIDattr(hlID("Keyword"), "fg#")'))
   2605    eq('#800000', eval('synIDattr(hlID("Keyword"), "sp#")'))
   2606  end)
   2607 
   2608  it('returns color number if non-RGB GUI', function()
   2609    local _ = Screen.new(50, 7, { rgb = false })
   2610    eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
   2611    eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
   2612  end)
   2613 
   2614  it('returns "1" if group has given highlight attribute', function()
   2615    local hl_attrs = {
   2616      'underline',
   2617      'undercurl',
   2618      'underdouble',
   2619      'underdotted',
   2620      'underdashed',
   2621      'strikethrough',
   2622    }
   2623    for _, hl_attr in ipairs(hl_attrs) do
   2624      local context = 'using ' .. hl_attr .. ' attr'
   2625      command('highlight Keyword cterm=' .. hl_attr .. ' gui=' .. hl_attr)
   2626      eq('', eval('synIDattr(hlID("Normal"), "' .. hl_attr .. '")'), context)
   2627      eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '")'), context)
   2628      eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '", "gui")'), context)
   2629    end
   2630  end)
   2631 end)
   2632 
   2633 describe('fg/bg special colors', function()
   2634  before_each(function()
   2635    clear()
   2636    command('highlight Normal ctermfg=145 ctermbg=16 guifg=#ff0000 guibg=Black')
   2637    command('highlight Visual ctermfg=bg ctermbg=fg guifg=bg guibg=fg guisp=bg')
   2638  end)
   2639 
   2640  it('resolve to "Normal" values', function()
   2641    eq(eval('synIDattr(hlID("Normal"), "bg")'), eval('synIDattr(hlID("Visual"), "fg")'))
   2642    eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")'))
   2643    eq(eval('synIDattr(hlID("Normal"), "fg")'), eval('synIDattr(hlID("Visual"), "bg")'))
   2644    eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")'))
   2645    eq('bg', eval('synIDattr(hlID("Visual"), "fg", "gui")'))
   2646    eq('bg', eval('synIDattr(hlID("Visual"), "fg#", "gui")'))
   2647    eq('fg', eval('synIDattr(hlID("Visual"), "bg", "gui")'))
   2648    eq('fg', eval('synIDattr(hlID("Visual"), "bg#", "gui")'))
   2649    eq('bg', eval('synIDattr(hlID("Visual"), "sp", "gui")'))
   2650    eq('bg', eval('synIDattr(hlID("Visual"), "sp#", "gui")'))
   2651  end)
   2652 
   2653  it('resolve to "Normal" values in RGB-capable UI', function()
   2654    local _ = Screen.new(50, 7, { rgb = true })
   2655    eq('bg', eval('synIDattr(hlID("Visual"), "fg")'))
   2656    eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")'))
   2657    eq('fg', eval('synIDattr(hlID("Visual"), "bg")'))
   2658    eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")'))
   2659    eq('bg', eval('synIDattr(hlID("Visual"), "sp")'))
   2660    eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "sp#")'))
   2661  end)
   2662 
   2663  it('resolve after the "Normal" group is modified', function()
   2664    local _ = Screen.new(50, 7, { rgb = true })
   2665    local new_guibg = '#282c34'
   2666    local new_guifg = '#abb2bf'
   2667    command('highlight Normal guifg=' .. new_guifg .. ' guibg=' .. new_guibg)
   2668    eq(new_guibg, eval('synIDattr(hlID("Visual"), "fg#")'))
   2669    eq(new_guifg, eval('synIDattr(hlID("Visual"), "bg#")'))
   2670    eq(new_guibg, eval('synIDattr(hlID("Visual"), "sp#")'))
   2671  end)
   2672 
   2673  it('changed highlight is reflected in messages before redraw #17832', function()
   2674    local screen = Screen.new(50, 7, { rgb = true })
   2675    command('set termguicolors')
   2676    -- :echomsg in the same request, before the next redraw.
   2677    command('call nvim_set_hl(0, "MsgArea", {"fg": "Red"}) | echomsg "foo"')
   2678    screen:expect({
   2679      grid = [[
   2680        ^                                                  |
   2681        {1:~                                                 }|*5
   2682        {19:foo                                               }|
   2683      ]],
   2684    })
   2685  end)
   2686 end)