1" Tests for the terminal window. 2 3source check.vim 4CheckFeature terminal 5 6source shared.vim 7source screendump.vim 8 9let s:python = PythonProg() 10let $PROMPT_COMMAND='' 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': buf->term_getjob()}) 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 StopShellInTerminal(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_TerminalWinOpen() 72 au TerminalWinOpen * let b:done = 'yes' 73 let buf = Run_shell_in_terminal({}) 74 call assert_equal('yes', b:done) 75 call StopShellInTerminal(buf) 76 " closing window wipes out the terminal buffer with the finished job 77 close 78 79 if has("unix") 80 terminal ++hidden ++open sleep 1 81 sleep 1 82 call assert_fails("echo b:done", 'E121:') 83 endif 84 85 au! TerminalWinOpen 86endfunc 87 88func Test_terminal_make_change() 89 let buf = Run_shell_in_terminal({}) 90 call StopShellInTerminal(buf) 91 call term_wait(buf) 92 93 setlocal modifiable 94 exe "normal Axxx\<Esc>" 95 call assert_fails(buf . 'bwipe', 'E517') 96 undo 97 98 exe buf . 'bwipe' 99 unlet g:job 100endfunc 101 102func Test_terminal_paste_register() 103 let @" = "text to paste" 104 105 let buf = Run_shell_in_terminal({}) 106 " Wait for the shell to display a prompt 107 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 108 109 call feedkeys("echo \<C-W>\"\" \<C-W>\"=37 + 5\<CR>\<CR>", 'xt') 110 call WaitForAssert({-> assert_match("echo text to paste 42$", getline(1))}) 111 call WaitForAssert({-> assert_equal('text to paste 42', 2->getline())}) 112 113 exe buf . 'bwipe!' 114 unlet g:job 115endfunc 116 117func Test_terminal_wipe_buffer() 118 let buf = Run_shell_in_terminal({}) 119 call assert_fails(buf . 'bwipe', 'E517') 120 exe buf . 'bwipe!' 121 call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) 122 call assert_equal("", bufname(buf)) 123 124 unlet g:job 125endfunc 126 127func Test_terminal_split_quit() 128 let buf = Run_shell_in_terminal({}) 129 call term_wait(buf) 130 split 131 quit! 132 call term_wait(buf) 133 sleep 50m 134 call assert_equal('run', job_status(g:job)) 135 136 quit! 137 call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) 138 139 exe buf . 'bwipe' 140 unlet g:job 141endfunc 142 143func Test_terminal_hide_buffer() 144 let buf = Run_shell_in_terminal({}) 145 setlocal bufhidden=hide 146 quit 147 for nr in range(1, winnr('$')) 148 call assert_notequal(winbufnr(nr), buf) 149 endfor 150 call assert_true(bufloaded(buf)) 151 call assert_true(buflisted(buf)) 152 153 exe 'split ' . buf . 'buf' 154 call StopShellInTerminal(buf) 155 exe buf . 'bwipe' 156 157 unlet g:job 158endfunc 159 160func s:Nasty_exit_cb(job, st) 161 exe g:buf . 'bwipe!' 162 let g:buf = 0 163endfunc 164 165func Get_cat_123_cmd() 166 if has('win32') 167 if !has('conpty') 168 return 'cmd /c "cls && color 2 && echo 123"' 169 else 170 " When clearing twice, extra sequence is not output. 171 return 'cmd /c "cls && cls && color 2 && echo 123"' 172 endif 173 else 174 call writefile(["\<Esc>[32m123"], 'Xtext') 175 return "cat Xtext" 176 endif 177endfunc 178 179func Test_terminal_nasty_cb() 180 let cmd = Get_cat_123_cmd() 181 let g:buf = term_start(cmd, {'exit_cb': function('s:Nasty_exit_cb')}) 182 let g:job = term_getjob(g:buf) 183 184 call WaitForAssert({-> assert_equal("dead", job_status(g:job))}) 185 call WaitForAssert({-> assert_equal(0, g:buf)}) 186 unlet g:job 187 unlet g:buf 188 call delete('Xtext') 189endfunc 190 191func Check_123(buf) 192 let l = term_scrape(a:buf, 0) 193 call assert_true(len(l) == 0) 194 let l = term_scrape(a:buf, 999) 195 call assert_true(len(l) == 0) 196 let l = a:buf->term_scrape(1) 197 call assert_true(len(l) > 0) 198 call assert_equal('1', l[0].chars) 199 call assert_equal('2', l[1].chars) 200 call assert_equal('3', l[2].chars) 201 call assert_equal('#00e000', l[0].fg) 202 call assert_equal(0, term_getattr(l[0].attr, 'bold')) 203 call assert_equal(0, l[0].attr->term_getattr('italic')) 204 if has('win32') 205 " On Windows 'background' always defaults to dark, even though the terminal 206 " may use a light background. Therefore accept both white and black. 207 call assert_match('#ffffff\|#000000', l[0].bg) 208 else 209 if &background == 'light' 210 call assert_equal('#ffffff', l[0].bg) 211 else 212 call assert_equal('#000000', l[0].bg) 213 endif 214 endif 215 216 let l = term_getline(a:buf, -1) 217 call assert_equal('', l) 218 let l = term_getline(a:buf, 0) 219 call assert_equal('', l) 220 let l = term_getline(a:buf, 999) 221 call assert_equal('', l) 222 let l = term_getline(a:buf, 1) 223 call assert_equal('123', l) 224endfunc 225 226func Test_terminal_scrape_123() 227 let cmd = Get_cat_123_cmd() 228 let buf = term_start(cmd) 229 230 let termlist = term_list() 231 call assert_equal(1, len(termlist)) 232 call assert_equal(buf, termlist[0]) 233 234 " Nothing happens with invalid buffer number 235 call term_wait(1234) 236 237 call term_wait(buf) 238 " On MS-Windows we first get a startup message of two lines, wait for the 239 " "cls" to happen, after that we have one line with three characters. 240 call WaitForAssert({-> assert_equal(3, len(term_scrape(buf, 1)))}) 241 call Check_123(buf) 242 243 " Must still work after the job ended. 244 let job = term_getjob(buf) 245 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 246 call term_wait(buf) 247 call Check_123(buf) 248 249 exe buf . 'bwipe' 250 call delete('Xtext') 251endfunc 252 253func Test_terminal_scrape_multibyte() 254 call writefile(["léttまrs"], 'Xtext') 255 if has('win32') 256 " Run cmd with UTF-8 codepage to make the type command print the expected 257 " multibyte characters. 258 let buf = term_start("cmd /K chcp 65001") 259 call term_sendkeys(buf, "type Xtext\<CR>") 260 eval buf->term_sendkeys("exit\<CR>") 261 let line = 4 262 else 263 let buf = term_start("cat Xtext") 264 let line = 1 265 endif 266 267 call WaitFor({-> len(term_scrape(buf, line)) >= 7 && term_scrape(buf, line)[0].chars == "l"}) 268 let l = term_scrape(buf, line) 269 call assert_true(len(l) >= 7) 270 call assert_equal('l', l[0].chars) 271 call assert_equal('é', l[1].chars) 272 call assert_equal(1, l[1].width) 273 call assert_equal('t', l[2].chars) 274 call assert_equal('t', l[3].chars) 275 call assert_equal('ま', l[4].chars) 276 call assert_equal(2, l[4].width) 277 call assert_equal('r', l[5].chars) 278 call assert_equal('s', l[6].chars) 279 280 let job = term_getjob(buf) 281 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 282 call term_wait(buf) 283 284 exe buf . 'bwipe' 285 call delete('Xtext') 286endfunc 287 288func Test_terminal_scroll() 289 call writefile(range(1, 200), 'Xtext') 290 if has('win32') 291 let cmd = 'cmd /c "type Xtext"' 292 else 293 let cmd = "cat Xtext" 294 endif 295 let buf = term_start(cmd) 296 297 let job = term_getjob(buf) 298 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 299 call term_wait(buf) 300 if has('win32') 301 " TODO: this should not be needed 302 sleep 100m 303 endif 304 305 let scrolled = buf->term_getscrolled() 306 call assert_equal(scrolled, term_getscrolled(buf)) 307 call assert_equal('1', getline(1)) 308 call assert_equal('1', term_getline(buf, 1 - scrolled)) 309 call assert_equal('49', getline(49)) 310 call assert_equal('49', term_getline(buf, 49 - scrolled)) 311 call assert_equal('200', getline(200)) 312 call assert_equal('200', term_getline(buf, 200 - scrolled)) 313 314 exe buf . 'bwipe' 315 call delete('Xtext') 316endfunc 317 318func Test_terminal_scrollback() 319 let buf = Run_shell_in_terminal({'term_rows': 15}) 320 set termwinscroll=100 321 call writefile(range(150), 'Xtext') 322 if has('win32') 323 call term_sendkeys(buf, "type Xtext\<CR>") 324 else 325 call term_sendkeys(buf, "cat Xtext\<CR>") 326 endif 327 let rows = term_getsize(buf)[0] 328 " On MS-Windows there is an empty line, check both last line and above it. 329 call WaitForAssert({-> assert_match( '149', term_getline(buf, rows - 1) . term_getline(buf, rows - 2))}) 330 let lines = line('$') 331 call assert_inrange(91, 100, lines) 332 333 call StopShellInTerminal(buf) 334 call term_wait(buf) 335 exe buf . 'bwipe' 336 set termwinscroll& 337 call delete('Xtext') 338endfunc 339 340func Test_terminal_postponed_scrollback() 341 " tail -f only works on Unix 342 CheckUnix 343 344 call writefile(range(50), 'Xtext') 345 call writefile([ 346 \ 'set shell=/bin/sh noruler', 347 \ 'terminal', 348 \ 'sleep 200m', 349 \ 'call feedkeys("tail -n 100 -f Xtext\<CR>", "xt")', 350 \ 'sleep 100m', 351 \ 'call feedkeys("\<C-W>N", "xt")', 352 \ ], 'XTest_postponed') 353 let buf = RunVimInTerminal('-S XTest_postponed', {}) 354 " Check that the Xtext lines are displayed and in Terminal-Normal mode 355 call VerifyScreenDump(buf, 'Test_terminal_01', {}) 356 357 silent !echo 'one more line' >>Xtext 358 " Screen will not change, move cursor to get a different dump 359 call term_sendkeys(buf, "k") 360 call VerifyScreenDump(buf, 'Test_terminal_02', {}) 361 362 " Back to Terminal-Job mode, text will scroll and show the extra line. 363 call term_sendkeys(buf, "a") 364 call VerifyScreenDump(buf, 'Test_terminal_03', {}) 365 366 call term_wait(buf) 367 call term_sendkeys(buf, "\<C-C>") 368 call term_wait(buf) 369 call term_sendkeys(buf, "exit\<CR>") 370 call term_wait(buf) 371 call term_sendkeys(buf, ":q\<CR>") 372 call StopVimInTerminal(buf) 373 call delete('XTest_postponed') 374 call delete('Xtext') 375endfunc 376 377" Run diff on two dumps with different size. 378func Test_terminal_dumpdiff_size() 379 call assert_equal(1, winnr('$')) 380 call term_dumpdiff('dumps/Test_incsearch_search_01.dump', 'dumps/Test_popup_command_01.dump') 381 call assert_equal(2, winnr('$')) 382 call assert_match('Test_incsearch_search_01.dump', getline(10)) 383 call assert_match(' +++++$', getline(11)) 384 call assert_match('Test_popup_command_01.dump', getline(31)) 385 call assert_equal(repeat('+', 75), getline(30)) 386 quit 387endfunc 388 389func Test_terminal_size() 390 let cmd = Get_cat_123_cmd() 391 392 exe 'terminal ++rows=5 ' . cmd 393 let size = term_getsize('') 394 bwipe! 395 call assert_equal(5, size[0]) 396 397 call term_start(cmd, {'term_rows': 6}) 398 let size = term_getsize('') 399 bwipe! 400 call assert_equal(6, size[0]) 401 402 vsplit 403 exe 'terminal ++rows=5 ++cols=33 ' . cmd 404 call assert_equal([5, 33], ''->term_getsize()) 405 406 call term_setsize('', 6, 0) 407 call assert_equal([6, 33], term_getsize('')) 408 409 eval ''->term_setsize(0, 35) 410 call assert_equal([6, 35], term_getsize('')) 411 412 call term_setsize('', 7, 30) 413 call assert_equal([7, 30], term_getsize('')) 414 415 bwipe! 416 call assert_fails("call term_setsize('', 7, 30)", "E955:") 417 418 call term_start(cmd, {'term_rows': 6, 'term_cols': 36}) 419 let size = term_getsize('') 420 bwipe! 421 call assert_equal([6, 36], size) 422 423 exe 'vertical terminal ++cols=20 ' . cmd 424 let size = term_getsize('') 425 bwipe! 426 call assert_equal(20, size[1]) 427 428 eval cmd->term_start({'vertical': 1, 'term_cols': 26}) 429 let size = term_getsize('') 430 bwipe! 431 call assert_equal(26, size[1]) 432 433 split 434 exe 'vertical terminal ++rows=6 ++cols=20 ' . cmd 435 let size = term_getsize('') 436 bwipe! 437 call assert_equal([6, 20], size) 438 439 call term_start(cmd, {'vertical': 1, 'term_rows': 7, 'term_cols': 27}) 440 let size = term_getsize('') 441 bwipe! 442 call assert_equal([7, 27], size) 443 444 call delete('Xtext') 445endfunc 446 447func Test_terminal_curwin() 448 let cmd = Get_cat_123_cmd() 449 call assert_equal(1, winnr('$')) 450 451 split dummy 452 exe 'terminal ++curwin ' . cmd 453 call assert_equal(2, winnr('$')) 454 bwipe! 455 456 split dummy 457 call term_start(cmd, {'curwin': 1}) 458 call assert_equal(2, winnr('$')) 459 bwipe! 460 461 split dummy 462 call setline(1, 'change') 463 call assert_fails('terminal ++curwin ' . cmd, 'E37:') 464 call assert_equal(2, winnr('$')) 465 exe 'terminal! ++curwin ' . cmd 466 call assert_equal(2, winnr('$')) 467 bwipe! 468 469 split dummy 470 call setline(1, 'change') 471 call assert_fails("call term_start(cmd, {'curwin': 1})", 'E37:') 472 call assert_equal(2, winnr('$')) 473 bwipe! 474 475 split dummy 476 bwipe! 477 call delete('Xtext') 478endfunc 479 480func s:get_sleep_cmd() 481 if s:python != '' 482 let cmd = s:python . " test_short_sleep.py" 483 " 500 was not enough for Travis 484 let waittime = 900 485 else 486 echo 'This will take five seconds...' 487 let waittime = 2000 488 if has('win32') 489 let cmd = $windir . '\system32\timeout.exe 1' 490 else 491 let cmd = 'sleep 1' 492 endif 493 endif 494 return [cmd, waittime] 495endfunc 496 497func Test_terminal_finish_open_close() 498 call assert_equal(1, winnr('$')) 499 500 let [cmd, waittime] = s:get_sleep_cmd() 501 502 " shell terminal closes automatically 503 terminal 504 let buf = bufnr('%') 505 call assert_equal(2, winnr('$')) 506 " Wait for the shell to display a prompt 507 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 508 call StopShellInTerminal(buf) 509 call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime) 510 511 " shell terminal that does not close automatically 512 terminal ++noclose 513 let buf = bufnr('%') 514 call assert_equal(2, winnr('$')) 515 " Wait for the shell to display a prompt 516 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 517 call StopShellInTerminal(buf) 518 call assert_equal(2, winnr('$')) 519 quit 520 call assert_equal(1, winnr('$')) 521 522 exe 'terminal ++close ' . cmd 523 call assert_equal(2, winnr('$')) 524 wincmd p 525 call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime) 526 527 call term_start(cmd, {'term_finish': 'close'}) 528 call assert_equal(2, winnr('$')) 529 wincmd p 530 call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime) 531 call assert_equal(1, winnr('$')) 532 533 exe 'terminal ++open ' . cmd 534 close! 535 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 536 bwipe 537 538 call term_start(cmd, {'term_finish': 'open'}) 539 close! 540 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 541 bwipe 542 543 exe 'terminal ++hidden ++open ' . cmd 544 call assert_equal(1, winnr('$')) 545 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 546 bwipe 547 548 call term_start(cmd, {'term_finish': 'open', 'hidden': 1}) 549 call assert_equal(1, winnr('$')) 550 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 551 bwipe 552 553 call assert_fails("call term_start(cmd, {'term_opencmd': 'open'})", 'E475:') 554 call assert_fails("call term_start(cmd, {'term_opencmd': 'split %x'})", 'E475:') 555 call assert_fails("call term_start(cmd, {'term_opencmd': 'split %d and %s'})", 'E475:') 556 call assert_fails("call term_start(cmd, {'term_opencmd': 'split % and %d'})", 'E475:') 557 558 call term_start(cmd, {'term_finish': 'open', 'term_opencmd': '4split | buffer %d'}) 559 close! 560 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 561 call assert_equal(4, winheight(0)) 562 bwipe 563endfunc 564 565func Test_terminal_cwd() 566 if has('win32') 567 let cmd = 'cmd /c cd' 568 else 569 CheckExecutable pwd 570 let cmd = 'pwd' 571 endif 572 call mkdir('Xdir') 573 let buf = term_start(cmd, {'cwd': 'Xdir'}) 574 call WaitForAssert({-> assert_equal('Xdir', fnamemodify(getline(1), ":t"))}) 575 576 exe buf . 'bwipe' 577 call delete('Xdir', 'rf') 578endfunc 579 580func Test_terminal_cwd_failure() 581 " Case 1: Provided directory is not actually a directory. Attempt to make 582 " the file executable as well. 583 call writefile([], 'Xfile') 584 call setfperm('Xfile', 'rwx------') 585 call assert_fails("call term_start(&shell, {'cwd': 'Xfile'})", 'E475:') 586 call delete('Xfile') 587 588 " Case 2: Directory does not exist. 589 call assert_fails("call term_start(&shell, {'cwd': 'Xdir'})", 'E475:') 590 591 " Case 3: Directory exists but is not accessible. 592 " Skip this for root, it will be accessible anyway. 593 if !IsRoot() 594 call mkdir('XdirNoAccess', '', '0600') 595 " return early if the directory permissions could not be set properly 596 if getfperm('XdirNoAccess')[2] == 'x' 597 call delete('XdirNoAccess', 'rf') 598 return 599 endif 600 call assert_fails("call term_start(&shell, {'cwd': 'XdirNoAccess'})", 'E475:') 601 call delete('XdirNoAccess', 'rf') 602 endif 603endfunc 604 605func Test_terminal_servername() 606 if !has('clientserver') 607 return 608 endif 609 call s:test_environment("VIM_SERVERNAME", v:servername) 610endfunc 611 612func Test_terminal_version() 613 call s:test_environment("VIM_TERMINAL", string(v:version)) 614endfunc 615 616func s:test_environment(name, value) 617 let buf = Run_shell_in_terminal({}) 618 " Wait for the shell to display a prompt 619 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 620 if has('win32') 621 call term_sendkeys(buf, "echo %" . a:name . "%\r") 622 else 623 call term_sendkeys(buf, "echo $" . a:name . "\r") 624 endif 625 call term_wait(buf) 626 call StopShellInTerminal(buf) 627 call WaitForAssert({-> assert_equal(a:value, getline(2))}) 628 629 exe buf . 'bwipe' 630 unlet buf 631endfunc 632 633func Test_terminal_env() 634 let buf = Run_shell_in_terminal({'env': {'TESTENV': 'correct'}}) 635 " Wait for the shell to display a prompt 636 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 637 if has('win32') 638 call term_sendkeys(buf, "echo %TESTENV%\r") 639 else 640 call term_sendkeys(buf, "echo $TESTENV\r") 641 endif 642 eval buf->term_wait() 643 call StopShellInTerminal(buf) 644 call WaitForAssert({-> assert_equal('correct', getline(2))}) 645 646 exe buf . 'bwipe' 647endfunc 648 649func Test_terminal_list_args() 650 let buf = term_start([&shell, &shellcmdflag, 'echo "123"']) 651 call assert_fails(buf . 'bwipe', 'E517') 652 exe buf . 'bwipe!' 653 call assert_equal("", bufname(buf)) 654endfunction 655 656func Test_terminal_noblock() 657 let buf = term_start(&shell) 658 if has('bsd') || has('mac') || has('sun') 659 " The shell or something else has a problem dealing with more than 1000 660 " characters at the same time. 661 let len = 1000 662 " NPFS is used in Windows, nonblocking mode does not work properly. 663 elseif has('win32') 664 let len = 1 665 else 666 let len = 5000 667 endif 668 669 for c in ['a','b','c','d','e','f','g','h','i','j','k'] 670 call term_sendkeys(buf, 'echo ' . repeat(c, len) . "\<cr>") 671 endfor 672 call term_sendkeys(buf, "echo done\<cr>") 673 674 " On MS-Windows there is an extra empty line below "done". Find "done" in 675 " the last-but-one or the last-but-two line. 676 let lnum = term_getsize(buf)[0] - 1 677 call WaitFor({-> term_getline(buf, lnum) =~ "done" || term_getline(buf, lnum - 1) =~ "done"}, 10000) 678 let line = term_getline(buf, lnum) 679 if line !~ 'done' 680 let line = term_getline(buf, lnum - 1) 681 endif 682 call assert_match('done', line) 683 684 let g:job = term_getjob(buf) 685 call StopShellInTerminal(buf) 686 call term_wait(buf) 687 unlet g:job 688 bwipe 689endfunc 690 691func Test_terminal_write_stdin() 692 " TODO: enable once writing to stdin works on MS-Windows 693 CheckNotMSWindows 694 CheckExecutable wc 695 696 call setline(1, ['one', 'two', 'three']) 697 %term wc 698 call WaitForAssert({-> assert_match('3', getline("$"))}) 699 let nrs = split(getline('$')) 700 call assert_equal(['3', '3', '14'], nrs) 701 %bwipe! 702 703 call setline(1, ['one', 'two', 'three', 'four']) 704 2,3term wc 705 call WaitForAssert({-> assert_match('2', getline("$"))}) 706 let nrs = split(getline('$')) 707 call assert_equal(['2', '2', '10'], nrs) 708 %bwipe! 709endfunc 710 711func Test_terminal_eof_arg() 712 CheckExecutable python 713 714 call setline(1, ['print("hello")']) 715 1term ++eof=exit(123) python 716 " MS-Windows echoes the input, Unix doesn't. 717 if has('win32') 718 call WaitFor({-> getline('$') =~ 'exit(123)'}) 719 call assert_equal('hello', getline(line('$') - 1)) 720 else 721 call WaitFor({-> getline('$') =~ 'hello'}) 722 call assert_equal('hello', getline('$')) 723 endif 724 call assert_equal(123, bufnr()->term_getjob()->job_info().exitval) 725 %bwipe! 726endfunc 727 728func Test_terminal_eof_arg_win32_ctrl_z() 729 CheckMSWindows 730 CheckExecutable python 731 732 call setline(1, ['print("hello")']) 733 1term ++eof=<C-Z> python 734 call WaitForAssert({-> assert_match('\^Z', getline(line('$') - 1))}) 735 call assert_match('\^Z', getline(line('$') - 1)) 736 %bwipe! 737endfunc 738 739func Test_terminal_duplicate_eof_arg() 740 CheckExecutable python 741 742 " Check the last specified ++eof arg is used and should not memory leak. 743 new 744 call setline(1, ['print("hello")']) 745 1term ++eof=<C-Z> ++eof=exit(123) python 746 " MS-Windows echoes the input, Unix doesn't. 747 if has('win32') 748 call WaitFor({-> getline('$') =~ 'exit(123)'}) 749 call assert_equal('hello', getline(line('$') - 1)) 750 else 751 call WaitFor({-> getline('$') =~ 'hello'}) 752 call assert_equal('hello', getline('$')) 753 endif 754 call assert_equal(123, bufnr()->term_getjob()->job_info().exitval) 755 %bwipe! 756endfunc 757 758func Test_terminal_no_cmd() 759 let buf = term_start('NONE', {}) 760 call assert_notequal(0, buf) 761 762 let pty = job_info(term_getjob(buf))['tty_out'] 763 call assert_notequal('', pty) 764 if has('gui_running') && !has('win32') 765 " In the GUI job_start() doesn't work, it does not read from the pty. 766 call system('echo "look here" > ' . pty) 767 else 768 " Otherwise using a job works on all systems. 769 call job_start([&shell, &shellcmdflag, 'echo "look here" > ' . pty]) 770 endif 771 call WaitForAssert({-> assert_match('look here', term_getline(buf, 1))}) 772 773 bwipe! 774endfunc 775 776func Test_terminal_special_chars() 777 " this file name only works on Unix 778 CheckUnix 779 780 call mkdir('Xdir with spaces') 781 call writefile(['x'], 'Xdir with spaces/quoted"file') 782 term ls Xdir\ with\ spaces/quoted\"file 783 call WaitForAssert({-> assert_match('quoted"file', term_getline('', 1))}) 784 call term_wait('') 785 786 call delete('Xdir with spaces', 'rf') 787 bwipe 788endfunc 789 790func Test_terminal_wrong_options() 791 call assert_fails('call term_start(&shell, { 792 \ "in_io": "file", 793 \ "in_name": "xxx", 794 \ "out_io": "file", 795 \ "out_name": "xxx", 796 \ "err_io": "file", 797 \ "err_name": "xxx" 798 \ })', 'E474:') 799 call assert_fails('call term_start(&shell, { 800 \ "out_buf": bufnr("%") 801 \ })', 'E474:') 802 call assert_fails('call term_start(&shell, { 803 \ "err_buf": bufnr("%") 804 \ })', 'E474:') 805endfunc 806 807func Test_terminal_redir_file() 808 let cmd = Get_cat_123_cmd() 809 let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'}) 810 call term_wait(buf) 811 " ConPTY may precede escape sequence. There are things that are not so. 812 if !has('conpty') 813 call WaitForAssert({-> assert_notequal(0, len(readfile("Xfile")))}) 814 call assert_match('123', readfile('Xfile')[0]) 815 endif 816 let g:job = term_getjob(buf) 817 call WaitForAssert({-> assert_equal("dead", job_status(g:job))}) 818 call delete('Xfile') 819 bwipe 820 821 if has('unix') 822 call writefile(['one line'], 'Xfile') 823 let buf = term_start('cat', {'in_io': 'file', 'in_name': 'Xfile'}) 824 call term_wait(buf) 825 call WaitForAssert({-> assert_equal('one line', term_getline(buf, 1))}) 826 let g:job = term_getjob(buf) 827 call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) 828 bwipe 829 call delete('Xfile') 830 endif 831endfunc 832 833func TerminalTmap(remap) 834 let buf = Run_shell_in_terminal({}) 835 call assert_equal('t', mode()) 836 837 if a:remap 838 tmap 123 456 839 else 840 tnoremap 123 456 841 endif 842 " don't use abcde, it's an existing command 843 tmap 456 abxde 844 call assert_equal('456', maparg('123', 't')) 845 call assert_equal('abxde', maparg('456', 't')) 846 call feedkeys("123", 'tx') 847 call WaitForAssert({-> assert_match('abxde\|456', term_getline(buf, term_getcursor(buf)[0]))}) 848 let lnum = term_getcursor(buf)[0] 849 if a:remap 850 call assert_match('abxde', term_getline(buf, lnum)) 851 else 852 call assert_match('456', term_getline(buf, lnum)) 853 endif 854 855 call term_sendkeys(buf, "\r") 856 call StopShellInTerminal(buf) 857 call term_wait(buf) 858 859 tunmap 123 860 tunmap 456 861 call assert_equal('', maparg('123', 't')) 862 close 863 unlet g:job 864endfunc 865 866func Test_terminal_tmap() 867 call TerminalTmap(1) 868 call TerminalTmap(0) 869endfunc 870 871func Test_terminal_wall() 872 let buf = Run_shell_in_terminal({}) 873 wall 874 call StopShellInTerminal(buf) 875 call term_wait(buf) 876 exe buf . 'bwipe' 877 unlet g:job 878endfunc 879 880func Test_terminal_wqall() 881 let buf = Run_shell_in_terminal({}) 882 call assert_fails('wqall', 'E948') 883 call StopShellInTerminal(buf) 884 call term_wait(buf) 885 exe buf . 'bwipe' 886 unlet g:job 887endfunc 888 889func Test_terminal_composing_unicode() 890 CheckNotBSD 891 let save_enc = &encoding 892 set encoding=utf-8 893 894 if has('win32') 895 let cmd = "cmd /K chcp 65001" 896 let lnum = [3, 6, 9] 897 else 898 let cmd = &shell 899 let lnum = [1, 3, 5] 900 endif 901 902 enew 903 let buf = term_start(cmd, {'curwin': bufnr('')}) 904 let g:job = term_getjob(buf) 905 call term_wait(buf, 50) 906 907 if has('win32') 908 call assert_equal('cmd', job_info(g:job).cmd[0]) 909 else 910 call assert_equal(&shell, job_info(g:job).cmd[0]) 911 endif 912 913 " ascii + composing 914 let txt = "a\u0308bc" 915 call term_sendkeys(buf, "echo " . txt . "\r") 916 call term_wait(buf, 50) 917 call assert_match("echo " . txt, term_getline(buf, lnum[0])) 918 call assert_equal(txt, term_getline(buf, lnum[0] + 1)) 919 let l = term_scrape(buf, lnum[0] + 1) 920 call assert_equal("a\u0308", l[0].chars) 921 call assert_equal("b", l[1].chars) 922 call assert_equal("c", l[2].chars) 923 924 " multibyte + composing 925 let txt = "\u304b\u3099\u304e\u304f\u3099\u3052\u3053\u3099" 926 call term_sendkeys(buf, "echo " . txt . "\r") 927 call term_wait(buf, 50) 928 call assert_match("echo " . txt, term_getline(buf, lnum[1])) 929 call assert_equal(txt, term_getline(buf, lnum[1] + 1)) 930 let l = term_scrape(buf, lnum[1] + 1) 931 call assert_equal("\u304b\u3099", l[0].chars) 932 call assert_equal("\u304e", l[1].chars) 933 call assert_equal("\u304f\u3099", l[2].chars) 934 call assert_equal("\u3052", l[3].chars) 935 call assert_equal("\u3053\u3099", l[4].chars) 936 937 " \u00a0 + composing 938 let txt = "abc\u00a0\u0308" 939 call term_sendkeys(buf, "echo " . txt . "\r") 940 call term_wait(buf, 50) 941 call assert_match("echo " . txt, term_getline(buf, lnum[2])) 942 call assert_equal(txt, term_getline(buf, lnum[2] + 1)) 943 let l = term_scrape(buf, lnum[2] + 1) 944 call assert_equal("\u00a0\u0308", l[3].chars) 945 946 call term_sendkeys(buf, "exit\r") 947 call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) 948 bwipe! 949 unlet g:job 950 let &encoding = save_enc 951endfunc 952 953func Test_terminal_aucmd_on_close() 954 fun Nop() 955 let s:called = 1 956 endfun 957 958 aug repro 959 au! 960 au BufWinLeave * call Nop() 961 aug END 962 963 let [cmd, waittime] = s:get_sleep_cmd() 964 965 call assert_equal(1, winnr('$')) 966 new 967 call setline(1, ['one', 'two']) 968 exe 'term ++close ' . cmd 969 wincmd p 970 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 971 call assert_equal(1, s:called) 972 bwipe! 973 974 unlet s:called 975 au! repro 976 delfunc Nop 977endfunc 978 979func Test_terminal_term_start_empty_command() 980 let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})" 981 call assert_fails(cmd, 'E474') 982 let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})" 983 call assert_fails(cmd, 'E474') 984 let cmd = "call term_start({}, {'curwin' : 1, 'term_finish' : 'close'})" 985 call assert_fails(cmd, 'E474') 986 let cmd = "call term_start(0, {'curwin' : 1, 'term_finish' : 'close'})" 987 call assert_fails(cmd, 'E474') 988endfunc 989 990func Test_terminal_response_to_control_sequence() 991 CheckUnix 992 993 let buf = Run_shell_in_terminal({}) 994 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 995 996 call term_sendkeys(buf, "cat\<CR>") 997 call WaitForAssert({-> assert_match('cat', term_getline(buf, 1))}) 998 999 " Request the cursor position. 1000 call term_sendkeys(buf, "\x1b[6n\<CR>") 1001 1002 " Wait for output from tty to display, below an empty line. 1003 call WaitForAssert({-> assert_match('3;1R', term_getline(buf, 4))}) 1004 1005 " End "cat" gently. 1006 call term_sendkeys(buf, "\<CR>\<C-D>") 1007 1008 call StopShellInTerminal(buf) 1009 exe buf . 'bwipe' 1010 unlet g:job 1011endfunc 1012 1013" Run Vim, start a terminal in that Vim with the kill argument, 1014" :qall works. 1015func Run_terminal_qall_kill(line1, line2) 1016 " 1. Open a terminal window and wait for the prompt to appear 1017 " 2. set kill using term_setkill() 1018 " 3. make Vim exit, it will kill the shell 1019 let after = [ 1020 \ a:line1, 1021 \ 'let buf = bufnr("%")', 1022 \ 'while term_getline(buf, 1) =~ "^\\s*$"', 1023 \ ' sleep 10m', 1024 \ 'endwhile', 1025 \ a:line2, 1026 \ 'au VimLeavePre * call writefile(["done"], "Xdone")', 1027 \ 'qall', 1028 \ ] 1029 if !RunVim([], after, '') 1030 return 1031 endif 1032 call assert_equal("done", readfile("Xdone")[0]) 1033 call delete("Xdone") 1034endfunc 1035 1036" Run Vim in a terminal, then start a terminal in that Vim with a kill 1037" argument, check that :qall works. 1038func Test_terminal_qall_kill_arg() 1039 call Run_terminal_qall_kill('term ++kill=kill', '') 1040endfunc 1041 1042" Run Vim, start a terminal in that Vim, set the kill argument with 1043" term_setkill(), check that :qall works. 1044func Test_terminal_qall_kill_func() 1045 call Run_terminal_qall_kill('term', 'eval buf->term_setkill("kill")') 1046endfunc 1047 1048" Run Vim, start a terminal in that Vim without the kill argument, 1049" check that :qall does not exit, :qall! does. 1050func Test_terminal_qall_exit() 1051 let after =<< trim [CODE] 1052 term 1053 let buf = bufnr("%") 1054 while term_getline(buf, 1) =~ "^\\s*$" 1055 sleep 10m 1056 endwhile 1057 set nomore 1058 au VimLeavePre * call writefile(["too early"], "Xdone") 1059 qall 1060 au! VimLeavePre * exe buf . "bwipe!" | call writefile(["done"], "Xdone") 1061 cquit 1062 [CODE] 1063 1064 if !RunVim([], after, '') 1065 return 1066 endif 1067 call assert_equal("done", readfile("Xdone")[0]) 1068 call delete("Xdone") 1069endfunc 1070 1071" Run Vim in a terminal, then start a terminal in that Vim without a kill 1072" argument, check that :confirm qall works. 1073func Test_terminal_qall_prompt() 1074 CheckRunVimInTerminal 1075 let buf = RunVimInTerminal('', {}) 1076 1077 " Open a terminal window and wait for the prompt to appear 1078 call term_sendkeys(buf, ":term\<CR>") 1079 call WaitForAssert({-> assert_match('\[running]', term_getline(buf, 10))}) 1080 call WaitForAssert({-> assert_notmatch('^\s*$', term_getline(buf, 1))}) 1081 1082 " make Vim exit, it will prompt to kill the shell 1083 call term_sendkeys(buf, "\<C-W>:confirm qall\<CR>") 1084 call WaitForAssert({-> assert_match('ancel:', term_getline(buf, 20))}) 1085 call term_sendkeys(buf, "y") 1086 call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))}) 1087 1088 " close the terminal window where Vim was running 1089 quit 1090endfunc 1091 1092" Run Vim in a terminal, then start a terminal window with a shell and check 1093" that Vim exits if it is closed. 1094func Test_terminal_exit() 1095 CheckRunVimInTerminal 1096 1097 let lines =<< trim END 1098 let winid = win_getid() 1099 help 1100 term 1101 let termid = win_getid() 1102 call win_gotoid(winid) 1103 close 1104 call win_gotoid(termid) 1105 END 1106 call writefile(lines, 'XtermExit') 1107 let buf = RunVimInTerminal('-S XtermExit', #{rows: 10}) 1108 let job = term_getjob(buf) 1109 call WaitForAssert({-> assert_equal("run", job_status(job))}) 1110 1111 " quit the shell, it will make Vim exit 1112 call term_sendkeys(buf, "exit\<CR>") 1113 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 1114 1115 call delete('XtermExit') 1116endfunc 1117 1118func Test_terminal_open_autocmd() 1119 augroup repro 1120 au! 1121 au TerminalOpen * let s:called += 1 1122 augroup END 1123 1124 let s:called = 0 1125 1126 " Open a terminal window with :terminal 1127 terminal 1128 call assert_equal(1, s:called) 1129 bwipe! 1130 1131 " Open a terminal window with term_start() 1132 call term_start(&shell) 1133 call assert_equal(2, s:called) 1134 bwipe! 1135 1136 " Open a hidden terminal buffer with :terminal 1137 terminal ++hidden 1138 call assert_equal(3, s:called) 1139 for buf in term_list() 1140 exe buf . "bwipe!" 1141 endfor 1142 1143 " Open a hidden terminal buffer with term_start() 1144 let buf = term_start(&shell, {'hidden': 1}) 1145 call assert_equal(4, s:called) 1146 exe buf . "bwipe!" 1147 1148 unlet s:called 1149 au! repro 1150endfunction 1151 1152func Check_dump01(off) 1153 call assert_equal('one two three four five', trim(getline(a:off + 1))) 1154 call assert_equal('~ Select Word', trim(getline(a:off + 7))) 1155 call assert_equal(':popup PopUp', trim(getline(a:off + 20))) 1156endfunc 1157 1158func Test_terminal_dumpwrite_composing() 1159 CheckRunVimInTerminal 1160 let save_enc = &encoding 1161 set encoding=utf-8 1162 call assert_equal(1, winnr('$')) 1163 1164 let text = " a\u0300 e\u0302 o\u0308" 1165 call writefile([text], 'Xcomposing') 1166 let buf = RunVimInTerminal('--cmd "set encoding=utf-8" Xcomposing', {}) 1167 call WaitForAssert({-> assert_match(text, term_getline(buf, 1))}) 1168 eval 'Xdump'->term_dumpwrite(buf) 1169 let dumpline = readfile('Xdump')[0] 1170 call assert_match('|à| |ê| |ö', dumpline) 1171 1172 call StopVimInTerminal(buf) 1173 call delete('Xcomposing') 1174 call delete('Xdump') 1175 let &encoding = save_enc 1176endfunc 1177 1178" just testing basic functionality. 1179func Test_terminal_dumpload() 1180 let curbuf = winbufnr('') 1181 call assert_equal(1, winnr('$')) 1182 let buf = term_dumpload('dumps/Test_popup_command_01.dump') 1183 call assert_equal(2, winnr('$')) 1184 call assert_equal(20, line('$')) 1185 call Check_dump01(0) 1186 1187 " Load another dump in the same window 1188 let buf2 = 'dumps/Test_diff_01.dump'->term_dumpload({'bufnr': buf}) 1189 call assert_equal(buf, buf2) 1190 call assert_notequal('one two three four five', trim(getline(1))) 1191 1192 " Load the first dump again in the same window 1193 let buf2 = term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': buf}) 1194 call assert_equal(buf, buf2) 1195 call Check_dump01(0) 1196 1197 call assert_fails("call term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': curbuf})", 'E475:') 1198 call assert_fails("call term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': 9999})", 'E86:') 1199 new 1200 let closedbuf = winbufnr('') 1201 quit 1202 call assert_fails("call term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': closedbuf})", 'E475:') 1203 1204 quit 1205endfunc 1206 1207func Test_terminal_dumpload_dump() 1208 CheckRunVimInTerminal 1209 1210 let lines =<< trim END 1211 call term_dumpload('dumps/Test_popupwin_22.dump', #{term_rows: 12}) 1212 END 1213 call writefile(lines, 'XtermDumpload') 1214 let buf = RunVimInTerminal('-S XtermDumpload', #{rows: 15}) 1215 call VerifyScreenDump(buf, 'Test_terminal_dumpload', {}) 1216 1217 call StopVimInTerminal(buf) 1218 call delete('XtermDumpload') 1219endfunc 1220 1221func Test_terminal_dumpdiff() 1222 call assert_equal(1, winnr('$')) 1223 eval 'dumps/Test_popup_command_01.dump'->term_dumpdiff('dumps/Test_popup_command_02.dump') 1224 call assert_equal(2, winnr('$')) 1225 call assert_equal(62, line('$')) 1226 call Check_dump01(0) 1227 call Check_dump01(42) 1228 call assert_equal(' bbbbbbbbbbbbbbbbbb ', getline(26)[0:29]) 1229 quit 1230endfunc 1231 1232func Test_terminal_dumpdiff_swap() 1233 call assert_equal(1, winnr('$')) 1234 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_03.dump') 1235 call assert_equal(2, winnr('$')) 1236 call assert_equal(62, line('$')) 1237 call assert_match('Test_popup_command_01.dump', getline(21)) 1238 call assert_match('Test_popup_command_03.dump', getline(42)) 1239 call assert_match('Undo', getline(3)) 1240 call assert_match('three four five', getline(45)) 1241 1242 normal s 1243 call assert_match('Test_popup_command_03.dump', getline(21)) 1244 call assert_match('Test_popup_command_01.dump', getline(42)) 1245 call assert_match('three four five', getline(3)) 1246 call assert_match('Undo', getline(45)) 1247 quit 1248endfunc 1249 1250func Test_terminal_dumpdiff_options() 1251 set laststatus=0 1252 call assert_equal(1, winnr('$')) 1253 let height = winheight(0) 1254 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 1, 'term_cols': 33}) 1255 call assert_equal(2, winnr('$')) 1256 call assert_equal(height, winheight(winnr())) 1257 call assert_equal(33, winwidth(winnr())) 1258 call assert_equal('dump diff dumps/Test_popup_command_01.dump', bufname('%')) 1259 quit 1260 1261 call assert_equal(1, winnr('$')) 1262 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 0, 'term_rows': 13, 'term_name': 'something else'}) 1263 call assert_equal(2, winnr('$')) 1264 call assert_equal(&columns, winwidth(0)) 1265 call assert_equal(13, winheight(0)) 1266 call assert_equal('something else', bufname('%')) 1267 quit 1268 1269 call assert_equal(1, winnr('$')) 1270 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'curwin': 1}) 1271 call assert_equal(1, winnr('$')) 1272 bwipe 1273 1274 set laststatus& 1275endfunc 1276 1277func Api_drop_common(options) 1278 call assert_equal(1, winnr('$')) 1279 1280 " Use the title termcap entries to output the escape sequence. 1281 call writefile([ 1282 \ 'set title', 1283 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1284 \ 'let &titlestring = ''["drop","Xtextfile"' . a:options . ']''', 1285 \ 'redraw', 1286 \ "set t_ts=", 1287 \ ], 'Xscript') 1288 let buf = RunVimInTerminal('-S Xscript', {}) 1289 call WaitFor({-> bufnr('Xtextfile') > 0}) 1290 call assert_equal('Xtextfile', expand('%:t')) 1291 call assert_true(winnr('$') >= 3) 1292 return buf 1293endfunc 1294 1295func Test_terminal_api_drop_newwin() 1296 CheckRunVimInTerminal 1297 let buf = Api_drop_common('') 1298 call assert_equal(0, &bin) 1299 call assert_equal('', &fenc) 1300 1301 call StopVimInTerminal(buf) 1302 call delete('Xscript') 1303 bwipe Xtextfile 1304endfunc 1305 1306func Test_terminal_api_drop_newwin_bin() 1307 CheckRunVimInTerminal 1308 let buf = Api_drop_common(',{"bin":1}') 1309 call assert_equal(1, &bin) 1310 1311 call StopVimInTerminal(buf) 1312 call delete('Xscript') 1313 bwipe Xtextfile 1314endfunc 1315 1316func Test_terminal_api_drop_newwin_binary() 1317 CheckRunVimInTerminal 1318 let buf = Api_drop_common(',{"binary":1}') 1319 call assert_equal(1, &bin) 1320 1321 call StopVimInTerminal(buf) 1322 call delete('Xscript') 1323 bwipe Xtextfile 1324endfunc 1325 1326func Test_terminal_api_drop_newwin_nobin() 1327 CheckRunVimInTerminal 1328 set binary 1329 let buf = Api_drop_common(',{"nobin":1}') 1330 call assert_equal(0, &bin) 1331 1332 call StopVimInTerminal(buf) 1333 call delete('Xscript') 1334 bwipe Xtextfile 1335 set nobinary 1336endfunc 1337 1338func Test_terminal_api_drop_newwin_nobinary() 1339 CheckRunVimInTerminal 1340 set binary 1341 let buf = Api_drop_common(',{"nobinary":1}') 1342 call assert_equal(0, &bin) 1343 1344 call StopVimInTerminal(buf) 1345 call delete('Xscript') 1346 bwipe Xtextfile 1347 set nobinary 1348endfunc 1349 1350func Test_terminal_api_drop_newwin_ff() 1351 CheckRunVimInTerminal 1352 let buf = Api_drop_common(',{"ff":"dos"}') 1353 call assert_equal("dos", &ff) 1354 1355 call StopVimInTerminal(buf) 1356 call delete('Xscript') 1357 bwipe Xtextfile 1358endfunc 1359 1360func Test_terminal_api_drop_newwin_fileformat() 1361 CheckRunVimInTerminal 1362 let buf = Api_drop_common(',{"fileformat":"dos"}') 1363 call assert_equal("dos", &ff) 1364 1365 call StopVimInTerminal(buf) 1366 call delete('Xscript') 1367 bwipe Xtextfile 1368endfunc 1369 1370func Test_terminal_api_drop_newwin_enc() 1371 CheckRunVimInTerminal 1372 let buf = Api_drop_common(',{"enc":"utf-16"}') 1373 call assert_equal("utf-16", &fenc) 1374 1375 call StopVimInTerminal(buf) 1376 call delete('Xscript') 1377 bwipe Xtextfile 1378endfunc 1379 1380func Test_terminal_api_drop_newwin_encoding() 1381 CheckRunVimInTerminal 1382 let buf = Api_drop_common(',{"encoding":"utf-16"}') 1383 call assert_equal("utf-16", &fenc) 1384 1385 call StopVimInTerminal(buf) 1386 call delete('Xscript') 1387 bwipe Xtextfile 1388endfunc 1389 1390func Test_terminal_api_drop_oldwin() 1391 CheckRunVimInTerminal 1392 let firstwinid = win_getid() 1393 split Xtextfile 1394 let textfile_winid = win_getid() 1395 call assert_equal(2, winnr('$')) 1396 call win_gotoid(firstwinid) 1397 1398 " Use the title termcap entries to output the escape sequence. 1399 call writefile([ 1400 \ 'set title', 1401 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1402 \ 'let &titlestring = ''["drop","Xtextfile"]''', 1403 \ 'redraw', 1404 \ "set t_ts=", 1405 \ ], 'Xscript') 1406 let buf = RunVimInTerminal('-S Xscript', {'rows': 10}) 1407 call WaitForAssert({-> assert_equal('Xtextfile', expand('%:t'))}) 1408 call assert_equal(textfile_winid, win_getid()) 1409 1410 call StopVimInTerminal(buf) 1411 call delete('Xscript') 1412 bwipe Xtextfile 1413endfunc 1414 1415func Tapi_TryThis(bufnum, arg) 1416 let g:called_bufnum = a:bufnum 1417 let g:called_arg = a:arg 1418endfunc 1419 1420func WriteApiCall(funcname) 1421 " Use the title termcap entries to output the escape sequence. 1422 call writefile([ 1423 \ 'set title', 1424 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1425 \ 'let &titlestring = ''["call","' . a:funcname . '",["hello",123]]''', 1426 \ 'redraw', 1427 \ "set t_ts=", 1428 \ ], 'Xscript') 1429endfunc 1430 1431func Test_terminal_api_call() 1432 CheckRunVimInTerminal 1433 1434 unlet! g:called_bufnum 1435 unlet! g:called_arg 1436 1437 call WriteApiCall('Tapi_TryThis') 1438 1439 " Default 1440 let buf = RunVimInTerminal('-S Xscript', {}) 1441 call WaitFor({-> exists('g:called_bufnum')}) 1442 call assert_equal(buf, g:called_bufnum) 1443 call assert_equal(['hello', 123], g:called_arg) 1444 call StopVimInTerminal(buf) 1445 1446 unlet! g:called_bufnum 1447 unlet! g:called_arg 1448 1449 " Enable explicitly 1450 let buf = RunVimInTerminal('-S Xscript', {'term_api': 'Tapi_Try'}) 1451 call WaitFor({-> exists('g:called_bufnum')}) 1452 call assert_equal(buf, g:called_bufnum) 1453 call assert_equal(['hello', 123], g:called_arg) 1454 call StopVimInTerminal(buf) 1455 1456 unlet! g:called_bufnum 1457 unlet! g:called_arg 1458 1459 func! ApiCall_TryThis(bufnum, arg) 1460 let g:called_bufnum2 = a:bufnum 1461 let g:called_arg2 = a:arg 1462 endfunc 1463 1464 call WriteApiCall('ApiCall_TryThis') 1465 1466 " Use prefix match 1467 let buf = RunVimInTerminal('-S Xscript', {'term_api': 'ApiCall_'}) 1468 call WaitFor({-> exists('g:called_bufnum2')}) 1469 call assert_equal(buf, g:called_bufnum2) 1470 call assert_equal(['hello', 123], g:called_arg2) 1471 call StopVimInTerminal(buf) 1472 1473 unlet! g:called_bufnum2 1474 unlet! g:called_arg2 1475 1476 call delete('Xscript') 1477 delfunction! ApiCall_TryThis 1478 unlet! g:called_bufnum2 1479 unlet! g:called_arg2 1480endfunc 1481 1482func Test_terminal_api_call_fails() 1483 CheckRunVimInTerminal 1484 1485 func! TryThis(bufnum, arg) 1486 let g:called_bufnum3 = a:bufnum 1487 let g:called_arg3 = a:arg 1488 endfunc 1489 1490 call WriteApiCall('TryThis') 1491 1492 unlet! g:called_bufnum3 1493 unlet! g:called_arg3 1494 1495 " Not permitted 1496 call ch_logfile('Xlog', 'w') 1497 let buf = RunVimInTerminal('-S Xscript', {'term_api': ''}) 1498 call WaitForAssert({-> assert_match('Unpermitted function: TryThis', string(readfile('Xlog')))}) 1499 call assert_false(exists('g:called_bufnum3')) 1500 call assert_false(exists('g:called_arg3')) 1501 call StopVimInTerminal(buf) 1502 1503 " No match 1504 call ch_logfile('Xlog', 'w') 1505 let buf = RunVimInTerminal('-S Xscript', {'term_api': 'TryThat'}) 1506 call WaitFor({-> string(readfile('Xlog')) =~ 'Unpermitted function: TryThis'}) 1507 call assert_false(exists('g:called_bufnum3')) 1508 call assert_false(exists('g:called_arg3')) 1509 call StopVimInTerminal(buf) 1510 1511 call delete('Xscript') 1512 call ch_logfile('') 1513 call delete('Xlog') 1514 delfunction! TryThis 1515 unlet! g:called_bufnum3 1516 unlet! g:called_arg3 1517endfunc 1518 1519let s:caught_e937 = 0 1520 1521func Tapi_Delete(bufnum, arg) 1522 try 1523 execute 'bdelete!' a:bufnum 1524 catch /E937:/ 1525 let s:caught_e937 = 1 1526 endtry 1527endfunc 1528 1529func Test_terminal_api_call_fail_delete() 1530 CheckRunVimInTerminal 1531 1532 call WriteApiCall('Tapi_Delete') 1533 let buf = RunVimInTerminal('-S Xscript', {}) 1534 call WaitForAssert({-> assert_equal(1, s:caught_e937)}) 1535 1536 call StopVimInTerminal(buf) 1537 call delete('Xscript') 1538 call ch_logfile('', '') 1539endfunc 1540 1541func Test_terminal_ansicolors_default() 1542 if !exists('*term_getansicolors') 1543 throw 'Skipped: term_getansicolors() not supported' 1544 endif 1545 let colors = [ 1546 \ '#000000', '#e00000', 1547 \ '#00e000', '#e0e000', 1548 \ '#0000e0', '#e000e0', 1549 \ '#00e0e0', '#e0e0e0', 1550 \ '#808080', '#ff4040', 1551 \ '#40ff40', '#ffff40', 1552 \ '#4040ff', '#ff40ff', 1553 \ '#40ffff', '#ffffff', 1554 \] 1555 1556 let buf = Run_shell_in_terminal({}) 1557 call assert_equal(colors, term_getansicolors(buf)) 1558 call StopShellInTerminal(buf) 1559 call term_wait(buf) 1560 1561 exe buf . 'bwipe' 1562endfunc 1563 1564let s:test_colors = [ 1565 \ '#616e64', '#0d0a79', 1566 \ '#6d610d', '#0a7373', 1567 \ '#690d0a', '#6d696e', 1568 \ '#0d0a6f', '#616e0d', 1569 \ '#0a6479', '#6d0d0a', 1570 \ '#617373', '#0d0a69', 1571 \ '#6d690d', '#0a6e6f', 1572 \ '#610d0a', '#6e6479', 1573 \] 1574 1575func Test_terminal_ansicolors_global() 1576 CheckFeature termguicolors 1577 if !exists('*term_getansicolors') 1578 throw 'Skipped: term_getansicolors() not supported' 1579 endif 1580 let g:terminal_ansi_colors = reverse(copy(s:test_colors)) 1581 let buf = Run_shell_in_terminal({}) 1582 call assert_equal(g:terminal_ansi_colors, term_getansicolors(buf)) 1583 call StopShellInTerminal(buf) 1584 call term_wait(buf) 1585 1586 exe buf . 'bwipe' 1587 unlet g:terminal_ansi_colors 1588endfunc 1589 1590func Test_terminal_ansicolors_func() 1591 CheckFeature termguicolors 1592 if !exists('*term_getansicolors') 1593 throw 'Skipped: term_getansicolors() not supported' 1594 endif 1595 let g:terminal_ansi_colors = reverse(copy(s:test_colors)) 1596 let buf = Run_shell_in_terminal({'ansi_colors': s:test_colors}) 1597 call assert_equal(s:test_colors, term_getansicolors(buf)) 1598 1599 call term_setansicolors(buf, g:terminal_ansi_colors) 1600 call assert_equal(g:terminal_ansi_colors, buf->term_getansicolors()) 1601 1602 let colors = [ 1603 \ 'ivory', 'AliceBlue', 1604 \ 'grey67', 'dark goldenrod', 1605 \ 'SteelBlue3', 'PaleVioletRed4', 1606 \ 'MediumPurple2', 'yellow2', 1607 \ 'RosyBrown3', 'OrangeRed2', 1608 \ 'white smoke', 'navy blue', 1609 \ 'grey47', 'gray97', 1610 \ 'MistyRose2', 'DodgerBlue4', 1611 \] 1612 eval buf->term_setansicolors(colors) 1613 1614 let colors[4] = 'Invalid' 1615 call assert_fails('call term_setansicolors(buf, colors)', 'E474:') 1616 1617 call StopShellInTerminal(buf) 1618 call term_wait(buf) 1619 exe buf . 'bwipe' 1620endfunc 1621 1622func Test_terminal_all_ansi_colors() 1623 CheckRunVimInTerminal 1624 1625 " Use all the ANSI colors. 1626 call writefile([ 1627 \ 'call setline(1, "AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPP XXYYZZ")', 1628 \ 'hi Tblack ctermfg=0 ctermbg=8', 1629 \ 'hi Tdarkred ctermfg=1 ctermbg=9', 1630 \ 'hi Tdarkgreen ctermfg=2 ctermbg=10', 1631 \ 'hi Tbrown ctermfg=3 ctermbg=11', 1632 \ 'hi Tdarkblue ctermfg=4 ctermbg=12', 1633 \ 'hi Tdarkmagenta ctermfg=5 ctermbg=13', 1634 \ 'hi Tdarkcyan ctermfg=6 ctermbg=14', 1635 \ 'hi Tlightgrey ctermfg=7 ctermbg=15', 1636 \ 'hi Tdarkgrey ctermfg=8 ctermbg=0', 1637 \ 'hi Tred ctermfg=9 ctermbg=1', 1638 \ 'hi Tgreen ctermfg=10 ctermbg=2', 1639 \ 'hi Tyellow ctermfg=11 ctermbg=3', 1640 \ 'hi Tblue ctermfg=12 ctermbg=4', 1641 \ 'hi Tmagenta ctermfg=13 ctermbg=5', 1642 \ 'hi Tcyan ctermfg=14 ctermbg=6', 1643 \ 'hi Twhite ctermfg=15 ctermbg=7', 1644 \ 'hi TdarkredBold ctermfg=1 cterm=bold', 1645 \ 'hi TgreenBold ctermfg=10 cterm=bold', 1646 \ 'hi TmagentaBold ctermfg=13 cterm=bold ctermbg=5', 1647 \ '', 1648 \ 'call matchadd("Tblack", "A")', 1649 \ 'call matchadd("Tdarkred", "B")', 1650 \ 'call matchadd("Tdarkgreen", "C")', 1651 \ 'call matchadd("Tbrown", "D")', 1652 \ 'call matchadd("Tdarkblue", "E")', 1653 \ 'call matchadd("Tdarkmagenta", "F")', 1654 \ 'call matchadd("Tdarkcyan", "G")', 1655 \ 'call matchadd("Tlightgrey", "H")', 1656 \ 'call matchadd("Tdarkgrey", "I")', 1657 \ 'call matchadd("Tred", "J")', 1658 \ 'call matchadd("Tgreen", "K")', 1659 \ 'call matchadd("Tyellow", "L")', 1660 \ 'call matchadd("Tblue", "M")', 1661 \ 'call matchadd("Tmagenta", "N")', 1662 \ 'call matchadd("Tcyan", "O")', 1663 \ 'call matchadd("Twhite", "P")', 1664 \ 'call matchadd("TdarkredBold", "X")', 1665 \ 'call matchadd("TgreenBold", "Y")', 1666 \ 'call matchadd("TmagentaBold", "Z")', 1667 \ 'redraw', 1668 \ ], 'Xcolorscript') 1669 let buf = RunVimInTerminal('-S Xcolorscript', {'rows': 10}) 1670 call VerifyScreenDump(buf, 'Test_terminal_all_ansi_colors', {}) 1671 1672 call term_sendkeys(buf, ":q\<CR>") 1673 call StopVimInTerminal(buf) 1674 call delete('Xcolorscript') 1675endfunc 1676 1677func Test_terminal_termwinsize_option_fixed() 1678 CheckRunVimInTerminal 1679 set termwinsize=6x40 1680 let text = [] 1681 for n in range(10) 1682 call add(text, repeat(n, 50)) 1683 endfor 1684 call writefile(text, 'Xwinsize') 1685 let buf = RunVimInTerminal('Xwinsize', {}) 1686 let win = bufwinid(buf) 1687 call assert_equal([6, 40], term_getsize(buf)) 1688 call assert_equal(6, winheight(win)) 1689 call assert_equal(40, winwidth(win)) 1690 1691 " resizing the window doesn't resize the terminal. 1692 resize 10 1693 vertical resize 60 1694 call assert_equal([6, 40], term_getsize(buf)) 1695 call assert_equal(10, winheight(win)) 1696 call assert_equal(60, winwidth(win)) 1697 1698 call StopVimInTerminal(buf) 1699 call delete('Xwinsize') 1700 1701 call assert_fails('set termwinsize=40', 'E474') 1702 call assert_fails('set termwinsize=10+40', 'E474') 1703 call assert_fails('set termwinsize=abc', 'E474') 1704 1705 set termwinsize= 1706endfunc 1707 1708func Test_terminal_termwinsize_option_zero() 1709 set termwinsize=0x0 1710 let buf = Run_shell_in_terminal({}) 1711 let win = bufwinid(buf) 1712 call assert_equal([winheight(win), winwidth(win)], term_getsize(buf)) 1713 call StopShellInTerminal(buf) 1714 call term_wait(buf) 1715 exe buf . 'bwipe' 1716 1717 set termwinsize=7x0 1718 let buf = Run_shell_in_terminal({}) 1719 let win = bufwinid(buf) 1720 call assert_equal([7, winwidth(win)], term_getsize(buf)) 1721 call StopShellInTerminal(buf) 1722 call term_wait(buf) 1723 exe buf . 'bwipe' 1724 1725 set termwinsize=0x33 1726 let buf = Run_shell_in_terminal({}) 1727 let win = bufwinid(buf) 1728 call assert_equal([winheight(win), 33], term_getsize(buf)) 1729 call StopShellInTerminal(buf) 1730 call term_wait(buf) 1731 exe buf . 'bwipe' 1732 1733 set termwinsize= 1734endfunc 1735 1736func Test_terminal_termwinsize_minimum() 1737 set termwinsize=10*50 1738 vsplit 1739 let buf = Run_shell_in_terminal({}) 1740 let win = bufwinid(buf) 1741 call assert_inrange(10, 1000, winheight(win)) 1742 call assert_inrange(50, 1000, winwidth(win)) 1743 call assert_equal([winheight(win), winwidth(win)], term_getsize(buf)) 1744 1745 resize 15 1746 vertical resize 60 1747 redraw 1748 call assert_equal([15, 60], term_getsize(buf)) 1749 call assert_equal(15, winheight(win)) 1750 call assert_equal(60, winwidth(win)) 1751 1752 resize 7 1753 vertical resize 30 1754 redraw 1755 call assert_equal([10, 50], term_getsize(buf)) 1756 call assert_equal(7, winheight(win)) 1757 call assert_equal(30, winwidth(win)) 1758 1759 call StopShellInTerminal(buf) 1760 call term_wait(buf) 1761 exe buf . 'bwipe' 1762 1763 set termwinsize=0*0 1764 let buf = Run_shell_in_terminal({}) 1765 let win = bufwinid(buf) 1766 call assert_equal([winheight(win), winwidth(win)], term_getsize(buf)) 1767 call StopShellInTerminal(buf) 1768 call term_wait(buf) 1769 exe buf . 'bwipe' 1770 1771 set termwinsize= 1772endfunc 1773 1774func Test_terminal_termwinkey() 1775 " make three tabpages, terminal in the middle 1776 0tabnew 1777 tabnext 1778 tabnew 1779 tabprev 1780 call assert_equal(1, winnr('$')) 1781 call assert_equal(2, tabpagenr()) 1782 let thiswin = win_getid() 1783 1784 let buf = Run_shell_in_terminal({}) 1785 let termwin = bufwinid(buf) 1786 set termwinkey=<C-L> 1787 call feedkeys("\<C-L>w", 'tx') 1788 call assert_equal(thiswin, win_getid()) 1789 call feedkeys("\<C-W>w", 'tx') 1790 call assert_equal(termwin, win_getid()) 1791 1792 if has('langmap') 1793 set langmap=xjyk 1794 call feedkeys("\<C-L>x", 'tx') 1795 call assert_equal(thiswin, win_getid()) 1796 call feedkeys("\<C-W>y", 'tx') 1797 call assert_equal(termwin, win_getid()) 1798 set langmap= 1799 endif 1800 1801 call feedkeys("\<C-L>gt", "xt") 1802 call assert_equal(3, tabpagenr()) 1803 tabprev 1804 call assert_equal(2, tabpagenr()) 1805 call assert_equal(termwin, win_getid()) 1806 1807 call feedkeys("\<C-L>gT", "xt") 1808 call assert_equal(1, tabpagenr()) 1809 tabnext 1810 call assert_equal(2, tabpagenr()) 1811 call assert_equal(termwin, win_getid()) 1812 1813 let job = term_getjob(buf) 1814 call feedkeys("\<C-L>\<C-C>", 'tx') 1815 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 1816 1817 set termwinkey& 1818 tabnext 1819 tabclose 1820 tabprev 1821 tabclose 1822endfunc 1823 1824func Test_terminal_out_err() 1825 CheckUnix 1826 1827 call writefile([ 1828 \ '#!/bin/sh', 1829 \ 'echo "this is standard error" >&2', 1830 \ 'echo "this is standard out" >&1', 1831 \ ], 'Xechoerrout.sh') 1832 call setfperm('Xechoerrout.sh', 'rwxrwx---') 1833 1834 let outfile = 'Xtermstdout' 1835 let buf = term_start(['./Xechoerrout.sh'], {'out_io': 'file', 'out_name': outfile}) 1836 1837 call WaitFor({-> !empty(readfile(outfile)) && !empty(term_getline(buf, 1))}) 1838 call assert_equal(['this is standard out'], readfile(outfile)) 1839 call assert_equal('this is standard error', term_getline(buf, 1)) 1840 1841 call WaitForAssert({-> assert_equal('dead', job_status(term_getjob(buf)))}) 1842 exe buf . 'bwipe' 1843 call delete('Xechoerrout.sh') 1844 call delete(outfile) 1845endfunc 1846 1847func Test_termwinscroll() 1848 CheckUnix 1849 1850 " Let the terminal output more than 'termwinscroll' lines, some at the start 1851 " will be dropped. 1852 exe 'set termwinscroll=' . &lines 1853 let buf = term_start('/bin/sh') 1854 for i in range(1, &lines) 1855 call feedkeys("echo " . i . "\<CR>", 'xt') 1856 call WaitForAssert({-> assert_match(string(i), term_getline(buf, term_getcursor(buf)[0] - 1))}) 1857 endfor 1858 " Go to Terminal-Normal mode to update the buffer. 1859 call feedkeys("\<C-W>N", 'xt') 1860 call assert_inrange(&lines, &lines * 110 / 100 + winheight(0), line('$')) 1861 1862 " Every "echo nr" must only appear once 1863 let lines = getline(1, line('$')) 1864 for i in range(&lines - len(lines) / 2 + 2, &lines) 1865 let filtered = filter(copy(lines), {idx, val -> val =~ 'echo ' . i . '\>'}) 1866 call assert_equal(1, len(filtered), 'for "echo ' . i . '"') 1867 endfor 1868 1869 exe buf . 'bwipe!' 1870endfunc 1871 1872" Resizing the terminal window caused an ml_get error. 1873" TODO: This does not reproduce the original problem. 1874func Test_terminal_resize() 1875 set statusline=x 1876 terminal 1877 call assert_equal(2, winnr('$')) 1878 1879 " Fill the terminal with text. 1880 if has('win32') 1881 call feedkeys("dir\<CR>", 'xt') 1882 else 1883 call feedkeys("ls\<CR>", 'xt') 1884 endif 1885 " Go to Terminal-Normal mode for a moment. 1886 call feedkeys("\<C-W>N", 'xt') 1887 " Open a new window 1888 call feedkeys("i\<C-W>n", 'xt') 1889 call assert_equal(3, winnr('$')) 1890 redraw 1891 1892 close 1893 call assert_equal(2, winnr('$')) 1894 call feedkeys("exit\<CR>", 'xt') 1895 set statusline& 1896endfunc 1897 1898" must be nearly the last, we can't go back from GUI to terminal 1899func Test_zz1_terminal_in_gui() 1900 CheckCanRunGui 1901 1902 " Ignore the "failed to create input context" error. 1903 call test_ignore_error('E285:') 1904 1905 gui -f 1906 1907 call assert_equal(1, winnr('$')) 1908 let buf = Run_shell_in_terminal({'term_finish': 'close'}) 1909 call StopShellInTerminal(buf) 1910 call term_wait(buf) 1911 1912 " closing window wipes out the terminal buffer a with finished job 1913 call WaitForAssert({-> assert_equal(1, winnr('$'))}) 1914 call assert_equal("", bufname(buf)) 1915 1916 unlet g:job 1917endfunc 1918 1919func Test_zz2_terminal_guioptions_bang() 1920 CheckGui 1921 set guioptions+=! 1922 1923 let filename = 'Xtestscript' 1924 if has('win32') 1925 let filename .= '.bat' 1926 let prefix = '' 1927 let contents = ['@echo off', 'exit %1'] 1928 else 1929 let filename .= '.sh' 1930 let prefix = './' 1931 let contents = ['#!/bin/sh', 'exit $1'] 1932 endif 1933 call writefile(contents, filename) 1934 call setfperm(filename, 'rwxrwx---') 1935 1936 " Check if v:shell_error is equal to the exit status. 1937 let exitval = 0 1938 execute printf(':!%s%s %d', prefix, filename, exitval) 1939 call assert_equal(exitval, v:shell_error) 1940 1941 let exitval = 9 1942 execute printf(':!%s%s %d', prefix, filename, exitval) 1943 call assert_equal(exitval, v:shell_error) 1944 1945 set guioptions& 1946 call delete(filename) 1947endfunc 1948 1949func Test_terminal_hidden() 1950 CheckUnix 1951 1952 term ++hidden cat 1953 let bnr = bufnr('$') 1954 call assert_equal('terminal', getbufvar(bnr, '&buftype')) 1955 exe 'sbuf ' . bnr 1956 call assert_equal('terminal', &buftype) 1957 call term_sendkeys(bnr, "asdf\<CR>") 1958 call WaitForAssert({-> assert_match('asdf', term_getline(bnr, 2))}) 1959 call term_sendkeys(bnr, "\<C-D>") 1960 call WaitForAssert({-> assert_equal('finished', bnr->term_getstatus())}) 1961 bwipe! 1962endfunc 1963 1964func Test_terminal_switch_mode() 1965 term 1966 let bnr = bufnr('$') 1967 call WaitForAssert({-> assert_equal('running', term_getstatus(bnr))}) 1968 call feedkeys("\<C-W>N", 'xt') 1969 call WaitForAssert({-> assert_equal('running,normal', term_getstatus(bnr))}) 1970 call feedkeys("A", 'xt') 1971 call WaitForAssert({-> assert_equal('running', term_getstatus(bnr))}) 1972 call feedkeys("\<C-W>N", 'xt') 1973 call WaitForAssert({-> assert_equal('running,normal', term_getstatus(bnr))}) 1974 call feedkeys("I", 'xt') 1975 call WaitForAssert({-> assert_equal('running', term_getstatus(bnr))}) 1976 call feedkeys("\<C-W>Nv", 'xt') 1977 call WaitForAssert({-> assert_equal('running,normal', term_getstatus(bnr))}) 1978 call feedkeys("I", 'xt') 1979 call WaitForAssert({-> assert_equal('running', term_getstatus(bnr))}) 1980 call feedkeys("\<C-W>Nv", 'xt') 1981 call WaitForAssert({-> assert_equal('running,normal', term_getstatus(bnr))}) 1982 call feedkeys("A", 'xt') 1983 call WaitForAssert({-> assert_equal('running', term_getstatus(bnr))}) 1984 bwipe! 1985endfunc 1986 1987func Test_terminal_normal_mode() 1988 CheckRunVimInTerminal 1989 1990 " Run Vim in a terminal and open a terminal window to run Vim in. 1991 let lines =<< trim END 1992 call setline(1, range(11111, 11122)) 1993 3 1994 END 1995 call writefile(lines, 'XtermNormal') 1996 let buf = RunVimInTerminal('-S XtermNormal', {'rows': 8}) 1997 call term_wait(buf) 1998 1999 call term_sendkeys(buf, "\<C-W>N") 2000 call term_sendkeys(buf, ":set number cursorline culopt=both\r") 2001 call VerifyScreenDump(buf, 'Test_terminal_normal_1', {}) 2002 2003 call term_sendkeys(buf, ":set culopt=number\r") 2004 call VerifyScreenDump(buf, 'Test_terminal_normal_2', {}) 2005 2006 call term_sendkeys(buf, ":set culopt=line\r") 2007 call VerifyScreenDump(buf, 'Test_terminal_normal_3', {}) 2008 2009 call term_sendkeys(buf, "a:q!\<CR>:q\<CR>:q\<CR>") 2010 call StopVimInTerminal(buf) 2011 call delete('XtermNormal') 2012endfunc 2013 2014func Test_terminal_hidden_and_close() 2015 CheckUnix 2016 2017 call assert_equal(1, winnr('$')) 2018 term ++hidden ++close ls 2019 let bnr = bufnr('$') 2020 call assert_equal('terminal', getbufvar(bnr, '&buftype')) 2021 call WaitForAssert({-> assert_false(bufexists(bnr))}) 2022 call assert_equal(1, winnr('$')) 2023endfunc 2024 2025func Test_terminal_does_not_truncate_last_newlines() 2026 " This test does not pass through ConPTY. 2027 if has('conpty') 2028 return 2029 endif 2030 let contents = [ 2031 \ [ 'One', '', 'X' ], 2032 \ [ 'Two', '', '' ], 2033 \ [ 'Three' ] + repeat([''], 30) 2034 \ ] 2035 2036 for c in contents 2037 call writefile(c, 'Xfile') 2038 if has('win32') 2039 term cmd /c type Xfile 2040 else 2041 term cat Xfile 2042 endif 2043 let bnr = bufnr('$') 2044 call assert_equal('terminal', getbufvar(bnr, '&buftype')) 2045 call WaitForAssert({-> assert_equal('finished', term_getstatus(bnr))}) 2046 sleep 100m 2047 call assert_equal(c, getline(1, line('$'))) 2048 quit 2049 endfor 2050 2051 call delete('Xfile') 2052endfunc 2053 2054func Test_terminal_no_job() 2055 if has('win32') 2056 let cmd = 'cmd /c ""' 2057 else 2058 CheckExecutable false 2059 let cmd = 'false' 2060 endif 2061 let term = term_start(cmd, {'term_finish': 'close'}) 2062 call WaitForAssert({-> assert_equal(v:null, term_getjob(term)) }) 2063endfunc 2064 2065func Test_term_getcursor() 2066 CheckUnix 2067 2068 let buf = Run_shell_in_terminal({}) 2069 2070 " Wait for the shell to display a prompt. 2071 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 2072 2073 " Hide the cursor. 2074 call term_sendkeys(buf, "echo -e '\\033[?25l'\r") 2075 call WaitForAssert({-> assert_equal(0, term_getcursor(buf)[2].visible)}) 2076 2077 " Show the cursor. 2078 call term_sendkeys(buf, "echo -e '\\033[?25h'\r") 2079 call WaitForAssert({-> assert_equal(1, buf->term_getcursor()[2].visible)}) 2080 2081 " Change color of cursor. 2082 call WaitForAssert({-> assert_equal('', term_getcursor(buf)[2].color)}) 2083 call term_sendkeys(buf, "echo -e '\\033]12;blue\\007'\r") 2084 call WaitForAssert({-> assert_equal('blue', term_getcursor(buf)[2].color)}) 2085 call term_sendkeys(buf, "echo -e '\\033]12;green\\007'\r") 2086 call WaitForAssert({-> assert_equal('green', term_getcursor(buf)[2].color)}) 2087 2088 " Make cursor a blinking block. 2089 call term_sendkeys(buf, "echo -e '\\033[1 q'\r") 2090 call WaitForAssert({-> assert_equal([1, 1], 2091 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2092 2093 " Make cursor a steady block. 2094 call term_sendkeys(buf, "echo -e '\\033[2 q'\r") 2095 call WaitForAssert({-> assert_equal([0, 1], 2096 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2097 2098 " Make cursor a blinking underline. 2099 call term_sendkeys(buf, "echo -e '\\033[3 q'\r") 2100 call WaitForAssert({-> assert_equal([1, 2], 2101 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2102 2103 " Make cursor a steady underline. 2104 call term_sendkeys(buf, "echo -e '\\033[4 q'\r") 2105 call WaitForAssert({-> assert_equal([0, 2], 2106 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2107 2108 " Make cursor a blinking vertical bar. 2109 call term_sendkeys(buf, "echo -e '\\033[5 q'\r") 2110 call WaitForAssert({-> assert_equal([1, 3], 2111 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2112 2113 " Make cursor a steady vertical bar. 2114 call term_sendkeys(buf, "echo -e '\\033[6 q'\r") 2115 call WaitForAssert({-> assert_equal([0, 3], 2116 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2117 2118 call StopShellInTerminal(buf) 2119endfunc 2120 2121func Test_term_gettitle() 2122 " term_gettitle() returns an empty string for a non-terminal buffer 2123 " and for a non-existing buffer. 2124 call assert_equal('', bufnr('%')->term_gettitle()) 2125 call assert_equal('', term_gettitle(bufnr('$') + 1)) 2126 2127 if !has('title') || &title == 0 || empty(&t_ts) 2128 throw "Skipped: can't get/set title" 2129 endif 2130 2131 let term = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile']) 2132 if has('autoservername') 2133 call WaitForAssert({-> assert_match('^\[No Name\] - VIM\d\+$', term_gettitle(term)) }) 2134 call term_sendkeys(term, ":e Xfoo\r") 2135 call WaitForAssert({-> assert_match('^Xfoo (.*[/\\]testdir) - VIM\d\+$', term_gettitle(term)) }) 2136 else 2137 call WaitForAssert({-> assert_equal('[No Name] - VIM', term_gettitle(term)) }) 2138 call term_sendkeys(term, ":e Xfoo\r") 2139 call WaitForAssert({-> assert_match('^Xfoo (.*[/\\]testdir) - VIM$', term_gettitle(term)) }) 2140 endif 2141 2142 call term_sendkeys(term, ":set titlestring=foo\r") 2143 call WaitForAssert({-> assert_equal('foo', term_gettitle(term)) }) 2144 2145 exe term . 'bwipe!' 2146endfunc 2147 2148" When drawing the statusline the cursor position may not have been updated 2149" yet. 2150" 1. create a terminal, make it show 2 lines 2151" 2. 0.5 sec later: leave terminal window, execute "i" 2152" 3. 0.5 sec later: clear terminal window, now it's 1 line 2153" 4. 0.5 sec later: redraw, including statusline (used to trigger bug) 2154" 4. 0.5 sec later: should be done, clean up 2155func Test_terminal_statusline() 2156 CheckUnix 2157 2158 set statusline=x 2159 terminal 2160 let tbuf = bufnr('') 2161 call term_sendkeys(tbuf, "clear; echo a; echo b; sleep 1; clear\n") 2162 call timer_start(500, { tid -> feedkeys("\<C-w>j", 'tx') }) 2163 call timer_start(1500, { tid -> feedkeys("\<C-l>", 'tx') }) 2164 au BufLeave * if &buftype == 'terminal' | silent! normal i | endif 2165 2166 sleep 2 2167 exe tbuf . 'bwipe!' 2168 au! BufLeave 2169 set statusline= 2170endfunc 2171 2172func Test_terminal_getwinpos() 2173 CheckRunVimInTerminal 2174 2175 " split, go to the bottom-right window 2176 split 2177 wincmd j 2178 set splitright 2179 2180 call writefile([ 2181 \ 'echo getwinpos()', 2182 \ ], 'XTest_getwinpos') 2183 let buf = RunVimInTerminal('-S XTest_getwinpos', {'cols': 60}) 2184 call term_wait(buf) 2185 2186 " Find the output of getwinpos() in the bottom line. 2187 let rows = term_getsize(buf)[0] 2188 call WaitForAssert({-> assert_match('\[\d\+, \d\+\]', term_getline(buf, rows))}) 2189 let line = term_getline(buf, rows) 2190 let xpos = str2nr(substitute(line, '\[\(\d\+\), \d\+\]', '\1', '')) 2191 let ypos = str2nr(substitute(line, '\[\d\+, \(\d\+\)\]', '\1', '')) 2192 2193 " Position must be bigger than the getwinpos() result of Vim itself. 2194 " The calculation in the console assumes a 10 x 7 character cell. 2195 " In the GUI it can be more, let's assume a 20 x 14 cell. 2196 " And then add 100 / 200 tolerance. 2197 let [xroot, yroot] = getwinpos() 2198 let winpos = 50->getwinpos() 2199 call assert_equal(xroot, winpos[0]) 2200 call assert_equal(yroot, winpos[1]) 2201 let [winrow, wincol] = win_screenpos('.') 2202 let xoff = wincol * (has('gui_running') ? 14 : 7) + 100 2203 let yoff = winrow * (has('gui_running') ? 20 : 10) + 200 2204 call assert_inrange(xroot + 2, xroot + xoff, xpos) 2205 call assert_inrange(yroot + 2, yroot + yoff, ypos) 2206 2207 call term_wait(buf) 2208 call term_sendkeys(buf, ":q\<CR>") 2209 call StopVimInTerminal(buf) 2210 call delete('XTest_getwinpos') 2211 exe buf . 'bwipe!' 2212 set splitright& 2213 only! 2214endfunc 2215 2216func Test_terminal_altscreen() 2217 " somehow doesn't work on MS-Windows 2218 CheckUnix 2219 let cmd = "cat Xtext\<CR>" 2220 2221 let buf = term_start(&shell, {}) 2222 call writefile(["\<Esc>[?1047h"], 'Xtext') 2223 call term_sendkeys(buf, cmd) 2224 call WaitForAssert({-> assert_equal(1, term_getaltscreen(buf))}) 2225 2226 call writefile(["\<Esc>[?1047l"], 'Xtext') 2227 call term_sendkeys(buf, cmd) 2228 call WaitForAssert({-> assert_equal(0, term_getaltscreen(buf))}) 2229 2230 call term_sendkeys(buf, "exit\r") 2231 exe buf . "bwipe!" 2232 call delete('Xtext') 2233endfunc 2234 2235func Test_terminal_shell_option() 2236 if has('unix') 2237 " exec is a shell builtin command, should fail without a shell. 2238 term exec ls runtest.vim 2239 call WaitForAssert({-> assert_match('job failed', term_getline(bufnr(), 1))}) 2240 bwipe! 2241 2242 term ++shell exec ls runtest.vim 2243 call WaitForAssert({-> assert_match('runtest.vim', term_getline(bufnr(), 1))}) 2244 bwipe! 2245 elseif has('win32') 2246 " dir is a shell builtin command, should fail without a shell. 2247 try 2248 term dir /b runtest.vim 2249 call WaitForAssert({-> assert_match('job failed\|cannot access .*: No such file or directory', term_getline(bufnr(), 1))}) 2250 catch /CreateProcess/ 2251 " ignore 2252 endtry 2253 bwipe! 2254 2255 term ++shell dir /b runtest.vim 2256 call WaitForAssert({-> assert_match('runtest.vim', term_getline(bufnr(), 1))}) 2257 bwipe! 2258 endif 2259endfunc 2260 2261func Test_terminal_setapi_and_call() 2262 CheckRunVimInTerminal 2263 2264 call WriteApiCall('Tapi_TryThis') 2265 call ch_logfile('Xlog', 'w') 2266 2267 unlet! g:called_bufnum 2268 unlet! g:called_arg 2269 2270 let buf = RunVimInTerminal('-S Xscript', {'term_api': ''}) 2271 call WaitForAssert({-> assert_match('Unpermitted function: Tapi_TryThis', string(readfile('Xlog')))}) 2272 call assert_false(exists('g:called_bufnum')) 2273 call assert_false(exists('g:called_arg')) 2274 2275 eval buf->term_setapi('Tapi_') 2276 call term_sendkeys(buf, ":set notitle\<CR>") 2277 call term_sendkeys(buf, ":source Xscript\<CR>") 2278 call WaitFor({-> exists('g:called_bufnum')}) 2279 call assert_equal(buf, g:called_bufnum) 2280 call assert_equal(['hello', 123], g:called_arg) 2281 2282 call StopVimInTerminal(buf) 2283 2284 call delete('Xscript') 2285 call ch_logfile('') 2286 call delete('Xlog') 2287 unlet! g:called_bufnum 2288 unlet! g:called_arg 2289endfunc 2290 2291func Test_terminal_api_arg() 2292 CheckRunVimInTerminal 2293 2294 call WriteApiCall('Tapi_TryThis') 2295 call ch_logfile('Xlog', 'w') 2296 2297 unlet! g:called_bufnum 2298 unlet! g:called_arg 2299 2300 execute 'term ++api= ' .. GetVimCommandCleanTerm() .. '-S Xscript' 2301 let buf = bufnr('%') 2302 call WaitForAssert({-> assert_match('Unpermitted function: Tapi_TryThis', string(readfile('Xlog')))}) 2303 call assert_false(exists('g:called_bufnum')) 2304 call assert_false(exists('g:called_arg')) 2305 2306 call StopVimInTerminal(buf) 2307 2308 call ch_logfile('Xlog', 'w') 2309 2310 execute 'term ++api=Tapi_ ' .. GetVimCommandCleanTerm() .. '-S Xscript' 2311 let buf = bufnr('%') 2312 call WaitFor({-> exists('g:called_bufnum')}) 2313 call assert_equal(buf, g:called_bufnum) 2314 call assert_equal(['hello', 123], g:called_arg) 2315 2316 call StopVimInTerminal(buf) 2317 2318 call delete('Xscript') 2319 call ch_logfile('') 2320 call delete('Xlog') 2321 unlet! g:called_bufnum 2322 unlet! g:called_arg 2323endfunc 2324 2325func Test_terminal_in_popup() 2326 CheckRunVimInTerminal 2327 2328 let text =<< trim END 2329 some text 2330 to edit 2331 in a popup window 2332 END 2333 call writefile(text, 'Xtext') 2334 let cmd = GetVimCommandCleanTerm() 2335 let lines = [ 2336 \ 'call setline(1, range(20))', 2337 \ 'hi PopTerm ctermbg=grey', 2338 \ 'func OpenTerm(setColor)', 2339 \ " let buf = term_start('" .. cmd .. " Xtext', #{hidden: 1, term_finish: 'close'})", 2340 \ ' let s:winid = popup_create(buf, #{minwidth: 45, minheight: 7, border: [], drag: 1, resize: 1})', 2341 \ ' if a:setColor', 2342 \ ' call win_execute(s:winid, "set wincolor=PopTerm")', 2343 \ ' endif', 2344 \ 'endfunc', 2345 \ 'call OpenTerm(0)', 2346 \ 'func HidePopup()', 2347 \ ' call popup_hide(s:winid)', 2348 \ 'endfunc', 2349 \ ] 2350 call writefile(lines, 'XtermPopup') 2351 let buf = RunVimInTerminal('-S XtermPopup', #{rows: 15}) 2352 call VerifyScreenDump(buf, 'Test_terminal_popup_1', {}) 2353 2354 call term_sendkeys(buf, ":q\<CR>") 2355 call VerifyScreenDump(buf, 'Test_terminal_popup_2', {}) 2356 2357 call term_sendkeys(buf, ":call OpenTerm(1)\<CR>") 2358 call term_sendkeys(buf, ":set hlsearch\<CR>") 2359 call term_sendkeys(buf, "/edit\<CR>") 2360 call VerifyScreenDump(buf, 'Test_terminal_popup_3', {}) 2361 2362 call term_sendkeys(buf, "\<C-W>:call HidePopup()\<CR>") 2363 call VerifyScreenDump(buf, 'Test_terminal_popup_4', {}) 2364 call term_sendkeys(buf, "\<CR>") 2365 call term_wait(buf, 100) 2366 2367 call term_sendkeys(buf, ":q\<CR>") 2368 call term_wait(buf, 100) " wait for terminal to vanish 2369 2370 call StopVimInTerminal(buf) 2371 call delete('XtermPopup') 2372endfunc 2373 2374func Test_issue_5607() 2375 let wincount = winnr('$') 2376 exe 'terminal' &shell &shellcmdflag 'exit' 2377 let job = term_getjob(bufnr()) 2378 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 2379 2380 let old_wincolor = &wincolor 2381 try 2382 set wincolor= 2383 finally 2384 let &wincolor = old_wincolor 2385 bw! 2386 endtry 2387endfunc 2388