1" Tests for the terminal window. 2" This is split in two, because it can take a lot of time. 3" See test_terminal2.vim and test_terminal3.vim for further tests. 4 5source check.vim 6CheckFeature terminal 7 8source shared.vim 9source screendump.vim 10source mouse.vim 11source term_util.vim 12 13let s:python = PythonProg() 14let $PROMPT_COMMAND='' 15 16func Test_terminal_basic() 17 au TerminalOpen * let b:done = 'yes' 18 let buf = Run_shell_in_terminal({}) 19 20 call assert_equal('t', mode()) 21 call assert_equal('yes', b:done) 22 call assert_match('%aR[^\n]*running]', execute('ls')) 23 call assert_match('%aR[^\n]*running]', execute('ls R')) 24 call assert_notmatch('%[^\n]*running]', execute('ls F')) 25 call assert_notmatch('%[^\n]*running]', execute('ls ?')) 26 call assert_fails('set modifiable', 'E946:') 27 28 call StopShellInTerminal(buf) 29 call TermWait(buf) 30 call assert_equal('n', mode()) 31 call assert_match('%aF[^\n]*finished]', execute('ls')) 32 call assert_match('%aF[^\n]*finished]', execute('ls F')) 33 call assert_notmatch('%[^\n]*finished]', execute('ls R')) 34 call assert_notmatch('%[^\n]*finished]', execute('ls ?')) 35 36 " closing window wipes out the terminal buffer a with finished job 37 close 38 call assert_equal("", bufname(buf)) 39 40 au! TerminalOpen 41 unlet g:job 42endfunc 43 44func Test_terminal_TerminalWinOpen() 45 au TerminalWinOpen * let b:done = 'yes' 46 let buf = Run_shell_in_terminal({}) 47 call assert_equal('yes', b:done) 48 call StopShellInTerminal(buf) 49 " closing window wipes out the terminal buffer with the finished job 50 close 51 52 if has("unix") 53 terminal ++hidden ++open sleep 1 54 sleep 1 55 call assert_fails("echo b:done", 'E121:') 56 endif 57 58 au! TerminalWinOpen 59endfunc 60 61func Test_terminal_make_change() 62 let buf = Run_shell_in_terminal({}) 63 call StopShellInTerminal(buf) 64 call TermWait(buf) 65 66 setlocal modifiable 67 exe "normal Axxx\<Esc>" 68 call assert_fails(buf . 'bwipe', ['E89:', 'E517']) 69 undo 70 71 exe buf . 'bwipe' 72 unlet g:job 73endfunc 74 75func Test_terminal_paste_register() 76 let @" = "text to paste" 77 78 let buf = Run_shell_in_terminal({}) 79 " Wait for the shell to display a prompt 80 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 81 82 call feedkeys("echo \<C-W>\"\" \<C-W>\"=37 + 5\<CR>\<CR>", 'xt') 83 call WaitForAssert({-> assert_match("echo text to paste 42$", getline(1))}) 84 call WaitForAssert({-> assert_equal('text to paste 42', 2->getline())}) 85 86 exe buf . 'bwipe!' 87 unlet g:job 88endfunc 89 90func Test_terminal_wipe_buffer() 91 let buf = Run_shell_in_terminal({}) 92 call assert_fails(buf . 'bwipe', ['E89', 'E517']) 93 exe buf . 'bwipe!' 94 call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) 95 call assert_equal("", bufname(buf)) 96 97 unlet g:job 98endfunc 99 100func Test_terminal_split_quit() 101 let buf = Run_shell_in_terminal({}) 102 call TermWait(buf) 103 split 104 quit! 105 call TermWait(buf) 106 sleep 50m 107 call assert_equal('run', job_status(g:job)) 108 109 quit! 110 call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) 111 112 exe buf . 'bwipe' 113 unlet g:job 114endfunc 115 116func Test_terminal_hide_buffer() 117 let buf = Run_shell_in_terminal({}) 118 setlocal bufhidden=hide 119 quit 120 for nr in range(1, winnr('$')) 121 call assert_notequal(winbufnr(nr), buf) 122 endfor 123 call assert_true(bufloaded(buf)) 124 call assert_true(buflisted(buf)) 125 126 exe 'split ' . buf . 'buf' 127 call StopShellInTerminal(buf) 128 exe buf . 'bwipe' 129 130 unlet g:job 131endfunc 132 133func s:Nasty_exit_cb(job, st) 134 exe g:buf . 'bwipe!' 135 let g:buf = 0 136endfunc 137 138func Get_cat_123_cmd() 139 if has('win32') 140 if !has('conpty') 141 return 'cmd /c "cls && color 2 && echo 123"' 142 else 143 " When clearing twice, extra sequence is not output. 144 return 'cmd /c "cls && cls && color 2 && echo 123"' 145 endif 146 else 147 call writefile(["\<Esc>[32m123"], 'Xtext') 148 return "cat Xtext" 149 endif 150endfunc 151 152func Test_terminal_nasty_cb() 153 let cmd = Get_cat_123_cmd() 154 let g:buf = term_start(cmd, {'exit_cb': function('s:Nasty_exit_cb')}) 155 let g:job = term_getjob(g:buf) 156 157 call WaitForAssert({-> assert_equal("dead", job_status(g:job))}) 158 call WaitForAssert({-> assert_equal(0, g:buf)}) 159 unlet g:job 160 unlet g:buf 161 call delete('Xtext') 162endfunc 163 164func Check_123(buf) 165 let l = term_scrape(a:buf, 0) 166 call assert_true(len(l) == 0) 167 let l = term_scrape(a:buf, 999) 168 call assert_true(len(l) == 0) 169 let l = a:buf->term_scrape(1) 170 call assert_true(len(l) > 0) 171 call assert_equal('1', l[0].chars) 172 call assert_equal('2', l[1].chars) 173 call assert_equal('3', l[2].chars) 174 call assert_equal('#00e000', l[0].fg) 175 call assert_equal(0, term_getattr(l[0].attr, 'bold')) 176 call assert_equal(0, l[0].attr->term_getattr('italic')) 177 if has('win32') 178 " On Windows 'background' always defaults to dark, even though the terminal 179 " may use a light background. Therefore accept both white and black. 180 call assert_match('#ffffff\|#000000', l[0].bg) 181 else 182 if &background == 'light' 183 call assert_equal('#ffffff', l[0].bg) 184 else 185 call assert_equal('#000000', l[0].bg) 186 endif 187 endif 188 189 let l = term_getline(a:buf, -1) 190 call assert_equal('', l) 191 let l = term_getline(a:buf, 0) 192 call assert_equal('', l) 193 let l = term_getline(a:buf, 999) 194 call assert_equal('', l) 195 let l = term_getline(a:buf, 1) 196 call assert_equal('123', l) 197endfunc 198 199func Test_terminal_scrape_123() 200 let cmd = Get_cat_123_cmd() 201 let buf = term_start(cmd) 202 203 let termlist = term_list() 204 call assert_equal(1, len(termlist)) 205 call assert_equal(buf, termlist[0]) 206 207 " Nothing happens with invalid buffer number 208 call term_wait(1234) 209 210 call TermWait(buf) 211 " On MS-Windows we first get a startup message of two lines, wait for the 212 " "cls" to happen, after that we have one line with three characters. 213 call WaitForAssert({-> assert_equal(3, len(term_scrape(buf, 1)))}) 214 call Check_123(buf) 215 216 " Must still work after the job ended. 217 let job = term_getjob(buf) 218 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 219 call TermWait(buf) 220 call Check_123(buf) 221 222 exe buf . 'bwipe' 223 call delete('Xtext') 224endfunc 225 226func Test_terminal_scrape_multibyte() 227 call writefile(["léttまrs"], 'Xtext') 228 if has('win32') 229 " Run cmd with UTF-8 codepage to make the type command print the expected 230 " multibyte characters. 231 let buf = term_start("cmd /K chcp 65001") 232 call term_sendkeys(buf, "type Xtext\<CR>") 233 eval buf->term_sendkeys("exit\<CR>") 234 let line = 4 235 else 236 let buf = term_start("cat Xtext") 237 let line = 1 238 endif 239 240 call WaitFor({-> len(term_scrape(buf, line)) >= 7 && term_scrape(buf, line)[0].chars == "l"}) 241 let l = term_scrape(buf, line) 242 call assert_true(len(l) >= 7) 243 call assert_equal('l', l[0].chars) 244 call assert_equal('é', l[1].chars) 245 call assert_equal(1, l[1].width) 246 call assert_equal('t', l[2].chars) 247 call assert_equal('t', l[3].chars) 248 call assert_equal('ま', l[4].chars) 249 call assert_equal(2, l[4].width) 250 call assert_equal('r', l[5].chars) 251 call assert_equal('s', l[6].chars) 252 253 let job = term_getjob(buf) 254 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 255 call TermWait(buf) 256 257 exe buf . 'bwipe' 258 call delete('Xtext') 259endfunc 260 261func Test_terminal_one_column() 262 " This creates a terminal, displays a double-wide character and makes the 263 " window one column wide. This used to cause a crash. 264 let width = &columns 265 botright vert term 266 let buf = bufnr('$') 267 call term_wait(buf, 100) 268 exe "set columns=" .. (width / 2) 269 redraw 270 call term_sendkeys(buf, "キ") 271 call term_wait(buf, 10) 272 exe "set columns=" .. width 273 exe buf . 'bwipe!' 274endfunc 275 276func Test_terminal_scroll() 277 call writefile(range(1, 200), 'Xtext') 278 if has('win32') 279 let cmd = 'cmd /c "type Xtext"' 280 else 281 let cmd = "cat Xtext" 282 endif 283 let buf = term_start(cmd) 284 285 let job = term_getjob(buf) 286 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 287 call TermWait(buf) 288 289 " wait until the scrolling stops 290 while 1 291 let scrolled = buf->term_getscrolled() 292 sleep 20m 293 if scrolled == buf->term_getscrolled() 294 break 295 endif 296 endwhile 297 298 call assert_equal('1', getline(1)) 299 call assert_equal('1', term_getline(buf, 1 - scrolled)) 300 call assert_equal('49', getline(49)) 301 call assert_equal('49', term_getline(buf, 49 - scrolled)) 302 call assert_equal('200', getline(200)) 303 call assert_equal('200', term_getline(buf, 200 - scrolled)) 304 305 exe buf . 'bwipe' 306 call delete('Xtext') 307endfunc 308 309func Test_terminal_scrollback() 310 let buf = Run_shell_in_terminal({'term_rows': 15}) 311 set termwinscroll=100 312 call writefile(range(150), 'Xtext') 313 if has('win32') 314 call term_sendkeys(buf, "type Xtext\<CR>") 315 else 316 call term_sendkeys(buf, "cat Xtext\<CR>") 317 endif 318 let rows = term_getsize(buf)[0] 319 " On MS-Windows there is an empty line, check both last line and above it. 320 call WaitForAssert({-> assert_match( '149', term_getline(buf, rows - 1) . term_getline(buf, rows - 2))}) 321 let lines = line('$') 322 call assert_inrange(91, 100, lines) 323 324 call StopShellInTerminal(buf) 325 call TermWait(buf) 326 exe buf . 'bwipe' 327 set termwinscroll& 328 call delete('Xtext') 329endfunc 330 331func Test_terminal_postponed_scrollback() 332 " tail -f only works on Unix 333 CheckUnix 334 335 call writefile(range(50), 'Xtext') 336 call writefile([ 337 \ 'set shell=/bin/sh noruler', 338 \ 'terminal', 339 \ 'sleep 200m', 340 \ 'call feedkeys("tail -n 100 -f Xtext\<CR>", "xt")', 341 \ 'sleep 100m', 342 \ 'call feedkeys("\<C-W>N", "xt")', 343 \ ], 'XTest_postponed') 344 let buf = RunVimInTerminal('-S XTest_postponed', {}) 345 " Check that the Xtext lines are displayed and in Terminal-Normal mode 346 call VerifyScreenDump(buf, 'Test_terminal_scrollback_1', {}) 347 348 silent !echo 'one more line' >>Xtext 349 " Screen will not change, move cursor to get a different dump 350 call term_sendkeys(buf, "k") 351 call VerifyScreenDump(buf, 'Test_terminal_scrollback_2', {}) 352 353 " Back to Terminal-Job mode, text will scroll and show the extra line. 354 call term_sendkeys(buf, "a") 355 call VerifyScreenDump(buf, 'Test_terminal_scrollback_3', {}) 356 357 " stop "tail -f" 358 call term_sendkeys(buf, "\<C-C>") 359 call TermWait(buf, 25) 360 " stop shell 361 call term_sendkeys(buf, "exit\<CR>") 362 call TermWait(buf, 50) 363 " close terminal window 364 let tsk_ret = term_sendkeys(buf, ":q\<CR>") 365 366 " check type of term_sendkeys() return value 367 echo type(tsk_ret) 368 369 call StopVimInTerminal(buf) 370 call delete('XTest_postponed') 371 call delete('Xtext') 372endfunc 373 374" Run diff on two dumps with different size. 375func Test_terminal_dumpdiff_size() 376 call assert_equal(1, winnr('$')) 377 call term_dumpdiff('dumps/Test_incsearch_search_01.dump', 'dumps/Test_popup_command_01.dump') 378 call assert_equal(2, winnr('$')) 379 call assert_match('Test_incsearch_search_01.dump', getline(10)) 380 call assert_match(' +++++$', getline(11)) 381 call assert_match('Test_popup_command_01.dump', getline(31)) 382 call assert_equal(repeat('+', 75), getline(30)) 383 quit 384endfunc 385 386func Test_terminal_size() 387 let cmd = Get_cat_123_cmd() 388 389 exe 'terminal ++rows=5 ' . cmd 390 let size = term_getsize('') 391 bwipe! 392 call assert_equal(5, size[0]) 393 394 call term_start(cmd, {'term_rows': 6}) 395 let size = term_getsize('') 396 bwipe! 397 call assert_equal(6, size[0]) 398 399 vsplit 400 exe 'terminal ++rows=5 ++cols=33 ' . cmd 401 call assert_equal([5, 33], ''->term_getsize()) 402 403 call term_setsize('', 6, 0) 404 call assert_equal([6, 33], term_getsize('')) 405 406 eval ''->term_setsize(0, 35) 407 call assert_equal([6, 35], term_getsize('')) 408 409 call term_setsize('', 7, 30) 410 call assert_equal([7, 30], term_getsize('')) 411 412 bwipe! 413 call assert_fails("call term_setsize('', 7, 30)", "E955:") 414 415 call term_start(cmd, {'term_rows': 6, 'term_cols': 36}) 416 let size = term_getsize('') 417 bwipe! 418 call assert_equal([6, 36], size) 419 420 exe 'vertical terminal ++cols=20 ' . cmd 421 let size = term_getsize('') 422 bwipe! 423 call assert_equal(20, size[1]) 424 425 eval cmd->term_start({'vertical': 1, 'term_cols': 26}) 426 let size = term_getsize('') 427 bwipe! 428 call assert_equal(26, size[1]) 429 430 split 431 exe 'vertical terminal ++rows=6 ++cols=20 ' . cmd 432 let size = term_getsize('') 433 bwipe! 434 call assert_equal([6, 20], size) 435 436 call term_start(cmd, {'vertical': 1, 'term_rows': 7, 'term_cols': 27}) 437 let size = term_getsize('') 438 bwipe! 439 call assert_equal([7, 27], size) 440 441 call delete('Xtext') 442endfunc 443 444func Test_terminal_curwin() 445 let cmd = Get_cat_123_cmd() 446 call assert_equal(1, winnr('$')) 447 448 split Xdummy 449 call setline(1, 'dummy') 450 write 451 call assert_equal(1, getbufinfo('Xdummy')[0].loaded) 452 exe 'terminal ++curwin ' . cmd 453 call assert_equal(2, winnr('$')) 454 call assert_equal(0, getbufinfo('Xdummy')[0].loaded) 455 bwipe! 456 457 split Xdummy 458 call term_start(cmd, {'curwin': 1}) 459 call assert_equal(2, winnr('$')) 460 bwipe! 461 462 split Xdummy 463 call setline(1, 'change') 464 call assert_fails('terminal ++curwin ' . cmd, 'E37:') 465 call assert_equal(2, winnr('$')) 466 exe 'terminal! ++curwin ' . cmd 467 call assert_equal(2, winnr('$')) 468 bwipe! 469 470 split Xdummy 471 call setline(1, 'change') 472 call assert_fails("call term_start(cmd, {'curwin': 1})", 'E37:') 473 call assert_equal(2, winnr('$')) 474 bwipe! 475 476 split Xdummy 477 bwipe! 478 call delete('Xtext') 479 call delete('Xdummy') 480endfunc 481 482func s:get_sleep_cmd() 483 if s:python != '' 484 let cmd = s:python . " test_short_sleep.py" 485 " 500 was not enough for Travis 486 let waittime = 900 487 else 488 echo 'This will take five seconds...' 489 let waittime = 2000 490 if has('win32') 491 let cmd = $windir . '\system32\timeout.exe 1' 492 else 493 let cmd = 'sleep 1' 494 endif 495 endif 496 return [cmd, waittime] 497endfunc 498 499func Test_terminal_finish_open_close() 500 call assert_equal(1, winnr('$')) 501 502 let [cmd, waittime] = s:get_sleep_cmd() 503 504 " shell terminal closes automatically 505 terminal 506 let buf = bufnr('%') 507 call assert_equal(2, winnr('$')) 508 " Wait for the shell to display a prompt 509 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 510 call StopShellInTerminal(buf) 511 call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime) 512 513 " shell terminal that does not close automatically 514 terminal ++noclose 515 let buf = bufnr('%') 516 call assert_equal(2, winnr('$')) 517 " Wait for the shell to display a prompt 518 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 519 call StopShellInTerminal(buf) 520 call assert_equal(2, winnr('$')) 521 quit 522 call assert_equal(1, winnr('$')) 523 524 exe 'terminal ++close ' . cmd 525 call assert_equal(2, winnr('$')) 526 wincmd p 527 call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime) 528 529 call term_start(cmd, {'term_finish': 'close'}) 530 call assert_equal(2, winnr('$')) 531 wincmd p 532 call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime) 533 call assert_equal(1, winnr('$')) 534 535 exe 'terminal ++open ' . cmd 536 close! 537 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 538 bwipe 539 540 call term_start(cmd, {'term_finish': 'open'}) 541 close! 542 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 543 bwipe 544 545 exe 'terminal ++hidden ++open ' . cmd 546 call assert_equal(1, winnr('$')) 547 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 548 bwipe 549 550 call term_start(cmd, {'term_finish': 'open', 'hidden': 1}) 551 call assert_equal(1, winnr('$')) 552 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 553 bwipe 554 555 call assert_fails("call term_start(cmd, {'term_opencmd': 'open'})", 'E475:') 556 call assert_fails("call term_start(cmd, {'term_opencmd': 'split %x'})", 'E475:') 557 call assert_fails("call term_start(cmd, {'term_opencmd': 'split %d and %s'})", 'E475:') 558 call assert_fails("call term_start(cmd, {'term_opencmd': 'split % and %d'})", 'E475:') 559 560 call term_start(cmd, {'term_finish': 'open', 'term_opencmd': '4split | buffer %d'}) 561 close! 562 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 563 call assert_equal(4, winheight(0)) 564 bwipe 565endfunc 566 567func Test_terminal_cwd() 568 if has('win32') 569 let cmd = 'cmd /c cd' 570 else 571 CheckExecutable pwd 572 let cmd = 'pwd' 573 endif 574 call mkdir('Xdir') 575 let buf = term_start(cmd, {'cwd': 'Xdir'}) 576 call WaitForAssert({-> assert_equal('Xdir', fnamemodify(getline(1), ":t"))}) 577 578 exe buf . 'bwipe' 579 call delete('Xdir', 'rf') 580endfunc 581 582func Test_terminal_cwd_failure() 583 " Case 1: Provided directory is not actually a directory. Attempt to make 584 " the file executable as well. 585 call writefile([], 'Xfile') 586 call setfperm('Xfile', 'rwx------') 587 call assert_fails("call term_start(&shell, {'cwd': 'Xfile'})", 'E475:') 588 call delete('Xfile') 589 590 " Case 2: Directory does not exist. 591 call assert_fails("call term_start(&shell, {'cwd': 'Xdir'})", 'E475:') 592 593 " Case 3: Directory exists but is not accessible. 594 " Skip this for root, it will be accessible anyway. 595 if !IsRoot() 596 call mkdir('XdirNoAccess', '', '0600') 597 " return early if the directory permissions could not be set properly 598 if getfperm('XdirNoAccess')[2] == 'x' 599 call delete('XdirNoAccess', 'rf') 600 return 601 endif 602 call assert_fails("call term_start(&shell, {'cwd': 'XdirNoAccess'})", 'E475:') 603 call delete('XdirNoAccess', 'rf') 604 endif 605endfunc 606 607func Test_terminal_servername() 608 if !has('clientserver') 609 return 610 endif 611 call s:test_environment("VIM_SERVERNAME", v:servername) 612endfunc 613 614func Test_terminal_version() 615 call s:test_environment("VIM_TERMINAL", string(v:version)) 616endfunc 617 618func s:test_environment(name, value) 619 let buf = Run_shell_in_terminal({}) 620 " Wait for the shell to display a prompt 621 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 622 if has('win32') 623 call term_sendkeys(buf, "echo %" . a:name . "%\r") 624 else 625 call term_sendkeys(buf, "echo $" . a:name . "\r") 626 endif 627 call TermWait(buf) 628 call StopShellInTerminal(buf) 629 call WaitForAssert({-> assert_equal(a:value, getline(2))}) 630 631 exe buf . 'bwipe' 632 unlet buf 633endfunc 634 635func Test_terminal_env() 636 let buf = Run_shell_in_terminal({'env': {'TESTENV': 'correct'}}) 637 " Wait for the shell to display a prompt 638 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 639 if has('win32') 640 call term_sendkeys(buf, "echo %TESTENV%\r") 641 else 642 call term_sendkeys(buf, "echo $TESTENV\r") 643 endif 644 eval buf->TermWait() 645 call StopShellInTerminal(buf) 646 call WaitForAssert({-> assert_equal('correct', getline(2))}) 647 648 exe buf . 'bwipe' 649endfunc 650 651func Test_terminal_list_args() 652 let buf = term_start([&shell, &shellcmdflag, 'echo "123"']) 653 call assert_fails(buf . 'bwipe', ['E89', 'E517']) 654 exe buf . 'bwipe!' 655 call assert_equal("", bufname(buf)) 656endfunction 657 658func Test_terminal_noblock() 659 let buf = term_start(&shell) 660 let wait_time = 5000 661 let letters = 'abcdefghijklmnopqrstuvwxyz' 662 if has('bsd') || has('mac') || has('sun') 663 " The shell or something else has a problem dealing with more than 1000 664 " characters at the same time. It's very slow too. 665 let len = 1000 666 let wait_time = 15000 667 let letters = 'abcdefghijklm' 668 " NPFS is used in Windows, nonblocking mode does not work properly. 669 elseif has('win32') 670 let len = 1 671 else 672 let len = 5000 673 endif 674 675 " Send a lot of text lines, should be buffered properly. 676 for c in split(letters, '\zs') 677 call term_sendkeys(buf, 'echo ' . repeat(c, len) . "\<cr>") 678 endfor 679 call term_sendkeys(buf, "echo done\<cr>") 680 681 " On MS-Windows there is an extra empty line below "done". Find "done" in 682 " the last-but-one or the last-but-two line. 683 let lnum = term_getsize(buf)[0] - 1 684 call WaitForAssert({-> assert_match('done', term_getline(buf, lnum - 1) .. '//' .. term_getline(buf, lnum))}, wait_time) 685 let line = term_getline(buf, lnum) 686 if line !~ 'done' 687 let line = term_getline(buf, lnum - 1) 688 endif 689 call assert_match('done', line) 690 691 let g:job = term_getjob(buf) 692 call StopShellInTerminal(buf) 693 call TermWait(buf) 694 unlet g:job 695 bwipe 696endfunc 697 698func Test_terminal_write_stdin() 699 " TODO: enable once writing to stdin works on MS-Windows 700 CheckNotMSWindows 701 CheckExecutable wc 702 703 call setline(1, ['one', 'two', 'three']) 704 %term wc 705 call WaitForAssert({-> assert_match('3', getline("$"))}) 706 let nrs = split(getline('$')) 707 call assert_equal(['3', '3', '14'], nrs) 708 %bwipe! 709 710 call setline(1, ['one', 'two', 'three', 'four']) 711 2,3term wc 712 call WaitForAssert({-> assert_match('2', getline("$"))}) 713 let nrs = split(getline('$')) 714 call assert_equal(['2', '2', '10'], nrs) 715 %bwipe! 716endfunc 717 718func Test_terminal_eof_arg() 719 call CheckPython(s:python) 720 721 call setline(1, ['print("hello")']) 722 exe '1term ++eof=exit(123) ' .. s:python 723 " MS-Windows echoes the input, Unix doesn't. 724 if has('win32') 725 call WaitFor({-> getline('$') =~ 'exit(123)'}) 726 call assert_equal('hello', getline(line('$') - 1)) 727 else 728 call WaitFor({-> getline('$') =~ 'hello'}) 729 call assert_equal('hello', getline('$')) 730 endif 731 call assert_equal(123, bufnr()->term_getjob()->job_info().exitval) 732 %bwipe! 733endfunc 734 735func Test_terminal_eof_arg_win32_ctrl_z() 736 CheckMSWindows 737 call CheckPython(s:python) 738 739 call setline(1, ['print("hello")']) 740 exe '1term ++eof=<C-Z> ' .. s:python 741 call WaitForAssert({-> assert_match('\^Z', getline(line('$') - 1))}) 742 call assert_match('\^Z', getline(line('$') - 1)) 743 %bwipe! 744endfunc 745 746func Test_terminal_duplicate_eof_arg() 747 call CheckPython(s:python) 748 749 " Check the last specified ++eof arg is used and should not memory leak. 750 new 751 call setline(1, ['print("hello")']) 752 exe '1term ++eof=<C-Z> ++eof=exit(123) ' .. s:python 753 " MS-Windows echoes the input, Unix doesn't. 754 if has('win32') 755 call WaitFor({-> getline('$') =~ 'exit(123)'}) 756 call assert_equal('hello', getline(line('$') - 1)) 757 else 758 call WaitFor({-> getline('$') =~ 'hello'}) 759 call assert_equal('hello', getline('$')) 760 endif 761 call assert_equal(123, bufnr()->term_getjob()->job_info().exitval) 762 %bwipe! 763endfunc 764 765func Test_terminal_no_cmd() 766 let buf = term_start('NONE', {}) 767 call assert_notequal(0, buf) 768 769 let pty = job_info(term_getjob(buf))['tty_out'] 770 call assert_notequal('', pty) 771 if has('gui_running') && !has('win32') 772 " In the GUI job_start() doesn't work, it does not read from the pty. 773 call system('echo "look here" > ' . pty) 774 else 775 " Otherwise using a job works on all systems. 776 call job_start([&shell, &shellcmdflag, 'echo "look here" > ' . pty]) 777 endif 778 call WaitForAssert({-> assert_match('look here', term_getline(buf, 1))}) 779 780 bwipe! 781endfunc 782 783func Test_terminal_special_chars() 784 " this file name only works on Unix 785 CheckUnix 786 787 call mkdir('Xdir with spaces') 788 call writefile(['x'], 'Xdir with spaces/quoted"file') 789 term ls Xdir\ with\ spaces/quoted\"file 790 call WaitForAssert({-> assert_match('quoted"file', term_getline('', 1))}) 791 " make sure the job has finished 792 call WaitForAssert({-> assert_match('finish', term_getstatus(bufnr()))}) 793 794 call delete('Xdir with spaces', 'rf') 795 bwipe 796endfunc 797 798func Test_terminal_wrong_options() 799 call assert_fails('call term_start(&shell, { 800 \ "in_io": "file", 801 \ "in_name": "xxx", 802 \ "out_io": "file", 803 \ "out_name": "xxx", 804 \ "err_io": "file", 805 \ "err_name": "xxx" 806 \ })', 'E474:') 807 call assert_fails('call term_start(&shell, { 808 \ "out_buf": bufnr("%") 809 \ })', 'E474:') 810 call assert_fails('call term_start(&shell, { 811 \ "err_buf": bufnr("%") 812 \ })', 'E474:') 813endfunc 814 815func Test_terminal_redir_file() 816 let cmd = Get_cat_123_cmd() 817 let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'}) 818 call TermWait(buf) 819 " ConPTY may precede escape sequence. There are things that are not so. 820 if !has('conpty') 821 call WaitForAssert({-> assert_notequal(0, len(readfile("Xfile")))}) 822 call assert_match('123', readfile('Xfile')[0]) 823 endif 824 let g:job = term_getjob(buf) 825 call WaitForAssert({-> assert_equal("dead", job_status(g:job))}) 826 827 if has('win32') 828 " On Windows we cannot delete a file being used by a process. When 829 " job_status() returns "dead", the process remains for a short time. 830 " Just wait for a moment. 831 sleep 50m 832 endif 833 call delete('Xfile') 834 bwipe 835 836 if has('unix') 837 call writefile(['one line'], 'Xfile') 838 let buf = term_start('cat', {'in_io': 'file', 'in_name': 'Xfile'}) 839 call TermWait(buf) 840 call WaitForAssert({-> assert_equal('one line', term_getline(buf, 1))}) 841 let g:job = term_getjob(buf) 842 call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) 843 bwipe 844 call delete('Xfile') 845 endif 846endfunc 847 848func TerminalTmap(remap) 849 let buf = Run_shell_in_terminal({}) 850 call assert_equal('t', mode()) 851 852 if a:remap 853 tmap 123 456 854 else 855 tnoremap 123 456 856 endif 857 " don't use abcde, it's an existing command 858 tmap 456 abxde 859 call assert_equal('456', maparg('123', 't')) 860 call assert_equal('abxde', maparg('456', 't')) 861 call feedkeys("123", 'tx') 862 call WaitForAssert({-> assert_match('abxde\|456', term_getline(buf, term_getcursor(buf)[0]))}) 863 let lnum = term_getcursor(buf)[0] 864 if a:remap 865 call assert_match('abxde', term_getline(buf, lnum)) 866 else 867 call assert_match('456', term_getline(buf, lnum)) 868 endif 869 870 call term_sendkeys(buf, "\r") 871 call StopShellInTerminal(buf) 872 call TermWait(buf) 873 874 tunmap 123 875 tunmap 456 876 call assert_equal('', maparg('123', 't')) 877 close 878 unlet g:job 879endfunc 880 881func Test_terminal_tmap() 882 call TerminalTmap(1) 883 call TerminalTmap(0) 884endfunc 885 886func Test_terminal_wall() 887 let buf = Run_shell_in_terminal({}) 888 wall 889 call StopShellInTerminal(buf) 890 call TermWait(buf) 891 exe buf . 'bwipe' 892 unlet g:job 893endfunc 894 895func Test_terminal_wqall() 896 let buf = Run_shell_in_terminal({}) 897 call assert_fails('wqall', 'E948') 898 call StopShellInTerminal(buf) 899 call TermWait(buf) 900 exe buf . 'bwipe' 901 unlet g:job 902endfunc 903 904func Test_terminal_composing_unicode() 905 let save_enc = &encoding 906 set encoding=utf-8 907 908 if has('win32') 909 let cmd = "cmd /K chcp 65001" 910 let lnum = [3, 6, 9] 911 else 912 let cmd = &shell 913 let lnum = [1, 3, 5] 914 endif 915 916 enew 917 let buf = term_start(cmd, {'curwin': bufnr('')}) 918 let g:job = term_getjob(buf) 919 call WaitFor({-> term_getline(buf, 1) !=# ''}, 1000) 920 921 if has('win32') 922 call assert_equal('cmd', job_info(g:job).cmd[0]) 923 else 924 call assert_equal(&shell, job_info(g:job).cmd[0]) 925 endif 926 927 " ascii + composing 928 let txt = "a\u0308bc" 929 call term_sendkeys(buf, "echo " . txt) 930 call TermWait(buf, 25) 931 call assert_match("echo " . txt, term_getline(buf, lnum[0])) 932 call term_sendkeys(buf, "\<cr>") 933 call WaitForAssert({-> assert_equal(txt, term_getline(buf, lnum[0] + 1))}, 1000) 934 let l = term_scrape(buf, lnum[0] + 1) 935 call assert_equal("a\u0308", l[0].chars) 936 call assert_equal("b", l[1].chars) 937 call assert_equal("c", l[2].chars) 938 939 " multibyte + composing 940 let txt = "\u304b\u3099\u304e\u304f\u3099\u3052\u3053\u3099" 941 call term_sendkeys(buf, "echo " . txt) 942 call TermWait(buf, 25) 943 call assert_match("echo " . txt, term_getline(buf, lnum[1])) 944 call term_sendkeys(buf, "\<cr>") 945 call WaitForAssert({-> assert_equal(txt, term_getline(buf, lnum[1] + 1))}, 1000) 946 let l = term_scrape(buf, lnum[1] + 1) 947 call assert_equal("\u304b\u3099", l[0].chars) 948 call assert_equal("\u304e", l[2].chars) 949 call assert_equal("\u304f\u3099", l[3].chars) 950 call assert_equal("\u3052", l[5].chars) 951 call assert_equal("\u3053\u3099", l[6].chars) 952 953 " \u00a0 + composing 954 let txt = "abc\u00a0\u0308" 955 call term_sendkeys(buf, "echo " . txt) 956 call TermWait(buf, 25) 957 call assert_match("echo " . txt, term_getline(buf, lnum[2])) 958 call term_sendkeys(buf, "\<cr>") 959 call WaitForAssert({-> assert_equal(txt, term_getline(buf, lnum[2] + 1))}, 1000) 960 let l = term_scrape(buf, lnum[2] + 1) 961 call assert_equal("\u00a0\u0308", l[3].chars) 962 963 call term_sendkeys(buf, "exit\r") 964 call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) 965 bwipe! 966 unlet g:job 967 let &encoding = save_enc 968endfunc 969 970func Test_terminal_aucmd_on_close() 971 fun Nop() 972 let s:called = 1 973 endfun 974 975 aug repro 976 au! 977 au BufWinLeave * call Nop() 978 aug END 979 980 let [cmd, waittime] = s:get_sleep_cmd() 981 982 call assert_equal(1, winnr('$')) 983 new 984 call setline(1, ['one', 'two']) 985 exe 'term ++close ' . cmd 986 wincmd p 987 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 988 call assert_equal(1, s:called) 989 bwipe! 990 991 unlet s:called 992 au! repro 993 delfunc Nop 994endfunc 995 996func Test_terminal_term_start_empty_command() 997 let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})" 998 call assert_fails(cmd, 'E474') 999 let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})" 1000 call assert_fails(cmd, 'E474') 1001 let cmd = "call term_start({}, {'curwin' : 1, 'term_finish' : 'close'})" 1002 call assert_fails(cmd, 'E474') 1003 let cmd = "call term_start(0, {'curwin' : 1, 'term_finish' : 'close'})" 1004 call assert_fails(cmd, 'E474') 1005 let cmd = "call term_start('', {'term_name' : []})" 1006 call assert_fails(cmd, 'E730') 1007 let cmd = "call term_start('', {'term_finish' : 'axby'})" 1008 call assert_fails(cmd, 'E475') 1009 let cmd = "call term_start('', {'eof_chars' : []})" 1010 call assert_fails(cmd, 'E730:') 1011 let cmd = "call term_start('', {'term_kill' : []})" 1012 call assert_fails(cmd, 'E730:') 1013 let cmd = "call term_start('', {'tty_type' : []})" 1014 call assert_fails(cmd, 'E730:') 1015 let cmd = "call term_start('', {'tty_type' : 'abc'})" 1016 call assert_fails(cmd, 'E475:') 1017 let cmd = "call term_start('', {'term_highlight' : []})" 1018 call assert_fails(cmd, 'E730:') 1019 if has('gui') || has('termguicolors') 1020 let cmd = "call term_start('', {'ansi_colors' : 'abc'})" 1021 call assert_fails(cmd, 'E475:') 1022 let cmd = "call term_start('', {'ansi_colors' : [[]]})" 1023 call assert_fails(cmd, 'E730:') 1024 let cmd = "call term_start('', {'ansi_colors' : repeat(['blue'], 18)})" 1025 if has('gui_running') || has('termguicolors') 1026 call assert_fails(cmd, 'E475:') 1027 else 1028 call assert_fails(cmd, 'E254:') 1029 endif 1030 endif 1031endfunc 1032 1033func Test_terminal_response_to_control_sequence() 1034 CheckUnix 1035 1036 let buf = Run_shell_in_terminal({}) 1037 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 1038 1039 call term_sendkeys(buf, "cat\<CR>") 1040 call WaitForAssert({-> assert_match('cat', term_getline(buf, 1))}) 1041 1042 " Request the cursor position. 1043 call term_sendkeys(buf, "\x1b[6n\<CR>") 1044 1045 " Wait for output from tty to display, below an empty line. 1046 call WaitForAssert({-> assert_match('3;1R', term_getline(buf, 4))}) 1047 1048 " End "cat" gently. 1049 call term_sendkeys(buf, "\<CR>\<C-D>") 1050 1051 call StopShellInTerminal(buf) 1052 exe buf . 'bwipe' 1053 unlet g:job 1054endfunc 1055 1056" Run Vim, start a terminal in that Vim with the kill argument, 1057" :qall works. 1058func Run_terminal_qall_kill(line1, line2) 1059 " 1. Open a terminal window and wait for the prompt to appear 1060 " 2. set kill using term_setkill() 1061 " 3. make Vim exit, it will kill the shell 1062 let after = [ 1063 \ a:line1, 1064 \ 'let buf = bufnr("%")', 1065 \ 'while term_getline(buf, 1) =~ "^\\s*$"', 1066 \ ' sleep 10m', 1067 \ 'endwhile', 1068 \ a:line2, 1069 \ 'au VimLeavePre * call writefile(["done"], "Xdone")', 1070 \ 'qall', 1071 \ ] 1072 if !RunVim([], after, '') 1073 return 1074 endif 1075 call assert_equal("done", readfile("Xdone")[0]) 1076 call delete("Xdone") 1077endfunc 1078 1079" Run Vim in a terminal, then start a terminal in that Vim with a kill 1080" argument, check that :qall works. 1081func Test_terminal_qall_kill_arg() 1082 call Run_terminal_qall_kill('term ++kill=kill', '') 1083endfunc 1084 1085" Run Vim, start a terminal in that Vim, set the kill argument with 1086" term_setkill(), check that :qall works. 1087func Test_terminal_qall_kill_func() 1088 call Run_terminal_qall_kill('term', 'eval buf->term_setkill("kill")') 1089endfunc 1090 1091" Run Vim, start a terminal in that Vim without the kill argument, 1092" check that :qall does not exit, :qall! does. 1093func Test_terminal_qall_exit() 1094 let after =<< trim [CODE] 1095 term 1096 let buf = bufnr("%") 1097 while term_getline(buf, 1) =~ "^\\s*$" 1098 sleep 10m 1099 endwhile 1100 set nomore 1101 au VimLeavePre * call writefile(["too early"], "Xdone") 1102 qall 1103 au! VimLeavePre * exe buf . "bwipe!" | call writefile(["done"], "Xdone") 1104 cquit 1105 [CODE] 1106 1107 if !RunVim([], after, '') 1108 return 1109 endif 1110 call assert_equal("done", readfile("Xdone")[0]) 1111 call delete("Xdone") 1112endfunc 1113 1114" Run Vim in a terminal, then start a terminal in that Vim without a kill 1115" argument, check that :confirm qall works. 1116func Test_terminal_qall_prompt() 1117 CheckRunVimInTerminal 1118 let buf = RunVimInTerminal('', {}) 1119 1120 " Open a terminal window and wait for the prompt to appear 1121 call term_sendkeys(buf, ":term\<CR>") 1122 call WaitForAssert({-> assert_match('\[running]', term_getline(buf, 10))}) 1123 call WaitForAssert({-> assert_notmatch('^\s*$', term_getline(buf, 1))}) 1124 1125 " make Vim exit, it will prompt to kill the shell 1126 call term_sendkeys(buf, "\<C-W>:confirm qall\<CR>") 1127 call WaitForAssert({-> assert_match('ancel:', term_getline(buf, 20))}) 1128 call term_sendkeys(buf, "y") 1129 call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))}) 1130 1131 " close the terminal window where Vim was running 1132 quit 1133endfunc 1134 1135" Run Vim in a terminal, then start a terminal window with a shell and check 1136" that Vim exits if it is closed. 1137func Test_terminal_exit() 1138 CheckRunVimInTerminal 1139 1140 let lines =<< trim END 1141 let winid = win_getid() 1142 help 1143 term 1144 let termid = win_getid() 1145 call win_gotoid(winid) 1146 close 1147 call win_gotoid(termid) 1148 END 1149 call writefile(lines, 'XtermExit') 1150 let buf = RunVimInTerminal('-S XtermExit', #{rows: 10}) 1151 let job = term_getjob(buf) 1152 call WaitForAssert({-> assert_equal("run", job_status(job))}) 1153 1154 " quit the shell, it will make Vim exit 1155 call term_sendkeys(buf, "exit\<CR>") 1156 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 1157 1158 call delete('XtermExit') 1159endfunc 1160 1161func Test_terminal_open_autocmd() 1162 augroup repro 1163 au! 1164 au TerminalOpen * let s:called += 1 1165 augroup END 1166 1167 let s:called = 0 1168 1169 " Open a terminal window with :terminal 1170 terminal 1171 call assert_equal(1, s:called) 1172 bwipe! 1173 1174 " Open a terminal window with term_start() 1175 call term_start(&shell) 1176 call assert_equal(2, s:called) 1177 bwipe! 1178 1179 " Open a hidden terminal buffer with :terminal 1180 terminal ++hidden 1181 call assert_equal(3, s:called) 1182 for buf in term_list() 1183 exe buf . "bwipe!" 1184 endfor 1185 1186 " Open a hidden terminal buffer with term_start() 1187 let buf = term_start(&shell, {'hidden': 1}) 1188 call assert_equal(4, s:called) 1189 exe buf . "bwipe!" 1190 1191 unlet s:called 1192 au! repro 1193endfunction 1194 1195func Check_dump01(off) 1196 call assert_equal('one two three four five', trim(getline(a:off + 1))) 1197 call assert_equal('~ Select Word', trim(getline(a:off + 7))) 1198 call assert_equal(':popup PopUp', trim(getline(a:off + 20))) 1199endfunc 1200 1201func Test_terminal_dumpwrite_composing() 1202 CheckRunVimInTerminal 1203 let save_enc = &encoding 1204 set encoding=utf-8 1205 call assert_equal(1, winnr('$')) 1206 1207 let text = " a\u0300 e\u0302 o\u0308" 1208 call writefile([text], 'Xcomposing') 1209 let buf = RunVimInTerminal('--cmd "set encoding=utf-8" Xcomposing', {}) 1210 call WaitForAssert({-> assert_match(text, term_getline(buf, 1))}) 1211 eval 'Xdump'->term_dumpwrite(buf) 1212 let dumpline = readfile('Xdump')[0] 1213 call assert_match('|à| |ê| |ö', dumpline) 1214 1215 call StopVimInTerminal(buf) 1216 call delete('Xcomposing') 1217 call delete('Xdump') 1218 let &encoding = save_enc 1219endfunc 1220 1221" Tests for failures in the term_dumpwrite() function 1222func Test_terminal_dumpwrite_errors() 1223 CheckRunVimInTerminal 1224 call assert_fails("call term_dumpwrite({}, 'Xtest.dump')", 'E728:') 1225 let buf = RunVimInTerminal('', {}) 1226 call term_wait(buf) 1227 call assert_fails("call term_dumpwrite(buf, 'Xtest.dump', '')", 'E715:') 1228 call assert_fails("call term_dumpwrite(buf, [])", 'E730:') 1229 call writefile([], 'Xtest.dump') 1230 call assert_fails("call term_dumpwrite(buf, 'Xtest.dump')", 'E953:') 1231 call delete('Xtest.dump') 1232 call assert_fails("call term_dumpwrite(buf, '')", 'E482:') 1233 call assert_fails("call term_dumpwrite(buf, test_null_string())", 'E482:') 1234 call test_garbagecollect_now() 1235 call StopVimInTerminal(buf) 1236 call term_wait(buf) 1237 call assert_fails("call term_dumpwrite(buf, 'Xtest.dump')", 'E958:') 1238 call assert_fails('call term_sendkeys([], ":q\<CR>")', 'E745:') 1239 call assert_equal(0, term_sendkeys(buf, ":q\<CR>")) 1240endfunc 1241 1242" just testing basic functionality. 1243func Test_terminal_dumpload() 1244 let curbuf = winbufnr('') 1245 call assert_equal(1, winnr('$')) 1246 let buf = term_dumpload('dumps/Test_popup_command_01.dump') 1247 call assert_equal(2, winnr('$')) 1248 call assert_equal(20, line('$')) 1249 call Check_dump01(0) 1250 1251 " Load another dump in the same window 1252 let buf2 = 'dumps/Test_diff_01.dump'->term_dumpload({'bufnr': buf}) 1253 call assert_equal(buf, buf2) 1254 call assert_notequal('one two three four five', trim(getline(1))) 1255 1256 " Load the first dump again in the same window 1257 let buf2 = term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': buf}) 1258 call assert_equal(buf, buf2) 1259 call Check_dump01(0) 1260 1261 call assert_fails("call term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': curbuf})", 'E475:') 1262 call assert_fails("call term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': 9999})", 'E86:') 1263 new 1264 let closedbuf = winbufnr('') 1265 quit 1266 call assert_fails("call term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': closedbuf})", 'E475:') 1267 call assert_fails('call term_dumpload([])', 'E730:') 1268 call assert_fails('call term_dumpload("xabcy.dump")', 'E485:') 1269 1270 quit 1271endfunc 1272 1273func Test_terminal_dumpload_dump() 1274 CheckRunVimInTerminal 1275 1276 let lines =<< trim END 1277 call term_dumpload('dumps/Test_popupwin_22.dump', #{term_rows: 12}) 1278 END 1279 call writefile(lines, 'XtermDumpload') 1280 let buf = RunVimInTerminal('-S XtermDumpload', #{rows: 15}) 1281 call VerifyScreenDump(buf, 'Test_terminal_dumpload', {}) 1282 1283 call StopVimInTerminal(buf) 1284 call delete('XtermDumpload') 1285endfunc 1286 1287func Test_terminal_dumpdiff() 1288 call assert_equal(1, winnr('$')) 1289 eval 'dumps/Test_popup_command_01.dump'->term_dumpdiff('dumps/Test_popup_command_02.dump') 1290 call assert_equal(2, winnr('$')) 1291 call assert_equal(62, line('$')) 1292 call Check_dump01(0) 1293 call Check_dump01(42) 1294 call assert_equal(' bbbbbbbbbbbbbbbbbb ', getline(26)[0:29]) 1295 quit 1296 1297 call assert_fails('call term_dumpdiff("X1.dump", [])', 'E730:') 1298 call assert_fails('call term_dumpdiff("X1.dump", "X2.dump")', 'E485:') 1299 call writefile([], 'X1.dump') 1300 call assert_fails('call term_dumpdiff("X1.dump", "X2.dump")', 'E485:') 1301 call delete('X1.dump') 1302endfunc 1303 1304func Test_terminal_dumpdiff_swap() 1305 call assert_equal(1, winnr('$')) 1306 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_03.dump') 1307 call assert_equal(2, winnr('$')) 1308 call assert_equal(62, line('$')) 1309 call assert_match('Test_popup_command_01.dump', getline(21)) 1310 call assert_match('Test_popup_command_03.dump', getline(42)) 1311 call assert_match('Undo', getline(3)) 1312 call assert_match('three four five', getline(45)) 1313 1314 normal s 1315 call assert_match('Test_popup_command_03.dump', getline(21)) 1316 call assert_match('Test_popup_command_01.dump', getline(42)) 1317 call assert_match('three four five', getline(3)) 1318 call assert_match('Undo', getline(45)) 1319 quit 1320 1321 " Diff two terminal dump files with different number of rows 1322 " Swap the diffs 1323 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_winline_rnu.dump') 1324 call assert_match('Test_popup_command_01.dump', getline(21)) 1325 call assert_match('Test_winline_rnu.dump', getline(42)) 1326 normal s 1327 call assert_match('Test_winline_rnu.dump', getline(6)) 1328 call assert_match('Test_popup_command_01.dump', getline(27)) 1329 quit 1330endfunc 1331 1332func Test_terminal_dumpdiff_options() 1333 set laststatus=0 1334 call assert_equal(1, winnr('$')) 1335 let height = winheight(0) 1336 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 1, 'term_cols': 33}) 1337 call assert_equal(2, winnr('$')) 1338 call assert_equal(height, winheight(winnr())) 1339 call assert_equal(33, winwidth(winnr())) 1340 call assert_equal('dump diff dumps/Test_popup_command_01.dump', bufname('%')) 1341 quit 1342 1343 call assert_equal(1, winnr('$')) 1344 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 0, 'term_rows': 13, 'term_name': 'something else'}) 1345 call assert_equal(2, winnr('$')) 1346 call assert_equal(&columns, winwidth(0)) 1347 call assert_equal(13, winheight(0)) 1348 call assert_equal('something else', bufname('%')) 1349 quit 1350 1351 call assert_equal(1, winnr('$')) 1352 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'curwin': 1}) 1353 call assert_equal(1, winnr('$')) 1354 call assert_fails("call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'bufnr': -1})", 'E475:') 1355 bwipe 1356 1357 set laststatus& 1358endfunc 1359 1360" When drawing the statusline the cursor position may not have been updated 1361" yet. 1362" 1. create a terminal, make it show 2 lines 1363" 2. 0.5 sec later: leave terminal window, execute "i" 1364" 3. 0.5 sec later: clear terminal window, now it's 1 line 1365" 4. 0.5 sec later: redraw, including statusline (used to trigger bug) 1366" 4. 0.5 sec later: should be done, clean up 1367func Test_terminal_statusline() 1368 CheckUnix 1369 1370 set statusline=x 1371 terminal 1372 let tbuf = bufnr('') 1373 call term_sendkeys(tbuf, "clear; echo a; echo b; sleep 1; clear\n") 1374 call timer_start(500, { tid -> feedkeys("\<C-w>j", 'tx') }) 1375 call timer_start(1500, { tid -> feedkeys("\<C-l>", 'tx') }) 1376 au BufLeave * if &buftype == 'terminal' | silent! normal i | endif 1377 1378 sleep 2 1379 exe tbuf . 'bwipe!' 1380 au! BufLeave 1381 set statusline= 1382endfunc 1383 1384func Api_drop_common(options) 1385 call assert_equal(1, winnr('$')) 1386 1387 " Use the title termcap entries to output the escape sequence. 1388 call writefile([ 1389 \ 'set title', 1390 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1391 \ 'let &titlestring = ''["drop","Xtextfile"' . a:options . ']''', 1392 \ 'redraw', 1393 \ "set t_ts=", 1394 \ ], 'Xscript') 1395 let buf = RunVimInTerminal('-S Xscript', {}) 1396 call WaitFor({-> bufnr('Xtextfile') > 0}) 1397 call assert_equal('Xtextfile', expand('%:t')) 1398 call assert_true(winnr('$') >= 3) 1399 return buf 1400endfunc 1401 1402func Test_terminal_api_drop_newwin() 1403 CheckRunVimInTerminal 1404 let buf = Api_drop_common('') 1405 call assert_equal(0, &bin) 1406 call assert_equal('', &fenc) 1407 1408 call StopVimInTerminal(buf) 1409 call delete('Xscript') 1410 bwipe Xtextfile 1411endfunc 1412 1413func Test_terminal_api_drop_newwin_bin() 1414 CheckRunVimInTerminal 1415 let buf = Api_drop_common(',{"bin":1}') 1416 call assert_equal(1, &bin) 1417 1418 call StopVimInTerminal(buf) 1419 call delete('Xscript') 1420 bwipe Xtextfile 1421endfunc 1422 1423func Test_terminal_api_drop_newwin_binary() 1424 CheckRunVimInTerminal 1425 let buf = Api_drop_common(',{"binary":1}') 1426 call assert_equal(1, &bin) 1427 1428 call StopVimInTerminal(buf) 1429 call delete('Xscript') 1430 bwipe Xtextfile 1431endfunc 1432 1433func Test_terminal_api_drop_newwin_nobin() 1434 CheckRunVimInTerminal 1435 set binary 1436 let buf = Api_drop_common(',{"nobin":1}') 1437 call assert_equal(0, &bin) 1438 1439 call StopVimInTerminal(buf) 1440 call delete('Xscript') 1441 bwipe Xtextfile 1442 set nobinary 1443endfunc 1444 1445func Test_terminal_api_drop_newwin_nobinary() 1446 CheckRunVimInTerminal 1447 set binary 1448 let buf = Api_drop_common(',{"nobinary":1}') 1449 call assert_equal(0, &bin) 1450 1451 call StopVimInTerminal(buf) 1452 call delete('Xscript') 1453 bwipe Xtextfile 1454 set nobinary 1455endfunc 1456 1457func Test_terminal_api_drop_newwin_ff() 1458 CheckRunVimInTerminal 1459 let buf = Api_drop_common(',{"ff":"dos"}') 1460 call assert_equal("dos", &ff) 1461 1462 call StopVimInTerminal(buf) 1463 call delete('Xscript') 1464 bwipe Xtextfile 1465endfunc 1466 1467func Test_terminal_api_drop_newwin_fileformat() 1468 CheckRunVimInTerminal 1469 let buf = Api_drop_common(',{"fileformat":"dos"}') 1470 call assert_equal("dos", &ff) 1471 1472 call StopVimInTerminal(buf) 1473 call delete('Xscript') 1474 bwipe Xtextfile 1475endfunc 1476 1477func Test_terminal_api_drop_newwin_enc() 1478 CheckRunVimInTerminal 1479 let buf = Api_drop_common(',{"enc":"utf-16"}') 1480 call assert_equal("utf-16", &fenc) 1481 1482 call StopVimInTerminal(buf) 1483 call delete('Xscript') 1484 bwipe Xtextfile 1485endfunc 1486 1487func Test_terminal_api_drop_newwin_encoding() 1488 CheckRunVimInTerminal 1489 let buf = Api_drop_common(',{"encoding":"utf-16"}') 1490 call assert_equal("utf-16", &fenc) 1491 1492 call StopVimInTerminal(buf) 1493 call delete('Xscript') 1494 bwipe Xtextfile 1495endfunc 1496 1497func Test_terminal_api_drop_oldwin() 1498 CheckRunVimInTerminal 1499 let firstwinid = win_getid() 1500 split Xtextfile 1501 let textfile_winid = win_getid() 1502 call assert_equal(2, winnr('$')) 1503 call win_gotoid(firstwinid) 1504 1505 " Use the title termcap entries to output the escape sequence. 1506 call writefile([ 1507 \ 'set title', 1508 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1509 \ 'let &titlestring = ''["drop","Xtextfile"]''', 1510 \ 'redraw', 1511 \ "set t_ts=", 1512 \ ], 'Xscript') 1513 let buf = RunVimInTerminal('-S Xscript', {'rows': 10}) 1514 call WaitForAssert({-> assert_equal('Xtextfile', expand('%:t'))}) 1515 call assert_equal(textfile_winid, win_getid()) 1516 1517 call StopVimInTerminal(buf) 1518 call delete('Xscript') 1519 bwipe Xtextfile 1520endfunc 1521 1522func Tapi_TryThis(bufnum, arg) 1523 let g:called_bufnum = a:bufnum 1524 let g:called_arg = a:arg 1525endfunc 1526 1527func WriteApiCall(funcname) 1528 " Use the title termcap entries to output the escape sequence. 1529 call writefile([ 1530 \ 'set title', 1531 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1532 \ 'let &titlestring = ''["call","' . a:funcname . '",["hello",123]]''', 1533 \ 'redraw', 1534 \ "set t_ts=", 1535 \ ], 'Xscript') 1536endfunc 1537 1538func Test_terminal_api_call() 1539 CheckRunVimInTerminal 1540 1541 unlet! g:called_bufnum 1542 unlet! g:called_arg 1543 1544 call WriteApiCall('Tapi_TryThis') 1545 1546 " Default 1547 let buf = RunVimInTerminal('-S Xscript', {}) 1548 call WaitFor({-> exists('g:called_bufnum')}) 1549 call assert_equal(buf, g:called_bufnum) 1550 call assert_equal(['hello', 123], g:called_arg) 1551 call StopVimInTerminal(buf) 1552 1553 unlet! g:called_bufnum 1554 unlet! g:called_arg 1555 1556 " Enable explicitly 1557 let buf = RunVimInTerminal('-S Xscript', {'term_api': 'Tapi_Try'}) 1558 call WaitFor({-> exists('g:called_bufnum')}) 1559 call assert_equal(buf, g:called_bufnum) 1560 call assert_equal(['hello', 123], g:called_arg) 1561 call StopVimInTerminal(buf) 1562 1563 unlet! g:called_bufnum 1564 unlet! g:called_arg 1565 1566 func! ApiCall_TryThis(bufnum, arg) 1567 let g:called_bufnum2 = a:bufnum 1568 let g:called_arg2 = a:arg 1569 endfunc 1570 1571 call WriteApiCall('ApiCall_TryThis') 1572 1573 " Use prefix match 1574 let buf = RunVimInTerminal('-S Xscript', {'term_api': 'ApiCall_'}) 1575 call WaitFor({-> exists('g:called_bufnum2')}) 1576 call assert_equal(buf, g:called_bufnum2) 1577 call assert_equal(['hello', 123], g:called_arg2) 1578 call StopVimInTerminal(buf) 1579 1580 call assert_fails("call term_start('ls', {'term_api' : []})", 'E730:') 1581 1582 unlet! g:called_bufnum2 1583 unlet! g:called_arg2 1584 1585 call delete('Xscript') 1586 delfunction! ApiCall_TryThis 1587 unlet! g:called_bufnum2 1588 unlet! g:called_arg2 1589endfunc 1590 1591func Test_terminal_api_call_fails() 1592 CheckRunVimInTerminal 1593 1594 func! TryThis(bufnum, arg) 1595 let g:called_bufnum3 = a:bufnum 1596 let g:called_arg3 = a:arg 1597 endfunc 1598 1599 call WriteApiCall('TryThis') 1600 1601 unlet! g:called_bufnum3 1602 unlet! g:called_arg3 1603 1604 " Not permitted 1605 call ch_logfile('Xlog', 'w') 1606 let buf = RunVimInTerminal('-S Xscript', {'term_api': ''}) 1607 call WaitForAssert({-> assert_match('Unpermitted function: TryThis', string(readfile('Xlog')))}) 1608 call assert_false(exists('g:called_bufnum3')) 1609 call assert_false(exists('g:called_arg3')) 1610 call StopVimInTerminal(buf) 1611 1612 " No match 1613 call ch_logfile('Xlog', 'w') 1614 let buf = RunVimInTerminal('-S Xscript', {'term_api': 'TryThat'}) 1615 call WaitFor({-> string(readfile('Xlog')) =~ 'Unpermitted function: TryThis'}) 1616 call assert_false(exists('g:called_bufnum3')) 1617 call assert_false(exists('g:called_arg3')) 1618 call StopVimInTerminal(buf) 1619 1620 call delete('Xscript') 1621 call ch_logfile('') 1622 call delete('Xlog') 1623 delfunction! TryThis 1624 unlet! g:called_bufnum3 1625 unlet! g:called_arg3 1626endfunc 1627 1628let s:caught_e937 = 0 1629 1630func Tapi_Delete(bufnum, arg) 1631 try 1632 execute 'bdelete!' a:bufnum 1633 catch /E937:/ 1634 let s:caught_e937 = 1 1635 endtry 1636endfunc 1637 1638func Test_terminal_api_call_fail_delete() 1639 CheckRunVimInTerminal 1640 1641 call WriteApiCall('Tapi_Delete') 1642 let buf = RunVimInTerminal('-S Xscript', {}) 1643 call WaitForAssert({-> assert_equal(1, s:caught_e937)}) 1644 1645 call StopVimInTerminal(buf) 1646 call delete('Xscript') 1647 call ch_logfile('', '') 1648endfunc 1649 1650func Test_terminal_setapi_and_call() 1651 CheckRunVimInTerminal 1652 1653 call WriteApiCall('Tapi_TryThis') 1654 call ch_logfile('Xlog', 'w') 1655 1656 unlet! g:called_bufnum 1657 unlet! g:called_arg 1658 1659 let buf = RunVimInTerminal('-S Xscript', {'term_api': ''}) 1660 call WaitForAssert({-> assert_match('Unpermitted function: Tapi_TryThis', string(readfile('Xlog')))}) 1661 call assert_false(exists('g:called_bufnum')) 1662 call assert_false(exists('g:called_arg')) 1663 1664 eval buf->term_setapi('Tapi_') 1665 call term_sendkeys(buf, ":set notitle\<CR>") 1666 call term_sendkeys(buf, ":source Xscript\<CR>") 1667 call WaitFor({-> exists('g:called_bufnum')}) 1668 call assert_equal(buf, g:called_bufnum) 1669 call assert_equal(['hello', 123], g:called_arg) 1670 1671 call StopVimInTerminal(buf) 1672 1673 call delete('Xscript') 1674 call ch_logfile('') 1675 call delete('Xlog') 1676 unlet! g:called_bufnum 1677 unlet! g:called_arg 1678endfunc 1679 1680func Test_terminal_api_arg() 1681 CheckRunVimInTerminal 1682 1683 call WriteApiCall('Tapi_TryThis') 1684 call ch_logfile('Xlog', 'w') 1685 1686 unlet! g:called_bufnum 1687 unlet! g:called_arg 1688 1689 execute 'term ++api= ' .. GetVimCommandCleanTerm() .. '-S Xscript' 1690 let buf = bufnr('%') 1691 call WaitForAssert({-> assert_match('Unpermitted function: Tapi_TryThis', string(readfile('Xlog')))}) 1692 call assert_false(exists('g:called_bufnum')) 1693 call assert_false(exists('g:called_arg')) 1694 1695 call StopVimInTerminal(buf) 1696 1697 call ch_logfile('Xlog', 'w') 1698 1699 execute 'term ++api=Tapi_ ' .. GetVimCommandCleanTerm() .. '-S Xscript' 1700 let buf = bufnr('%') 1701 call WaitFor({-> exists('g:called_bufnum')}) 1702 call assert_equal(buf, g:called_bufnum) 1703 call assert_equal(['hello', 123], g:called_arg) 1704 1705 call StopVimInTerminal(buf) 1706 1707 call delete('Xscript') 1708 call ch_logfile('') 1709 call delete('Xlog') 1710 unlet! g:called_bufnum 1711 unlet! g:called_arg 1712endfunc 1713 1714func Test_terminal_ansicolors_default() 1715 CheckFunction term_getansicolors 1716 1717 let colors = [ 1718 \ '#000000', '#e00000', 1719 \ '#00e000', '#e0e000', 1720 \ '#0000e0', '#e000e0', 1721 \ '#00e0e0', '#e0e0e0', 1722 \ '#808080', '#ff4040', 1723 \ '#40ff40', '#ffff40', 1724 \ '#4040ff', '#ff40ff', 1725 \ '#40ffff', '#ffffff', 1726 \] 1727 1728 let buf = Run_shell_in_terminal({}) 1729 call assert_equal(colors, term_getansicolors(buf)) 1730 call StopShellInTerminal(buf) 1731 call TermWait(buf) 1732 call assert_equal([], term_getansicolors(buf)) 1733 1734 exe buf . 'bwipe' 1735endfunc 1736 1737let s:test_colors = [ 1738 \ '#616e64', '#0d0a79', 1739 \ '#6d610d', '#0a7373', 1740 \ '#690d0a', '#6d696e', 1741 \ '#0d0a6f', '#616e0d', 1742 \ '#0a6479', '#6d0d0a', 1743 \ '#617373', '#0d0a69', 1744 \ '#6d690d', '#0a6e6f', 1745 \ '#610d0a', '#6e6479', 1746 \] 1747 1748func Test_terminal_ansicolors_global() 1749 CheckFeature termguicolors 1750 CheckFunction term_getansicolors 1751 1752 let g:terminal_ansi_colors = reverse(copy(s:test_colors)) 1753 let buf = Run_shell_in_terminal({}) 1754 call assert_equal(g:terminal_ansi_colors, term_getansicolors(buf)) 1755 call StopShellInTerminal(buf) 1756 call TermWait(buf) 1757 1758 exe buf . 'bwipe' 1759 unlet g:terminal_ansi_colors 1760endfunc 1761 1762func Test_terminal_ansicolors_func() 1763 CheckFeature termguicolors 1764 CheckFunction term_getansicolors 1765 1766 let g:terminal_ansi_colors = reverse(copy(s:test_colors)) 1767 let buf = Run_shell_in_terminal({'ansi_colors': s:test_colors}) 1768 call assert_equal(s:test_colors, term_getansicolors(buf)) 1769 1770 call term_setansicolors(buf, g:terminal_ansi_colors) 1771 call assert_equal(g:terminal_ansi_colors, buf->term_getansicolors()) 1772 1773 let colors = [ 1774 \ 'ivory', 'AliceBlue', 1775 \ 'grey67', 'dark goldenrod', 1776 \ 'SteelBlue3', 'PaleVioletRed4', 1777 \ 'MediumPurple2', 'yellow2', 1778 \ 'RosyBrown3', 'OrangeRed2', 1779 \ 'white smoke', 'navy blue', 1780 \ 'grey47', 'gray97', 1781 \ 'MistyRose2', 'DodgerBlue4', 1782 \] 1783 eval buf->term_setansicolors(colors) 1784 1785 let colors[4] = 'Invalid' 1786 call assert_fails('call term_setansicolors(buf, colors)', 'E254:') 1787 call assert_fails('call term_setansicolors(buf, {})', 'E714:') 1788 1789 call StopShellInTerminal(buf) 1790 call TermWait(buf) 1791 call assert_equal(0, term_setansicolors(buf, [])) 1792 exe buf . 'bwipe' 1793endfunc 1794 1795func Test_terminal_all_ansi_colors() 1796 CheckRunVimInTerminal 1797 1798 " Use all the ANSI colors. 1799 call writefile([ 1800 \ 'call setline(1, "AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPP XXYYZZ")', 1801 \ 'hi Tblack ctermfg=0 ctermbg=8', 1802 \ 'hi Tdarkred ctermfg=1 ctermbg=9', 1803 \ 'hi Tdarkgreen ctermfg=2 ctermbg=10', 1804 \ 'hi Tbrown ctermfg=3 ctermbg=11', 1805 \ 'hi Tdarkblue ctermfg=4 ctermbg=12', 1806 \ 'hi Tdarkmagenta ctermfg=5 ctermbg=13', 1807 \ 'hi Tdarkcyan ctermfg=6 ctermbg=14', 1808 \ 'hi Tlightgrey ctermfg=7 ctermbg=15', 1809 \ 'hi Tdarkgrey ctermfg=8 ctermbg=0', 1810 \ 'hi Tred ctermfg=9 ctermbg=1', 1811 \ 'hi Tgreen ctermfg=10 ctermbg=2', 1812 \ 'hi Tyellow ctermfg=11 ctermbg=3', 1813 \ 'hi Tblue ctermfg=12 ctermbg=4', 1814 \ 'hi Tmagenta ctermfg=13 ctermbg=5', 1815 \ 'hi Tcyan ctermfg=14 ctermbg=6', 1816 \ 'hi Twhite ctermfg=15 ctermbg=7', 1817 \ 'hi TdarkredBold ctermfg=1 cterm=bold', 1818 \ 'hi TgreenBold ctermfg=10 cterm=bold', 1819 \ 'hi TmagentaBold ctermfg=13 cterm=bold ctermbg=5', 1820 \ '', 1821 \ 'call matchadd("Tblack", "A")', 1822 \ 'call matchadd("Tdarkred", "B")', 1823 \ 'call matchadd("Tdarkgreen", "C")', 1824 \ 'call matchadd("Tbrown", "D")', 1825 \ 'call matchadd("Tdarkblue", "E")', 1826 \ 'call matchadd("Tdarkmagenta", "F")', 1827 \ 'call matchadd("Tdarkcyan", "G")', 1828 \ 'call matchadd("Tlightgrey", "H")', 1829 \ 'call matchadd("Tdarkgrey", "I")', 1830 \ 'call matchadd("Tred", "J")', 1831 \ 'call matchadd("Tgreen", "K")', 1832 \ 'call matchadd("Tyellow", "L")', 1833 \ 'call matchadd("Tblue", "M")', 1834 \ 'call matchadd("Tmagenta", "N")', 1835 \ 'call matchadd("Tcyan", "O")', 1836 \ 'call matchadd("Twhite", "P")', 1837 \ 'call matchadd("TdarkredBold", "X")', 1838 \ 'call matchadd("TgreenBold", "Y")', 1839 \ 'call matchadd("TmagentaBold", "Z")', 1840 \ 'redraw', 1841 \ ], 'Xcolorscript') 1842 let buf = RunVimInTerminal('-S Xcolorscript', {'rows': 10}) 1843 call VerifyScreenDump(buf, 'Test_terminal_all_ansi_colors', {}) 1844 1845 call term_sendkeys(buf, ":q\<CR>") 1846 call StopVimInTerminal(buf) 1847 call delete('Xcolorscript') 1848endfunc 1849 1850 1851" vim: shiftwidth=2 sts=2 expandtab 1852