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