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)