neovim

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

test_modeline.vim (17039B)


      1 " Tests for parsing the modeline.
      2 
      3 source check.vim
      4 
      5 func Test_modeline_invalid()
      6  " This was reading allocated memory in the past.
      7  call writefile(['vi:0', 'nothing'], 'Xmodeline')
      8  let modeline = &modeline
      9  set modeline
     10  call assert_fails('split Xmodeline', 'E518:')
     11 
     12  " Missing end colon (ignored).
     13  call writefile(['// vim: set ts=2'], 'Xmodeline')
     14  edit Xmodeline_version
     15  call assert_equal(8, &ts)
     16  bwipe!
     17 
     18  " Missing colon at beginning (ignored).
     19  call writefile(['// vim set ts=2:'], 'Xmodeline')
     20  edit Xmodeline_version
     21  call assert_equal(8, &ts)
     22  bwipe!
     23 
     24  " Missing space after vim (ignored).
     25  call writefile(['// vim:ts=2:'], 'Xmodeline')
     26  edit Xmodeline_version
     27  call assert_equal(8, &ts)
     28  bwipe!
     29 
     30  let &modeline = modeline
     31  bwipe!
     32  call delete('Xmodeline')
     33 endfunc
     34 
     35 func Test_modeline_filetype()
     36  call writefile(['vim: set ft=c :', 'nothing'], 'Xmodeline_filetype')
     37  let modeline = &modeline
     38  set modeline
     39  filetype plugin on
     40  split Xmodeline_filetype
     41  call assert_equal("c", &filetype)
     42  call assert_equal(1, b:did_ftplugin)
     43  call assert_equal("ccomplete#Complete", &ofu)
     44 
     45  bwipe!
     46  call delete('Xmodeline_filetype')
     47  let &modeline = modeline
     48  filetype plugin off
     49 endfunc
     50 
     51 func Test_modeline_syntax()
     52  call writefile(['vim: set syn=c :', 'nothing'], 'Xmodeline_syntax')
     53  let modeline = &modeline
     54  set modeline
     55  syntax enable
     56  split Xmodeline_syntax
     57  call assert_equal("c", &syntax)
     58  call assert_equal("c", b:current_syntax)
     59 
     60  bwipe!
     61  call delete('Xmodeline_syntax')
     62  let &modeline = modeline
     63  syntax off
     64 endfunc
     65 
     66 func Test_modeline_keymap()
     67  if !has('keymap')
     68    return
     69  endif
     70  call writefile(['vim: set keymap=greek :', 'nothing'], 'Xmodeline_keymap')
     71  let modeline = &modeline
     72  set modeline
     73  split Xmodeline_keymap
     74  call assert_equal("greek", &keymap)
     75  call assert_match('greek\|grk', b:keymap_name)
     76 
     77  bwipe!
     78  call delete('Xmodeline_keymap')
     79  let &modeline = modeline
     80  set keymap= iminsert=0 imsearch=-1
     81 endfunc
     82 
     83 func Test_modeline_version()
     84  let modeline = &modeline
     85  set modeline
     86 
     87  " Test with vim:{vers}: (version {vers} or later).
     88  call writefile(['// vim' .. v:version .. ': ts=2:'], 'Xmodeline_version')
     89  edit Xmodeline_version
     90  call assert_equal(2, &ts)
     91  bwipe!
     92 
     93  call writefile(['// vim' .. (v:version - 100) .. ': ts=2:'], 'Xmodeline_version')
     94  edit Xmodeline_version
     95  call assert_equal(2, &ts)
     96  bwipe!
     97 
     98  call writefile(['// vim' .. (v:version + 100) .. ': ts=2:'], 'Xmodeline_version')
     99  edit Xmodeline_version
    100  call assert_equal(8, &ts)
    101  bw!
    102 
    103  " Test with vim>{vers}: (version after {vers}).
    104  call writefile(['// vim>' .. v:version .. ': ts=2:'], 'Xmodeline_version')
    105  edit Xmodeline_version
    106  call assert_equal(8, &ts)
    107  bwipe!
    108 
    109  call writefile(['// vim>' .. (v:version - 100) .. ': ts=2:'], 'Xmodeline_version')
    110  edit Xmodeline_version
    111  call assert_equal(2, &ts)
    112  bwipe!
    113 
    114  call writefile(['// vim>' .. (v:version + 100) .. ': ts=2:'], 'Xmodeline_version')
    115  edit Xmodeline_version
    116  call assert_equal(8, &ts)
    117  bwipe!
    118 
    119  " Test with vim<{vers}: (version before {vers}).
    120  call writefile(['// vim<' .. v:version .. ': ts=2:'], 'Xmodeline_version')
    121  edit Xmodeline_version
    122  call assert_equal(8, &ts)
    123  bwipe!
    124 
    125  call writefile(['// vim<' .. (v:version - 100) .. ': ts=2:'], 'Xmodeline_version')
    126  edit Xmodeline_version
    127  call assert_equal(8, &ts)
    128  bwipe!
    129 
    130  call writefile(['// vim<' .. (v:version + 100) .. ': ts=2:'], 'Xmodeline_version')
    131  edit Xmodeline_version
    132  call assert_equal(2, &ts)
    133  bwipe!
    134 
    135  " Test with vim={vers}: (version {vers} only).
    136  call writefile(['// vim=' .. v:version .. ': ts=2:'], 'Xmodeline_version')
    137  edit Xmodeline_version
    138  call assert_equal(2, &ts)
    139  bwipe!
    140 
    141  call writefile(['// vim=' .. (v:version - 100) .. ': ts=2:'], 'Xmodeline_version')
    142  edit Xmodeline_version
    143  call assert_equal(8, &ts)
    144  bwipe!
    145 
    146  call writefile(['// vim=' .. (v:version + 100) .. ': ts=2:'], 'Xmodeline_version')
    147  edit Xmodeline_version
    148  call assert_equal(8, &ts)
    149  bwipe!
    150 
    151  let &modeline = modeline
    152  call delete('Xmodeline_version')
    153 endfunc
    154 
    155 func Test_modeline_colon()
    156  let modeline = &modeline
    157  set modeline
    158 
    159  call writefile(['// vim: set showbreak=\: ts=2: sw=2'], 'Xmodeline_colon')
    160  edit Xmodeline_colon
    161 
    162  " backlash colon should become colon.
    163  call assert_equal(':', &showbreak)
    164 
    165  " 'ts' should be set.
    166  " 'sw' should be ignored because it is after the end colon.
    167  call assert_equal(2, &ts)
    168  call assert_equal(8, &sw)
    169 
    170  let &modeline = modeline
    171  call delete('Xmodeline_colon')
    172 endfunc
    173 
    174 func s:modeline_fails(what, text, error)
    175  " Don't use CheckOption(), it would skip the whole test
    176  " just for a single un-supported option
    177  if !exists('+' .. a:what)
    178    return
    179  endif
    180  let fname = "Xmodeline_fails_" . a:what
    181  call writefile(['vim: set ' . a:text . ' :', 'nothing'], fname)
    182  let modeline = &modeline
    183  set modeline
    184  filetype plugin on
    185  syntax enable
    186  call assert_fails('split ' . fname, a:error)
    187  call assert_equal("", &filetype)
    188  call assert_equal("", &syntax)
    189 
    190  bwipe!
    191  call delete(fname)
    192  let &modeline = modeline
    193  filetype plugin off
    194  syntax off
    195 endfunc
    196 
    197 func Test_modeline_filetype_fails()
    198  call s:modeline_fails('filetype', 'ft=evil$CMD', 'E474:')
    199 endfunc
    200 
    201 func Test_modeline_syntax_fails()
    202  call s:modeline_fails('syntax', 'syn=evil$CMD', 'E474:')
    203 endfunc
    204 
    205 func Test_modeline_keymap_fails()
    206  call s:modeline_fails('keymap', 'keymap=evil$CMD', 'E474:')
    207 endfunc
    208 
    209 func Test_modeline_fails_always()
    210  call s:modeline_fails('backupdir', 'backupdir=Something()', 'E520:')
    211  call s:modeline_fails('cdpath', 'cdpath=Something()', 'E520:')
    212  call s:modeline_fails('charconvert', 'charconvert=Something()', 'E520:')
    213  call s:modeline_fails('completefunc', 'completefunc=Something()', 'E520:')
    214  call s:modeline_fails('cscopeprg', 'cscopeprg=Something()', 'E520:')
    215  call s:modeline_fails('diffexpr', 'diffexpr=Something()', 'E520:')
    216  call s:modeline_fails('directory', 'directory=Something()', 'E520:')
    217  call s:modeline_fails('equalprg', 'equalprg=Something()', 'E520:')
    218  call s:modeline_fails('errorfile', 'errorfile=Something()', 'E520:')
    219  call s:modeline_fails('exrc', 'exrc=Something()', 'E520:')
    220  call s:modeline_fails('findfunc', 'findfunc=Something', 'E520:')
    221  call s:modeline_fails('formatprg', 'formatprg=Something()', 'E520:')
    222  call s:modeline_fails('fsync', 'fsync=Something()', 'E520:')
    223  call s:modeline_fails('grepprg', 'grepprg=Something()', 'E520:')
    224  call s:modeline_fails('helpfile', 'helpfile=Something()', 'E520:')
    225  call s:modeline_fails('imactivatefunc', 'imactivatefunc=Something()', 'E520:')
    226  call s:modeline_fails('imstatusfunc', 'imstatusfunc=Something()', 'E520:')
    227  call s:modeline_fails('imstyle', 'imstyle=Something()', 'E520:')
    228  call s:modeline_fails('keywordprg', 'keywordprg=Something()', 'E520:')
    229  call s:modeline_fails('langmap', 'langmap=Something()', 'E520:')
    230  call s:modeline_fails('luadll', 'luadll=Something()', 'E520:')
    231  call s:modeline_fails('makeef', 'makeef=Something()', 'E520:')
    232  call s:modeline_fails('makeprg', 'makeprg=Something()', 'E520:')
    233  call s:modeline_fails('mkspellmem', 'mkspellmem=Something()', 'E520:')
    234  call s:modeline_fails('mzschemedll', 'mzschemedll=Something()', 'E520:')
    235  call s:modeline_fails('mzschemegcdll', 'mzschemegcdll=Something()', 'E520:')
    236  call s:modeline_fails('modelineexpr', 'modelineexpr', 'E520:')
    237  call s:modeline_fails('omnifunc', 'omnifunc=Something()', 'E520:')
    238  call s:modeline_fails('operatorfunc', 'operatorfunc=Something()', 'E520:')
    239  call s:modeline_fails('perldll', 'perldll=Something()', 'E520:')
    240  call s:modeline_fails('printdevice', 'printdevice=Something()', 'E520:')
    241  call s:modeline_fails('patchexpr', 'patchexpr=Something()', 'E520:')
    242  call s:modeline_fails('printexpr', 'printexpr=Something()', 'E520:')
    243  call s:modeline_fails('pythondll', 'pythondll=Something()', 'E520:')
    244  call s:modeline_fails('pythonhome', 'pythonhome=Something()', 'E520:')
    245  call s:modeline_fails('pythonthreedll', 'pythonthreedll=Something()', 'E520:')
    246  call s:modeline_fails('pythonthreehome', 'pythonthreehome=Something()', 'E520:')
    247  call s:modeline_fails('pyxversion', 'pyxversion=Something()', 'E520:')
    248  call s:modeline_fails('rubydll', 'rubydll=Something()', 'E520:')
    249  call s:modeline_fails('runtimepath', 'runtimepath=Something()', 'E520:')
    250  call s:modeline_fails('secure', 'secure=Something()', 'E520:')
    251  call s:modeline_fails('shell', 'shell=Something()', 'E520:')
    252  call s:modeline_fails('shellcmdflag', 'shellcmdflag=Something()', 'E520:')
    253  call s:modeline_fails('shellpipe', 'shellpipe=Something()', 'E520:')
    254  call s:modeline_fails('shellquote', 'shellquote=Something()', 'E520:')
    255  call s:modeline_fails('shellredir', 'shellredir=Something()', 'E520:')
    256  call s:modeline_fails('shellxquote', 'shellxquote=Something()', 'E520:')
    257  call s:modeline_fails('spellfile', 'spellfile=Something()', 'E520:')
    258  call s:modeline_fails('spellsuggest', 'spellsuggest=Something()', 'E520:')
    259  call s:modeline_fails('tcldll', 'tcldll=Something()', 'E520:')
    260  call s:modeline_fails('titleold', 'titleold=Something()', 'E520:')
    261  call s:modeline_fails('viewdir', 'viewdir=Something()', 'E520:')
    262  call s:modeline_fails('viminfo', 'viminfo=Something()', 'E520:')
    263  call s:modeline_fails('viminfofile', 'viminfofile=Something()', 'E520:')
    264  call s:modeline_fails('winptydll', 'winptydll=Something()', 'E520:')
    265  call s:modeline_fails('undodir', 'undodir=Something()', 'E520:')
    266  " only check a few terminal options
    267  " Skip these since nvim doesn't support termcodes as options
    268  "call s:modeline_fails('t_AB', 't_AB=Something()', 'E520:')
    269  "call s:modeline_fails('t_ce', 't_ce=Something()', 'E520:')
    270  "call s:modeline_fails('t_sr', 't_sr=Something()', 'E520:')
    271  "call s:modeline_fails('t_8b', 't_8b=Something()', 'E520:')
    272 endfunc
    273 
    274 func Test_modeline_fails_modelineexpr()
    275  call s:modeline_fails('balloonexpr', 'balloonexpr=Something()', 'E992:')
    276  call s:modeline_fails('foldexpr', 'foldexpr=Something()', 'E992:')
    277  call s:modeline_fails('foldtext', 'foldtext=Something()', 'E992:')
    278  call s:modeline_fails('formatexpr', 'formatexpr=Something()', 'E992:')
    279  call s:modeline_fails('guitablabel', 'guitablabel=Something()', 'E992:')
    280  call s:modeline_fails('iconstring', 'iconstring=Something()', 'E992:')
    281  call s:modeline_fails('includeexpr', 'includeexpr=Something()', 'E992:')
    282  call s:modeline_fails('indentexpr', 'indentexpr=Something()', 'E992:')
    283  call s:modeline_fails('rulerformat', 'rulerformat=Something()', 'E992:')
    284  call s:modeline_fails('statusline', 'statusline=Something()', 'E992:')
    285  call s:modeline_fails('tabline', 'tabline=Something()', 'E992:')
    286  call s:modeline_fails('titlestring', 'titlestring=Something()', 'E992:')
    287 endfunc
    288 
    289 func Test_modeline_setoption_verbose()
    290  let modeline = &modeline
    291  set modeline
    292 
    293  let lines =<< trim END
    294  1 vim:ts=2
    295  2 two
    296  3 three
    297  4 four
    298  5 five
    299  6 six
    300  7 seven
    301  8 eight
    302  END
    303  call writefile(lines, 'Xmodeline')
    304  edit Xmodeline
    305  let info = split(execute('verbose set tabstop?'), "\n")
    306  call assert_match('^\s*Last set from modeline line 1$', info[-1])
    307  bwipe!
    308 
    309  let lines =<< trim END
    310  1 one
    311  2 two
    312  3 three
    313  4 vim:ts=4
    314  5 five
    315  6 six
    316  7 seven
    317  8 eight
    318  END
    319  call writefile(lines, 'Xmodeline')
    320  edit Xmodeline
    321  let info = split(execute('verbose set tabstop?'), "\n")
    322  call assert_match('^\s*Last set from modeline line 4$', info[-1])
    323  bwipe!
    324 
    325  let lines =<< trim END
    326  1 one
    327  2 two
    328  3 three
    329  4 four
    330  5 five
    331  6 six
    332  7 seven
    333  8 vim:ts=8
    334  END
    335  call writefile(lines, 'Xmodeline')
    336  edit Xmodeline
    337  let info = split(execute('verbose set tabstop?'), "\n")
    338  call assert_match('^\s*Last set from modeline line 8$', info[-1])
    339  bwipe!
    340 
    341  let &modeline = modeline
    342  call delete('Xmodeline')
    343 endfunc
    344 
    345 " Test for the 'modeline' default value in compatible and non-compatible modes
    346 " for root and non-root accounts
    347 func Test_modeline_default()
    348  " set compatible
    349  " call assert_false(&modeline)
    350  set nocompatible
    351  call assert_equal(IsRoot() ? 0 : 1, &modeline)
    352  " set compatible&vi
    353  " call assert_false(&modeline)
    354  set compatible&vim
    355  call assert_equal(IsRoot() ? 0 : 1, &modeline)
    356  set compatible& modeline&
    357 endfunc
    358 
    359 " Some options cannot be set from the modeline when 'diff' option is set
    360 func Test_modeline_diff_buffer()
    361  call writefile(['vim: diff foldmethod=marker wrap'], 'Xmdifile', 'D')
    362  set foldmethod& nowrap
    363  new Xmdifile
    364  call assert_equal('manual', &foldmethod)
    365  call assert_false(&wrap)
    366  set wrap&
    367  bw
    368 endfunc
    369 
    370 func Test_modeline_disable()
    371  set modeline
    372  call writefile(['vim: sw=2', 'vim: nomodeline', 'vim: sw=3'], 'Xmodeline_disable', 'D')
    373  edit Xmodeline_disable
    374  call assert_equal(2, &sw)
    375 endfunc
    376 
    377 " If 'nowrap' is set from a modeline, '>' is used forcibly as lcs-extends.
    378 func Test_modeline_nowrap_lcs_extends()
    379  call writefile([
    380        \ 'aaa',
    381        \ 'bbb',
    382        \ 'ccc                    evil',
    383        \ 'ddd                    vim: nowrap',
    384        \ ], 'Xmodeline_nowrap', 'D')
    385  set noequalalways
    386  11new | 20vsplit
    387 
    388  func Check_modeline_nowrap(expect_insecure, expect_secure, set_cmd)
    389    edit Xmodeline_nowrap
    390    call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20))
    391 
    392    5split
    393    call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20))
    394    call assert_equal(a:expect_insecure, ScreenLines([7, 11], 20))
    395 
    396    exe a:set_cmd 'nowrap'
    397    call assert_equal(a:expect_secure, ScreenLines([1, 5], 20))
    398    call assert_equal(a:expect_insecure, ScreenLines([7, 11], 20))
    399 
    400    close
    401    call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20))
    402 
    403    setglobal nowrap
    404    call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20))
    405    setglobal wrap
    406    call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20))
    407 
    408    exe a:set_cmd 'nowrap'
    409    call assert_equal(a:expect_secure, ScreenLines([1, 5], 20))
    410 
    411    exe 'sandbox' a:set_cmd 'nowrap'
    412    call assert_equal(a:expect_insecure, ScreenLines([1, 5], 20))
    413 
    414    exe a:set_cmd 'nowrap'
    415    call assert_equal(a:expect_secure, ScreenLines([1, 5], 20))
    416  endfunc
    417 
    418  setlocal nolist listchars=
    419  let expect_insecure = [
    420        \ 'aaa                 ',
    421        \ 'bbb                 ',
    422        \ 'ccc                >',
    423        \ 'ddd                >',
    424        \ '~                   ',
    425        \ ]
    426  let expect_secure = [
    427        \ 'aaa                 ',
    428        \ 'bbb                 ',
    429        \ 'ccc                 ',
    430        \ 'ddd                 ',
    431        \ '~                   ',
    432        \ ]
    433  call Check_modeline_nowrap(expect_insecure, expect_secure, 'setlocal')
    434  call Check_modeline_nowrap(expect_insecure, expect_secure, 'set')
    435 
    436  setlocal list listchars=extends:+
    437  let expect_secure = [
    438        \ 'aaa                 ',
    439        \ 'bbb                 ',
    440        \ 'ccc                +',
    441        \ 'ddd                +',
    442        \ '~                   ',
    443        \ ]
    444  call assert_equal(expect_secure, ScreenLines([1, 5], 20))
    445  call Check_modeline_nowrap(expect_insecure, expect_secure, 'setlocal')
    446  call Check_modeline_nowrap(expect_insecure, expect_secure, 'set')
    447 
    448  " Other 'listchars' flags are not affected.
    449  call writefile([
    450        \ "aa\ta",
    451        \ "bb\tb",
    452        \ "cc\tc              evil",
    453        \ "dd\td              vim: nowrap lcs=tab\\:<->",
    454        \ ], 'Xmodeline_nowrap')
    455  let expect_insecure = [
    456        \ 'aa<---->a           ',
    457        \ 'bb<---->b           ',
    458        \ 'cc<---->c          >',
    459        \ 'dd<---->d          >',
    460        \ '~                   ',
    461        \ ]
    462  let expect_secure = [
    463        \ 'aa<---->a           ',
    464        \ 'bb<---->b           ',
    465        \ 'cc<---->c           ',
    466        \ 'dd<---->d           ',
    467        \ '~                   ',
    468        \ ]
    469  call Check_modeline_nowrap(expect_insecure, expect_secure, 'setlocal')
    470  call Check_modeline_nowrap(expect_insecure, expect_secure, 'set')
    471 
    472  " Same behavior even if modeline sets "extends" to a space.
    473  call writefile([
    474        \ "aa\ta",
    475        \ "bb\tb",
    476        \ "cc\tc              evil",
    477        \ "dd\td              vim: nowrap lcs=tab\\:<->",
    478        \ ], 'Xmodeline_nowrap')
    479  call Check_modeline_nowrap(expect_insecure, expect_secure, 'setlocal')
    480  call Check_modeline_nowrap(expect_insecure, expect_secure, 'set')
    481 
    482  sandbox setglobal nowrap
    483  setglobal list listchars=eol:$
    484  setlocal bufhidden=wipe
    485  enew!
    486  call setline(1, ['aaa                    bbb'])
    487  call assert_equal(['aaa                >'], ScreenLines(1, 20))
    488  setglobal nowrap
    489  call assert_equal(['aaa                >'], ScreenLines(1, 20))
    490  setlocal nowrap
    491  call assert_equal(['aaa                 '], ScreenLines(1, 20))
    492  normal! 20zl
    493  call assert_equal(['   bbb$             '], ScreenLines(1, 20))
    494  setlocal bufhidden=wipe
    495  enew!
    496  call setline(1, ['ccc                    ddd'])
    497  call assert_equal(['ccc                 '], ScreenLines(1, 20))
    498  normal! 20zl
    499  call assert_equal(['   ddd$             '], ScreenLines(1, 20))
    500 
    501  bwipe!
    502  delfunc Check_modeline_nowrap
    503  set equalalways&
    504 endfunc
    505 
    506 " vim: shiftwidth=2 sts=2 expandtab