neovim/test/old/testdir/test_syntax.vim
Evgeni Chasnovski 64a14026d7
feat(highlight): update default color scheme
Problem: Default color scheme is suboptimal.

Solution: Start using new color scheme. Introduce new `vim` color scheme
for opt-in backward compatibility.

------
Main design ideas
- Be "Neovim branded".
- Be minimal for 256 colors with a bit more shades for true colors.
- Be accessible through high enough contrast ratios.
- Be suitable for dark and light backgrounds via exchange of dark and
  light palettes.

------
Palettes

- Have dark and light variants. Implemented through exporeted
  `NvimDark*` and `NvimLight*` hex colors.

- Palettes have 4 shades of grey for UI elements and 6 colors (red,
  yellow, green, cyan, blue, magenta).

- Actual values are computed procedurally in Oklch color space based on
  a handful of hyperparameters.

- Each color has a 256 colors variant with perceptually closest color.

------
Highlight groups

Use:

- Grey shades for general UI according to their design.

- Bold text for keywords (`Statement` highlight group). This is an
  important choice to increase accessibility for people with color
  deficiencies, as it doesn't rely on actual color.

- Green for strings, `DiffAdd` (as background), `DiagnosticOk`, and some
  minor text UI elements.

- Cyan as main syntax color, i.e. for function usage (`Function`
  highlight group), `DiffText`, `DiagnosticInfo`, and some minor text UI
  elements.

- Red to generally mean high user attention, i.e. errors; in particular
  for `ErrorMsg`, `DiffDelete`, `DiagnosticError`.

- Yellow very sparingly only with true colors to mean mild user
  attention, i.e. warnings. That is, `DiagnosticWarn` and `WarningMsg`.

- Blue very sparingly only with true colors as `DiagnosticHint` and some
  additional important syntax group (like `Identifier`).

- Magenta very carefully (if at all).

------
Notes

- To make tests work without relatively larege updates, each one is
  prepended with an equivalent of the call `:colorscheme vim`.

  Plus some tests which spawn new Neovim instances also now use 'vim'
  color scheme.

  In some cases tests are updated to fit new default color scheme.
2023-12-02 18:53:19 +02:00

982 lines
28 KiB
VimL

