neovim

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

highlight_spec.lua (20095B)


      1 local t = require('test.testutil')
      2 local n = require('test.functional.testnvim')()
      3 
      4 local clear, eq, neq = n.clear, t.eq, t.neq
      5 local command = n.command
      6 local exec_capture = n.exec_capture
      7 local api = n.api
      8 local fn = n.fn
      9 local pcall_err = t.pcall_err
     10 local ok = t.ok
     11 local assert_alive = n.assert_alive
     12 
     13 describe('API: set highlight', function()
     14  local highlight_color = {
     15    fg = tonumber('0xff0000'),
     16    bg = tonumber('0x0032aa'),
     17    ctermfg = 8,
     18    ctermbg = 15,
     19  }
     20  local highlight1 = {
     21    bg = highlight_color.bg,
     22    fg = highlight_color.fg,
     23    bold = true,
     24    italic = true,
     25  }
     26  local highlight2_config = {
     27    ctermbg = highlight_color.ctermbg,
     28    ctermfg = highlight_color.ctermfg,
     29    underline = true,
     30    reverse = true,
     31  }
     32  local highlight2_result = {
     33    ctermbg = highlight_color.ctermbg,
     34    ctermfg = highlight_color.ctermfg,
     35    underline = true,
     36    reverse = true,
     37  }
     38  local highlight3_config = {
     39    bg = highlight_color.bg,
     40    fg = highlight_color.fg,
     41    ctermbg = highlight_color.ctermbg,
     42    ctermfg = highlight_color.ctermfg,
     43    bold = true,
     44    italic = true,
     45    reverse = true,
     46    underdashed = true,
     47    strikethrough = true,
     48    altfont = true,
     49    dim = true,
     50    blink = true,
     51    conceal = true,
     52    overline = true,
     53    cterm = {
     54      italic = true,
     55      reverse = true,
     56      strikethrough = true,
     57      altfont = true,
     58      dim = true,
     59      blink = true,
     60      conceal = true,
     61      overline = true,
     62      nocombine = true,
     63    },
     64  }
     65  local highlight3_result_gui = {
     66    bg = highlight_color.bg,
     67    fg = highlight_color.fg,
     68    bold = true,
     69    italic = true,
     70    reverse = true,
     71    underdashed = true,
     72    strikethrough = true,
     73    altfont = true,
     74    dim = true,
     75    blink = true,
     76    conceal = true,
     77    overline = true,
     78  }
     79  local highlight3_result_cterm = {
     80    ctermbg = highlight_color.ctermbg,
     81    ctermfg = highlight_color.ctermfg,
     82    italic = true,
     83    reverse = true,
     84    strikethrough = true,
     85    altfont = true,
     86    dim = true,
     87    blink = true,
     88    conceal = true,
     89    overline = true,
     90    nocombine = true,
     91  }
     92 
     93  local function get_ns()
     94    local ns = api.nvim_create_namespace('Test_set_hl')
     95    api.nvim_set_hl_ns(ns)
     96    return ns
     97  end
     98 
     99  ---@param expect table<string, any>
    100  ---@param result table<string, any>
    101  ---@param cterm? boolean
    102  local function match(expect, result, cterm)
    103    for k, v in pairs(expect) do
    104      eq(v, cterm and result.cterm[k] or result[k])
    105    end
    106  end
    107 
    108  before_each(clear)
    109 
    110  it('validation', function()
    111    eq(
    112      "Invalid 'blend': out of range",
    113      pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { fg = '#FF00FF', blend = 999 })
    114    )
    115    eq(
    116      "Invalid 'blend': expected Integer, got Array",
    117      pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { fg = '#FF00FF', blend = {} })
    118    )
    119  end)
    120 
    121  it('can set gui highlight', function()
    122    local ns = get_ns()
    123    api.nvim_set_hl(ns, 'Test_hl', highlight1)
    124    match(highlight1, api.nvim_get_hl(ns, { name = 'Test_hl' }))
    125  end)
    126 
    127  it('can set cterm highlight', function()
    128    local ns = get_ns()
    129    api.nvim_set_hl(ns, 'Test_hl', highlight2_config)
    130    match(highlight2_result, api.nvim_get_hl(ns, { name = 'Test_hl' }))
    131  end)
    132 
    133  it('can set empty cterm attr', function()
    134    local ns = get_ns()
    135    api.nvim_set_hl(ns, 'Test_hl', { cterm = {} })
    136    eq({}, api.nvim_get_hl(ns, { name = 'Test_hl' }))
    137  end)
    138 
    139  it('cterm attr defaults to gui attr', function()
    140    local ns = get_ns()
    141    api.nvim_set_hl(ns, 'Test_hl', highlight1)
    142    match({
    143      bold = true,
    144      italic = true,
    145    }, api.nvim_get_hl(ns, { name = 'Test_hl' }))
    146  end)
    147 
    148  it('can overwrite attr for cterm #test', function()
    149    local ns = get_ns()
    150    api.nvim_set_hl(ns, 'Test_hl', highlight3_config)
    151    match(highlight3_result_gui, api.nvim_get_hl(ns, { name = 'Test_hl' }))
    152    match(highlight3_result_cterm, api.nvim_get_hl(ns, { name = 'Test_hl' }), true)
    153  end)
    154 
    155  it('only allows one underline attribute #22371', function()
    156    local ns = get_ns()
    157    api.nvim_set_hl(ns, 'Test_hl', {
    158      underdouble = true,
    159      underdotted = true,
    160      cterm = {
    161        underline = true,
    162        undercurl = true,
    163      },
    164    })
    165    local result = api.nvim_get_hl(ns, { name = 'Test_hl' })
    166    match({ undercurl = true }, result, true)
    167    match({ underdotted = true }, result)
    168  end)
    169 
    170  it('can set all underline cterm attributes #31385', function()
    171    local ns = get_ns()
    172    local attrs = { 'underline', 'undercurl', 'underdouble', 'underdotted', 'underdashed' }
    173    for _, attr in ipairs(attrs) do
    174      api.nvim_set_hl(ns, 'Test_' .. attr, { cterm = { [attr] = true } })
    175      match({ [attr] = true }, api.nvim_get_hl(ns, { name = 'Test_' .. attr }), true)
    176    end
    177  end)
    178 
    179  it('can set a highlight in the global namespace', function()
    180    api.nvim_set_hl(0, 'Test_hl', highlight2_config)
    181    eq(
    182      'Test_hl        xxx cterm=underline,reverse ctermfg=8 ctermbg=15 gui=underline,reverse',
    183      exec_capture('highlight Test_hl')
    184    )
    185 
    186    api.nvim_set_hl(0, 'Test_hl', { background = highlight_color.bg })
    187    eq('Test_hl        xxx guibg=#0032aa', exec_capture('highlight Test_hl'))
    188 
    189    api.nvim_set_hl(0, 'Test_hl2', highlight3_config)
    190    eq(
    191      'Test_hl2       xxx cterm=italic,reverse,strikethrough,altfont,dim,blink,conceal,overline,nocombine ctermfg=8 ctermbg=15 gui=bold,underdashed,italic,reverse,strikethrough,altfont,dim,blink,conceal,overline guifg=#ff0000 guibg=#0032aa',
    192      exec_capture('highlight Test_hl2')
    193    )
    194 
    195    -- Colors are stored with the name they are defined, but
    196    -- with canonical casing
    197    api.nvim_set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' })
    198    eq('Test_hl3       xxx guifg=Blue guibg=Red', exec_capture('highlight Test_hl3'))
    199  end)
    200 
    201  it('can modify a highlight in the global namespace', function()
    202    api.nvim_set_hl(0, 'Test_hl3', { bg = 'red', fg = 'blue' })
    203    eq('Test_hl3       xxx guifg=Blue guibg=Red', exec_capture('highlight Test_hl3'))
    204 
    205    api.nvim_set_hl(0, 'Test_hl3', { bg = 'red' })
    206    eq('Test_hl3       xxx guibg=Red', exec_capture('highlight Test_hl3'))
    207 
    208    api.nvim_set_hl(0, 'Test_hl3', { ctermbg = 9, ctermfg = 12 })
    209    eq('Test_hl3       xxx ctermfg=12 ctermbg=9', exec_capture('highlight Test_hl3'))
    210 
    211    api.nvim_set_hl(0, 'Test_hl3', { ctermbg = 'red', ctermfg = 'blue' })
    212    eq('Test_hl3       xxx ctermfg=12 ctermbg=9', exec_capture('highlight Test_hl3'))
    213 
    214    api.nvim_set_hl(0, 'Test_hl3', { ctermbg = 9 })
    215    eq('Test_hl3       xxx ctermbg=9', exec_capture('highlight Test_hl3'))
    216 
    217    eq(
    218      "Invalid highlight color: 'redd'",
    219      pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { fg = 'redd' })
    220    )
    221 
    222    eq(
    223      "Invalid highlight color: 'bleu'",
    224      pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { ctermfg = 'bleu' })
    225    )
    226 
    227    api.nvim_set_hl(0, 'Test_hl3', { fg = '#FF00FF' })
    228    eq('Test_hl3       xxx guifg=#ff00ff', exec_capture('highlight Test_hl3'))
    229 
    230    eq(
    231      "Invalid highlight color: '#FF00FF'",
    232      pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { ctermfg = '#FF00FF' })
    233    )
    234 
    235    for _, fg_val in ipairs { nil, 'NONE', 'nOnE', '', -1 } do
    236      api.nvim_set_hl(0, 'Test_hl3', { fg = fg_val })
    237      eq('Test_hl3       xxx cleared', exec_capture('highlight Test_hl3'))
    238    end
    239 
    240    api.nvim_set_hl(0, 'Test_hl3', { fg = '#FF00FF', blend = 50 })
    241    eq('Test_hl3       xxx guifg=#ff00ff blend=50', exec_capture('highlight Test_hl3'))
    242  end)
    243 
    244  it("correctly sets 'Normal' internal properties", function()
    245    -- Normal has some special handling internally. #18024
    246    api.nvim_set_hl(0, 'Normal', { fg = '#000083', bg = '#0000F3' })
    247    eq({ fg = 131, bg = 243 }, api.nvim_get_hl(0, { name = 'Normal' }))
    248  end)
    249 
    250  it('does not segfault on invalid group name #20009', function()
    251    eq(
    252      "Invalid highlight name: 'foo bar'",
    253      pcall_err(api.nvim_set_hl, 0, 'foo bar', { bold = true })
    254    )
    255    assert_alive()
    256  end)
    257 end)
    258 
    259 describe('API: get highlight', function()
    260  local highlight_color = {
    261    fg = tonumber('0xff0000'),
    262    bg = tonumber('0x0032aa'),
    263    ctermfg = 8,
    264    ctermbg = 15,
    265  }
    266  local highlight1 = {
    267    bg = highlight_color.bg,
    268    fg = highlight_color.fg,
    269    bold = true,
    270    italic = true,
    271    cterm = { bold = true, italic = true },
    272  }
    273  local highlight2 = {
    274    ctermbg = highlight_color.ctermbg,
    275    ctermfg = highlight_color.ctermfg,
    276    underline = true,
    277    reverse = true,
    278    cterm = { underline = true, reverse = true },
    279  }
    280  local highlight3_config = {
    281    bg = highlight_color.bg,
    282    fg = highlight_color.fg,
    283    ctermbg = highlight_color.ctermbg,
    284    ctermfg = highlight_color.ctermfg,
    285    bold = true,
    286    italic = true,
    287    reverse = true,
    288    underdashed = true,
    289    strikethrough = true,
    290    altfont = true,
    291    dim = true,
    292    blink = true,
    293    conceal = true,
    294    overline = true,
    295    cterm = {
    296      italic = true,
    297      reverse = true,
    298      strikethrough = true,
    299      altfont = true,
    300      dim = true,
    301      blink = true,
    302      conceal = true,
    303      overline = true,
    304      nocombine = true,
    305    },
    306  }
    307  local highlight3_result = {
    308    bg = highlight_color.bg,
    309    fg = highlight_color.fg,
    310    ctermbg = highlight_color.ctermbg,
    311    ctermfg = highlight_color.ctermfg,
    312    bold = true,
    313    italic = true,
    314    reverse = true,
    315    underdashed = true,
    316    strikethrough = true,
    317    altfont = true,
    318    dim = true,
    319    blink = true,
    320    conceal = true,
    321    overline = true,
    322    cterm = {
    323      italic = true,
    324      nocombine = true,
    325      reverse = true,
    326      strikethrough = true,
    327      altfont = true,
    328      dim = true,
    329      blink = true,
    330      conceal = true,
    331      overline = true,
    332    },
    333  }
    334 
    335  local function get_ns()
    336    -- Test namespace filtering behavior
    337    local ns2 = api.nvim_create_namespace('Another_namespace')
    338    api.nvim_set_hl(ns2, 'Test_hl', { ctermfg = 23 })
    339    api.nvim_set_hl(ns2, 'Test_another_hl', { link = 'Test_hl' })
    340    api.nvim_set_hl(ns2, 'Test_hl_link', { link = 'Test_another_hl' })
    341    api.nvim_set_hl(ns2, 'Test_another_hl_link', { link = 'Test_hl_link' })
    342 
    343    local ns = api.nvim_create_namespace('Test_set_hl')
    344    api.nvim_set_hl_ns(ns)
    345 
    346    return ns
    347  end
    348 
    349  before_each(clear)
    350 
    351  it('validation', function()
    352    eq(
    353      "Invalid 'name': expected String, got Integer",
    354      pcall_err(api.nvim_get_hl, 0, { name = 177 })
    355    )
    356    eq('Highlight id out of bounds', pcall_err(api.nvim_get_hl, 0, { name = 'Test set hl' }))
    357  end)
    358 
    359  it('nvim_get_hl with create flag', function()
    360    eq({}, api.nvim_get_hl(0, { name = 'Foo', create = false }))
    361    eq(0, fn.hlexists('Foo'))
    362    api.nvim_get_hl(0, { name = 'Bar', create = true })
    363    eq(1, fn.hlexists('Bar'))
    364    api.nvim_get_hl(0, { name = 'FooBar' })
    365    eq(1, fn.hlexists('FooBar'))
    366  end)
    367 
    368  it('can get all highlights in current namespace', function()
    369    local ns = get_ns()
    370    api.nvim_set_hl(ns, 'Test_hl', { bg = '#B4BEFE' })
    371    api.nvim_set_hl(ns, 'Test_hl_link', { link = 'Test_hl' })
    372    eq({
    373      Test_hl = {
    374        bg = 11845374,
    375      },
    376      Test_hl_link = {
    377        link = 'Test_hl',
    378      },
    379    }, api.nvim_get_hl(ns, {}))
    380  end)
    381 
    382  it('can get gui highlight', function()
    383    local ns = get_ns()
    384    api.nvim_set_hl(ns, 'Test_hl', highlight1)
    385    eq(highlight1, api.nvim_get_hl(ns, { name = 'Test_hl' }))
    386  end)
    387 
    388  it('can get cterm highlight', function()
    389    local ns = get_ns()
    390    api.nvim_set_hl(ns, 'Test_hl', highlight2)
    391    eq(highlight2, api.nvim_get_hl(ns, { name = 'Test_hl' }))
    392  end)
    393 
    394  it('can get empty cterm attr', function()
    395    local ns = get_ns()
    396    api.nvim_set_hl(ns, 'Test_hl', { cterm = {} })
    397    eq({}, api.nvim_get_hl(ns, { name = 'Test_hl' }))
    398  end)
    399 
    400  it('cterm attr defaults to gui attr', function()
    401    local ns = get_ns()
    402    api.nvim_set_hl(ns, 'Test_hl', highlight1)
    403    eq(highlight1, api.nvim_get_hl(ns, { name = 'Test_hl' }))
    404  end)
    405 
    406  it('can overwrite attr for cterm', function()
    407    local ns = get_ns()
    408    api.nvim_set_hl(ns, 'Test_hl', highlight3_config)
    409    eq(highlight3_result, api.nvim_get_hl(ns, { name = 'Test_hl' }))
    410  end)
    411 
    412  it('only allows one underline attribute #22371', function()
    413    local ns = get_ns()
    414    api.nvim_set_hl(ns, 'Test_hl', {
    415      underdouble = true,
    416      underdotted = true,
    417      cterm = {
    418        underline = true,
    419        undercurl = true,
    420      },
    421    })
    422    eq(
    423      { underdotted = true, cterm = { undercurl = true } },
    424      api.nvim_get_hl(ns, { name = 'Test_hl' })
    425    )
    426  end)
    427 
    428  it('can get a highlight in the global namespace', function()
    429    api.nvim_set_hl(0, 'Test_hl', highlight2)
    430    eq(highlight2, api.nvim_get_hl(0, { name = 'Test_hl' }))
    431 
    432    api.nvim_set_hl(0, 'Test_hl', { background = highlight_color.bg })
    433    eq({
    434      bg = 12970,
    435    }, api.nvim_get_hl(0, { name = 'Test_hl' }))
    436 
    437    api.nvim_set_hl(0, 'Test_hl2', highlight3_config)
    438    eq(highlight3_result, api.nvim_get_hl(0, { name = 'Test_hl2' }))
    439 
    440    -- Colors are stored with the name they are defined, but
    441    -- with canonical casing
    442    api.nvim_set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' })
    443    eq({
    444      bg = 16711680,
    445      fg = 255,
    446    }, api.nvim_get_hl(0, { name = 'Test_hl3' }))
    447  end)
    448 
    449  it('nvim_get_hl by id', function()
    450    local hl_id = api.nvim_get_hl_id_by_name('NewHighlight')
    451 
    452    command(
    453      'hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold'
    454    )
    455    eq({
    456      fg = 16711680,
    457      bg = 16776960,
    458      sp = 255,
    459      bold = true,
    460      ctermbg = 10,
    461      cterm = { underline = true },
    462    }, api.nvim_get_hl(0, { id = hl_id }))
    463 
    464    -- Test 0 argument
    465    eq('Highlight id out of bounds', pcall_err(api.nvim_get_hl, 0, { id = 0 }))
    466 
    467    eq(
    468      "Invalid 'id': expected Integer, got String",
    469      pcall_err(api.nvim_get_hl, 0, { id = 'Test_set_hl' })
    470    )
    471 
    472    -- Test all highlight properties.
    473    command(
    474      'hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,dim,blink,conceal,overline,nocombine'
    475    )
    476    eq({
    477      fg = 16711680,
    478      bg = 16776960,
    479      sp = 255,
    480      altfont = true,
    481      blink = true,
    482      bold = true,
    483      conceal = true,
    484      dim = true,
    485      italic = true,
    486      nocombine = true,
    487      overline = true,
    488      reverse = true,
    489      strikethrough = true,
    490      underline = true,
    491      ctermbg = 10,
    492      cterm = { underline = true },
    493    }, api.nvim_get_hl(0, { id = hl_id }))
    494 
    495    -- Test undercurl
    496    command('hi NewHighlight gui=undercurl')
    497    eq({
    498      fg = 16711680,
    499      bg = 16776960,
    500      sp = 255,
    501      undercurl = true,
    502      ctermbg = 10,
    503      cterm = { underline = true },
    504    }, api.nvim_get_hl(0, { id = hl_id }))
    505  end)
    506 
    507  it('can correctly detect links', function()
    508    command('hi String guifg=#a6e3a1 ctermfg=NONE')
    509    command('hi link @string string')
    510    command('hi link @string.cpp @string')
    511    eq({ fg = 10937249 }, api.nvim_get_hl(0, { name = 'String' }))
    512    eq({ link = 'String' }, api.nvim_get_hl(0, { name = '@string' }))
    513    eq({ fg = 10937249 }, api.nvim_get_hl(0, { name = '@string.cpp', link = false }))
    514  end)
    515 
    516  it('can get all attributes for a linked group', function()
    517    command('hi Bar guifg=red')
    518    command('hi Foo guifg=#00ff00 gui=bold,underline')
    519    command('hi! link Foo Bar')
    520    eq(
    521      { link = 'Bar', fg = tonumber('00ff00', 16), bold = true, underline = true },
    522      api.nvim_get_hl(0, { name = 'Foo', link = true })
    523    )
    524  end)
    525 
    526  it('can set link as well as other attributes', function()
    527    command('hi Bar guifg=red')
    528    local hl = { link = 'Bar', fg = tonumber('00ff00', 16), bold = true, cterm = { bold = true } }
    529    api.nvim_set_hl(0, 'Foo', hl)
    530    eq(hl, api.nvim_get_hl(0, { name = 'Foo', link = true }))
    531  end)
    532 
    533  it("doesn't contain unset groups", function()
    534    local id = api.nvim_get_hl_id_by_name '@foobar.hubbabubba'
    535    ok(id > 0)
    536 
    537    local data = api.nvim_get_hl(0, {})
    538    eq(nil, data['@foobar.hubbabubba'])
    539    eq(nil, data['@foobar'])
    540 
    541    command 'hi @foobar.hubbabubba gui=bold'
    542    data = api.nvim_get_hl(0, {})
    543    eq({ bold = true }, data['@foobar.hubbabubba'])
    544    eq(nil, data['@foobar'])
    545 
    546    -- @foobar.hubbabubba was explicitly cleared and thus shows up
    547    -- but @foobar was never touched, and thus doesn't
    548    command 'hi clear @foobar.hubbabubba'
    549    data = api.nvim_get_hl(0, {})
    550    eq({}, data['@foobar.hubbabubba'])
    551    eq(nil, data['@foobar'])
    552  end)
    553 
    554  it('should return default flag', function()
    555    api.nvim_set_hl(0, 'Tried', { fg = '#00ff00', default = true })
    556    eq({ fg = tonumber('00ff00', 16), default = true }, api.nvim_get_hl(0, { name = 'Tried' }))
    557  end)
    558 
    559  it('should not output empty gui and cterm #23474', function()
    560    api.nvim_set_hl(0, 'Foo', { default = true })
    561    api.nvim_set_hl(0, 'Bar', { default = true, fg = '#ffffff' })
    562    api.nvim_set_hl(0, 'FooBar', { default = true, fg = '#ffffff', cterm = { bold = true } })
    563    api.nvim_set_hl(
    564      0,
    565      'FooBarA',
    566      { default = true, fg = '#ffffff', cterm = { bold = true, italic = true } }
    567    )
    568 
    569    eq('Foo            xxx cleared', exec_capture('highlight Foo'))
    570    eq({ default = true }, api.nvim_get_hl(0, { name = 'Foo' }))
    571    eq('Bar            xxx guifg=#ffffff', exec_capture('highlight Bar'))
    572    eq('FooBar         xxx cterm=bold guifg=#ffffff', exec_capture('highlight FooBar'))
    573    eq('FooBarA        xxx cterm=bold,italic guifg=#ffffff', exec_capture('highlight FooBarA'))
    574  end)
    575 
    576  it('can override exist highlight group by force #20323', function()
    577    local white = tonumber('ffffff', 16)
    578    local green = tonumber('00ff00', 16)
    579    api.nvim_set_hl(0, 'Foo', { fg = white })
    580    api.nvim_set_hl(0, 'Foo', { fg = green, force = true })
    581    eq({ fg = green }, api.nvim_get_hl(0, { name = 'Foo' }))
    582    api.nvim_set_hl(0, 'Bar', { link = 'Comment', default = true })
    583    api.nvim_set_hl(0, 'Bar', { link = 'Foo', default = true, force = true })
    584    eq({ link = 'Foo', default = true }, api.nvim_get_hl(0, { name = 'Bar' }))
    585  end)
    586 end)
    587 
    588 describe('API: set/get highlight namespace', function()
    589  before_each(clear)
    590 
    591  it('set/get highlight namespace', function()
    592    eq(0, api.nvim_get_hl_ns({}))
    593    local ns = api.nvim_create_namespace('')
    594    api.nvim_set_hl_ns(ns)
    595    eq(ns, api.nvim_get_hl_ns({}))
    596  end)
    597 
    598  it('set/get window highlight namespace', function()
    599    eq(-1, api.nvim_get_hl_ns({ winid = 0 }))
    600    local ns = api.nvim_create_namespace('')
    601    api.nvim_win_set_hl_ns(0, ns)
    602    eq(ns, api.nvim_get_hl_ns({ winid = 0 }))
    603  end)
    604 
    605  it('setting namespace takes priority over &winhighlight', function()
    606    local win = api.nvim_get_current_win()
    607    eq(-1, api.nvim_get_hl_ns({ winid = win }))
    608    command('set winhighlight=Visual:Search')
    609    local winhl_ns = api.nvim_get_hl_ns({ winid = win })
    610    neq(0, winhl_ns)
    611    eq('Search', api.nvim_get_hl(winhl_ns, { name = 'Visual' }).link)
    612    n.insert('foobar')
    613    local ns = api.nvim_create_namespace('')
    614    neq(winhl_ns, ns)
    615    api.nvim_win_set_hl_ns(win, ns)
    616    eq(ns, api.nvim_get_hl_ns({ winid = win }))
    617    command('enew') -- Switching buffer keeps namespace. #30904
    618    eq(ns, api.nvim_get_hl_ns({ winid = win }))
    619    command('set winhighlight=')
    620    eq(ns, api.nvim_get_hl_ns({ winid = win }))
    621    -- Setting 'winhighlight' changes its namespace even when not using it.
    622    command('set winhighlight=Visual:IncSearch')
    623    eq('IncSearch', api.nvim_get_hl(winhl_ns, { name = 'Visual' }).link)
    624    eq(ns, api.nvim_get_hl_ns({ winid = win }))
    625    -- Setting 'winhighlight' works with global namespace. #37865
    626    api.nvim_win_set_hl_ns(win, 0)
    627    eq(0, api.nvim_get_hl_ns({ winid = win }))
    628    command('set winhighlight=Visual:IncSearch')
    629    eq('IncSearch', api.nvim_get_hl(winhl_ns, { name = 'Visual' }).link)
    630    eq(winhl_ns, api.nvim_get_hl_ns({ winid = win }))
    631    command('set winhighlight=')
    632    eq(0, api.nvim_get_hl_ns({ winid = win }))
    633    -- 'winhighlight' keeps the same namespace.
    634    api.nvim_win_set_hl_ns(win, winhl_ns)
    635    eq(winhl_ns, api.nvim_get_hl_ns({ winid = win }))
    636    command('set winhighlight=Visual:Substitute')
    637    eq('Substitute', api.nvim_get_hl(winhl_ns, { name = 'Visual' }).link)
    638    eq(winhl_ns, api.nvim_get_hl_ns({ winid = win }))
    639  end)
    640 end)