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