" Test for syntax and syntax iskeyword option
source check.vim
CheckFeature syntax
source view_util.vim
source screendump.vim
func GetSyntaxItem(pat)
let c = ''
let a = ['a', getreg('a'), getregtype('a')]
0
redraw!
call search(a:pat, 'W')
let synid = synID(line('.'), col('.'), 1)
while synid == synID(line('.'), col('.'), 1)
norm! v"ay
" stop at whitespace
if @a =~# '\s'
break
endif
let c .= @a
norm! l
endw
call call('setreg', a)
0
return c
endfunc
func AssertHighlightGroups(lnum, startcol, expected, trans = 1, msg = "")
" Assert that the characters starting at a given (line, col)
" sequentially match the expected highlight groups.
" If groups are provided as a string, each character is assumed to be a
" group and spaces represent no group, useful for visually describing tests.
let l:expectedGroups = type(a:expected) == v:t_string
\ ? a:expected->split('\zs')->map({_, v -> trim(v)})
\ : a:expected
let l:errors = 0
let l:msg = (a:msg->empty() ? "" : a:msg .. ": ")
\ .. "Wrong highlight group at " .. a:lnum .. ","
for l:i in range(a:startcol, a:startcol + l:expectedGroups->len() - 1)
let l:errors += synID(a:lnum, l:i, a:trans)
\ ->synIDattr("name")
\ ->assert_equal(l:expectedGroups[l:i - 1],
\ l:msg .. l:i)
endfor
endfunc
func Test_syn_iskeyword()
new
call setline(1, [
\ 'CREATE TABLE FOOBAR(',
\ ' DLTD_BY VARCHAR2(100)',
\ ');',
\ ''])
syntax on
set ft=sql
syn match SYN /C\k\+\>/
hi link SYN ErrorMsg
call assert_equal('DLTD_BY', GetSyntaxItem('DLTD'))
/\<D\k\+\>/:norm! ygn
call assert_equal('DLTD_BY', @0)
redir @c
syn iskeyword
redir END
call assert_equal("\nsyntax iskeyword not set", @c)
syn iskeyword @,48-57,_,192-255
redir @c
syn iskeyword
redir END
call assert_equal("\nsyntax iskeyword @,48-57,_,192-255", @c)
setlocal isk-=_
call assert_equal('DLTD_BY', GetSyntaxItem('DLTD'))
/\<D\k\+\>/:norm! ygn
let b2 = @0
call assert_equal('DLTD', @0)
syn iskeyword clear
redir @c
syn iskeyword
redir END
call assert_equal("\nsyntax iskeyword not set", @c)
quit!
endfunc
func Test_syntax_after_reload()
split Xsomefile
call setline(1, ['hello', 'there'])
w!
only!
setl filetype=hello
au FileType hello let g:gotit = 1
call assert_false(exists('g:gotit'))
edit other
buf Xsomefile
call assert_equal('hello', &filetype)
call assert_true(exists('g:gotit'))
call delete('Xsomefile')
endfunc
func Test_syntime()
if !has('profile')
return
endif
syntax on
syntime on
let a = execute('syntime report')
call assert_equal("\nNo Syntax items defined for this buffer", a)
let a = execute('syntime clear')
call assert_equal("\nNo Syntax items defined for this buffer", a)
view ../memfile_test.c
setfiletype cpp
redraw
let a = execute('syntime report')
call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
call assert_match(' \d*\.\d* \+[^0]\d* .* cppRawString ', a)
call assert_match(' \d*\.\d* \+[^0]\d* .* cppNumber ', a)
syntime off
syntime clear
let a = execute('syntime report')
call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
call assert_notmatch('.* cppRawString *', a)
call assert_notmatch('.* cppNumber*', a)
call assert_notmatch('[1-9]', a)
call assert_fails('syntime abc', 'E475')
syntax clear
let a = execute('syntime report')
call assert_equal("\nNo Syntax items defined for this buffer", a)
bd
endfunc
func Test_syntime_completion()
if !has('profile')
return
endif
call feedkeys(":syntime \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syntime clear off on report', @:)
endfunc
func Test_syntax_list()
syntax on
let a = execute('syntax list')
call assert_equal("\nNo Syntax items defined for this buffer", a)
view ../memfile_test.c
setfiletype c
let a = execute('syntax list')
call assert_match('cInclude*', a)
call assert_match('cDefine', a)
let a = execute('syntax list cDefine')
call assert_notmatch('cInclude*', a)
call assert_match('cDefine', a)
call assert_match(' links to Macro$', a)
call assert_fails('syntax list ABCD', 'E28:')
call assert_fails('syntax list @ABCD', 'E392:')
syntax clear
let a = execute('syntax list')
call assert_equal("\nNo Syntax items defined for this buffer", a)
syntax keyword Type int containedin=g1 skipwhite skipempty skipnl nextgroup=Abc
let exp = "Type xxx containedin=g1 nextgroup=Abc skipnl skipwhite skipempty int"
call assert_equal(exp, split(execute("syntax list"), "\n")[1])
bd
endfunc
func Test_syntax_completion()
call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syn case clear cluster conceal enable foldlevel include iskeyword keyword list manual match off on region reset spell sync', @:)
call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syn case ignore match', @:)
call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syn spell default notoplevel toplevel', @:)
call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:)
" Check that clearing "Aap" avoids it showing up before Boolean.
hi @Aap ctermfg=blue
call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_match('^"syn list @Aap @boolean @character ', @:)
hi clear @Aap
call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_match('^"syn list @boolean @character ', @:)
call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_match('^"syn match @boolean @character ', @:)
syn cluster Aax contains=Aap
call feedkeys(":syn list @A\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_match('^"syn list @Aax', @:)
endfunc
func Test_echohl_completion()
call feedkeys(":echohl no\<C-A>\<C-B>\"\<CR>", 'tx')
" call assert_equal('"echohl NonText Normal none', @:)
call assert_equal('"echohl NonText Normal NormalFloat NormalNC none', @:)
endfunc
func Test_syntax_arg_skipped()
syn clear
syntax case ignore
if 0
syntax case match
endif
call assert_match('case ignore', execute('syntax case'))
syn keyword Foo foo
call assert_match('Foo', execute('syntax'))
syn clear
call assert_match('case match', execute('syntax case'))
call assert_notmatch('Foo', execute('syntax'))
if has('conceal')
syn clear
syntax conceal on
if 0
syntax conceal off
endif
call assert_match('conceal on', execute('syntax conceal'))
syn clear
call assert_match('conceal off', execute('syntax conceal'))
endif
syntax conceal on
syntax conceal off
call assert_match('conceal off', execute('syntax conceal'))
syntax region Bar start=/</ end=/>/
if 0
syntax region NotTest start=/</ end=/>/ contains=@Spell
endif
call assert_match('Bar', execute('syntax'))
call assert_notmatch('NotTest', execute('syntax'))
call assert_notmatch('Spell', execute('syntax'))
hi Foo ctermfg=blue
let a = execute('hi Foo')
if 0
syntax rest
endif
call assert_equal(a, execute('hi Foo'))
hi clear Bar
hi clear Foo
set ft=tags
syn off
if 0
syntax enable
endif
call assert_match('No Syntax items defined', execute('syntax'))
syntax enable
call assert_match('tagComment', execute('syntax'))
set ft=
syn clear
if 0
syntax include @Spell nothing
endif
call assert_notmatch('Spell', execute('syntax'))
syn clear
syn iskeyword 48-57,$,_
call assert_match('48-57,$,_', execute('syntax iskeyword'))
if 0
syn clear
syn iskeyword clear
endif
call assert_match('48-57,$,_', execute('syntax iskeyword'))
syn iskeyword clear
call assert_match('not set', execute('syntax iskeyword'))
syn iskeyword 48-57,$,_
syn clear
call assert_match('not set', execute('syntax iskeyword'))
syn clear
syn keyword Foo foo
if 0
syn keyword NotAdded bar
endif
call assert_match('Foo', execute('syntax'))
call assert_notmatch('NotAdded', execute('highlight'))
syn clear
syn keyword Foo foo
call assert_match('Foo', execute('syntax'))
call assert_match('Foo', execute('syntax list'))
call assert_notmatch('Foo', execute('if 0 | syntax | endif'))
call assert_notmatch('Foo', execute('if 0 | syntax list | endif'))
syn clear
syn match Fopi /asdf/
if 0
syn match Fopx /asdf/
endif
call assert_match('Fopi', execute('syntax'))
call assert_notmatch('Fopx', execute('syntax'))
syn clear
syn spell toplevel
call assert_match('spell toplevel', execute('syntax spell'))
if 0
syn spell notoplevel
endif
call assert_match('spell toplevel', execute('syntax spell'))
syn spell notoplevel
call assert_match('spell notoplevel', execute('syntax spell'))
syn spell default
call assert_match('spell default', execute('syntax spell'))
syn clear
if 0
syntax cluster Spell
endif
call assert_notmatch('Spell', execute('syntax'))
syn clear
syn keyword Foo foo
syn sync ccomment
syn sync maxlines=5
if 0
syn sync maxlines=11
endif
call assert_match('on C-style comments', execute('syntax sync'))
call assert_match('maximal 5 lines', execute('syntax sync'))
syn sync clear
if 0
syn sync ccomment
endif
call assert_notmatch('on C-style comments', execute('syntax sync'))
syn sync fromstart
call assert_match('syncing starts at the first line', execute('syntax sync'))
syn clear
endfunc
" Check for an error. Used when multiple errors are thrown and we are checking
" for an earliest error.
func AssertFails(cmd, errcode)
let save_exception = ''
try
exe a:cmd
catch
let save_exception = v:exception
endtry
call assert_match(a:errcode, save_exception)
endfunc
func Test_syntax_invalid_arg()
call assert_fails('syntax case asdf', 'E390:')
if has('conceal')
call assert_fails('syntax conceal asdf', 'E390:')
endif
call assert_fails('syntax spell asdf', 'E390:')
call assert_fails('syntax clear @ABCD', 'E391:')
call assert_fails('syntax include random_file', 'E484:')
call assert_fails('syntax include <afile>', 'E495:')
call assert_fails('syntax sync x', 'E404:')
call assert_fails('syntax keyword Abc a[', 'E789:')
call assert_fails('syntax keyword Abc a[bc]d', 'E890:')
call assert_fails('syntax cluster Abc add=A add=', 'E406:')
" Test for too many \z\( and unmatched \z\(
" Not able to use assert_fails() here because both E50:/E879: and E475:
" messages are emitted.
set regexpengine=1
call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E52:')
let cmd = "syntax region MyRegion start='"
let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
call AssertFails(cmd, 'E50:')
set regexpengine=2
call AssertFails("syntax region MyRegion start='\\z\\(' end='\\*/'", 'E54:')
let cmd = "syntax region MyRegion start='"
let cmd ..= repeat("\\z\\(.\\)", 10) .. "' end='\*/'"
call AssertFails(cmd, 'E879:')
set regexpengine&
call AssertFails('syntax keyword cMyItem grouphere G1', 'E393:')
call AssertFails('syntax sync match Abc grouphere MyItem "abc"', 'E394:')
call AssertFails('syn keyword Type contains int', 'E395:')
call assert_fails('syntax include @Xxx', 'E397:')
call AssertFails('syntax region X start', 'E398:')
call assert_fails('syntax region X start="{"', 'E399:')
call AssertFails('syntax cluster contains=Abc', 'E400:')
call AssertFails("syntax match Character /'.'", 'E401:')
call AssertFails("syntax match Character /'.'/a", 'E402:')
call assert_fails('syntax sync linecont /\%(/', 'E53:')
call assert_fails('syntax sync linecont /pat', 'E404:')
call assert_fails('syntax sync linecont', 'E404:')
call assert_fails('syntax sync linecont /pat1/ linecont /pat2/', 'E403:')
call assert_fails('syntax sync minlines=a', 'E404:')
call AssertFails('syntax match ABC /x/ contains=', 'E406:')
call AssertFails("syntax match Character contains /'.'/", 'E405:')
call AssertFails('syntax match ccFoo "Foo" nextgroup=ALLBUT,F', 'E407:')
call AssertFails('syntax region Block start="{" contains=F,ALLBUT', 'E408:')
call AssertFails("syntax match Characters contains=a.*x /'.'/", 'E409:')
call assert_fails('syntax match Search /abc/ contains=ALLBUT,/\%(/', 'E53:')
endfunc
func Test_syn_sync()
syntax region HereGroup start=/this/ end=/that/
syntax sync match SyncHere grouphere HereGroup "pattern"
call assert_match('SyncHere', execute('syntax sync'))
syn sync clear
call assert_notmatch('SyncHere', execute('syntax sync'))
syn clear
endfunc
func Test_syn_clear()
syntax keyword Foo foo
syntax keyword Bar tar
call assert_match('Foo', execute('syntax'))
call assert_match('Bar', execute('syntax'))
call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
syn clear Foo
call assert_notmatch('Foo', execute('syntax'))
call assert_match('Bar', execute('syntax'))
call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
syn clear Foo Bar
call assert_notmatch('Foo', execute('syntax'))
call assert_notmatch('Bar', execute('syntax'))
hi clear Foo
call assert_equal('Foo', synIDattr(hlID("Foo"), "name"))
hi clear Bar
call assert_fails('syntax clear invalid_syngroup', 'E28:')
endfunc
func Test_invalid_name()
syn clear
syn keyword Nop yes
call assert_fails("syntax keyword Wr\x17ong bar", 'E669:')
syntax keyword @Wrong bar
call assert_fails("syntax keyword @#Wrong bar", 'E5248:')
syn clear
hi clear Nop
hi clear @Wrong
endfunc
func Test_ownsyntax()
new XfooOwnSyntax
call setline(1, '#define FOO')
syntax on
set filetype=c
ownsyntax perl
" this should not crash
set
call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name'))
call assert_equal('c', b:current_syntax)
call assert_equal('perl', w:current_syntax)
" A new split window should have the original syntax.
split
call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name'))
call assert_equal('c', b:current_syntax)
call assert_equal(0, exists('w:current_syntax'))
wincmd x
call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name"))
syntax off
set filetype&
%bw!
endfunc
func Test_ownsyntax_completion()
call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"ownsyntax java javacc javascript javascriptreact', @:)
endfunc
func Test_highlight_invalid_arg()
if has('gui_running')
call assert_fails('hi XXX guifg=xxx', 'E254:')
endif
call assert_fails('hi DoesNotExist', 'E411:')
call assert_fails('hi link', 'E412:')
call assert_fails('hi link a', 'E412:')
call assert_fails('hi link a b c', 'E413:')
call assert_fails('hi XXX =', 'E415:')
call assert_fails('hi XXX cterm', 'E416:')
call assert_fails('hi XXX cterm=', 'E417:')
call assert_fails('hi XXX cterm=DoesNotExist', 'E418:')
call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:')
call assert_fails('hi XXX xxx=White', 'E423:')
endfunc
func Test_conceal()
if !has('conceal')
return
endif
new
call setline(1, ['', '123456'])
syn match test23 "23" conceal cchar=X
syn match test45 "45" conceal
set conceallevel=0
call assert_equal('123456 ', ScreenLines(2, 7)[0])
call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
set conceallevel=1
call assert_equal('1X 6 ', ScreenLines(2, 7)[0])
call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, ' ', 2], [1, ' ', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
set conceallevel=1
set listchars=conceal:Y
call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, 'Y', 2], [1, 'Y', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
call assert_equal('1XY6 ', ScreenLines(2, 7)[0])
set conceallevel=2
call assert_match('1X6 ', ScreenLines(2, 7)[0])
call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
set conceallevel=3
call assert_match('16 ', ScreenLines(2, 7)[0])
call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)'))
call AssertFails("syntax match Entity '&amp;' conceal cchar=\<Tab>", 'E844:')
syn clear
set conceallevel&
bw!
endfunc
func Test_bg_detection()
CheckNotGui
" auto-detection of &bg, make sure sure it isn't set anywhere before
" this test
hi Normal ctermbg=0
call assert_equal('dark', &bg)
hi Normal ctermbg=4
call assert_equal('dark', &bg)
hi Normal ctermbg=12
call assert_equal('light', &bg)
hi Normal ctermbg=15
call assert_equal('light', &bg)
" manually-set &bg takes precedence over auto-detection
set bg=light
hi Normal ctermbg=4
call assert_equal('light', &bg)
set bg=dark
hi Normal ctermbg=12
call assert_equal('dark', &bg)
hi Normal ctermbg=NONE
endfunc
func Test_syntax_hangs()
if !has('reltime') || !has('float') || !has('syntax')
return
endif
" This pattern takes a long time to match, it should timeout.
new
call setline(1, ['aaa', repeat('abc ', 1000), 'ccc'])
let start = reltime()
set nolazyredraw redrawtime=101
syn match Error /\%#=1a*.*X\@<=b*/
redraw
let elapsed = reltimefloat(reltime(start))
call assert_true(elapsed > 0.1)
call assert_true(elapsed < 1.0)
" second time syntax HL is disabled
let start = reltime()
redraw
let elapsed = reltimefloat(reltime(start))
call assert_true(elapsed < 0.1)
" after CTRL-L the timeout flag is reset
let start = reltime()
exe "normal \<C-L>"
redraw
let elapsed = reltimefloat(reltime(start))
call assert_true(elapsed > 0.1)
call assert_true(elapsed < 1.0)
set redrawtime&
bwipe!
endfunc
func Test_synstack_synIDtrans()
new
setfiletype c
syntax on
call setline(1, ' /* A comment with a TODO */')
call assert_equal([], synstack(1, 1))
norm f/
eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart'])
eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment'])
norm fA
call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
call assert_equal(['Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
norm fT
call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
call assert_equal(['Comment', 'Todo'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
call assert_fails("let n=synIDtrans([])", 'E745:')
syn clear
bw!
endfunc
" Check highlighting for a small piece of C code with a screen dump.
func Test_syntax_c()
CheckRunVimInTerminal
call writefile([
\ '/* comment line at the top */',
\ 'int main(int argc, char **argv) { // another comment',
\ '#if 0',
\ ' int not_used;',
\ '#else',
\ ' int used;',
\ '#endif',
\ ' printf("Just an example piece of C code\n");',
\ ' return 0x0ff;',
\ '}',
\ ' static void',
\ 'myFunction(const double count, struct nothing, long there) {',
\ ' // 123: nothing to read here',
\ ' for (int i = 0; i < count; ++i) {',
\ ' break;',
\ ' }',
\ " Note: asdf",
\ '}',
\ ], 'Xtest.c')
" This makes the default for 'background' use "dark", check that the
" response to t_RB corrects it to "light".
let $COLORFGBG = '15;0'
let buf = RunVimInTerminal('Xtest.c', {})
call term_sendkeys(buf, ":syn keyword Search Note\r")
call VerifyScreenDump(buf, 'Test_syntax_c_01', {})
call StopVimInTerminal(buf)
let $COLORFGBG = ''
call delete('Xtest.c')
endfun
" Test \z(...) along with \z1
func Test_syn_zsub()
new
syntax on
call setline(1, 'xxx start foo xxx not end foo xxx end foo xxx')
let l:expected = ' ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ '
for l:re in [0, 1, 2]
" Example taken from :help :syn-ext-match
syntax region Z start="start \z(\I\i*\)" skip="not end \z1" end="end \z1"
eval AssertHighlightGroups(1, 1, l:expected, 1, 'regexp=' .. l:re)
syntax clear Z
endfor
set re&
bw!
endfunc
" Using \z() in a region with NFA failing should not crash.
func Test_syn_wrong_z_one()
new
call setline(1, ['just some text', 'with foo and bar to match with'])
syn region FooBar start="foo\z(.*\)bar" end="\z1"
" call test_override("nfa_fail", 1)
redraw!
redraw!
" call test_override("ALL", 0)
bwipe!
endfunc
func Test_syntax_after_bufdo()
call writefile(['/* aaa comment */'], 'Xaaa.c')
call writefile(['/* bbb comment */'], 'Xbbb.c')
call writefile(['/* ccc comment */'], 'Xccc.c')
call writefile(['/* ddd comment */'], 'Xddd.c')
let bnr = bufnr('%')
new Xaaa.c
badd Xbbb.c
badd Xccc.c
badd Xddd.c
exe "bwipe " . bnr
let l = []
bufdo call add(l, bufnr('%'))
call assert_equal(4, len(l))
syntax on
" This used to only enable syntax HL in the last buffer.
bufdo tab split
tabrewind
for tab in range(1, 4)
norm fm
call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
tabnext
endfor
bwipe! Xaaa.c
bwipe! Xbbb.c
bwipe! Xccc.c
bwipe! Xddd.c
syntax off
call delete('Xaaa.c')
call delete('Xbbb.c')
call delete('Xccc.c')
call delete('Xddd.c')
endfunc
func Test_syntax_foldlevel()
new
call setline(1, [
\ 'void f(int a)',
\ '{',
\ ' if (a == 1) {',
\ ' a = 0;',
\ ' } else if (a == 2) {',
\ ' a = 1;',
\ ' } else {',
\ ' a = 2;',
\ ' }',
\ ' if (a > 0) {',
\ ' if (a == 1) {',
\ ' a = 0;',
\ ' } /* missing newline */ } /* end of outer if */ else {',
\ ' a = 1;',
\ ' }',
\ ' if (a == 1)',
\ ' {',
\ ' a = 0;',
\ ' }',
\ ' else if (a == 2)',
\ ' {',
\ ' a = 1;',
\ ' }',
\ ' else',
\ ' {',
\ ' a = 2;',
\ ' }',
\ '}',
\ ])
setfiletype c
syntax on
set foldmethod=syntax
call assert_fails('syn foldlevel start start', 'E390')
call assert_fails('syn foldlevel not_an_option', 'E390')
set foldlevel=1
syn foldlevel start
redir @c
syn foldlevel
redir END
call assert_equal("\nsyntax foldlevel start", @c)
syn sync fromstart
call assert_match('from the first line$', execute('syn sync'))
let a = map(range(3,9), 'foldclosed(v:val)')
call assert_equal([3,3,3,3,3,3,3], a) " attached cascade folds together
let a = map(range(10,15), 'foldclosed(v:val)')
call assert_equal([10,10,10,10,10,10], a) " over-attached 'else' hidden
let a = map(range(16,27), 'foldclosed(v:val)')
let unattached_results = [-1,17,17,17,-1,21,21,21,-1,25,25,25]
call assert_equal(unattached_results, a) " unattached cascade folds separately
syn foldlevel minimum
redir @c
syn foldlevel
redir END
call assert_equal("\nsyntax foldlevel minimum", @c)
syn sync fromstart
let a = map(range(3,9), 'foldclosed(v:val)')
call assert_equal([3,3,5,5,7,7,7], a) " attached cascade folds separately
let a = map(range(10,15), 'foldclosed(v:val)')
call assert_equal([10,10,10,13,13,13], a) " over-attached 'else' visible
let a = map(range(16,27), 'foldclosed(v:val)')
call assert_equal(unattached_results, a) " unattached cascade folds separately
set foldlevel=2
syn foldlevel start
syn sync fromstart
let a = map(range(11,14), 'foldclosed(v:val)')
call assert_equal([11,11,11,-1], a) " over-attached 'else' hidden
syn foldlevel minimum
syn sync fromstart
let a = map(range(11,14), 'foldclosed(v:val)')
call assert_equal([11,11,-1,-1], a) " over-attached 'else' visible
quit!
endfunc
func Test_search_syntax_skip()
new
let lines =<< trim END
/* This is VIM */
Another Text for VIM
let a = "VIM"
END
call setline(1, lines)
syntax on
syntax match Comment "^/\*.*\*/"
syntax match String '".*"'
" Skip argument using string evaluation.
1
call search('VIM', 'w', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"')
call assert_equal('Another Text for VIM', getline('.'))
1
call search('VIM', 'cw', '', 0, 'synIDattr(synID(line("."), col("."), 1), "name") !~? "string"')
call assert_equal(' let a = "VIM"', getline('.'))
" Skip argument using Lambda.
1
call search('VIM', 'w', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"})
call assert_equal('Another Text for VIM', getline('.'))
1
call search('VIM', 'cw', '', 0, { -> synIDattr(synID(line("."), col("."), 1), "name") !~? "string"})
call assert_equal(' let a = "VIM"', getline('.'))
" Skip argument using funcref.
func InComment()
return synIDattr(synID(line("."), col("."), 1), "name") =~? "comment"
endfunc
func NotInString()
return synIDattr(synID(line("."), col("."), 1), "name") !~? "string"
endfunc
1
call search('VIM', 'w', '', 0, function('InComment'))
call assert_equal('Another Text for VIM', getline('.'))
1
call search('VIM', 'cw', '', 0, function('NotInString'))
call assert_equal(' let a = "VIM"', getline('.'))
delfunc InComment
delfunc NotInString
bwipe!
endfunc
func Test_syn_contained_transparent()
" Comments starting with "Regression:" show the result when the highlighting
" span of the containing item is assigned to the contained region.
syntax on
let l:case = "Transparent region contained in region"
new
syntax region X start=/\[/ end=/\]/ contained transparent
syntax region Y start=/(/ end=/)/ contains=X
call setline(1, "==(--[~~]--)==")
let l:expected = " YYYYYYYYYY "
eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
syntax clear Y X
bw!
let l:case = "Transparent region extends region"
new
syntax region X start=/\[/ end=/\]/ contained transparent
syntax region Y start=/(/ end=/)/ end=/e/ contains=X
call setline(1, "==(--[~~e~~]--)==")
let l:expected = " YYYYYYYYYYYYY "
" Regression: " YYYYYYY YYY "
eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
syntax clear Y X
bw!
let l:case = "Nested transparent regions extend region"
new
syntax region X start=/\[/ end=/\]/ contained transparent
syntax region Y start=/(/ end=/)/ end=/e/ contains=X
call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==")
let l:expected = " YYYYYYYYYYYYYYYYYYYYYYYYY "
" Regression: " YYYYYYY YYYYYYYYY "
eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
syntax clear Y X
bw!
let l:case = "Transparent region contained in match"
new
syntax region X start=/\[/ end=/\]/ contained transparent
syntax match Y /(.\{-})/ contains=X
call setline(1, "==(--[~~]--)==")
let l:expected = " YYYYYYYYYY "
eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
syntax clear Y X
bw!
let l:case = "Transparent region extends match"
new
syntax region X start=/\[/ end=/\]/ contained transparent
syntax match Y /(.\{-}[e)]/ contains=X
call setline(1, "==(--[~~e~~]--)==")
let l:expected = " YYYYYYYYYY "
" Regression: " YYYYYYY "
eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
syntax clear Y X
bw!
let l:case = "Nested transparent regions extend match"
new
syntax region X start=/\[/ end=/\]/ contained transparent
syntax match Y /(.\{-}[e)]/ contains=X
call setline(1, "==(--[~~e~~[~~e~~]~~e~~]--)==")
let l:expected = " YYYYYYYYYYYYYYYYYYYYYY "
" Regression: " YYYYYYY YYYYYY "
eval AssertHighlightGroups(1, 1, l:expected, 1, l:case)
syntax clear Y X
bw!
endfunc
func Test_syn_include_contains_TOP()
let l:case = "TOP in included syntax means its group list name"
new
syntax include @INCLUDED syntax/c.vim
syntax region FencedCodeBlockC start=/```c/ end=/```/ contains=@INCLUDED
call setline(1, ['```c', '#if 0', 'int', '#else', 'int', '#endif', '```' ])
let l:expected = ["cCppOutIf2"]
eval AssertHighlightGroups(3, 1, l:expected, 1)
" cCppOutElse has contains=TOP
let l:expected = ["cType"]
eval AssertHighlightGroups(5, 1, l:expected, 1, l:case)
syntax clear
bw!
endfunc
" This was using freed memory
func Test_WinEnter_synstack_synID()
autocmd WinEnter * call synstack(line("."), col("."))
autocmd WinEnter * call synID(line('.'), col('.') - 1, 1)
call setline(1, 'aaaaa')
normal! $
new
close
au! WinEnter
bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab