neovim

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

test_undo.vim (23467B)


      1 " Tests for the undo tree.
      2 " Since this script is sourced we need to explicitly break changes up in
      3 " undo-able pieces.  Do that by setting 'undolevels'.
      4 " Also tests :earlier and :later.
      5 
      6 source check.vim
      7 source screendump.vim
      8 
      9 func Test_undotree()
     10  new
     11 
     12  normal! Aabc
     13  set ul=100
     14  let d = undotree()
     15  call assert_equal(1, d.seq_last)
     16  call assert_equal(1, d.seq_cur)
     17  call assert_equal(0, d.save_last)
     18  call assert_equal(0, d.save_cur)
     19  call assert_equal(1, len(d.entries))
     20  call assert_equal(1, d.entries[0].newhead)
     21  call assert_equal(1, d.entries[0].seq)
     22  call assert_true(d.entries[0].time <= d.time_cur)
     23 
     24  normal! Adef
     25  set ul=100
     26  let d = undotree()
     27  call assert_equal(2, d.seq_last)
     28  call assert_equal(2, d.seq_cur)
     29  call assert_equal(0, d.save_last)
     30  call assert_equal(0, d.save_cur)
     31  call assert_equal(2, len(d.entries))
     32  call assert_equal(1, d.entries[0].seq)
     33  call assert_equal(1, d.entries[1].newhead)
     34  call assert_equal(2, d.entries[1].seq)
     35  call assert_true(d.entries[1].time <= d.time_cur)
     36 
     37  undo
     38  set ul=100
     39  let d = undotree()
     40  call assert_equal(2, d.seq_last)
     41  call assert_equal(1, d.seq_cur)
     42  call assert_equal(0, d.save_last)
     43  call assert_equal(0, d.save_cur)
     44  call assert_equal(2, len(d.entries))
     45  call assert_equal(1, d.entries[0].seq)
     46  call assert_equal(1, d.entries[1].curhead)
     47  call assert_equal(1, d.entries[1].newhead)
     48  call assert_equal(2, d.entries[1].seq)
     49  call assert_true(d.entries[1].time == d.time_cur)
     50 
     51  normal! Aghi
     52  set ul=100
     53  let d = undotree()
     54  call assert_equal(3, d.seq_last)
     55  call assert_equal(3, d.seq_cur)
     56  call assert_equal(0, d.save_last)
     57  call assert_equal(0, d.save_cur)
     58  call assert_equal(2, len(d.entries))
     59  call assert_equal(1, d.entries[0].seq)
     60  call assert_equal(2, d.entries[1].alt[0].seq)
     61  call assert_equal(1, d.entries[1].newhead)
     62  call assert_equal(3, d.entries[1].seq)
     63  call assert_true(d.entries[1].time <= d.time_cur)
     64 
     65  undo
     66  set ul=100
     67  let d = undotree()
     68  call assert_equal(3, d.seq_last)
     69  call assert_equal(1, d.seq_cur)
     70  call assert_equal(0, d.save_last)
     71  call assert_equal(0, d.save_cur)
     72  call assert_equal(2, len(d.entries))
     73  call assert_equal(1, d.entries[0].seq)
     74  call assert_equal(2, d.entries[1].alt[0].seq)
     75  call assert_equal(1, d.entries[1].curhead)
     76  call assert_equal(1, d.entries[1].newhead)
     77  call assert_equal(3, d.entries[1].seq)
     78  call assert_true(d.entries[1].time == d.time_cur)
     79 
     80  w! Xtest
     81  let d = undotree()
     82  call assert_equal(1, d.save_cur)
     83  call assert_equal(1, d.save_last)
     84  call delete('Xtest')
     85  bwipe! Xtest
     86 endfunc
     87 
     88 func FillBuffer()
     89  for i in range(1,13)
     90    put=i
     91    " Set 'undolevels' to split undo.
     92    exe "setg ul=" . &g:ul
     93  endfor
     94 endfunc
     95 
     96 func Test_undotree_bufnr()
     97  new
     98  let buf1 = bufnr()
     99 
    100  normal! Aabc
    101  set ul=100
    102 
    103  " Save undo tree without bufnr as ground truth for buffer 1
    104  let d1 = undotree()
    105 
    106  new
    107  let buf2 = bufnr()
    108 
    109  normal! Adef
    110  set ul=100
    111 
    112  normal! Aghi
    113  set ul=100
    114 
    115  " Save undo tree without bufnr as ground truth for buffer 2
    116  let d2 = undotree()
    117 
    118  " Check undotree() with bufnr argument
    119  let d = undotree(buf1)
    120  call assert_equal(d1, d)
    121  call assert_notequal(d2, d)
    122 
    123  let d = undotree(buf2)
    124  call assert_notequal(d1, d)
    125  call assert_equal(d2, d)
    126 
    127  " Switch buffers and check again
    128  wincmd p
    129 
    130  let d = undotree(buf1)
    131  call assert_equal(d1, d)
    132 
    133  let d = undotree(buf2)
    134  call assert_notequal(d1, d)
    135  call assert_equal(d2, d)
    136 
    137  " error cases
    138  call assert_fails('call undotree(-1)', 'E158:')
    139  call assert_fails('call undotree("nosuchbuf")', 'E158:')
    140 
    141  " after creating a buffer nosuchbuf, undotree('nosuchbuf') should
    142  " not error out
    143  new nosuchbuf
    144  let d = {'seq_last': 0, 'entries': [], 'time_cur': 0, 'save_last': 0, 'synced': 1, 'save_cur': 0, 'seq_cur': 0}
    145  call assert_equal(d, undotree("nosuchbuf"))
    146  " clean up
    147  bw nosuchbuf
    148 
    149  " Drop created windows
    150  set ul&
    151  new
    152  only!
    153 endfunc
    154 
    155 func Test_global_local_undolevels()
    156  new one
    157  set undolevels=5
    158  call FillBuffer()
    159  " will only undo the last 5 changes, end up with 13 - (5 + 1) = 7 lines
    160  earlier 10
    161  call assert_equal(5, &g:undolevels)
    162  call assert_equal(-123456, &l:undolevels)
    163  call assert_equal('7', getline('$'))
    164 
    165  new two
    166  setlocal undolevels=2
    167  call FillBuffer()
    168  " will only undo the last 2 changes, end up with 13 - (2 + 1) = 10 lines
    169  earlier 10
    170  call assert_equal(5, &g:undolevels)
    171  call assert_equal(2, &l:undolevels)
    172  call assert_equal('10', getline('$'))
    173 
    174  setlocal ul=10
    175  call assert_equal(5, &g:undolevels)
    176  call assert_equal(10, &l:undolevels)
    177 
    178  " Setting local value in "two" must not change local value in "one"
    179  wincmd p
    180  call assert_equal(5, &g:undolevels)
    181  call assert_equal(-123456, &l:undolevels)
    182 
    183  new three
    184  setglobal ul=50
    185  call assert_equal(50, &g:undolevels)
    186  call assert_equal(-123456, &l:undolevels)
    187 
    188  " Resetting the local 'undolevels' value to use the global value
    189  setlocal undolevels=5
    190  "setlocal undolevels<
    191  set undolevels<
    192  call assert_equal(-123456, &l:undolevels)
    193 
    194  " Drop created windows
    195  set ul&
    196  new
    197  only!
    198 endfunc
    199 
    200 func BackOne(expected)
    201  call feedkeys('g-', 'xt')
    202  call assert_equal(a:expected, getline(1))
    203 endfunc
    204 
    205 func Test_undo_del_chars()
    206  throw 'Skipped: Nvim does not support test_settime()'
    207  " Setup a buffer without creating undo entries
    208  new
    209  set ul=-1
    210  call setline(1, ['123-456'])
    211  set ul=100
    212  1
    213  call test_settime(100)
    214 
    215  " Delete three characters and undo with g-
    216  call feedkeys('x', 'xt')
    217  call feedkeys('x', 'xt')
    218  call feedkeys('x', 'xt')
    219  call assert_equal('-456', getline(1))
    220  call BackOne('3-456')
    221  call BackOne('23-456')
    222  call BackOne('123-456')
    223  call assert_fails("BackOne('123-456')", "E492: Not an editor command: BackOne('123-456')")
    224 
    225  :" Delete three other characters and go back in time with g-
    226  call feedkeys('$x', 'xt')
    227  call feedkeys('x', 'xt')
    228  call feedkeys('x', 'xt')
    229  call assert_equal('123-', getline(1))
    230  call test_settime(101)
    231 
    232  call BackOne('123-4')
    233  call BackOne('123-45')
    234  " skips '123-456' because it's older
    235  call BackOne('-456')
    236  call BackOne('3-456')
    237  call BackOne('23-456')
    238  call BackOne('123-456')
    239  call assert_fails("BackOne('123-456')", "E492: Not an editor command: BackOne('123-456')")
    240  normal 10g+
    241  call assert_equal('123-', getline(1))
    242 
    243  :" Jump two seconds and go some seconds forward and backward
    244  call test_settime(103)
    245  call feedkeys("Aa\<Esc>", 'xt')
    246  call feedkeys("Ab\<Esc>", 'xt')
    247  call feedkeys("Ac\<Esc>", 'xt')
    248  call assert_equal('123-abc', getline(1))
    249  earlier 1s
    250  call assert_equal('123-', getline(1))
    251  earlier 3s
    252  call assert_equal('123-456', getline(1))
    253  later 1s
    254  call assert_equal('123-', getline(1))
    255  later 1h
    256  call assert_equal('123-abc', getline(1))
    257 
    258  close!
    259 endfunc
    260 
    261 func Test_undolist()
    262  new
    263  set ul=100
    264 
    265  let a = execute('undolist')
    266  call assert_equal("\nNothing to undo", a)
    267 
    268  " 1 leaf (2 changes).
    269  call feedkeys('achange1', 'xt')
    270  call feedkeys('achange2', 'xt')
    271  let a = execute('undolist')
    272  call assert_match("^\nnumber changes  when  *saved\n *2  *2 .*$", a)
    273 
    274  " 2 leaves.
    275  call feedkeys('u', 'xt')
    276  call feedkeys('achange3\<Esc>', 'xt')
    277  let a = execute('undolist')
    278  call assert_match("^\nnumber changes  when  *saved\n *2  *2  *.*\n *3  *2 .*$", a)
    279  close!
    280 endfunc
    281 
    282 func Test_U_command()
    283  new
    284  set ul=100
    285  call feedkeys("achange1\<Esc>", 'xt')
    286  call feedkeys("achange2\<Esc>", 'xt')
    287  norm! U
    288  call assert_equal('', getline(1))
    289  norm! U
    290  call assert_equal('change1change2', getline(1))
    291  close!
    292 endfunc
    293 
    294 func Test_undojoin()
    295  new
    296  call feedkeys("Goaaaa\<Esc>", 'xt')
    297  call feedkeys("obbbb\<Esc>", 'xt')
    298  call assert_equal(['aaaa', 'bbbb'], getline(2, '$'))
    299  call feedkeys("u", 'xt')
    300  call assert_equal(['aaaa'], getline(2, '$'))
    301  call feedkeys("obbbb\<Esc>", 'xt')
    302  undojoin
    303  " Note: next change must not be as if typed
    304  call feedkeys("occcc\<Esc>", 'x')
    305  call assert_equal(['aaaa', 'bbbb', 'cccc'], getline(2, '$'))
    306  call feedkeys("u", 'xt')
    307  call assert_equal(['aaaa'], getline(2, '$'))
    308  bwipe!
    309 endfunc
    310 
    311 func Test_undojoin_redo()
    312  new
    313  call setline(1, ['first line', 'second line'])
    314  call feedkeys("ixx\<Esc>", 'xt')
    315  call feedkeys(":undojoin | redo\<CR>", 'xt')
    316  call assert_equal('xxfirst line', getline(1))
    317  call assert_equal('second line', getline(2))
    318  bwipe!
    319 endfunc
    320 
    321 " undojoin not allowed after undo
    322 func Test_undojoin_after_undo()
    323  new
    324  call feedkeys("ixx\<Esc>u", 'xt')
    325  call assert_fails(':undojoin', 'E790:')
    326  bwipe!
    327 endfunc
    328 
    329 " undojoin is a noop when no change yet, or when 'undolevels' is negative
    330 func Test_undojoin_noop()
    331  new
    332  call feedkeys(":undojoin\<CR>", 'xt')
    333  call assert_equal([''], getline(1, '$'))
    334  setlocal undolevels=-1
    335  call feedkeys("ixx\<Esc>u", 'xt')
    336  call feedkeys(":undojoin\<CR>", 'xt')
    337  call assert_equal(['xx'], getline(1, '$'))
    338  bwipe!
    339 endfunc
    340 
    341 func Test_undo_write()
    342  call delete('Xtest')
    343  split Xtest
    344  call feedkeys("ione one one\<Esc>", 'xt')
    345  w!
    346  call feedkeys("otwo\<Esc>", 'xt')
    347  call feedkeys("otwo\<Esc>", 'xt')
    348  w
    349  call feedkeys("othree\<Esc>", 'xt')
    350  call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$'))
    351  earlier 1f
    352  call assert_equal(['one one one', 'two', 'two'], getline(1, '$'))
    353  earlier 1f
    354  call assert_equal(['one one one'], getline(1, '$'))
    355  earlier 1f
    356  call assert_equal([''], getline(1, '$'))
    357  later 1f
    358  call assert_equal(['one one one'], getline(1, '$'))
    359  later 1f
    360  call assert_equal(['one one one', 'two', 'two'], getline(1, '$'))
    361  later 1f
    362  call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$'))
    363 
    364  close!
    365  call delete('Xtest')
    366  bwipe! Xtest
    367 
    368  call assert_fails('earlier xyz', 'E475:')
    369 endfunc
    370 
    371 func Test_insert_expr()
    372  new
    373  " calling setline() triggers undo sync
    374  call feedkeys("oa\<Esc>", 'xt')
    375  call feedkeys("ob\<Esc>", 'xt')
    376  set ul=100
    377  call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x')
    378  call assert_equal(['a', 'b', '120', '34'], getline(2, '$'))
    379  call feedkeys("u", 'x')
    380  call assert_equal(['a', 'b', '12'], getline(2, '$'))
    381  call feedkeys("u", 'x')
    382  call assert_equal(['a', 'b'], getline(2, '$'))
    383 
    384  call feedkeys("oc\<Esc>", 'xt')
    385  set ul=100
    386  call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x')
    387  call assert_equal(['a', 'b', 'c', '120', '34'], getline(2, '$'))
    388  call feedkeys("u", 'x')
    389  call assert_equal(['a', 'b', 'c', '12'], getline(2, '$'))
    390 
    391  call feedkeys("od\<Esc>", 'xt')
    392  set ul=100
    393  call feedkeys("o1\<Esc>a2\<C-R>=string(123)\<CR>\<Esc>", 'x')
    394  call assert_equal(['a', 'b', 'c', '12', 'd', '12123'], getline(2, '$'))
    395  call feedkeys("u", 'x')
    396  call assert_equal(['a', 'b', 'c', '12', 'd'], getline(2, '$'))
    397 
    398  close!
    399 endfunc
    400 
    401 func Test_undofile_earlier()
    402  throw 'Skipped: Nvim does not support test_settime()'
    403  if has('win32')
    404    " FIXME: This test is flaky on MS-Windows.
    405    let g:test_is_flaky = 1
    406  endif
    407 
    408  " Issue #1254
    409  " create undofile with timestamps older than Vim startup time.
    410  let t0 = localtime() - 43200
    411  call test_settime(t0)
    412  new XfileEarlier
    413  call feedkeys("ione\<Esc>", 'xt')
    414  set ul=100
    415  call test_settime(t0 + 1)
    416  call feedkeys("otwo\<Esc>", 'xt')
    417  set ul=100
    418  call test_settime(t0 + 2)
    419  call feedkeys("othree\<Esc>", 'xt')
    420  set ul=100
    421  w
    422  wundo Xundofile
    423  bwipe!
    424  " restore normal timestamps.
    425  call test_settime(0)
    426  new XfileEarlier
    427  rundo Xundofile
    428  earlier 1d
    429  call assert_equal('', getline(1))
    430  bwipe!
    431  call delete('XfileEarlier')
    432  call delete('Xundofile')
    433 endfunc
    434 
    435 func Test_wundo_errors()
    436  new
    437  call setline(1, 'hello')
    438  call assert_fails('wundo! Xdoesnotexist/Xundofile', 'E828:')
    439  bwipe!
    440 endfunc
    441 
    442 " Check that reading a truncated undo file doesn't hang.
    443 func Test_undofile_truncated()
    444  new
    445  call setline(1, 'hello')
    446  set ul=100
    447  wundo Xundofile
    448  let contents = readfile('Xundofile', 'B')
    449 
    450  " try several sizes
    451  for size in range(20, 500, 33)
    452    call writefile(contents[0:size], 'Xundofile')
    453    call assert_fails('rundo Xundofile', 'E825:')
    454  endfor
    455 
    456  bwipe!
    457  call delete('Xundofile')
    458 endfunc
    459 
    460 func Test_rundo_errors()
    461  call assert_fails('rundo XfileDoesNotExist', 'E822:')
    462 
    463  call writefile(['abc'], 'Xundofile')
    464  call assert_fails('rundo Xundofile', 'E823:')
    465 
    466  call delete('Xundofile')
    467 endfunc
    468 
    469 func Test_undofile_next()
    470  set undofile
    471  new Xfoo.txt
    472  execute "norm ix\<c-g>uy\<c-g>uz\<Esc>"
    473  write
    474  bwipe
    475 
    476  next Xfoo.txt
    477  call assert_equal('xyz', getline(1))
    478  silent undo
    479  call assert_equal('xy', getline(1))
    480  silent undo
    481  call assert_equal('x', getline(1))
    482  bwipe!
    483 
    484  call delete('Xfoo.txt')
    485  call delete('.Xfoo.txt.un~')
    486  set undofile&
    487 endfunc
    488 
    489 " Test for undo working properly when executing commands from a register.
    490 " Also test this in an empty buffer.
    491 func Test_cmd_in_reg_undo()
    492  enew!
    493  let @a = "Ox\<Esc>jAy\<Esc>kdd"
    494  edit +/^$ test_undo.vim
    495  normal @au
    496  call assert_equal(0, &modified)
    497  return
    498  new
    499  normal @au
    500  call assert_equal(0, &modified)
    501  only!
    502  let @a = ''
    503 endfunc
    504 
    505 " This used to cause an illegal memory access
    506 func Test_undo_append()
    507  new
    508  call feedkeys("axx\<Esc>v", 'xt')
    509  undo
    510  norm o
    511  quit
    512 endfunc
    513 
    514 func Test_undo_0()
    515  new
    516  set ul=100
    517  normal i1
    518  undo
    519  normal i2
    520  undo
    521  normal i3
    522 
    523  undo 0
    524  let d = undotree()
    525  call assert_equal('', getline(1))
    526  call assert_equal(0, d.seq_cur)
    527 
    528  redo
    529  let d = undotree()
    530  call assert_equal('3', getline(1))
    531  call assert_equal(3, d.seq_cur)
    532 
    533  undo 2
    534  undo 0
    535  let d = undotree()
    536  call assert_equal('', getline(1))
    537  call assert_equal(0, d.seq_cur)
    538 
    539  redo
    540  let d = undotree()
    541  call assert_equal('2', getline(1))
    542  call assert_equal(2, d.seq_cur)
    543 
    544  undo 1
    545  undo 0
    546  let d = undotree()
    547  call assert_equal('', getline(1))
    548  call assert_equal(0, d.seq_cur)
    549 
    550  redo
    551  let d = undotree()
    552  call assert_equal('1', getline(1))
    553  call assert_equal(1, d.seq_cur)
    554 
    555  bwipe!
    556 endfunc
    557 
    558 " undo or redo are noop if there is nothing to undo or redo
    559 func Test_undo_redo_noop()
    560  new
    561  call assert_fails('undo 2', 'E830:')
    562 
    563  message clear
    564  undo
    565  let messages = split(execute('message'), "\n")
    566  call assert_equal('Already at oldest change', messages[-1])
    567 
    568  message clear
    569  redo
    570  let messages = split(execute('message'), "\n")
    571  call assert_equal('Already at newest change', messages[-1])
    572 
    573  bwipe!
    574 endfunc
    575 
    576 func Test_redo_empty_line()
    577  new
    578  exe "norm\x16r\x160"
    579  exe "norm."
    580  bwipe!
    581 endfunc
    582 
    583 funct Test_undofile()
    584  " Test undofile() without setting 'undodir'.
    585  if has('persistent_undo')
    586    call assert_equal(fnamemodify('.Xundofoo.un~', ':p'), undofile('Xundofoo'))
    587  else
    588    call assert_equal('', undofile('Xundofoo'))
    589  endif
    590  call assert_equal('', undofile(''))
    591 
    592  " Test undofile() with 'undodir' set to an existing directory.
    593  call mkdir('Xundodir')
    594  set undodir=Xundodir
    595  let cwd = getcwd()
    596  if has('win32')
    597    " Replace windows drive such as C:... into C%...
    598    let cwd = substitute(cwd, '^\([a-zA-Z]\):', '\1%', 'g')
    599  endif
    600  let cwd = substitute(cwd . '/Xundofoo', '/', '%', 'g')
    601  if has('persistent_undo')
    602    call assert_equal('Xundodir/' . cwd, undofile('Xundofoo'))
    603  else
    604    call assert_equal('', undofile('Xundofoo'))
    605  endif
    606  call assert_equal('', undofile(''))
    607  call delete('Xundodir', 'd')
    608 
    609  " Test undofile() with 'undodir' set to a non-existing directory.
    610  " call assert_equal('', 'Xundofoo'->undofile())
    611 
    612  if isdirectory('/tmp')
    613    set undodir=/tmp
    614    if has('osx')
    615      call assert_equal('/tmp/%private%tmp%file', undofile('///tmp/file'))
    616    else
    617      call assert_equal('/tmp/%tmp%file', undofile('///tmp/file'))
    618    endif
    619  endif
    620 
    621  set undodir&
    622 endfunc
    623 
    624 " Tests for the undo file
    625 " Explicitly break changes up in undo-able pieces by setting 'undolevels'.
    626 func Test_undofile_2()
    627  set undolevels=100 undofile
    628  edit Xtestfile
    629  call append(0, 'this is one line')
    630  call cursor(1, 1)
    631 
    632  " first a simple one-line change.
    633  set undolevels=100
    634  s/one/ONE/
    635  set undolevels=100
    636  write
    637  bwipe!
    638  edit Xtestfile
    639  undo
    640  call assert_equal('this is one line', getline(1))
    641 
    642  " change in original file fails check
    643  set noundofile
    644  edit! Xtestfile
    645  s/line/Line/
    646  write
    647  set undofile
    648  bwipe!
    649  edit Xtestfile
    650  undo
    651  call assert_equal('this is ONE Line', getline(1))
    652 
    653  " add 10 lines, delete 6 lines, undo 3
    654  set undofile
    655  call setbufline('%', 1, ['one', 'two', 'three', 'four', 'five', 'six',
    656       \ 'seven', 'eight', 'nine', 'ten'])
    657  set undolevels=100
    658  normal 3Gdd
    659  set undolevels=100
    660  normal dd
    661  set undolevels=100
    662  normal dd
    663  set undolevels=100
    664  normal dd
    665  set undolevels=100
    666  normal dd
    667  set undolevels=100
    668  normal dd
    669  set undolevels=100
    670  write
    671  bwipe!
    672  edit Xtestfile
    673  normal uuu
    674  call assert_equal(['one', 'two', 'six', 'seven', 'eight', 'nine', 'ten'],
    675       \ getline(1, '$'))
    676 
    677  " Test that reading the undofiles when setting undofile works
    678  set noundofile undolevels=0
    679  exe "normal i\n"
    680  undo
    681  edit! Xtestfile
    682  set undofile undolevels=100
    683  normal uuuuuu
    684  call assert_equal(['one', 'two', 'three', 'four', 'five', 'six', 'seven',
    685       \ 'eight', 'nine', 'ten'], getline(1, '$'))
    686 
    687  bwipe!
    688  call delete('Xtestfile')
    689  let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
    690  call delete(ufile)
    691  set undofile& undolevels&
    692 endfunc
    693 
    694 " Test 'undofile' using a file encrypted with 'zip' crypt method
    695 func Test_undofile_cryptmethod_zip()
    696  throw 'skipped: Nvim does not support cryptmethod'
    697  edit Xtestfile
    698  set undofile cryptmethod=zip
    699  call append(0, ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
    700  call cursor(5, 1)
    701 
    702  set undolevels=100
    703  normal kkkdd
    704  set undolevels=100
    705  normal dd
    706  set undolevels=100
    707  normal dd
    708  set undolevels=100
    709  " encrypt the file using key 'foobar'
    710  call feedkeys("foobar\nfoobar\n")
    711  X
    712  write!
    713  bwipe!
    714 
    715  call feedkeys("foobar\n")
    716  edit Xtestfile
    717  set key=
    718  normal uu
    719  call assert_equal(['monday', 'wednesday', 'thursday', 'friday', ''],
    720                    \ getline(1, '$'))
    721 
    722  bwipe!
    723  call delete('Xtestfile')
    724  let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
    725  call delete(ufile)
    726  set undofile& undolevels& cryptmethod&
    727 endfunc
    728 
    729 " Test 'undofile' using a file encrypted with 'blowfish' crypt method
    730 func Test_undofile_cryptmethod_blowfish()
    731  throw 'skipped: Nvim does not support cryptmethod'
    732  edit Xtestfile
    733  set undofile cryptmethod=blowfish
    734  call append(0, ['jan', 'feb', 'mar', 'apr', 'jun'])
    735  call cursor(5, 1)
    736 
    737  set undolevels=100
    738  exe 'normal kk0ifoo '
    739  set undolevels=100
    740  normal dd
    741  set undolevels=100
    742  exe 'normal ibar '
    743  set undolevels=100
    744  " encrypt the file using key 'foobar'
    745  call feedkeys("foobar\nfoobar\n")
    746  X
    747  write!
    748  bwipe!
    749 
    750  call feedkeys("foobar\n")
    751  edit Xtestfile
    752  set key=
    753  call search('bar')
    754  call assert_equal('bar apr', getline('.'))
    755  undo
    756  call assert_equal('apr', getline('.'))
    757  undo
    758  call assert_equal('foo mar', getline('.'))
    759  undo
    760  call assert_equal('mar', getline('.'))
    761 
    762  bwipe!
    763  call delete('Xtestfile')
    764  let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
    765  call delete(ufile)
    766  set undofile& undolevels& cryptmethod&
    767 endfunc
    768 
    769 " Test 'undofile' using a file encrypted with 'blowfish2' crypt method
    770 func Test_undofile_cryptmethod_blowfish2()
    771  throw 'skipped: Nvim does not support cryptmethod'
    772  edit Xtestfile
    773  set undofile cryptmethod=blowfish2
    774  call append(0, ['jan', 'feb', 'mar', 'apr', 'jun'])
    775  call cursor(5, 1)
    776 
    777  set undolevels=100
    778  exe 'normal kk0ifoo '
    779  set undolevels=100
    780  normal dd
    781  set undolevels=100
    782  exe 'normal ibar '
    783  set undolevels=100
    784  " encrypt the file using key 'foo2bar'
    785  call feedkeys("foo2bar\nfoo2bar\n")
    786  X
    787  write!
    788  bwipe!
    789 
    790  call feedkeys("foo2bar\n")
    791  edit Xtestfile
    792  set key=
    793  call search('bar')
    794  call assert_equal('bar apr', getline('.'))
    795  normal u
    796  call assert_equal('apr', getline('.'))
    797  normal u
    798  call assert_equal('foo mar', getline('.'))
    799  normal u
    800  call assert_equal('mar', getline('.'))
    801 
    802  bwipe!
    803  call delete('Xtestfile')
    804  let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
    805  call delete(ufile)
    806  set undofile& undolevels& cryptmethod&
    807 endfunc
    808 
    809 " Test for redoing with incrementing numbered registers
    810 func Test_redo_repeat_numbered_register()
    811  new
    812  for [i, v] in [[1, 'one'], [2, 'two'], [3, 'three'],
    813        \ [4, 'four'], [5, 'five'], [6, 'six'],
    814        \ [7, 'seven'], [8, 'eight'], [9, 'nine']]
    815    exe 'let @' .. i .. '="' .. v .. '\n"'
    816  endfor
    817  call feedkeys('"1p.........', 'xt')
    818  call assert_equal(['', 'one', 'two', 'three', 'four', 'five', 'six',
    819        \ 'seven', 'eight', 'nine', 'nine'], getline(1, '$'))
    820  bwipe!
    821 endfunc
    822 
    823 " Test for redo in insert mode using CTRL-O with multibyte characters
    824 func Test_redo_multibyte_in_insert_mode()
    825  new
    826  call feedkeys("a\<C-K>ft", 'xt')
    827  call feedkeys("uiHe\<C-O>.llo", 'xt')
    828  call assert_equal("He\ufb05llo", getline(1))
    829  bwipe!
    830 endfunc
    831 
    832 func Test_undo_mark()
    833  new
    834  " The undo is applied to the only line.
    835  call setline(1, 'hello')
    836  call feedkeys("ggyiw$p", 'xt')
    837  undo
    838  call assert_equal([0, 1, 1, 0], getpos("'["))
    839  call assert_equal([0, 1, 1, 0], getpos("']"))
    840  " The undo removes the last line.
    841  call feedkeys("Goaaaa\<Esc>", 'xt')
    842  call feedkeys("obbbb\<Esc>", 'xt')
    843  undo
    844  call assert_equal([0, 2, 1, 0], getpos("'["))
    845  call assert_equal([0, 2, 1, 0], getpos("']"))
    846  bwipe!
    847 endfunc
    848 
    849 func Test_undo_after_write()
    850  CheckScreendump
    851  " use a terminal to make undo work like when text is typed
    852  CheckRunVimInTerminal
    853 
    854  let lines =<< trim END
    855      edit Xtestfile.txt
    856      set undolevels=100 undofile
    857      imap . <Cmd>write<CR>
    858      write
    859  END
    860  call writefile(lines, 'Xtest_undo_after_write', 'D')
    861  let buf = RunVimInTerminal('-S Xtest_undo_after_write', #{rows: 6})
    862 
    863  call term_sendkeys(buf, "Otest.\<CR>boo!!!\<Esc>")
    864  sleep 100m
    865  call term_sendkeys(buf, "u")
    866  call VerifyScreenDump(buf, 'Test_undo_after_write_1', {})
    867 
    868  call term_sendkeys(buf, "u")
    869  call VerifyScreenDump(buf, 'Test_undo_after_write_2', {})
    870 
    871  call StopVimInTerminal(buf)
    872  call delete('Xtestfile.txt')
    873  call delete('.Xtestfile.txt.un~')
    874 endfunc
    875 
    876 func Test_undo_range_normal()
    877  new
    878  call setline(1, ['asa', 'bsb'])
    879  let &l:undolevels = &l:undolevels
    880  %normal dfs
    881  call assert_equal(['a', 'b'], getline(1, '$'))
    882  undo
    883  call assert_equal(['asa', 'bsb'], getline(1, '$'))
    884  bwipe!
    885 endfunc
    886 
    887 func Test_load_existing_undofile()
    888  CheckFeature persistent_undo
    889  sp samples/test_undo.txt
    890  let mess=execute(':verbose rundo samples/test_undo.txt.undo')
    891  call assert_match('Finished reading undo file', mess)
    892 
    893  call assert_equal(['one', 'two', 'three'], getline(1, '$'))
    894  norm! u
    895  call assert_equal(['one', 'two'], getline(1, '$'))
    896  norm! u
    897  call assert_equal(['one'], getline(1, '$'))
    898  norm! u
    899  call assert_equal([''], getline(1, '$'))
    900  let mess = execute(':norm! u')
    901  call assert_equal([''], getline(1, '$'))
    902  call assert_match('Already at oldest change', mess)
    903  exe ":norm! \<c-r>"
    904  call assert_equal(['one'], getline(1, '$'))
    905  exe ":norm! \<c-r>"
    906  call assert_equal(['one', 'two'], getline(1, '$'))
    907  exe ":norm! \<c-r>"
    908  call assert_equal(['one', 'two', 'three'], getline(1, '$'))
    909  let mess = execute(":norm! \<c-r>")
    910  call assert_equal(['one', 'two', 'three'], getline(1, '$'))
    911  call assert_match('Already at newest change', mess)
    912  bw!
    913 endfunc
    914 
    915 func Test_restore_cursor_position_after_undo()
    916  CheckFeature persistent_undo
    917  sp samples/test_undo.txt
    918 
    919  3 | exe "norm! gqk" | undojoin | 1 delete
    920  call assert_equal(1, line('.'))
    921  norm! u
    922  call assert_equal(3, line('.'))
    923  bw!
    924 endfunc
    925 
    926 
    927 " vim: shiftwidth=2 sts=2 expandtab