neovim

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

test_regexp_latin.vim (46167B)


      1 " Tests for regexp in latin1 encoding
      2 
      3 " set encoding=latin1
      4 scriptencoding latin1
      5 
      6 source check.vim
      7 
      8 func s:equivalence_test()
      9  let str = 'A������ B C D E���� F G H I���� J K L M N� O������ P Q R S T U���� V W X Y� Z '
     10  \      .. 'a������ b c d e���� f g h i���� j k l m n� o������ p q r s t u���� v w x y�� z '
     11  \      .. "0 1 2 3 4 5 6 7 8 9 "
     12  \      .. "` ~ ! ? ; : . , / \\ ' \" | < > [ ] { } ( ) @ # $ % ^ & * _ - + \b \e \f \n \r \t"
     13  let groups = split(str)
     14  for group1 in groups
     15      for c in split(group1, '\zs')
     16 " next statement confirms that equivalence class matches every
     17 " character in group
     18        call assert_match('^[[=' . c . '=]]*$', group1)
     19        for group2 in groups
     20          if group2 != group1
     21     " next statement converts that equivalence class doesn't match
     22     " a character in any other group
     23            call assert_equal(-1, match(group2, '[[=' . c . '=]]'))
     24          endif
     25        endfor
     26      endfor
     27  endfor
     28 endfunc
     29 
     30 func Test_equivalence_re1()
     31  set re=1
     32  call s:equivalence_test()
     33  set re=0
     34 endfunc
     35 
     36 func Test_equivalence_re2()
     37  set re=2
     38  call s:equivalence_test()
     39  set re=0
     40 endfunc
     41 
     42 func Test_recursive_substitute()
     43  new
     44  s/^/\=execute("s#^##gn")
     45  " check we are now not in the sandbox
     46  call setwinvar(1, 'myvar', 1)
     47  bwipe!
     48 endfunc
     49 
     50 func Test_nested_backrefs()
     51  " Check example in change.txt.
     52  new
     53  for re in range(0, 2)
     54    exe 'set re=' . re
     55    call setline(1, 'aa ab x')
     56    1s/\(\(a[a-d] \)*\)\(x\)/-\1- -\2- -\3-/
     57    call assert_equal('-aa ab - -ab - -x-', getline(1))
     58 
     59    call assert_equal('-aa ab - -ab - -x-', substitute('aa ab x', '\(\(a[a-d] \)*\)\(x\)', '-\1- -\2- -\3-', ''))
     60  endfor
     61  bwipe!
     62  set re=0
     63 endfunc
     64 
     65 func Test_eow_with_optional()
     66  let expected = ['abc def', 'abc', 'def', '', '', '', '', '', '', '']
     67  for re in range(0, 2)
     68    exe 'set re=' . re
     69    let actual = matchlist('abc def', '\(abc\>\)\?\s*\(def\)')
     70    call assert_equal(expected, actual)
     71  endfor
     72  set re=0
     73 endfunc
     74 
     75 func Test_backref()
     76  new
     77  call setline(1, ['one', 'two', 'three', 'four', 'five'])
     78  call assert_equal(3, search('\%#=1\(e\)\1'))
     79  call assert_equal(3, search('\%#=2\(e\)\1'))
     80  call assert_fails('call search("\\%#=1\\(e\\1\\)")', 'E65:')
     81  call assert_fails('call search("\\%#=2\\(e\\1\\)")', 'E65:')
     82  bwipe!
     83 endfunc
     84 
     85 func Test_multi_failure()
     86  set re=1
     87  call assert_fails('/a**', 'E61:')
     88  call assert_fails('/a*\+', 'E62:')
     89  call assert_fails('/a\{a}', 'E554:')
     90  set re=2
     91  call assert_fails('/a**', 'E871:')
     92  call assert_fails('/a*\+', 'E871:')
     93  call assert_fails('/a\{a}', 'E554:')
     94  set re=0
     95 endfunc
     96 
     97 func Test_column_success_failure()
     98  new
     99  call setline(1, 'xbar')
    100 
    101  set re=1
    102  %s/\%>0v./A/
    103  call assert_equal('Abar', getline(1))
    104  call assert_fails('/\%v', 'E71:')
    105  call assert_fails('/\%>v', 'E71:')
    106  call assert_fails('/\%c', 'E71:')
    107  call assert_fails('/\%<c', 'E71:')
    108  call assert_fails('/\%l', 'E71:')
    109  set re=2
    110  %s/\%>0v./B/
    111  call assert_equal('Bbar', getline(1))
    112  call assert_fails('/\%v', 'E1273:')
    113  call assert_fails('/\%>v', 'E1273:')
    114  call assert_fails('/\%c', 'E1273:')
    115  call assert_fails('/\%<c', 'E1273:')
    116  call assert_fails('/\%l', 'E1273:')
    117 
    118  set re=0
    119  bwipe!
    120 endfunc
    121 
    122 func Test_recursive_addstate()
    123  throw 'skipped: TODO: '
    124  " This will call addstate() recursively until it runs into the limit.
    125  let lnum = search('\v((){328}){389}')
    126  call assert_equal(0, lnum)
    127 endfunc
    128 
    129 func Test_out_of_memory()
    130  new
    131  s/^/,n
    132  " This will be slow...
    133  call assert_fails('call search("\\v((n||<)+);")', 'E363:')
    134 endfunc
    135 
    136 func Test_get_equi_class()
    137  new
    138  " Incomplete equivalence class caused invalid memory access
    139  s/^/[[=
    140  call assert_equal(1, search(getline(1)))
    141  s/.*/[[.
    142  call assert_equal(1, search(getline(1)))
    143 endfunc
    144 
    145 func Test_rex_init()
    146  set noincsearch
    147  set re=1
    148  new
    149  setlocal iskeyword=a-z
    150  call setline(1, ['abc', 'ABC'])
    151  call assert_equal(1, search('[[:keyword:]]'))
    152  new
    153  setlocal iskeyword=A-Z
    154  call setline(1, ['abc', 'ABC'])
    155  call assert_equal(2, search('[[:keyword:]]'))
    156  bwipe!
    157  bwipe!
    158  set re=0
    159 endfunc
    160 
    161 func Test_range_with_newline()
    162  new
    163  call setline(1, "a")
    164  call assert_equal(0, search("[ -*\\n- ]"))
    165  call assert_equal(0, search("[ -*\\t-\\n]"))
    166  bwipe!
    167 endfunc
    168 
    169 func Test_pattern_compile_speed()
    170  CheckOption spellcapcheck
    171  CheckFunction reltimefloat
    172 
    173  let start = reltime()
    174  " this used to be very slow, not it should be about a second
    175  set spc=\\v(((((Nxxxxxxx&&xxxx){179})+)+)+){179}
    176  call assert_inrange(0.01, 10.0, reltimefloat(reltime(start)))
    177  set spc=
    178 endfunc
    179 
    180 " Tests for regexp patterns without multi-byte support.
    181 func Test_regexp_single_line_pat()
    182  " tl is a List of Lists with:
    183  "    regexp engines to test
    184  "       0 - test with 'regexpengine' values 0 and 1
    185  "       1 - test with 'regexpengine' values 0 and 2
    186  "       2 - test with 'regexpengine' values 0, 1 and 2
    187  "    regexp pattern
    188  "    text to test the pattern on
    189  "    expected match (optional)
    190  "    expected submatch 1 (optional)
    191  "    expected submatch 2 (optional)
    192  "    etc.
    193  "  When there is no match use only the first two items.
    194  let tl = []
    195 
    196  call add(tl, [2, 'ab', 'aab', 'ab'])
    197  call add(tl, [2, 'b', 'abcdef', 'b'])
    198  call add(tl, [2, 'bc*', 'abccccdef', 'bcccc'])
    199  call add(tl, [2, 'bc\{-}', 'abccccdef', 'b'])
    200  call add(tl, [2, 'bc\{-}\(d\)', 'abccccdef', 'bccccd', 'd'])
    201  call add(tl, [2, 'bc*', 'abbdef', 'b'])
    202  call add(tl, [2, 'c*', 'ccc', 'ccc'])
    203  call add(tl, [2, 'bc*', 'abdef', 'b'])
    204  call add(tl, [2, 'c*', 'abdef', ''])
    205  call add(tl, [2, 'bc\+', 'abccccdef', 'bcccc'])
    206  call add(tl, [2, 'bc\+', 'abdef']) " no match
    207  " match escape character in a string
    208  call add(tl, [2, '.\e.', "one\<Esc>two", "e\<Esc>t"])
    209  " match backspace character in a string
    210  call add(tl, [2, '.\b.', "one\<C-H>two", "e\<C-H>t"])
    211  " match newline character in a string
    212  call add(tl, [2, 'o\nb', "foo\nbar", "o\nb"])
    213 
    214  " operator \|
    215  call add(tl, [2, 'a\|ab', 'cabd', 'a']) " alternation is ordered
    216 
    217  call add(tl, [2, 'c\?', 'ccb', 'c'])
    218  call add(tl, [2, 'bc\?', 'abd', 'b'])
    219  call add(tl, [2, 'bc\?', 'abccd', 'bc'])
    220 
    221  call add(tl, [2, '\va{1}', 'ab', 'a'])
    222 
    223  call add(tl, [2, '\va{2}', 'aa', 'aa'])
    224  call add(tl, [2, '\va{2}', 'caad', 'aa'])
    225  call add(tl, [2, '\va{2}', 'aba'])
    226  call add(tl, [2, '\va{2}', 'ab'])
    227  call add(tl, [2, '\va{2}', 'abaa', 'aa'])
    228  call add(tl, [2, '\va{2}', 'aaa', 'aa'])
    229 
    230  call add(tl, [2, '\vb{1}', 'abca', 'b'])
    231  call add(tl, [2, '\vba{2}', 'abaa', 'baa'])
    232  call add(tl, [2, '\vba{3}', 'aabaac'])
    233 
    234  call add(tl, [2, '\v(ab){1}', 'ab', 'ab', 'ab'])
    235  call add(tl, [2, '\v(ab){1}', 'dabc', 'ab', 'ab'])
    236  call add(tl, [2, '\v(ab){1}', 'acb'])
    237 
    238  call add(tl, [2, '\v(ab){0,2}', 'acb', "", ""])
    239  call add(tl, [2, '\v(ab){0,2}', 'ab', 'ab', 'ab'])
    240  call add(tl, [2, '\v(ab){1,2}', 'ab', 'ab', 'ab'])
    241  call add(tl, [2, '\v(ab){1,2}', 'ababc', 'abab', 'ab'])
    242  call add(tl, [2, '\v(ab){2,4}', 'ababcab', 'abab', 'ab'])
    243  call add(tl, [2, '\v(ab){2,4}', 'abcababa', 'abab', 'ab'])
    244 
    245  call add(tl, [2, '\v(ab){2}', 'abab', 'abab', 'ab'])
    246  call add(tl, [2, '\v(ab){2}', 'cdababe', 'abab', 'ab'])
    247  call add(tl, [2, '\v(ab){2}', 'abac'])
    248  call add(tl, [2, '\v(ab){2}', 'abacabab', 'abab', 'ab'])
    249  call add(tl, [2, '\v((ab){2}){2}', 'abababab', 'abababab', 'abab', 'ab'])
    250  call add(tl, [2, '\v((ab){2}){2}', 'abacabababab', 'abababab', 'abab', 'ab'])
    251 
    252  call add(tl, [2, '\v(a{1}){1}', 'a', 'a', 'a'])
    253  call add(tl, [2, '\v(a{2}){1}', 'aa', 'aa', 'aa'])
    254  call add(tl, [2, '\v(a{2}){1}', 'aaac', 'aa', 'aa'])
    255  call add(tl, [2, '\v(a{2}){1}', 'daaac', 'aa', 'aa'])
    256  call add(tl, [2, '\v(a{1}){2}', 'daaac', 'aa', 'a'])
    257  call add(tl, [2, '\v(a{1}){2}', 'aaa', 'aa', 'a'])
    258  call add(tl, [2, '\v(a{2})+', 'adaac', 'aa', 'aa'])
    259  call add(tl, [2, '\v(a{2})+', 'aa', 'aa', 'aa'])
    260  call add(tl, [2, '\v(a{2}){1}', 'aa', 'aa', 'aa'])
    261  call add(tl, [2, '\v(a{1}){2}', 'aa', 'aa', 'a'])
    262  call add(tl, [2, '\v(a{1}){1}', 'a', 'a', 'a'])
    263  call add(tl, [2, '\v(a{2}){2}', 'aaaa', 'aaaa', 'aa'])
    264  call add(tl, [2, '\v(a{2}){2}', 'aaabaaaa', 'aaaa', 'aa'])
    265 
    266  call add(tl, [2, '\v(a+){2}', 'dadaac', 'aa', 'a'])
    267  call add(tl, [2, '\v(a{3}){2}', 'aaaaaaa', 'aaaaaa', 'aaa'])
    268 
    269  call add(tl, [2, '\v(a{1,2}){2}', 'daaac', 'aaa', 'a'])
    270  call add(tl, [2, '\v(a{1,3}){2}', 'daaaac', 'aaaa', 'a'])
    271  call add(tl, [2, '\v(a{1,3}){2}', 'daaaaac', 'aaaaa', 'aa'])
    272  call add(tl, [2, '\v(a{1,3}){3}', 'daac'])
    273  call add(tl, [2, '\v(a{1,2}){2}', 'dac'])
    274  call add(tl, [2, '\v(a+)+', 'daac', 'aa', 'aa'])
    275  call add(tl, [2, '\v(a+)+', 'aaa', 'aaa', 'aaa'])
    276  call add(tl, [2, '\v(a+){1,2}', 'aaa', 'aaa', 'aaa'])
    277  call add(tl, [2, '\v(a+)(a+)', 'aaa', 'aaa', 'aa', 'a'])
    278  call add(tl, [2, '\v(a{3})+', 'daaaac', 'aaa', 'aaa'])
    279  call add(tl, [2, '\v(a|b|c)+', 'aacb', 'aacb', 'b'])
    280  call add(tl, [2, '\v(a|b|c){2}', 'abcb', 'ab', 'b'])
    281  call add(tl, [2, '\v(abc){2}', 'abcabd', ])
    282  call add(tl, [2, '\v(abc){2}', 'abdabcabc','abcabc', 'abc'])
    283 
    284  call add(tl, [2, 'a*', 'cc', ''])
    285  call add(tl, [2, '\v(a*)+', 'cc', ''])
    286  call add(tl, [2, '\v((ab)+)+', 'ab', 'ab', 'ab', 'ab'])
    287  call add(tl, [2, '\v(((ab)+)+)+', 'ab', 'ab', 'ab', 'ab', 'ab'])
    288  call add(tl, [2, '\v(((ab)+)+)+', 'dababc', 'abab', 'abab', 'abab', 'ab'])
    289  call add(tl, [2, '\v(a{0,2})+', 'cc', ''])
    290  call add(tl, [2, '\v(a*)+', '', ''])
    291  call add(tl, [2, '\v((a*)+)+', '', ''])
    292  call add(tl, [2, '\v((ab)*)+', '', ''])
    293  call add(tl, [2, '\va{1,3}', 'aab', 'aa'])
    294  call add(tl, [2, '\va{2,3}', 'abaa', 'aa'])
    295 
    296  call add(tl, [2, '\v((ab)+|c*)+', 'abcccaba', 'abcccab', '', 'ab'])
    297  call add(tl, [2, '\v(a{2})|(b{3})', 'bbabbbb', 'bbb', '', 'bbb'])
    298  call add(tl, [2, '\va{2}|b{2}', 'abab'])
    299  call add(tl, [2, '\v(a)+|(c)+', 'bbacbaacbbb', 'a', 'a'])
    300  call add(tl, [2, '\vab{2,3}c', 'aabbccccccccccccc', 'abbc'])
    301  call add(tl, [2, '\vab{2,3}c', 'aabbbccccccccccccc', 'abbbc'])
    302  call add(tl, [2, '\vab{2,3}cd{2,3}e', 'aabbbcddee', 'abbbcdde'])
    303  call add(tl, [2, '\va(bc){2}d', 'aabcbfbc' ])
    304  call add(tl, [2, '\va*a{2}', 'a', ])
    305  call add(tl, [2, '\va*a{2}', 'aa', 'aa' ])
    306  call add(tl, [2, '\va*a{2}', 'aaa', 'aaa' ])
    307  call add(tl, [2, '\va*a{2}', 'bbbabcc', ])
    308  call add(tl, [2, '\va*b*|a*c*', 'a', 'a'])
    309  call add(tl, [2, '\va{1}b{1}|a{1}b{1}', ''])
    310 
    311  " submatches
    312  call add(tl, [2, '\v(a)', 'ab', 'a', 'a'])
    313  call add(tl, [2, '\v(a)(b)', 'ab', 'ab', 'a', 'b'])
    314  call add(tl, [2, '\v(ab)(b)(c)', 'abbc', 'abbc', 'ab', 'b', 'c'])
    315  call add(tl, [2, '\v((a)(b))', 'ab', 'ab', 'ab', 'a', 'b'])
    316  call add(tl, [2, '\v(a)|(b)', 'ab', 'a', 'a'])
    317 
    318  call add(tl, [2, '\v(a*)+', 'aaaa', 'aaaa', ''])
    319  call add(tl, [2, 'x', 'abcdef'])
    320 
    321  "
    322  " Simple tests
    323  "
    324 
    325  " Search single groups
    326  call add(tl, [2, 'ab', 'aab', 'ab'])
    327  call add(tl, [2, 'ab', 'baced'])
    328  call add(tl, [2, 'ab', '                    ab           ', 'ab'])
    329 
    330  " Search multi-modifiers
    331  call add(tl, [2, 'x*', 'xcd', 'x'])
    332  call add(tl, [2, 'x*', 'xxxxxxxxxxxxxxxxsofijiojgf', 'xxxxxxxxxxxxxxxx'])
    333  " empty match is good
    334  call add(tl, [2, 'x*', 'abcdoij', ''])
    335  " no match here
    336  call add(tl, [2, 'x\+', 'abcdoin'])
    337  call add(tl, [2, 'x\+', 'abcdeoijdfxxiuhfij', 'xx'])
    338  call add(tl, [2, 'x\+', 'xxxxx', 'xxxxx'])
    339  call add(tl, [2, 'x\+', 'abc x siufhiush xxxxxxxxx', 'x'])
    340  call add(tl, [2, 'x\=', 'x sdfoij', 'x'])
    341  call add(tl, [2, 'x\=', 'abc sfoij', '']) " empty match is good
    342  call add(tl, [2, 'x\=', 'xxxxxxxxx c', 'x'])
    343  call add(tl, [2, 'x\?', 'x sdfoij', 'x'])
    344  " empty match is good
    345  call add(tl, [2, 'x\?', 'abc sfoij', ''])
    346  call add(tl, [2, 'x\?', 'xxxxxxxxxx c', 'x'])
    347 
    348  call add(tl, [2, 'a\{0,0}', 'abcdfdoij', ''])
    349  " same thing as 'a?'
    350  call add(tl, [2, 'a\{0,1}', 'asiubid axxxaaa', 'a'])
    351  " same thing as 'a\{0,1}'
    352  call add(tl, [2, 'a\{1,0}', 'asiubid axxxaaa', 'a'])
    353  call add(tl, [2, 'a\{3,6}', 'aa siofuh'])
    354  call add(tl, [2, 'a\{3,6}', 'aaaaa asfoij afaa', 'aaaaa'])
    355  call add(tl, [2, 'a\{3,6}', 'aaaaaaaa', 'aaaaaa'])
    356  call add(tl, [2, 'a\{0}', 'asoiuj', ''])
    357  call add(tl, [2, 'a\{2}', 'aaaa', 'aa'])
    358  call add(tl, [2, 'a\{2}', 'iuash fiusahfliusah fiushfilushfi uhsaifuh askfj nasfvius afg aaaa sfiuhuhiushf', 'aa'])
    359  call add(tl, [2, 'a\{2}', 'abcdefghijklmnopqrestuvwxyz1234567890'])
    360  " same thing as 'a*'
    361  call add(tl, [2, 'a\{0,}', 'oij sdigfusnf', ''])
    362  call add(tl, [2, 'a\{0,}', 'aaaaa aa', 'aaaaa'])
    363  call add(tl, [2, 'a\{2,}', 'sdfiougjdsafg'])
    364  call add(tl, [2, 'a\{2,}', 'aaaaasfoij ', 'aaaaa'])
    365  call add(tl, [2, 'a\{5,}', 'xxaaaaxxx '])
    366  call add(tl, [2, 'a\{5,}', 'xxaaaaaxxx ', 'aaaaa'])
    367  call add(tl, [2, 'a\{,0}', 'oidfguih iuhi hiu aaaa', ''])
    368  call add(tl, [2, 'a\{,5}', 'abcd', 'a'])
    369  call add(tl, [2, 'a\{,5}', 'aaaaaaaaaa', 'aaaaa'])
    370  " leading star as normal char when \{} follows
    371  call add(tl, [2, '^*\{4,}$', '***'])
    372  call add(tl, [2, '^*\{4,}$', '****', '****'])
    373  call add(tl, [2, '^*\{4,}$', '*****', '*****'])
    374  " same thing as 'a*'
    375  call add(tl, [2, 'a\{}', 'bbbcddiuhfcd', ''])
    376  call add(tl, [2, 'a\{}', 'aaaaioudfh coisf jda', 'aaaa'])
    377 
    378  call add(tl, [2, 'a\{-0,0}', 'abcdfdoij', ''])
    379  " anti-greedy version of 'a?'
    380  call add(tl, [2, 'a\{-0,1}', 'asiubid axxxaaa', ''])
    381  call add(tl, [2, 'a\{-3,6}', 'aa siofuh'])
    382  call add(tl, [2, 'a\{-3,6}', 'aaaaa asfoij afaa', 'aaa'])
    383  call add(tl, [2, 'a\{-3,6}', 'aaaaaaaa', 'aaa'])
    384  call add(tl, [2, 'a\{-0}', 'asoiuj', ''])
    385  call add(tl, [2, 'a\{-2}', 'aaaa', 'aa'])
    386  call add(tl, [2, 'a\{-2}', 'abcdefghijklmnopqrestuvwxyz1234567890'])
    387  call add(tl, [2, 'a\{-0,}', 'oij sdigfusnf', ''])
    388  call add(tl, [2, 'a\{-0,}', 'aaaaa aa', ''])
    389  call add(tl, [2, 'a\{-2,}', 'sdfiougjdsafg'])
    390  call add(tl, [2, 'a\{-2,}', 'aaaaasfoij ', 'aa'])
    391  call add(tl, [2, 'a\{-,0}', 'oidfguih iuhi hiu aaaa', ''])
    392  call add(tl, [2, 'a\{-,5}', 'abcd', ''])
    393  call add(tl, [2, 'a\{-,5}', 'aaaaaaaaaa', ''])
    394  " anti-greedy version of 'a*'
    395  call add(tl, [2, 'a\{-}', 'bbbcddiuhfcd', ''])
    396  call add(tl, [2, 'a\{-}', 'aaaaioudfh coisf jda', ''])
    397 
    398  " Test groups of characters and submatches
    399  call add(tl, [2, '\(abc\)*', 'abcabcabc', 'abcabcabc', 'abc'])
    400  call add(tl, [2, '\(ab\)\+', 'abababaaaaa', 'ababab', 'ab'])
    401  call add(tl, [2, '\(abaaaaa\)*cd', 'cd', 'cd', ''])
    402  call add(tl, [2, '\(test1\)\? \(test2\)\?', 'test1 test3', 'test1 ', 'test1', ''])
    403  call add(tl, [2, '\(test1\)\= \(test2\) \(test4443\)\=', ' test2 test4443 yupiiiiiiiiiii', ' test2 test4443', '', 'test2', 'test4443'])
    404  call add(tl, [2, '\(\(sub1\) hello \(sub 2\)\)', 'asterix sub1 hello sub 2 obelix', 'sub1 hello sub 2', 'sub1 hello sub 2', 'sub1', 'sub 2'])
    405  call add(tl, [2, '\(\(\(yyxxzz\)\)\)', 'abcdddsfiusfyyzzxxyyxxzz', 'yyxxzz', 'yyxxzz', 'yyxxzz', 'yyxxzz'])
    406  call add(tl, [2, '\v((ab)+|c+)+', 'abcccaba', 'abcccab', 'ab', 'ab'])
    407  call add(tl, [2, '\v((ab)|c*)+', 'abcccaba', 'abcccab', '', 'ab'])
    408  call add(tl, [2, '\v(a(c*)+b)+', 'acbababaaa', 'acbabab', 'ab', ''])
    409  call add(tl, [2, '\v(a|b*)+', 'aaaa', 'aaaa', ''])
    410  call add(tl, [2, '\p*', 'a� 	', 'a� '])
    411 
    412  " Test greedy-ness and lazy-ness
    413  call add(tl, [2, 'a\{-2,7}','aaaaaaaaaaaaa', 'aa'])
    414  call add(tl, [2, 'a\{-2,7}x','aaaaaaaaax', 'aaaaaaax'])
    415  call add(tl, [2, 'a\{2,7}','aaaaaaaaaaaaaaaaaaaa', 'aaaaaaa'])
    416  call add(tl, [2, 'a\{2,7}x','aaaaaaaaax', 'aaaaaaax'])
    417  call add(tl, [2, '\vx(.{-,8})yz(.*)','xayxayzxayzxayz','xayxayzxayzxayz','ayxa','xayzxayz'])
    418  call add(tl, [2, '\vx(.*)yz(.*)','xayxayzxayzxayz','xayxayzxayzxayz', 'ayxayzxayzxa',''])
    419  call add(tl, [2, '\v(a{1,2}){-2,3}','aaaaaaa','aaaa','aa'])
    420  call add(tl, [2, '\v(a{-1,3})+', 'aa', 'aa', 'a'])
    421  call add(tl, [2, '^\s\{-}\zs\( x\|x$\)', ' x', ' x', ' x'])
    422  call add(tl, [2, '^\s\{-}\zs\(x\| x$\)', ' x', ' x', ' x'])
    423  call add(tl, [2, '^\s\{-}\ze\(x\| x$\)', ' x', '', ' x'])
    424  call add(tl, [2, '^\(\s\{-}\)\(x\| x$\)', ' x', ' x', '', ' x'])
    425 
    426  " Test Character classes
    427  call add(tl, [2, '\d\+e\d\d','test 10e23 fd','10e23'])
    428 
    429  " Test collections and character range []
    430  call add(tl, [2, '\v[a]', 'abcd', 'a'])
    431  call add(tl, [2, 'a[bcd]', 'abcd', 'ab'])
    432  call add(tl, [2, 'a[b-d]', 'acbd', 'ac'])
    433  call add(tl, [2, '[a-d][e-f][x-x]d', 'cexdxx', 'cexd'])
    434  call add(tl, [2, '\v[[:alpha:]]+', 'abcdefghijklmnopqrstuvwxyz6','abcdefghijklmnopqrstuvwxyz'])
    435  call add(tl, [2, '[[:alpha:]\+]', '6x8','x'])
    436  call add(tl, [2, '[^abc]\+','abcabcabc'])
    437  call add(tl, [2, '[^abc]','defghiasijvoinasoiunbvb','d'])
    438  call add(tl, [2, '[^abc]\+','ddddddda','ddddddd'])
    439  call add(tl, [2, '[^a-d]\+','aaaAAAZIHFNCddd','AAAZIHFNC'])
    440  call add(tl, [2, '[a-f]*','iiiiiiii',''])
    441  call add(tl, [2, '[a-f]*','abcdefgh','abcdef'])
    442  call add(tl, [2, '[^a-f]\+','abcdefgh','gh'])
    443  call add(tl, [2, '[a-c]\{-3,6}','abcabc','abc'])
    444  call add(tl, [2, '[^[:alpha:]]\+','abcccadfoij7787ysf287yrnccdu','7787'])
    445  call add(tl, [2, '[-a]', '-', '-'])
    446  call add(tl, [2, '[a-]', '-', '-'])
    447  call add(tl, [2, '[a-f]*\c','ABCDEFGH','ABCDEF'])
    448  call add(tl, [2, '[abc][xyz]\c','-af-AF-BY--','BY'])
    449  " filename regexp
    450  call add(tl, [2, '[-./[:alnum:]_~]\+', 'log13.file', 'log13.file'])
    451  " special chars
    452  call add(tl, [2, '[\]\^\-\\]\+', '\^\\\-\---^', '\^\\\-\---^'])
    453  " collation elem
    454  call add(tl, [2, '[[.a.]]\+', 'aa', 'aa'])
    455  " middle of regexp
    456  call add(tl, [2, 'abc[0-9]*ddd', 'siuhabc ii'])
    457  call add(tl, [2, 'abc[0-9]*ddd', 'adf abc44482ddd oijs', 'abc44482ddd'])
    458  call add(tl, [2, '\_[0-9]\+', 'asfi9888u', '9888'])
    459  call add(tl, [2, '[0-9\n]\+', 'asfi9888u', '9888'])
    460  call add(tl, [2, '\_[0-9]\+', "asfi\n9888u", "\n9888"])
    461  call add(tl, [2, '\_f', "  \na ", "\n"])
    462  call add(tl, [2, '\_f\+', "  \na ", "\na"])
    463  call add(tl, [2, '[0-9A-Za-z-_.]\+', " @0_a.A-{ ", "0_a.A-"])
    464 
    465  " Test start/end of line, start/end of file
    466  call add(tl, [2, '^a.', "a_\nb ", "a_"])
    467  call add(tl, [2, '^a.', "b a \na_"])
    468  call add(tl, [2, '.a$', " a\n "])
    469  call add(tl, [2, '.a$', " a b\n_a", "_a"])
    470  call add(tl, [2, '\%^a.', "a a\na", "a "])
    471  call add(tl, [2, '\%^a', " a \na "])
    472  call add(tl, [2, '.a\%$', " a\n "])
    473  call add(tl, [2, '.a\%$', " a\n_a", "_a"])
    474 
    475  " Test recognition of character classes
    476  call add(tl, [2, '[0-7]\+', 'x0123456789x', '01234567'])
    477  call add(tl, [2, '[^0-7]\+', '0a;X+% 897', 'a;X+% 89'])
    478  call add(tl, [2, '[0-9]\+', 'x0123456789x', '0123456789'])
    479  call add(tl, [2, '[^0-9]\+', '0a;X+% 9', 'a;X+% '])
    480  call add(tl, [2, '[0-9a-fA-F]\+', 'x0189abcdefg', '0189abcdef'])
    481  call add(tl, [2, '[^0-9A-Fa-f]\+', '0189g;X+% ab', 'g;X+% '])
    482  call add(tl, [2, '[a-z_A-Z0-9]\+', ';+aso_SfOij ', 'aso_SfOij'])
    483  call add(tl, [2, '[^a-z_A-Z0-9]\+', 'aSo_;+% sfOij', ';+% '])
    484  call add(tl, [2, '[a-z_A-Z]\+', '0abyz_ABYZ;', 'abyz_ABYZ'])
    485  call add(tl, [2, '[^a-z_A-Z]\+', 'abAB_09;+% yzYZ', '09;+% '])
    486  call add(tl, [2, '[a-z]\+', '0abcxyz1', 'abcxyz'])
    487  call add(tl, [2, '[a-z]\+', 'AabxyzZ', 'abxyz'])
    488  call add(tl, [2, '[^a-z]\+', 'a;X09+% x', ';X09+% '])
    489  call add(tl, [2, '[^a-z]\+', 'abX0;%yz', 'X0;%'])
    490  call add(tl, [2, '[a-zA-Z]\+', '0abABxzXZ9', 'abABxzXZ'])
    491  call add(tl, [2, '[^a-zA-Z]\+', 'ab09_;+ XZ', '09_;+ '])
    492  call add(tl, [2, '[A-Z]\+', 'aABXYZz', 'ABXYZ'])
    493  call add(tl, [2, '[^A-Z]\+', 'ABx0;%YZ', 'x0;%'])
    494  call add(tl, [2, '[a-z]\+\c', '0abxyzABXYZ;', 'abxyzABXYZ'])
    495  call add(tl, [2, '[A-Z]\+\c', '0abABxzXZ9', 'abABxzXZ'])
    496  call add(tl, [2, '\c[^a-z]\+', 'ab09_;+ XZ', '09_;+ '])
    497  call add(tl, [2, '\c[^A-Z]\+', 'ab09_;+ XZ', '09_;+ '])
    498  call add(tl, [2, '\C[^A-Z]\+', 'ABCOIJDEOIFNSD jsfoij sa', ' jsfoij sa'])
    499 
    500  " Tests for \z features
    501  " match ends at \ze
    502  call add(tl, [2, 'xx \ze test', 'xx '])
    503  call add(tl, [2, 'abc\zeend', 'oij abcend', 'abc'])
    504  call add(tl, [2, 'aa\zebb\|aaxx', ' aabb ', 'aa'])
    505  call add(tl, [2, 'aa\zebb\|aaxx', ' aaxx ', 'aaxx'])
    506  call add(tl, [2, 'aabb\|aa\zebb', ' aabb ', 'aabb'])
    507  call add(tl, [2, 'aa\zebb\|aaebb', ' aabb ', 'aa'])
    508  " match starts at \zs
    509  call add(tl, [2, 'abc\zsdd', 'ddabcddxyzt', 'dd'])
    510  call add(tl, [2, 'aa \zsax', ' ax'])
    511  call add(tl, [2, 'abc \zsmatch\ze abc', 'abc abc abc match abc abc', 'match'])
    512  call add(tl, [2, '\v(a \zsif .*){2}', 'a if then a if last', 'if last', 'a if last'])
    513  call add(tl, [2, '\>\zs.', 'aword. ', '.'])
    514  call add(tl, [2, '\s\+\ze\[/\|\s\zs\s\+', 'is   [a t', '  '])
    515 
    516  " Tests for \@= and \& features
    517  call add(tl, [2, 'abc\@=', 'abc', 'ab'])
    518  call add(tl, [2, 'abc\@=cd', 'abcd', 'abcd'])
    519  call add(tl, [2, 'abc\@=', 'ababc', 'ab'])
    520  " will never match, no matter the input text
    521  call add(tl, [2, 'abcd\@=e', 'abcd'])
    522  " will never match
    523  call add(tl, [2, 'abcd\@=e', 'any text in here ... '])
    524  call add(tl, [2, '\v(abc)@=..', 'xabcd', 'ab', 'abc'])
    525  call add(tl, [2, '\(.*John\)\@=.*Bob', 'here is John, and here is B'])
    526  call add(tl, [2, '\(John.*\)\@=.*Bob', 'John is Bobs friend', 'John is Bob', 'John is Bobs friend'])
    527  call add(tl, [2, '\<\S\+\())\)\@=', '$((i=i+1))', 'i=i+1', '))'])
    528  call add(tl, [2, '.*John\&.*Bob', 'here is John, and here is B'])
    529  call add(tl, [2, '.*John\&.*Bob', 'John is Bobs friend', 'John is Bob'])
    530  call add(tl, [2, '\v(test1)@=.*yep', 'this is a test1, yep it is', 'test1, yep', 'test1'])
    531  call add(tl, [2, 'foo\(bar\)\@!', 'foobar'])
    532  call add(tl, [2, 'foo\(bar\)\@!', 'foo bar', 'foo'])
    533  call add(tl, [2, 'if \(\(then\)\@!.\)*$', ' if then else'])
    534  call add(tl, [2, 'if \(\(then\)\@!.\)*$', ' if else ', 'if else ', ' '])
    535  call add(tl, [2, '\(foo\)\@!bar', 'foobar', 'bar'])
    536  call add(tl, [2, '\(foo\)\@!...bar', 'foobar'])
    537  call add(tl, [2, '^\%(.*bar\)\@!.*\zsfoo', ' bar foo '])
    538  call add(tl, [2, '^\%(.*bar\)\@!.*\zsfoo', ' foo bar '])
    539  call add(tl, [2, '^\%(.*bar\)\@!.*\zsfoo', ' foo xxx ', 'foo'])
    540  call add(tl, [2, '[ ]\@!\p\%([ ]\@!\p\)*:', 'implicit mappings:', 'mappings:'])
    541  call add(tl, [2, '[ ]\@!\p\([ ]\@!\p\)*:', 'implicit mappings:', 'mappings:', 's'])
    542  call add(tl, [2, 'm\k\+_\@=\%(_\@!\k\)\@<=\k\+e', 'mx__xe', 'mx__xe'])
    543  call add(tl, [2, '\%(\U\@<=S\k*\|S\l\)R', 'SuR', 'SuR'])
    544 
    545  " Combining different tests and features
    546  call add(tl, [2, '[[:alpha:]]\{-2,6}', '787abcdiuhsasiuhb4', 'ab'])
    547  call add(tl, [2, '', 'abcd', ''])
    548  call add(tl, [2, '\v(())', 'any possible text', ''])
    549  call add(tl, [2, '\v%(ab(xyz)c)', '   abxyzc ', 'abxyzc', 'xyz'])
    550  call add(tl, [2, '\v(test|)empty', 'tesempty', 'empty', ''])
    551  call add(tl, [2, '\v(a|aa)(a|aa)', 'aaa', 'aa', 'a', 'a'])
    552 
    553  " \%u and friends
    554  call add(tl, [2, '\%d32', 'yes no', ' '])
    555  call add(tl, [2, '\%o40', 'yes no', ' '])
    556  call add(tl, [2, '\%x20', 'yes no', ' '])
    557  call add(tl, [2, '\%u0020', 'yes no', ' '])
    558  call add(tl, [2, '\%U00000020', 'yes no', ' '])
    559  call add(tl, [2, '\%d0', "yes\x0ano", "\x0a"])
    560 
    561  "" \%[abc]
    562  call add(tl, [2, 'foo\%[bar]', 'fobar'])
    563  call add(tl, [2, 'foo\%[bar]', 'foobar', 'foobar'])
    564  call add(tl, [2, 'foo\%[bar]', 'fooxx', 'foo'])
    565  call add(tl, [2, 'foo\%[bar]', 'foobxx', 'foob'])
    566  call add(tl, [2, 'foo\%[bar]', 'foobaxx', 'fooba'])
    567  call add(tl, [2, 'foo\%[bar]', 'foobarxx', 'foobar'])
    568  call add(tl, [2, 'foo\%[bar]x', 'foobxx', 'foobx'])
    569  call add(tl, [2, 'foo\%[bar]x', 'foobarxx', 'foobarx'])
    570  call add(tl, [2, '\%[bar]x', 'barxx', 'barx'])
    571  call add(tl, [2, '\%[bar]x', 'bxx', 'bx'])
    572  call add(tl, [2, '\%[bar]x', 'xxx', 'x'])
    573  call add(tl, [2, 'b\%[[ao]r]', 'bar bor', 'bar'])
    574  call add(tl, [2, 'b\%[[]]r]', 'b]r bor', 'b]r'])
    575  call add(tl, [2, '@\%[\w\-]*', '<http://john.net/pandoc/>[@pandoc]', '@pandoc'])
    576 
    577  " Alternatives, must use first longest match
    578  call add(tl, [2, 'goo\|go', 'google', 'goo'])
    579  call add(tl, [2, '\<goo\|\<go', 'google', 'goo'])
    580  call add(tl, [2, '\<goo\|go', 'google', 'goo'])
    581 
    582  " Back references
    583  call add(tl, [2, '\(\i\+\) \1', ' abc abc', 'abc abc', 'abc'])
    584  call add(tl, [2, '\(\i\+\) \1', 'xgoo goox', 'goo goo', 'goo'])
    585  call add(tl, [2, '\(a\)\(b\)\(c\)\(dd\)\(e\)\(f\)\(g\)\(h\)\(i\)\1\2\3\4\5\6\7\8\9', 'xabcddefghiabcddefghix', 'abcddefghiabcddefghi', 'a', 'b', 'c', 'dd', 'e', 'f', 'g', 'h', 'i'])
    586  call add(tl, [2, '\(\d*\)a \1b', ' a b ', 'a b', ''])
    587  call add(tl, [2, '^.\(.\).\_..\1.', "aaa\naaa\nb", "aaa\naaa", 'a'])
    588  call add(tl, [2, '^.*\.\(.*\)/.\+\(\1\)\@<!$', 'foo.bat/foo.com', 'foo.bat/foo.com', 'bat'])
    589  call add(tl, [2, '^.*\.\(.*\)/.\+\(\1\)\@<!$', 'foo.bat/foo.bat'])
    590  call add(tl, [2, '^.*\.\(.*\)/.\+\(\1\)\@<=$', 'foo.bat/foo.bat', 'foo.bat/foo.bat', 'bat', 'bat'])
    591  call add(tl, [2, '\\\@<!\${\(\d\+\%(:.\{-}\)\?\\\@<!\)}', '2013-06-27${0}', '${0}', '0'])
    592  call add(tl, [2, '^\(a*\)\1$', 'aaaaaaaa', 'aaaaaaaa', 'aaaa'])
    593  call add(tl, [2, '^\(a\{-2,}\)\1\+$', 'aaaaaaaaa', 'aaaaaaaaa', 'aaa'])
    594 
    595  " Look-behind with limit
    596  call add(tl, [2, '<\@<=span.', 'xxspanxx<spanyyy', 'spany'])
    597  call add(tl, [2, '<\@1<=span.', 'xxspanxx<spanyyy', 'spany'])
    598  call add(tl, [2, '<\@2<=span.', 'xxspanxx<spanyyy', 'spany'])
    599  call add(tl, [2, '\(<<\)\@<=span.', 'xxspanxxxx<spanxx<<spanyyy', 'spany', '<<'])
    600  call add(tl, [2, '\(<<\)\@1<=span.', 'xxspanxxxx<spanxx<<spanyyy'])
    601  call add(tl, [2, '\(<<\)\@2<=span.', 'xxspanxxxx<spanxx<<spanyyy', 'spany', '<<'])
    602  call add(tl, [2, '\(foo\)\@<!bar.', 'xx foobar1 xbar2 xx', 'bar2'])
    603 
    604  " look-behind match in front of a zero-width item
    605  call add(tl, [2, '\v\C%(<Last Changed:\s+)@<=.*$', '" test header'])
    606  call add(tl, [2, '\v\C%(<Last Changed:\s+)@<=.*$', '" Last Changed: 1970', '1970'])
    607  call add(tl, [2, '\(foo\)\@<=\>', 'foobar'])
    608  call add(tl, [2, '\(foo\)\@<=\>', 'barfoo', '', 'foo'])
    609  call add(tl, [2, '\(foo\)\@<=.*', 'foobar', 'bar', 'foo'])
    610 
    611  " complicated look-behind match
    612  call add(tl, [2, '\(r\@<=\|\w\@<!\)\/', 'x = /word/;', '/'])
    613  call add(tl, [2, '^[a-z]\+\ze \&\(asdf\)\@<!', 'foo bar', 'foo'])
    614 
    615  "" \@>
    616  call add(tl, [2, '\(a*\)\@>a', 'aaaa'])
    617  call add(tl, [2, '\(a*\)\@>b', 'aaab', 'aaab', 'aaa'])
    618  call add(tl, [2, '^\(.\{-}b\)\@>.', '  abcbd', '  abc', '  ab'])
    619  call add(tl, [2, '\(.\{-}\)\(\)\@>$', 'abc', 'abc', 'abc', ''])
    620  " TODO: BT engine does not restore submatch after failure
    621  call add(tl, [1, '\(a*\)\@>a\|a\+', 'aaaa', 'aaaa'])
    622 
    623  " "\_" prepended negated collection matches EOL
    624  call add(tl, [2, '\_[^8-9]\+', "asfi\n9888", "asfi\n"])
    625  call add(tl, [2, '\_[^a]\+', "asfi\n9888", "sfi\n9888"])
    626 
    627  " Requiring lots of states.
    628  call add(tl, [2, '[0-9a-zA-Z]\{8}-\([0-9a-zA-Z]\{4}-\)\{3}[0-9a-zA-Z]\{12}', " 12345678-1234-1234-1234-123456789012 ", "12345678-1234-1234-1234-123456789012", "1234-"])
    629 
    630  " Skip adding state twice
    631  call add(tl, [2, '^\%(\%(^\s*#\s*if\>\|#\s*if\)\)\(\%>1c.*$\)\@=', "#if FOO", "#if", ' FOO'])
    632 
    633  " Test \%V atom
    634  call add(tl, [2, '\%>70vGesamt', 'Jean-Michel Charlier & Victor Hubinon\Gesamtausgabe [Salleck]    Buck Danny {Jean-Michel Charlier & Victor Hubinon}\Gesamtausgabe', 'Gesamt'])
    635 
    636  " Test for ignoring case and matching repeated characters
    637  call add(tl, [2, '\cb\+', 'aAbBbBcC', 'bBbB'])
    638 
    639  " Run the tests
    640  for t in tl
    641    let re = t[0]
    642    let pat = t[1]
    643    let text = t[2]
    644    let matchidx = 3
    645    for engine in [0, 1, 2]
    646      if engine == 2 && re == 0 || engine == 1 && re == 1
    647        continue
    648      endif
    649      let &regexpengine = engine
    650      try
    651        let l = matchlist(text, pat)
    652      catch
    653        call assert_report('Error ' . engine . ': pat: \"' . pat
    654              \ . '\", text: \"' . text . '\", caused an exception: \"'
    655              \ . v:exception . '\"')
    656      endtry
    657      " check the match itself
    658      if len(l) == 0 && len(t) > matchidx
    659        call assert_report('Error ' . engine . ': pat: \"' . pat
    660              \ . '\", text: \"' . text . '\", did not match, expected: \"'
    661              \ . t[matchidx] . '\"')
    662      elseif len(l) > 0 && len(t) == matchidx
    663        call assert_report('Error ' . engine . ': pat: \"' . pat
    664              \ . '\", text: \"' . text . '\", match: \"' . l[0]
    665              \ . '\", expected no match')
    666      elseif len(t) > matchidx && l[0] != t[matchidx]
    667        call assert_report('Error ' . engine . ': pat: \"' . pat
    668              \ . '\", text: \"' . text . '\", match: \"' . l[0]
    669              \ . '\", expected: \"' . t[matchidx] . '\"')
    670      else
    671        " Test passed
    672      endif
    673 
    674      " check all the nine submatches
    675      if len(l) > 0
    676        for i in range(1, 9)
    677          if len(t) <= matchidx + i
    678            let e = ''
    679          else
    680            let e = t[matchidx + i]
    681          endif
    682          if l[i] != e
    683            call assert_report('Error ' . engine . ': pat: \"' . pat
    684                  \ . '\", text: \"' . text . '\", submatch ' . i . ': \"'
    685                  \ . l[i] . '\", expected: \"' . e . '\"')
    686          endif
    687        endfor
    688        unlet i
    689      endif
    690    endfor
    691  endfor
    692 
    693  unlet t tl e l
    694 endfunc
    695 
    696 " Tests for multi-line regexp patterns without multi-byte support.
    697 func Test_regexp_multiline_pat()
    698  " tl is a List of Lists with:
    699  "    regexp engines to test
    700  "       0 - test with 'regexpengine' values 0 and 1
    701  "       1 - test with 'regexpengine' values 0 and 2
    702  "       2 - test with 'regexpengine' values 0, 1 and 2
    703  "    regexp pattern
    704  "    List with text to test the pattern on
    705  "    List with the expected match
    706  let tl = []
    707 
    708  " back references
    709  call add(tl, [2, '^.\(.\).\_..\1.', ['aaa', 'aaa', 'b'], ['XX', 'b']])
    710  call add(tl, [2, '\v.*\/(.*)\n.*\/\1$', ['./Dir1/Dir2/zyxwvuts.txt', './Dir1/Dir2/abcdefgh.bat', '', './Dir1/Dir2/file1.txt', './OtherDir1/OtherDir2/file1.txt'], ['./Dir1/Dir2/zyxwvuts.txt', './Dir1/Dir2/abcdefgh.bat', '', 'XX']])
    711 
    712  " line breaks
    713  call add(tl, [2, '\S.*\nx', ['abc', 'def', 'ghi', 'xjk', 'lmn'], ['abc', 'def', 'XXjk', 'lmn']])
    714 
    715  " Any single character or end-of-line
    716  call add(tl, [2, '\_.\+', ['a', 'b', 'c'], ['XX']])
    717  " Any identifier or end-of-line
    718  call add(tl, [2, '\_i\+', ['a', 'b', ';', '2'], ['XX;XX']])
    719  " Any identifier but excluding digits or end-of-line
    720  call add(tl, [2, '\_I\+', ['a', 'b', ';', '2'], ['XX;XX2XX']])
    721  " Any keyword or end-of-line
    722  call add(tl, [2, '\_k\+', ['a', 'b', '=', '2'], ['XX=XX']])
    723  " Any keyword but excluding digits or end-of-line
    724  call add(tl, [2, '\_K\+', ['a', 'b', '=', '2'], ['XX=XX2XX']])
    725  " Any filename character or end-of-line
    726  call add(tl, [2, '\_f\+', ['a', 'b', '.', '5'], ['XX']])
    727  " Any filename character but excluding digits or end-of-line
    728  call add(tl, [2, '\_F\+', ['a', 'b', '.', '5'], ['XX5XX']])
    729  " Any printable character or end-of-line
    730  call add(tl, [2, '\_p\+', ['a', 'b', '=', '4'], ['XX']])
    731  " Any printable character excluding digits or end-of-line
    732  call add(tl, [2, '\_P\+', ['a', 'b', '=', '4'], ['XX4XX']])
    733  " Any whitespace character or end-of-line
    734  call add(tl, [2, '\_s\+', [' ', ' ', 'a', 'b'], ['XXaXXbXX']])
    735  " Any non-whitespace character or end-of-line
    736  call add(tl, [2, '\_S\+', [' ', ' ', 'a', 'b'], [' XX XX']])
    737  " Any decimal digit or end-of-line
    738  call add(tl, [2, '\_d\+', ['1', 'a', '2', 'b', '3'], ['XXaXXbXX']])
    739  " Any non-decimal digit or end-of-line
    740  call add(tl, [2, '\_D\+', ['1', 'a', '2', 'b', '3'], ['1XX2XX3XX']])
    741  " Any hexadecimal digit or end-of-line
    742  call add(tl, [2, '\_x\+', ['1', 'a', 'g', '9', '8'], ['XXgXX']])
    743  " Any non-hexadecimal digit or end-of-line
    744  call add(tl, [2, '\_X\+', ['1', 'a', 'g', '9', '8'], ['1XXaXX9XX8XX']])
    745  " Any octal digit or end-of-line
    746  call add(tl, [2, '\_o\+', ['0', '7', '8', '9', '0'], ['XX8XX9XX']])
    747  " Any non-octal digit or end-of-line
    748  call add(tl, [2, '\_O\+', ['0', '7', '8', '9', '0'], ['0XX7XX0XX']])
    749  " Any word character or end-of-line
    750  call add(tl, [2, '\_w\+', ['A', 'B', '=', 'C', 'D'], ['XX=XX']])
    751  " Any non-word character or end-of-line
    752  call add(tl, [2, '\_W\+', ['A', 'B', '=', 'C', 'D'], ['AXXBXXCXXDXX']])
    753  " Any head-of-word character or end-of-line
    754  call add(tl, [2, '\_h\+', ['a', '1', 'b', '2', 'c'], ['XX1XX2XX']])
    755  " Any non-head-of-word character or end-of-line
    756  call add(tl, [2, '\_H\+', ['a', '1', 'b', '2', 'c'], ['aXXbXXcXX']])
    757  " Any alphabetic character or end-of-line
    758  call add(tl, [2, '\_a\+', ['a', '1', 'b', '2', 'c'], ['XX1XX2XX']])
    759  " Any non-alphabetic character or end-of-line
    760  call add(tl, [2, '\_A\+', ['a', '1', 'b', '2', 'c'], ['aXXbXXcXX']])
    761  " Any lowercase character or end-of-line
    762  call add(tl, [2, '\_l\+', ['a', 'A', 'b', 'B'], ['XXAXXBXX']])
    763  " Any non-lowercase character or end-of-line
    764  call add(tl, [2, '\_L\+', ['a', 'A', 'b', 'B'], ['aXXbXX']])
    765  " Any uppercase character or end-of-line
    766  call add(tl, [2, '\_u\+', ['a', 'A', 'b', 'B'], ['aXXbXX']])
    767  " Any non-uppercase character or end-of-line
    768  call add(tl, [2, '\_U\+', ['a', 'A', 'b', 'B'], ['XXAXXBXX']])
    769  " Collection or end-of-line
    770  call add(tl, [2, '\_[a-z]\+', ['a', 'A', 'b', 'B'], ['XXAXXBXX']])
    771  " start of line anywhere in the text
    772  call add(tl, [2, 'one\zs\_s*\_^\zetwo',
    773        \ ['', 'one', ' two', 'one', '', 'two'],
    774        \ ['', 'one', ' two', 'oneXXtwo']])
    775  " end of line anywhere in the text
    776  call add(tl, [2, 'one\zs\_$\_s*two',
    777        \ ['', 'one', ' two', 'one', '', 'two'], ['', 'oneXX', 'oneXX']])
    778 
    779  " Check that \_[0-9] matching EOL does not break a following \>
    780  call add(tl, [2, '\<\(\(25\_[0-5]\|2\_[0-4]\_[0-9]\|\_[01]\?\_[0-9]\_[0-9]\?\)\.\)\{3\}\(25\_[0-5]\|2\_[0-4]\_[0-9]\|\_[01]\?\_[0-9]\_[0-9]\?\)\>', ['', 'localnet/192.168.0.1', ''], ['', 'localnet/XX', '']])
    781 
    782  " Check a pattern with a line break and ^ and $
    783  call add(tl, [2, 'a\n^b$\n^c', ['a', 'b', 'c'], ['XX']])
    784 
    785  call add(tl, [2, '\(^.\+\n\)\1', [' dog', ' dog', 'asdf'], ['XXasdf']])
    786 
    787  " Run the multi-line tests
    788  for t in tl
    789    let re = t[0]
    790    let pat = t[1]
    791    let before = t[2]
    792    let after = t[3]
    793    for engine in [0, 1, 2]
    794      if engine == 2 && re == 0 || engine == 1 && re == 1
    795        continue
    796      endif
    797      let &regexpengine = engine
    798      new
    799      call setline(1, before)
    800      exe '%s/' . pat . '/XX/'
    801      let result = getline(1, '$')
    802      q!
    803      if result != after
    804        call assert_report('Error: pat: \"' . pat . '\", text: \"'
    805              \ . string(before) . '\", expected: \"' . string(after)
    806              \ . '\", got: \"' . string(result) . '\"')
    807      else
    808        " Test passed
    809      endif
    810    endfor
    811  endfor
    812  unlet t tl
    813 endfunc
    814 
    815 " Check that using a pattern on two lines doesn't get messed up by using
    816 " matchstr() with \ze in between.
    817 func Test_matchstr_with_ze()
    818  new
    819  call append(0, ['Substitute here:', '<T="">Ta 5</Title>',
    820        \ '<T="">Ac 7</Title>'])
    821  call cursor(1, 1)
    822  set re=0
    823 
    824  .+1,.+2s/""/\='"' . matchstr(getline("."), '\d\+\ze<') . '"'
    825  call assert_equal(['Substitute here:', '<T="5">Ta 5</Title>',
    826        \ '<T="7">Ac 7</Title>', ''], getline(1, '$'))
    827 
    828  bwipe!
    829 endfunc
    830 
    831 " Check a pattern with a look behind crossing a line boundary
    832 func Test_lookbehind_across_line()
    833  new
    834  call append(0, ['Behind:', 'asdfasd<yyy', 'xxstart1', 'asdfasd<yy',
    835        \ 'xxxstart2', 'asdfasd<yy', 'xxstart3'])
    836  call cursor(1, 1)
    837  call search('\(<\_[xy]\+\)\@3<=start')
    838  call assert_equal([0, 7, 3, 0], getpos('.'))
    839  bwipe!
    840 endfunc
    841 
    842 " Test for the \%V atom (match inside the visual area)
    843 func Regex_Match_Visual_Area()
    844  call append(0, ['Visual:', 'thexe the thexethe', 'andaxand andaxand',
    845        \ 'oooxofor foroxooo', 'oooxofor foroxooo'])
    846  call cursor(1, 1)
    847  exe "normal jfxvfx:s/\\%Ve/E/g\<CR>"
    848  exe "normal jV:s/\\%Va/A/g\<CR>"
    849  exe "normal jfx\<C-V>fxj:s/\\%Vo/O/g\<CR>"
    850  call assert_equal(['Visual:', 'thexE thE thExethe', 'AndAxAnd AndAxAnd',
    851        \ 'oooxOfOr fOrOxooo', 'oooxOfOr fOrOxooo', ''], getline(1, '$'))
    852  %d
    853 endfunc
    854 
    855 " Check matching Visual area
    856 func Test_matching_visual_area()
    857  new
    858  set regexpengine=1
    859  call Regex_Match_Visual_Area()
    860  set regexpengine=2
    861  call Regex_Match_Visual_Area()
    862  set regexpengine&
    863  bwipe!
    864 endfunc
    865 
    866 " Check matching marks
    867 func Regex_Mark()
    868  call append(0, ['', '', '', 'Marks:', 'asdfSasdfsadfEasdf', 'asdfSas',
    869        \ 'dfsadfEasdf', '', '', '', '', ''])
    870  call cursor(4, 1)
    871  exe "normal jfSmsfEme:.-4,.+6s/.\\%>'s.*\\%<'e../here/\<CR>"
    872  exe "normal jfSmsj0fEme:.-4,.+6s/.\\%>'s\\_.*\\%<'e../again/\<CR>"
    873  call assert_equal(['', '', '', 'Marks:', 'asdfhereasdf', 'asdfagainasdf',
    874        \ '', '', '', '', '', ''], getline(1, '$'))
    875  %d
    876 endfunc
    877 
    878 " Same test as above, but use verymagic
    879 func Regex_Mark_Verymagic()
    880  call append(0, ['', '', '', 'Marks:', 'asdfSasdfsadfEasdf', 'asdfSas',
    881        \ 'dfsadfEasdf', '', '', '', '', ''])
    882  call cursor(4, 1)
    883  exe "normal jfSmsfEme:.-4,.+6s/\\v.%>'s.*%<'e../here/\<CR>"
    884  exe "normal jfSmsj0fEme:.-4,.+6s/\\v.%>'s\\_.*%<'e../again/\<CR>"
    885  call assert_equal(['', '', '', 'Marks:', 'asdfhereasdf', 'asdfagainasdf',
    886        \ '', '', '', '', '', ''], getline(1, '$'))
    887  %d
    888 endfunc
    889 
    890 func Test_matching_marks()
    891  new
    892  set regexpengine=1
    893  call Regex_Mark()
    894  call Regex_Mark_Verymagic()
    895  set regexpengine=2
    896  call Regex_Mark()
    897  call Regex_Mark_Verymagic()
    898  bwipe!
    899 endfunc
    900 
    901 " Check patterns matching cursor position.
    902 func s:curpos_test()
    903  new
    904  call setline(1, ['ffooooo', 'boboooo', 'zoooooo', 'koooooo', 'moooooo',
    905        \ "\t\t\tfoo", 'abababababababfoo', 'bababababababafoo', '********_',
    906        \ '        xxxxxxxxxxxx    xxxx xxxxxx xxxxxxx x xxxxxxxxx xx xxxxxx xxxxxx xxxxx xxxxxxx xx xxxx xxxxxxxx xxxx xxxxxxxxxxx xxx xxxxxxx xxxxxxxxx xx xxxxxx xx xxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxx  xxx xxxxxxxx xxxxxxxxx xxxx xxx xxxx xxx xxx xxxxx xxxxxxxxxxxx xxxx xxxxxxxxx xxxxxxxxxxx xx xxxxx xxx xxxxxxxx xxxxxx xxx xxx xxxxxxxxx xxxxxxx x xxxxxxxxx xx xxxxxx xxxxxxx  xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxx xxx xxx xxxxxxxx xxxxxxx  xxxx xxx xxxxxx xxxxx xxxxx xx xxxxxx xxxxxxx xxx xxxxxxxxxxxx xxxx xxxxxxxxx xxxxxx xxxxxx xxxxx xxx xxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxx  xxxxxxxxxx xxxx xx xxxxxxxx xxx xxxxxxxxxxx xxxxx'])
    907  call setpos('.', [0, 1, 0, 0])
    908  s/\%>3c.//g
    909  call setpos('.', [0, 2, 4, 0])
    910  s/\%#.*$//g
    911  call setpos('.', [0, 3, 0, 0])
    912  s/\%<3c./_/g
    913  %s/\%4l\%>5c./_/g
    914  %s/\%6l\%>25v./_/g
    915  %s/\%>6l\%3c./!/g
    916  %s/\%>7l\%12c./?/g
    917  %s/\%>7l\%<9l\%>5v\%<8v./#/g
    918  $s/\%(|\u.*\)\@<=[^|\t]\+$//ge
    919  call assert_equal(['ffo', 'bob', '__ooooo', 'koooo__', 'moooooo',
    920        \ '			f__', 'ab!babababababfoo',
    921        \ 'ba!ab##abab?bafoo', '**!*****_',
    922        \ '  !     xxx?xxxxxxxx    xxxx xxxxxx xxxxxxx x xxxxxxxxx xx xxxxxx xxxxxx xxxxx xxxxxxx xx xxxx xxxxxxxx xxxx xxxxxxxxxxx xxx xxxxxxx xxxxxxxxx xx xxxxxx xx xxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxx  xxx xxxxxxxx xxxxxxxxx xxxx xxx xxxx xxx xxx xxxxx xxxxxxxxxxxx xxxx xxxxxxxxx xxxxxxxxxxx xx xxxxx xxx xxxxxxxx xxxxxx xxx xxx xxxxxxxxx xxxxxxx x xxxxxxxxx xx xxxxxx xxxxxxx  xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxx xxx xxx xxxxxxxx xxxxxxx  xxxx xxx xxxxxx xxxxx xxxxx xx xxxxxx xxxxxxx xxx xxxxxxxxxxxx xxxx xxxxxxxxx xxxxxx xxxxxx xxxxx xxx xxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxx  xxxxxxxxxx xxxx xx xxxxxxxx xxx xxxxxxxxxxx xxxxx'],
    923        \ getline(1, '$'))
    924  bwipe!
    925 endfunc
    926 
    927 func Test_matching_curpos()
    928  set re=0
    929  call s:curpos_test()
    930  set re=1
    931  call s:curpos_test()
    932  set re=2
    933  call s:curpos_test()
    934  set re&
    935 endfunc
    936 
    937 " Test for matching the start and end of a buffer
    938 func Regex_start_end_buffer()
    939  call setline(1, repeat(['vim edit'], 20))
    940  /\%^
    941  call assert_equal([0, 1, 1, 0], getpos('.'))
    942  exe "normal 50%/\\%^..\<CR>"
    943  call assert_equal([0, 1, 1, 0], getpos('.'))
    944  exe "normal 50%/\\%$\<CR>"
    945  call assert_equal([0, 20, 8, 0], getpos('.'))
    946  exe "normal 6gg/..\\%$\<CR>"
    947  call assert_equal([0, 20, 7, 0], getpos('.'))
    948  %d
    949 endfunc
    950 
    951 func Test_start_end_of_buffer_match()
    952  new
    953  set regexpengine=1
    954  call Regex_start_end_buffer()
    955  set regexpengine=2
    956  call Regex_start_end_buffer()
    957  bwipe!
    958 endfunc
    959 
    960 func Test_ze_before_zs()
    961  call assert_equal('', matchstr(' ', '\%#=1\ze \zs'))
    962  call assert_equal('', matchstr(' ', '\%#=2\ze \zs'))
    963  call assert_equal(repeat([''], 10), matchlist(' ', '\%#=1\ze \zs'))
    964  call assert_equal(repeat([''], 10), matchlist(' ', '\%#=2\ze \zs'))
    965 endfunc
    966 
    967 " Check for detecting error
    968 func Test_regexp_error()
    969  call assert_fails("call matchlist('x x', '\\%#=1 \\zs*')", 'E888:')
    970  call assert_fails("call matchlist('x x', '\\%#=1 \\ze*')", 'E888:')
    971  call assert_fails("call matchlist('x x', '\\%#=2 \\zs*')", 'E888:')
    972  call assert_fails("call matchlist('x x', '\\%#=2 \\ze*')", 'E888:')
    973  call assert_fails("call matchstr('abcd', '\\%o841\\%o142')", 'E678:')
    974  call assert_fails("call matchstr('abcd', '\\%#=2\\%2147483647c')", 'E951:')
    975  call assert_fails("call matchstr('abcd', '\\%#=2\\%2147483647l')", 'E951:')
    976  call assert_fails("call matchstr('abcd', '\\%#=2\\%2147483647v')", 'E951:')
    977  call assert_fails('exe "normal /\\%#=1\\%[x\\%[x]]\<CR>"',   'E369:')
    978  call assert_fails('exe "normal /\\%#=2\\%2147483647l\<CR>"', 'E951:')
    979  call assert_fails('exe "normal /\\%#=2\\%2147483647c\<CR>"', 'E951:')
    980  call assert_fails('exe "normal /\\%#=2\\%102261126v\<CR>"',  'E951:')
    981  call assert_fails('exe "normal /\\%#=2\\%2147483646l\<CR>"', 'E486:')
    982  call assert_fails('exe "normal /\\%#=2\\%2147483646c\<CR>"', 'E486:')
    983  call assert_fails('exe "normal /\\%#=2\\%102261125v\<CR>"',  'E486:')
    984  call assert_equal('', matchstr('abcd', '\%o181\%o142'))
    985 endfunc
    986 
    987 " Test for using the last substitute string pattern (~)
    988 func Test_regexp_last_subst_string()
    989  new
    990  s/bar/baz/e
    991  call assert_equal(matchstr("foo\nbaz\nbar", "\\%#=1\~"), "baz")
    992  call assert_equal(matchstr("foo\nbaz\nbar", "\\%#=2\~"), "baz")
    993  close!
    994 endfunc
    995 
    996 " Check patterns matching cursor position.
    997 func s:curpos_test2()
    998  new
    999  call setline(1, ['1', '2 foobar eins zwei drei vier f�nf sechse',
   1000        \ '3 foobar eins zwei drei vier f�nf sechse',
   1001        \ '4 foobar eins zwei drei vier f�nf sechse',
   1002        \ '5	foobar eins zwei drei vier f�nf sechse',
   1003        \ '6	foobar eins zwei drei vier f�nf sechse',
   1004        \ '7	foobar eins zwei drei vier f�nf sechse'])
   1005  call setpos('.', [0, 2, 10, 0])
   1006  s/\%.c.*//g
   1007  call setpos('.', [0, 3, 15, 0])
   1008  s/\%.l.*//g
   1009  call setpos('.', [0, 5, 3, 0])
   1010  s/\%.v.*/_/g
   1011  call assert_equal(['1',
   1012        \ '2 foobar ',
   1013        \ '',
   1014        \ '4 foobar eins zwei drei vier f�nf sechse',
   1015        \ '5	_',
   1016        \ '6	foobar eins zwei drei vier f�nf sechse',
   1017        \ '7	foobar eins zwei drei vier f�nf sechse'],
   1018        \ getline(1, '$'))
   1019  call assert_fails('call search("\\%.1l")', 'E1204:')
   1020  call assert_fails('call search("\\%.1c")', 'E1204:')
   1021  call assert_fails('call search("\\%.1v")', 'E1204:')
   1022  bwipe!
   1023 endfunc
   1024 
   1025 " Check patterns matching before or after cursor position.
   1026 func s:curpos_test3()
   1027  new
   1028  call setline(1, ['1', '2 foobar eins zwei drei vier f�nf sechse',
   1029        \ '3 foobar eins zwei drei vier f�nf sechse',
   1030        \ '4 foobar eins zwei drei vier f�nf sechse',
   1031        \ '5	foobar eins zwei drei vier f�nf sechse',
   1032        \ '6	foobar eins zwei drei vier f�nf sechse',
   1033        \ '7	foobar eins zwei drei vier f�nf sechse'])
   1034  call setpos('.', [0, 2, 10, 0])
   1035  " Note: This removes all columns, except for the column directly in front of
   1036  " the cursor. Bug????
   1037  :s/^.*\%<.c//
   1038  call setpos('.', [0, 3, 10, 0])
   1039  :s/\%>.c.*$//
   1040  call setpos('.', [0, 5, 4, 0])
   1041  " Note: This removes all columns, except for the column directly in front of
   1042  " the cursor. Bug????
   1043  :s/^.*\%<.v/_/
   1044  call setpos('.', [0, 6, 4, 0])
   1045  :s/\%>.v.*$/_/
   1046  call assert_equal(['1',
   1047        \ ' eins zwei drei vier f�nf sechse',
   1048        \ '3 foobar e',
   1049        \ '4 foobar eins zwei drei vier f�nf sechse',
   1050        \ '_foobar eins zwei drei vier f�nf sechse',
   1051        \ '6	fo_',
   1052        \ '7	foobar eins zwei drei vier f�nf sechse'],
   1053        \ getline(1, '$'))
   1054  sil %d
   1055  call setline(1, ['1', '2 foobar eins zwei drei vier f�nf sechse',
   1056        \ '3 foobar eins zwei drei vier f�nf sechse',
   1057        \ '4 foobar eins zwei drei vier f�nf sechse',
   1058        \ '5	foobar eins zwei drei vier f�nf sechse',
   1059        \ '6	foobar eins zwei drei vier f�nf sechse',
   1060        \ '7	foobar eins zwei drei vier f�nf sechse'])
   1061  call setpos('.', [0, 4, 4, 0])
   1062  %s/\%<.l.*//
   1063  call setpos('.', [0, 5, 4, 0])
   1064  %s/\%>.l.*//
   1065  call assert_equal(['', '', '',
   1066        \ '4 foobar eins zwei drei vier f�nf sechse',
   1067        \ '5	foobar eins zwei drei vier f�nf sechse',
   1068        \ '', ''],
   1069        \ getline(1, '$'))
   1070  bwipe!
   1071 endfunc
   1072 
   1073 " Test that matching below, at or after the
   1074 " cursor position work
   1075 func Test_matching_pos()
   1076  for val in range(3)
   1077    exe "set re=" .. val
   1078    " Match at cursor position
   1079    call s:curpos_test2()
   1080    " Match before or after cursor position
   1081    call s:curpos_test3()
   1082  endfor
   1083  set re&
   1084 endfunc
   1085 
   1086 func Test_using_mark_position()
   1087  " this was using freed memory
   1088  " new engine
   1089  new
   1090  norm O0
   1091  call assert_fails("s/\\%')", 'E486:')
   1092  bwipe!
   1093 
   1094  " old engine
   1095  new
   1096  norm O0
   1097  call assert_fails("s/\\%#=1\\%')", 'E486:')
   1098  bwipe!
   1099 endfunc
   1100 
   1101 func Test_using_visual_position()
   1102  " this was using freed memory
   1103  new
   1104  exe "norm 0o\<Esc>\<C-V>k\<C-X>o0"
   1105  /\%V
   1106  bwipe!
   1107 endfunc
   1108 
   1109 func Test_using_invalid_visual_position()
   1110  " this was going beyond the end of the line
   1111  new
   1112  exe "norm 0o000\<Esc>0\<C-V>$s0"
   1113  /\%V
   1114  bwipe!
   1115 endfunc
   1116 
   1117 func Test_using_two_engines_pattern()
   1118  new
   1119  call setline(1, ['foobar=0', 'foobar=1', 'foobar=2'])
   1120  " \%#= at the end of the pattern
   1121  for i in range(0, 2)
   1122    for j in range(0, 2)
   1123      exe "set re=" .. i
   1124      call cursor(j + 1, 7)
   1125      call assert_fails("%s/foobar\\%#=" .. j, 'E1281:')
   1126    endfor
   1127  endfor
   1128  set re=0
   1129 
   1130  " \%#= at the start of the pattern
   1131  for i in range(0, 2)
   1132    call cursor(i + 1, 7)
   1133    exe ":%s/\\%#=" .. i .. "foobar=" .. i .. "/xx"
   1134  endfor
   1135  call assert_equal(['xx', 'xx', 'xx'], getline(1, '$'))
   1136  bwipe!
   1137 endfunc
   1138 
   1139 func Test_recursive_substitute_expr()
   1140  new
   1141  func Repl()
   1142    s
   1143  endfunc
   1144  silent! s/\%')/~\=Repl()
   1145 
   1146  bwipe!
   1147  delfunc Repl
   1148 endfunc
   1149 
   1150 " def Test_compare_columns()
   1151 "   # this was using a line below the last line
   1152 "   enew
   1153 "   setline(1, ['', ''])
   1154 "   prop_type_add('name', {highlight: 'ErrorMsg'})
   1155 "   prop_add(1, 1, {length: 1, type: 'name'})
   1156 "   search('\%#=1\%>.l\n.*\%<2v', 'nW')
   1157 "   search('\%#=2\%>.l\n.*\%<2v', 'nW')
   1158 "   bwipe!
   1159 "   prop_type_delete('name')
   1160 " enddef
   1161 
   1162 func Test_compare_column_matchstr()
   1163  " do some search in text to set the line number, it should be ignored in
   1164  " matchstr().
   1165  enew
   1166  call setline(1, ['one', 'two', 'three'])
   1167  :3
   1168  :/ee
   1169  bwipe!
   1170  set re=1
   1171  call assert_equal('aaa', matchstr('aaaaaaaaaaaaaaaaaaaa', '.*\%<5v'))
   1172  set re=2
   1173  call assert_equal('aaa', matchstr('aaaaaaaaaaaaaaaaaaaa', '.*\%<5v'))
   1174  set re=0
   1175 endfunc
   1176 
   1177 
   1178 " vim: shiftwidth=2 sts=2 expandtab