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 if !executable('wc') 693 throw 'skipped: wc command not available' 694 endif 695 if has('win32') 696 " TODO: enable once writing to stdin works on MS-Windows 697 return 698 endif 699 new 700 call setline(1, ['one', 'two', 'three']) 701 %term wc 702 call WaitForAssert({-> assert_match('3', getline("$"))}) 703 let nrs = split(getline('$')) 704 call assert_equal(['3', '3', '14'], nrs) 705 bwipe 706 707 new 708 call setline(1, ['one', 'two', 'three', 'four']) 709 2,3term wc 710 call WaitForAssert({-> assert_match('2', getline("$"))}) 711 let nrs = split(getline('$')) 712 call assert_equal(['2', '2', '10'], nrs) 713 bwipe 714 715 if executable('python') 716 new 717 call setline(1, ['print("hello")']) 718 1term ++eof=exit() python 719 " MS-Windows echoes the input, Unix doesn't. 720 call WaitFor('getline("$") =~ "exit" || getline(1) =~ "hello"') 721 if getline(1) =~ 'hello' 722 call assert_equal('hello', getline(1)) 723 else 724 call assert_equal('hello', getline(line('$') - 1)) 725 endif 726 bwipe 727 728 if has('win32') 729 new 730 call setline(1, ['print("hello")']) 731 1term ++eof=<C-Z> python 732 call WaitForAssert({-> assert_match('Z', getline("$"))}) 733 call assert_equal('hello', getline(line('$') - 1)) 734 bwipe 735 endif 736 endif 737 738 bwipe! 739endfunc 740 741func Test_terminal_no_cmd() 742 let buf = term_start('NONE', {}) 743 call assert_notequal(0, buf) 744 745 let pty = job_info(term_getjob(buf))['tty_out'] 746 call assert_notequal('', pty) 747 if has('gui_running') && !has('win32') 748 " In the GUI job_start() doesn't work, it does not read from the pty. 749 call system('echo "look here" > ' . pty) 750 else 751 " Otherwise using a job works on all systems. 752 call job_start([&shell, &shellcmdflag, 'echo "look here" > ' . pty]) 753 endif 754 call WaitForAssert({-> assert_match('look here', term_getline(buf, 1))}) 755 756 bwipe! 757endfunc 758 759func Test_terminal_special_chars() 760 " this file name only works on Unix 761 CheckUnix 762 763 call mkdir('Xdir with spaces') 764 call writefile(['x'], 'Xdir with spaces/quoted"file') 765 term ls Xdir\ with\ spaces/quoted\"file 766 call WaitForAssert({-> assert_match('quoted"file', term_getline('', 1))}) 767 call term_wait('') 768 769 call delete('Xdir with spaces', 'rf') 770 bwipe 771endfunc 772 773func Test_terminal_wrong_options() 774 call assert_fails('call term_start(&shell, { 775 \ "in_io": "file", 776 \ "in_name": "xxx", 777 \ "out_io": "file", 778 \ "out_name": "xxx", 779 \ "err_io": "file", 780 \ "err_name": "xxx" 781 \ })', 'E474:') 782 call assert_fails('call term_start(&shell, { 783 \ "out_buf": bufnr("%") 784 \ })', 'E474:') 785 call assert_fails('call term_start(&shell, { 786 \ "err_buf": bufnr("%") 787 \ })', 'E474:') 788endfunc 789 790func Test_terminal_redir_file() 791 let cmd = Get_cat_123_cmd() 792 let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'}) 793 call term_wait(buf) 794 " ConPTY may precede escape sequence. There are things that are not so. 795 if !has('conpty') 796 call WaitForAssert({-> assert_notequal(0, len(readfile("Xfile")))}) 797 call assert_match('123', readfile('Xfile')[0]) 798 endif 799 let g:job = term_getjob(buf) 800 call WaitForAssert({-> assert_equal("dead", job_status(g:job))}) 801 call delete('Xfile') 802 bwipe 803 804 if has('unix') 805 call writefile(['one line'], 'Xfile') 806 let buf = term_start('cat', {'in_io': 'file', 'in_name': 'Xfile'}) 807 call term_wait(buf) 808 call WaitForAssert({-> assert_equal('one line', term_getline(buf, 1))}) 809 let g:job = term_getjob(buf) 810 call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) 811 bwipe 812 call delete('Xfile') 813 endif 814endfunc 815 816func TerminalTmap(remap) 817 let buf = Run_shell_in_terminal({}) 818 call assert_equal('t', mode()) 819 820 if a:remap 821 tmap 123 456 822 else 823 tnoremap 123 456 824 endif 825 " don't use abcde, it's an existing command 826 tmap 456 abxde 827 call assert_equal('456', maparg('123', 't')) 828 call assert_equal('abxde', maparg('456', 't')) 829 call feedkeys("123", 'tx') 830 call WaitForAssert({-> assert_match('abxde\|456', term_getline(buf, term_getcursor(buf)[0]))}) 831 let lnum = term_getcursor(buf)[0] 832 if a:remap 833 call assert_match('abxde', term_getline(buf, lnum)) 834 else 835 call assert_match('456', term_getline(buf, lnum)) 836 endif 837 838 call term_sendkeys(buf, "\r") 839 call StopShellInTerminal(buf) 840 call term_wait(buf) 841 842 tunmap 123 843 tunmap 456 844 call assert_equal('', maparg('123', 't')) 845 close 846 unlet g:job 847endfunc 848 849func Test_terminal_tmap() 850 call TerminalTmap(1) 851 call TerminalTmap(0) 852endfunc 853 854func Test_terminal_wall() 855 let buf = Run_shell_in_terminal({}) 856 wall 857 call StopShellInTerminal(buf) 858 call term_wait(buf) 859 exe buf . 'bwipe' 860 unlet g:job 861endfunc 862 863func Test_terminal_wqall() 864 let buf = Run_shell_in_terminal({}) 865 call assert_fails('wqall', 'E948') 866 call StopShellInTerminal(buf) 867 call term_wait(buf) 868 exe buf . 'bwipe' 869 unlet g:job 870endfunc 871 872func Test_terminal_composing_unicode() 873 CheckNotBSD 874 let save_enc = &encoding 875 set encoding=utf-8 876 877 if has('win32') 878 let cmd = "cmd /K chcp 65001" 879 let lnum = [3, 6, 9] 880 else 881 let cmd = &shell 882 let lnum = [1, 3, 5] 883 endif 884 885 enew 886 let buf = term_start(cmd, {'curwin': bufnr('')}) 887 let g:job = term_getjob(buf) 888 call term_wait(buf, 50) 889 890 if has('win32') 891 call assert_equal('cmd', job_info(g:job).cmd[0]) 892 else 893 call assert_equal(&shell, job_info(g:job).cmd[0]) 894 endif 895 896 " ascii + composing 897 let txt = "a\u0308bc" 898 call term_sendkeys(buf, "echo " . txt . "\r") 899 call term_wait(buf, 50) 900 call assert_match("echo " . txt, term_getline(buf, lnum[0])) 901 call assert_equal(txt, term_getline(buf, lnum[0] + 1)) 902 let l = term_scrape(buf, lnum[0] + 1) 903 call assert_equal("a\u0308", l[0].chars) 904 call assert_equal("b", l[1].chars) 905 call assert_equal("c", l[2].chars) 906 907 " multibyte + composing 908 let txt = "\u304b\u3099\u304e\u304f\u3099\u3052\u3053\u3099" 909 call term_sendkeys(buf, "echo " . txt . "\r") 910 call term_wait(buf, 50) 911 call assert_match("echo " . txt, term_getline(buf, lnum[1])) 912 call assert_equal(txt, term_getline(buf, lnum[1] + 1)) 913 let l = term_scrape(buf, lnum[1] + 1) 914 call assert_equal("\u304b\u3099", l[0].chars) 915 call assert_equal("\u304e", l[1].chars) 916 call assert_equal("\u304f\u3099", l[2].chars) 917 call assert_equal("\u3052", l[3].chars) 918 call assert_equal("\u3053\u3099", l[4].chars) 919 920 " \u00a0 + composing 921 let txt = "abc\u00a0\u0308" 922 call term_sendkeys(buf, "echo " . txt . "\r") 923 call term_wait(buf, 50) 924 call assert_match("echo " . txt, term_getline(buf, lnum[2])) 925 call assert_equal(txt, term_getline(buf, lnum[2] + 1)) 926 let l = term_scrape(buf, lnum[2] + 1) 927 call assert_equal("\u00a0\u0308", l[3].chars) 928 929 call term_sendkeys(buf, "exit\r") 930 call WaitForAssert({-> assert_equal('dead', job_status(g:job))}) 931 bwipe! 932 unlet g:job 933 let &encoding = save_enc 934endfunc 935 936func Test_terminal_aucmd_on_close() 937 fun Nop() 938 let s:called = 1 939 endfun 940 941 aug repro 942 au! 943 au BufWinLeave * call Nop() 944 aug END 945 946 let [cmd, waittime] = s:get_sleep_cmd() 947 948 call assert_equal(1, winnr('$')) 949 new 950 call setline(1, ['one', 'two']) 951 exe 'term ++close ' . cmd 952 wincmd p 953 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime) 954 call assert_equal(1, s:called) 955 bwipe! 956 957 unlet s:called 958 au! repro 959 delfunc Nop 960endfunc 961 962func Test_terminal_term_start_empty_command() 963 let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})" 964 call assert_fails(cmd, 'E474') 965 let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})" 966 call assert_fails(cmd, 'E474') 967 let cmd = "call term_start({}, {'curwin' : 1, 'term_finish' : 'close'})" 968 call assert_fails(cmd, 'E474') 969 let cmd = "call term_start(0, {'curwin' : 1, 'term_finish' : 'close'})" 970 call assert_fails(cmd, 'E474') 971endfunc 972 973func Test_terminal_response_to_control_sequence() 974 CheckUnix 975 976 let buf = Run_shell_in_terminal({}) 977 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 978 979 call term_sendkeys(buf, "cat\<CR>") 980 call WaitForAssert({-> assert_match('cat', term_getline(buf, 1))}) 981 982 " Request the cursor position. 983 call term_sendkeys(buf, "\x1b[6n\<CR>") 984 985 " Wait for output from tty to display, below an empty line. 986 call WaitForAssert({-> assert_match('3;1R', term_getline(buf, 4))}) 987 988 " End "cat" gently. 989 call term_sendkeys(buf, "\<CR>\<C-D>") 990 991 call StopShellInTerminal(buf) 992 exe buf . 'bwipe' 993 unlet g:job 994endfunc 995 996" Run Vim, start a terminal in that Vim with the kill argument, 997" :qall works. 998func Run_terminal_qall_kill(line1, line2) 999 " 1. Open a terminal window and wait for the prompt to appear 1000 " 2. set kill using term_setkill() 1001 " 3. make Vim exit, it will kill the shell 1002 let after = [ 1003 \ a:line1, 1004 \ 'let buf = bufnr("%")', 1005 \ 'while term_getline(buf, 1) =~ "^\\s*$"', 1006 \ ' sleep 10m', 1007 \ 'endwhile', 1008 \ a:line2, 1009 \ 'au VimLeavePre * call writefile(["done"], "Xdone")', 1010 \ 'qall', 1011 \ ] 1012 if !RunVim([], after, '') 1013 return 1014 endif 1015 call assert_equal("done", readfile("Xdone")[0]) 1016 call delete("Xdone") 1017endfunc 1018 1019" Run Vim in a terminal, then start a terminal in that Vim with a kill 1020" argument, check that :qall works. 1021func Test_terminal_qall_kill_arg() 1022 call Run_terminal_qall_kill('term ++kill=kill', '') 1023endfunc 1024 1025" Run Vim, start a terminal in that Vim, set the kill argument with 1026" term_setkill(), check that :qall works. 1027func Test_terminal_qall_kill_func() 1028 call Run_terminal_qall_kill('term', 'eval buf->term_setkill("kill")') 1029endfunc 1030 1031" Run Vim, start a terminal in that Vim without the kill argument, 1032" check that :qall does not exit, :qall! does. 1033func Test_terminal_qall_exit() 1034 let after =<< trim [CODE] 1035 term 1036 let buf = bufnr("%") 1037 while term_getline(buf, 1) =~ "^\\s*$" 1038 sleep 10m 1039 endwhile 1040 set nomore 1041 au VimLeavePre * call writefile(["too early"], "Xdone") 1042 qall 1043 au! VimLeavePre * exe buf . "bwipe!" | call writefile(["done"], "Xdone") 1044 cquit 1045 [CODE] 1046 1047 if !RunVim([], after, '') 1048 return 1049 endif 1050 call assert_equal("done", readfile("Xdone")[0]) 1051 call delete("Xdone") 1052endfunc 1053 1054" Run Vim in a terminal, then start a terminal in that Vim without a kill 1055" argument, check that :confirm qall works. 1056func Test_terminal_qall_prompt() 1057 CheckRunVimInTerminal 1058 let buf = RunVimInTerminal('', {}) 1059 1060 " Open a terminal window and wait for the prompt to appear 1061 call term_sendkeys(buf, ":term\<CR>") 1062 call WaitForAssert({-> assert_match('\[running]', term_getline(buf, 10))}) 1063 call WaitForAssert({-> assert_notmatch('^\s*$', term_getline(buf, 1))}) 1064 1065 " make Vim exit, it will prompt to kill the shell 1066 call term_sendkeys(buf, "\<C-W>:confirm qall\<CR>") 1067 call WaitForAssert({-> assert_match('ancel:', term_getline(buf, 20))}) 1068 call term_sendkeys(buf, "y") 1069 call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))}) 1070 1071 " close the terminal window where Vim was running 1072 quit 1073endfunc 1074 1075" Run Vim in a terminal, then start a terminal window with a shell and check 1076" that Vim exits if it is closed. 1077func Test_terminal_exit() 1078 CheckRunVimInTerminal 1079 1080 let lines =<< trim END 1081 let winid = win_getid() 1082 help 1083 term 1084 let termid = win_getid() 1085 call win_gotoid(winid) 1086 close 1087 call win_gotoid(termid) 1088 END 1089 call writefile(lines, 'XtermExit') 1090 let buf = RunVimInTerminal('-S XtermExit', #{rows: 10}) 1091 let job = term_getjob(buf) 1092 call WaitForAssert({-> assert_equal("run", job_status(job))}) 1093 1094 " quit the shell, it will make Vim exit 1095 call term_sendkeys(buf, "exit\<CR>") 1096 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 1097 1098 call delete('XtermExit') 1099endfunc 1100 1101func Test_terminal_open_autocmd() 1102 augroup repro 1103 au! 1104 au TerminalOpen * let s:called += 1 1105 augroup END 1106 1107 let s:called = 0 1108 1109 " Open a terminal window with :terminal 1110 terminal 1111 call assert_equal(1, s:called) 1112 bwipe! 1113 1114 " Open a terminal window with term_start() 1115 call term_start(&shell) 1116 call assert_equal(2, s:called) 1117 bwipe! 1118 1119 " Open a hidden terminal buffer with :terminal 1120 terminal ++hidden 1121 call assert_equal(3, s:called) 1122 for buf in term_list() 1123 exe buf . "bwipe!" 1124 endfor 1125 1126 " Open a hidden terminal buffer with term_start() 1127 let buf = term_start(&shell, {'hidden': 1}) 1128 call assert_equal(4, s:called) 1129 exe buf . "bwipe!" 1130 1131 unlet s:called 1132 au! repro 1133endfunction 1134 1135func Check_dump01(off) 1136 call assert_equal('one two three four five', trim(getline(a:off + 1))) 1137 call assert_equal('~ Select Word', trim(getline(a:off + 7))) 1138 call assert_equal(':popup PopUp', trim(getline(a:off + 20))) 1139endfunc 1140 1141func Test_terminal_dumpwrite_composing() 1142 CheckRunVimInTerminal 1143 let save_enc = &encoding 1144 set encoding=utf-8 1145 call assert_equal(1, winnr('$')) 1146 1147 let text = " a\u0300 e\u0302 o\u0308" 1148 call writefile([text], 'Xcomposing') 1149 let buf = RunVimInTerminal('--cmd "set encoding=utf-8" Xcomposing', {}) 1150 call WaitForAssert({-> assert_match(text, term_getline(buf, 1))}) 1151 eval 'Xdump'->term_dumpwrite(buf) 1152 let dumpline = readfile('Xdump')[0] 1153 call assert_match('|à| |ê| |ö', dumpline) 1154 1155 call StopVimInTerminal(buf) 1156 call delete('Xcomposing') 1157 call delete('Xdump') 1158 let &encoding = save_enc 1159endfunc 1160 1161" just testing basic functionality. 1162func Test_terminal_dumpload() 1163 let curbuf = winbufnr('') 1164 call assert_equal(1, winnr('$')) 1165 let buf = term_dumpload('dumps/Test_popup_command_01.dump') 1166 call assert_equal(2, winnr('$')) 1167 call assert_equal(20, line('$')) 1168 call Check_dump01(0) 1169 1170 " Load another dump in the same window 1171 let buf2 = 'dumps/Test_diff_01.dump'->term_dumpload({'bufnr': buf}) 1172 call assert_equal(buf, buf2) 1173 call assert_notequal('one two three four five', trim(getline(1))) 1174 1175 " Load the first dump again in the same window 1176 let buf2 = term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': buf}) 1177 call assert_equal(buf, buf2) 1178 call Check_dump01(0) 1179 1180 call assert_fails("call term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': curbuf})", 'E475:') 1181 call assert_fails("call term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': 9999})", 'E86:') 1182 new 1183 let closedbuf = winbufnr('') 1184 quit 1185 call assert_fails("call term_dumpload('dumps/Test_popup_command_01.dump', {'bufnr': closedbuf})", 'E475:') 1186 1187 quit 1188endfunc 1189 1190func Test_terminal_dumpload_dump() 1191 CheckRunVimInTerminal 1192 1193 let lines =<< trim END 1194 call term_dumpload('dumps/Test_popupwin_22.dump', #{term_rows: 12}) 1195 END 1196 call writefile(lines, 'XtermDumpload') 1197 let buf = RunVimInTerminal('-S XtermDumpload', #{rows: 15}) 1198 call VerifyScreenDump(buf, 'Test_terminal_dumpload', {}) 1199 1200 call StopVimInTerminal(buf) 1201 call delete('XtermDumpload') 1202endfunc 1203 1204func Test_terminal_dumpdiff() 1205 call assert_equal(1, winnr('$')) 1206 eval 'dumps/Test_popup_command_01.dump'->term_dumpdiff('dumps/Test_popup_command_02.dump') 1207 call assert_equal(2, winnr('$')) 1208 call assert_equal(62, line('$')) 1209 call Check_dump01(0) 1210 call Check_dump01(42) 1211 call assert_equal(' bbbbbbbbbbbbbbbbbb ', getline(26)[0:29]) 1212 quit 1213endfunc 1214 1215func Test_terminal_dumpdiff_swap() 1216 call assert_equal(1, winnr('$')) 1217 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_03.dump') 1218 call assert_equal(2, winnr('$')) 1219 call assert_equal(62, line('$')) 1220 call assert_match('Test_popup_command_01.dump', getline(21)) 1221 call assert_match('Test_popup_command_03.dump', getline(42)) 1222 call assert_match('Undo', getline(3)) 1223 call assert_match('three four five', getline(45)) 1224 1225 normal s 1226 call assert_match('Test_popup_command_03.dump', getline(21)) 1227 call assert_match('Test_popup_command_01.dump', getline(42)) 1228 call assert_match('three four five', getline(3)) 1229 call assert_match('Undo', getline(45)) 1230 quit 1231endfunc 1232 1233func Test_terminal_dumpdiff_options() 1234 set laststatus=0 1235 call assert_equal(1, winnr('$')) 1236 let height = winheight(0) 1237 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 1, 'term_cols': 33}) 1238 call assert_equal(2, winnr('$')) 1239 call assert_equal(height, winheight(winnr())) 1240 call assert_equal(33, winwidth(winnr())) 1241 call assert_equal('dump diff dumps/Test_popup_command_01.dump', bufname('%')) 1242 quit 1243 1244 call assert_equal(1, winnr('$')) 1245 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 0, 'term_rows': 13, 'term_name': 'something else'}) 1246 call assert_equal(2, winnr('$')) 1247 call assert_equal(&columns, winwidth(0)) 1248 call assert_equal(13, winheight(0)) 1249 call assert_equal('something else', bufname('%')) 1250 quit 1251 1252 call assert_equal(1, winnr('$')) 1253 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'curwin': 1}) 1254 call assert_equal(1, winnr('$')) 1255 bwipe 1256 1257 set laststatus& 1258endfunc 1259 1260func Api_drop_common(options) 1261 call assert_equal(1, winnr('$')) 1262 1263 " Use the title termcap entries to output the escape sequence. 1264 call writefile([ 1265 \ 'set title', 1266 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1267 \ 'let &titlestring = ''["drop","Xtextfile"' . a:options . ']''', 1268 \ 'redraw', 1269 \ "set t_ts=", 1270 \ ], 'Xscript') 1271 let buf = RunVimInTerminal('-S Xscript', {}) 1272 call WaitFor({-> bufnr('Xtextfile') > 0}) 1273 call assert_equal('Xtextfile', expand('%:t')) 1274 call assert_true(winnr('$') >= 3) 1275 return buf 1276endfunc 1277 1278func Test_terminal_api_drop_newwin() 1279 CheckRunVimInTerminal 1280 let buf = Api_drop_common('') 1281 call assert_equal(0, &bin) 1282 call assert_equal('', &fenc) 1283 1284 call StopVimInTerminal(buf) 1285 call delete('Xscript') 1286 bwipe Xtextfile 1287endfunc 1288 1289func Test_terminal_api_drop_newwin_bin() 1290 CheckRunVimInTerminal 1291 let buf = Api_drop_common(',{"bin":1}') 1292 call assert_equal(1, &bin) 1293 1294 call StopVimInTerminal(buf) 1295 call delete('Xscript') 1296 bwipe Xtextfile 1297endfunc 1298 1299func Test_terminal_api_drop_newwin_binary() 1300 CheckRunVimInTerminal 1301 let buf = Api_drop_common(',{"binary":1}') 1302 call assert_equal(1, &bin) 1303 1304 call StopVimInTerminal(buf) 1305 call delete('Xscript') 1306 bwipe Xtextfile 1307endfunc 1308 1309func Test_terminal_api_drop_newwin_nobin() 1310 CheckRunVimInTerminal 1311 set binary 1312 let buf = Api_drop_common(',{"nobin":1}') 1313 call assert_equal(0, &bin) 1314 1315 call StopVimInTerminal(buf) 1316 call delete('Xscript') 1317 bwipe Xtextfile 1318 set nobinary 1319endfunc 1320 1321func Test_terminal_api_drop_newwin_nobinary() 1322 CheckRunVimInTerminal 1323 set binary 1324 let buf = Api_drop_common(',{"nobinary":1}') 1325 call assert_equal(0, &bin) 1326 1327 call StopVimInTerminal(buf) 1328 call delete('Xscript') 1329 bwipe Xtextfile 1330 set nobinary 1331endfunc 1332 1333func Test_terminal_api_drop_newwin_ff() 1334 CheckRunVimInTerminal 1335 let buf = Api_drop_common(',{"ff":"dos"}') 1336 call assert_equal("dos", &ff) 1337 1338 call StopVimInTerminal(buf) 1339 call delete('Xscript') 1340 bwipe Xtextfile 1341endfunc 1342 1343func Test_terminal_api_drop_newwin_fileformat() 1344 CheckRunVimInTerminal 1345 let buf = Api_drop_common(',{"fileformat":"dos"}') 1346 call assert_equal("dos", &ff) 1347 1348 call StopVimInTerminal(buf) 1349 call delete('Xscript') 1350 bwipe Xtextfile 1351endfunc 1352 1353func Test_terminal_api_drop_newwin_enc() 1354 CheckRunVimInTerminal 1355 let buf = Api_drop_common(',{"enc":"utf-16"}') 1356 call assert_equal("utf-16", &fenc) 1357 1358 call StopVimInTerminal(buf) 1359 call delete('Xscript') 1360 bwipe Xtextfile 1361endfunc 1362 1363func Test_terminal_api_drop_newwin_encoding() 1364 CheckRunVimInTerminal 1365 let buf = Api_drop_common(',{"encoding":"utf-16"}') 1366 call assert_equal("utf-16", &fenc) 1367 1368 call StopVimInTerminal(buf) 1369 call delete('Xscript') 1370 bwipe Xtextfile 1371endfunc 1372 1373func Test_terminal_api_drop_oldwin() 1374 CheckRunVimInTerminal 1375 let firstwinid = win_getid() 1376 split Xtextfile 1377 let textfile_winid = win_getid() 1378 call assert_equal(2, winnr('$')) 1379 call win_gotoid(firstwinid) 1380 1381 " Use the title termcap entries to output the escape sequence. 1382 call writefile([ 1383 \ 'set title', 1384 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1385 \ 'let &titlestring = ''["drop","Xtextfile"]''', 1386 \ 'redraw', 1387 \ "set t_ts=", 1388 \ ], 'Xscript') 1389 let buf = RunVimInTerminal('-S Xscript', {'rows': 10}) 1390 call WaitForAssert({-> assert_equal('Xtextfile', expand('%:t'))}) 1391 call assert_equal(textfile_winid, win_getid()) 1392 1393 call StopVimInTerminal(buf) 1394 call delete('Xscript') 1395 bwipe Xtextfile 1396endfunc 1397 1398func Tapi_TryThis(bufnum, arg) 1399 let g:called_bufnum = a:bufnum 1400 let g:called_arg = a:arg 1401endfunc 1402 1403func WriteApiCall(funcname) 1404 " Use the title termcap entries to output the escape sequence. 1405 call writefile([ 1406 \ 'set title', 1407 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1408 \ 'let &titlestring = ''["call","' . a:funcname . '",["hello",123]]''', 1409 \ 'redraw', 1410 \ "set t_ts=", 1411 \ ], 'Xscript') 1412endfunc 1413 1414func Test_terminal_api_call() 1415 CheckRunVimInTerminal 1416 1417 unlet! g:called_bufnum 1418 unlet! g:called_arg 1419 1420 call WriteApiCall('Tapi_TryThis') 1421 1422 " Default 1423 let buf = RunVimInTerminal('-S Xscript', {}) 1424 call WaitFor({-> exists('g:called_bufnum')}) 1425 call assert_equal(buf, g:called_bufnum) 1426 call assert_equal(['hello', 123], g:called_arg) 1427 call StopVimInTerminal(buf) 1428 1429 unlet! g:called_bufnum 1430 unlet! g:called_arg 1431 1432 " Enable explicitly 1433 let buf = RunVimInTerminal('-S Xscript', {'term_api': 'Tapi_Try'}) 1434 call WaitFor({-> exists('g:called_bufnum')}) 1435 call assert_equal(buf, g:called_bufnum) 1436 call assert_equal(['hello', 123], g:called_arg) 1437 call StopVimInTerminal(buf) 1438 1439 unlet! g:called_bufnum 1440 unlet! g:called_arg 1441 1442 func! ApiCall_TryThis(bufnum, arg) 1443 let g:called_bufnum2 = a:bufnum 1444 let g:called_arg2 = a:arg 1445 endfunc 1446 1447 call WriteApiCall('ApiCall_TryThis') 1448 1449 " Use prefix match 1450 let buf = RunVimInTerminal('-S Xscript', {'term_api': 'ApiCall_'}) 1451 call WaitFor({-> exists('g:called_bufnum2')}) 1452 call assert_equal(buf, g:called_bufnum2) 1453 call assert_equal(['hello', 123], g:called_arg2) 1454 call StopVimInTerminal(buf) 1455 1456 unlet! g:called_bufnum2 1457 unlet! g:called_arg2 1458 1459 call delete('Xscript') 1460 delfunction! ApiCall_TryThis 1461 unlet! g:called_bufnum2 1462 unlet! g:called_arg2 1463endfunc 1464 1465func Test_terminal_api_call_fails() 1466 CheckRunVimInTerminal 1467 1468 func! TryThis(bufnum, arg) 1469 let g:called_bufnum3 = a:bufnum 1470 let g:called_arg3 = a:arg 1471 endfunc 1472 1473 call WriteApiCall('TryThis') 1474 1475 unlet! g:called_bufnum3 1476 unlet! g:called_arg3 1477 1478 " Not permitted 1479 call ch_logfile('Xlog', 'w') 1480 let buf = RunVimInTerminal('-S Xscript', {'term_api': ''}) 1481 call WaitForAssert({-> assert_match('Unpermitted function: TryThis', string(readfile('Xlog')))}) 1482 call assert_false(exists('g:called_bufnum3')) 1483 call assert_false(exists('g:called_arg3')) 1484 call StopVimInTerminal(buf) 1485 1486 " No match 1487 call ch_logfile('Xlog', 'w') 1488 let buf = RunVimInTerminal('-S Xscript', {'term_api': 'TryThat'}) 1489 call WaitFor({-> string(readfile('Xlog')) =~ 'Unpermitted function: TryThis'}) 1490 call assert_false(exists('g:called_bufnum3')) 1491 call assert_false(exists('g:called_arg3')) 1492 call StopVimInTerminal(buf) 1493 1494 call delete('Xscript') 1495 call ch_logfile('') 1496 call delete('Xlog') 1497 delfunction! TryThis 1498 unlet! g:called_bufnum3 1499 unlet! g:called_arg3 1500endfunc 1501 1502let s:caught_e937 = 0 1503 1504func Tapi_Delete(bufnum, arg) 1505 try 1506 execute 'bdelete!' a:bufnum 1507 catch /E937:/ 1508 let s:caught_e937 = 1 1509 endtry 1510endfunc 1511 1512func Test_terminal_api_call_fail_delete() 1513 CheckRunVimInTerminal 1514 1515 call WriteApiCall('Tapi_Delete') 1516 let buf = RunVimInTerminal('-S Xscript', {}) 1517 call WaitForAssert({-> assert_equal(1, s:caught_e937)}) 1518 1519 call StopVimInTerminal(buf) 1520 call delete('Xscript') 1521 call ch_logfile('', '') 1522endfunc 1523 1524func Test_terminal_ansicolors_default() 1525 if !exists('*term_getansicolors') 1526 throw 'Skipped: term_getansicolors() not supported' 1527 endif 1528 let colors = [ 1529 \ '#000000', '#e00000', 1530 \ '#00e000', '#e0e000', 1531 \ '#0000e0', '#e000e0', 1532 \ '#00e0e0', '#e0e0e0', 1533 \ '#808080', '#ff4040', 1534 \ '#40ff40', '#ffff40', 1535 \ '#4040ff', '#ff40ff', 1536 \ '#40ffff', '#ffffff', 1537 \] 1538 1539 let buf = Run_shell_in_terminal({}) 1540 call assert_equal(colors, term_getansicolors(buf)) 1541 call StopShellInTerminal(buf) 1542 call term_wait(buf) 1543 1544 exe buf . 'bwipe' 1545endfunc 1546 1547let s:test_colors = [ 1548 \ '#616e64', '#0d0a79', 1549 \ '#6d610d', '#0a7373', 1550 \ '#690d0a', '#6d696e', 1551 \ '#0d0a6f', '#616e0d', 1552 \ '#0a6479', '#6d0d0a', 1553 \ '#617373', '#0d0a69', 1554 \ '#6d690d', '#0a6e6f', 1555 \ '#610d0a', '#6e6479', 1556 \] 1557 1558func Test_terminal_ansicolors_global() 1559 CheckFeature termguicolors 1560 if !exists('*term_getansicolors') 1561 throw 'Skipped: term_getansicolors() not supported' 1562 endif 1563 let g:terminal_ansi_colors = reverse(copy(s:test_colors)) 1564 let buf = Run_shell_in_terminal({}) 1565 call assert_equal(g:terminal_ansi_colors, term_getansicolors(buf)) 1566 call StopShellInTerminal(buf) 1567 call term_wait(buf) 1568 1569 exe buf . 'bwipe' 1570 unlet g:terminal_ansi_colors 1571endfunc 1572 1573func Test_terminal_ansicolors_func() 1574 CheckFeature termguicolors 1575 if !exists('*term_getansicolors') 1576 throw 'Skipped: term_getansicolors() not supported' 1577 endif 1578 let g:terminal_ansi_colors = reverse(copy(s:test_colors)) 1579 let buf = Run_shell_in_terminal({'ansi_colors': s:test_colors}) 1580 call assert_equal(s:test_colors, term_getansicolors(buf)) 1581 1582 call term_setansicolors(buf, g:terminal_ansi_colors) 1583 call assert_equal(g:terminal_ansi_colors, buf->term_getansicolors()) 1584 1585 let colors = [ 1586 \ 'ivory', 'AliceBlue', 1587 \ 'grey67', 'dark goldenrod', 1588 \ 'SteelBlue3', 'PaleVioletRed4', 1589 \ 'MediumPurple2', 'yellow2', 1590 \ 'RosyBrown3', 'OrangeRed2', 1591 \ 'white smoke', 'navy blue', 1592 \ 'grey47', 'gray97', 1593 \ 'MistyRose2', 'DodgerBlue4', 1594 \] 1595 eval buf->term_setansicolors(colors) 1596 1597 let colors[4] = 'Invalid' 1598 call assert_fails('call term_setansicolors(buf, colors)', 'E474:') 1599 1600 call StopShellInTerminal(buf) 1601 call term_wait(buf) 1602 exe buf . 'bwipe' 1603endfunc 1604 1605func Test_terminal_all_ansi_colors() 1606 CheckRunVimInTerminal 1607 1608 " Use all the ANSI colors. 1609 call writefile([ 1610 \ 'call setline(1, "AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPP XXYYZZ")', 1611 \ 'hi Tblack ctermfg=0 ctermbg=8', 1612 \ 'hi Tdarkred ctermfg=1 ctermbg=9', 1613 \ 'hi Tdarkgreen ctermfg=2 ctermbg=10', 1614 \ 'hi Tbrown ctermfg=3 ctermbg=11', 1615 \ 'hi Tdarkblue ctermfg=4 ctermbg=12', 1616 \ 'hi Tdarkmagenta ctermfg=5 ctermbg=13', 1617 \ 'hi Tdarkcyan ctermfg=6 ctermbg=14', 1618 \ 'hi Tlightgrey ctermfg=7 ctermbg=15', 1619 \ 'hi Tdarkgrey ctermfg=8 ctermbg=0', 1620 \ 'hi Tred ctermfg=9 ctermbg=1', 1621 \ 'hi Tgreen ctermfg=10 ctermbg=2', 1622 \ 'hi Tyellow ctermfg=11 ctermbg=3', 1623 \ 'hi Tblue ctermfg=12 ctermbg=4', 1624 \ 'hi Tmagenta ctermfg=13 ctermbg=5', 1625 \ 'hi Tcyan ctermfg=14 ctermbg=6', 1626 \ 'hi Twhite ctermfg=15 ctermbg=7', 1627 \ 'hi TdarkredBold ctermfg=1 cterm=bold', 1628 \ 'hi TgreenBold ctermfg=10 cterm=bold', 1629 \ 'hi TmagentaBold ctermfg=13 cterm=bold ctermbg=5', 1630 \ '', 1631 \ 'call matchadd("Tblack", "A")', 1632 \ 'call matchadd("Tdarkred", "B")', 1633 \ 'call matchadd("Tdarkgreen", "C")', 1634 \ 'call matchadd("Tbrown", "D")', 1635 \ 'call matchadd("Tdarkblue", "E")', 1636 \ 'call matchadd("Tdarkmagenta", "F")', 1637 \ 'call matchadd("Tdarkcyan", "G")', 1638 \ 'call matchadd("Tlightgrey", "H")', 1639 \ 'call matchadd("Tdarkgrey", "I")', 1640 \ 'call matchadd("Tred", "J")', 1641 \ 'call matchadd("Tgreen", "K")', 1642 \ 'call matchadd("Tyellow", "L")', 1643 \ 'call matchadd("Tblue", "M")', 1644 \ 'call matchadd("Tmagenta", "N")', 1645 \ 'call matchadd("Tcyan", "O")', 1646 \ 'call matchadd("Twhite", "P")', 1647 \ 'call matchadd("TdarkredBold", "X")', 1648 \ 'call matchadd("TgreenBold", "Y")', 1649 \ 'call matchadd("TmagentaBold", "Z")', 1650 \ 'redraw', 1651 \ ], 'Xcolorscript') 1652 let buf = RunVimInTerminal('-S Xcolorscript', {'rows': 10}) 1653 call VerifyScreenDump(buf, 'Test_terminal_all_ansi_colors', {}) 1654 1655 call term_sendkeys(buf, ":q\<CR>") 1656 call StopVimInTerminal(buf) 1657 call delete('Xcolorscript') 1658endfunc 1659 1660func Test_terminal_termwinsize_option_fixed() 1661 CheckRunVimInTerminal 1662 set termwinsize=6x40 1663 let text = [] 1664 for n in range(10) 1665 call add(text, repeat(n, 50)) 1666 endfor 1667 call writefile(text, 'Xwinsize') 1668 let buf = RunVimInTerminal('Xwinsize', {}) 1669 let win = bufwinid(buf) 1670 call assert_equal([6, 40], term_getsize(buf)) 1671 call assert_equal(6, winheight(win)) 1672 call assert_equal(40, winwidth(win)) 1673 1674 " resizing the window doesn't resize the terminal. 1675 resize 10 1676 vertical resize 60 1677 call assert_equal([6, 40], term_getsize(buf)) 1678 call assert_equal(10, winheight(win)) 1679 call assert_equal(60, winwidth(win)) 1680 1681 call StopVimInTerminal(buf) 1682 call delete('Xwinsize') 1683 1684 call assert_fails('set termwinsize=40', 'E474') 1685 call assert_fails('set termwinsize=10+40', 'E474') 1686 call assert_fails('set termwinsize=abc', 'E474') 1687 1688 set termwinsize= 1689endfunc 1690 1691func Test_terminal_termwinsize_option_zero() 1692 set termwinsize=0x0 1693 let buf = Run_shell_in_terminal({}) 1694 let win = bufwinid(buf) 1695 call assert_equal([winheight(win), winwidth(win)], term_getsize(buf)) 1696 call StopShellInTerminal(buf) 1697 call term_wait(buf) 1698 exe buf . 'bwipe' 1699 1700 set termwinsize=7x0 1701 let buf = Run_shell_in_terminal({}) 1702 let win = bufwinid(buf) 1703 call assert_equal([7, winwidth(win)], term_getsize(buf)) 1704 call StopShellInTerminal(buf) 1705 call term_wait(buf) 1706 exe buf . 'bwipe' 1707 1708 set termwinsize=0x33 1709 let buf = Run_shell_in_terminal({}) 1710 let win = bufwinid(buf) 1711 call assert_equal([winheight(win), 33], term_getsize(buf)) 1712 call StopShellInTerminal(buf) 1713 call term_wait(buf) 1714 exe buf . 'bwipe' 1715 1716 set termwinsize= 1717endfunc 1718 1719func Test_terminal_termwinsize_minimum() 1720 set termwinsize=10*50 1721 vsplit 1722 let buf = Run_shell_in_terminal({}) 1723 let win = bufwinid(buf) 1724 call assert_inrange(10, 1000, winheight(win)) 1725 call assert_inrange(50, 1000, winwidth(win)) 1726 call assert_equal([winheight(win), winwidth(win)], term_getsize(buf)) 1727 1728 resize 15 1729 vertical resize 60 1730 redraw 1731 call assert_equal([15, 60], term_getsize(buf)) 1732 call assert_equal(15, winheight(win)) 1733 call assert_equal(60, winwidth(win)) 1734 1735 resize 7 1736 vertical resize 30 1737 redraw 1738 call assert_equal([10, 50], term_getsize(buf)) 1739 call assert_equal(7, winheight(win)) 1740 call assert_equal(30, winwidth(win)) 1741 1742 call StopShellInTerminal(buf) 1743 call term_wait(buf) 1744 exe buf . 'bwipe' 1745 1746 set termwinsize=0*0 1747 let buf = Run_shell_in_terminal({}) 1748 let win = bufwinid(buf) 1749 call assert_equal([winheight(win), winwidth(win)], term_getsize(buf)) 1750 call StopShellInTerminal(buf) 1751 call term_wait(buf) 1752 exe buf . 'bwipe' 1753 1754 set termwinsize= 1755endfunc 1756 1757func Test_terminal_termwinkey() 1758 " make three tabpages, terminal in the middle 1759 0tabnew 1760 tabnext 1761 tabnew 1762 tabprev 1763 call assert_equal(1, winnr('$')) 1764 call assert_equal(2, tabpagenr()) 1765 let thiswin = win_getid() 1766 1767 let buf = Run_shell_in_terminal({}) 1768 let termwin = bufwinid(buf) 1769 set termwinkey=<C-L> 1770 call feedkeys("\<C-L>w", 'tx') 1771 call assert_equal(thiswin, win_getid()) 1772 call feedkeys("\<C-W>w", 'tx') 1773 call assert_equal(termwin, win_getid()) 1774 1775 if has('langmap') 1776 set langmap=xjyk 1777 call feedkeys("\<C-L>x", 'tx') 1778 call assert_equal(thiswin, win_getid()) 1779 call feedkeys("\<C-W>y", 'tx') 1780 call assert_equal(termwin, win_getid()) 1781 set langmap= 1782 endif 1783 1784 call feedkeys("\<C-L>gt", "xt") 1785 call assert_equal(3, tabpagenr()) 1786 tabprev 1787 call assert_equal(2, tabpagenr()) 1788 call assert_equal(termwin, win_getid()) 1789 1790 call feedkeys("\<C-L>gT", "xt") 1791 call assert_equal(1, tabpagenr()) 1792 tabnext 1793 call assert_equal(2, tabpagenr()) 1794 call assert_equal(termwin, win_getid()) 1795 1796 let job = term_getjob(buf) 1797 call feedkeys("\<C-L>\<C-C>", 'tx') 1798 call WaitForAssert({-> assert_equal("dead", job_status(job))}) 1799 1800 set termwinkey& 1801 tabnext 1802 tabclose 1803 tabprev 1804 tabclose 1805endfunc 1806 1807func Test_terminal_out_err() 1808 CheckUnix 1809 1810 call writefile([ 1811 \ '#!/bin/sh', 1812 \ 'echo "this is standard error" >&2', 1813 \ 'echo "this is standard out" >&1', 1814 \ ], 'Xechoerrout.sh') 1815 call setfperm('Xechoerrout.sh', 'rwxrwx---') 1816 1817 let outfile = 'Xtermstdout' 1818 let buf = term_start(['./Xechoerrout.sh'], {'out_io': 'file', 'out_name': outfile}) 1819 1820 call WaitFor({-> !empty(readfile(outfile)) && !empty(term_getline(buf, 1))}) 1821 call assert_equal(['this is standard out'], readfile(outfile)) 1822 call assert_equal('this is standard error', term_getline(buf, 1)) 1823 1824 call WaitForAssert({-> assert_equal('dead', job_status(term_getjob(buf)))}) 1825 exe buf . 'bwipe' 1826 call delete('Xechoerrout.sh') 1827 call delete(outfile) 1828endfunc 1829 1830func Test_termwinscroll() 1831 CheckUnix 1832 1833 " Let the terminal output more than 'termwinscroll' lines, some at the start 1834 " will be dropped. 1835 exe 'set termwinscroll=' . &lines 1836 let buf = term_start('/bin/sh') 1837 for i in range(1, &lines) 1838 call feedkeys("echo " . i . "\<CR>", 'xt') 1839 call WaitForAssert({-> assert_match(string(i), term_getline(buf, term_getcursor(buf)[0] - 1))}) 1840 endfor 1841 " Go to Terminal-Normal mode to update the buffer. 1842 call feedkeys("\<C-W>N", 'xt') 1843 call assert_inrange(&lines, &lines * 110 / 100 + winheight(0), line('$')) 1844 1845 " Every "echo nr" must only appear once 1846 let lines = getline(1, line('$')) 1847 for i in range(&lines - len(lines) / 2 + 2, &lines) 1848 let filtered = filter(copy(lines), {idx, val -> val =~ 'echo ' . i . '\>'}) 1849 call assert_equal(1, len(filtered), 'for "echo ' . i . '"') 1850 endfor 1851 1852 exe buf . 'bwipe!' 1853endfunc 1854 1855" Resizing the terminal window caused an ml_get error. 1856" TODO: This does not reproduce the original problem. 1857func Test_terminal_resize() 1858 set statusline=x 1859 terminal 1860 call assert_equal(2, winnr('$')) 1861 1862 " Fill the terminal with text. 1863 if has('win32') 1864 call feedkeys("dir\<CR>", 'xt') 1865 else 1866 call feedkeys("ls\<CR>", 'xt') 1867 endif 1868 " Go to Terminal-Normal mode for a moment. 1869 call feedkeys("\<C-W>N", 'xt') 1870 " Open a new window 1871 call feedkeys("i\<C-W>n", 'xt') 1872 call assert_equal(3, winnr('$')) 1873 redraw 1874 1875 close 1876 call assert_equal(2, winnr('$')) 1877 call feedkeys("exit\<CR>", 'xt') 1878 set statusline& 1879endfunc 1880 1881" must be nearly the last, we can't go back from GUI to terminal 1882func Test_zz1_terminal_in_gui() 1883 CheckCanRunGui 1884 1885 " Ignore the "failed to create input context" error. 1886 call test_ignore_error('E285:') 1887 1888 gui -f 1889 1890 call assert_equal(1, winnr('$')) 1891 let buf = Run_shell_in_terminal({'term_finish': 'close'}) 1892 call StopShellInTerminal(buf) 1893 call term_wait(buf) 1894 1895 " closing window wipes out the terminal buffer a with finished job 1896 call WaitForAssert({-> assert_equal(1, winnr('$'))}) 1897 call assert_equal("", bufname(buf)) 1898 1899 unlet g:job 1900endfunc 1901 1902func Test_zz2_terminal_guioptions_bang() 1903 CheckGui 1904 set guioptions+=! 1905 1906 let filename = 'Xtestscript' 1907 if has('win32') 1908 let filename .= '.bat' 1909 let prefix = '' 1910 let contents = ['@echo off', 'exit %1'] 1911 else 1912 let filename .= '.sh' 1913 let prefix = './' 1914 let contents = ['#!/bin/sh', 'exit $1'] 1915 endif 1916 call writefile(contents, filename) 1917 call setfperm(filename, 'rwxrwx---') 1918 1919 " Check if v:shell_error is equal to the exit status. 1920 let exitval = 0 1921 execute printf(':!%s%s %d', prefix, filename, exitval) 1922 call assert_equal(exitval, v:shell_error) 1923 1924 let exitval = 9 1925 execute printf(':!%s%s %d', prefix, filename, exitval) 1926 call assert_equal(exitval, v:shell_error) 1927 1928 set guioptions& 1929 call delete(filename) 1930endfunc 1931 1932func Test_terminal_hidden() 1933 CheckUnix 1934 1935 term ++hidden cat 1936 let bnr = bufnr('$') 1937 call assert_equal('terminal', getbufvar(bnr, '&buftype')) 1938 exe 'sbuf ' . bnr 1939 call assert_equal('terminal', &buftype) 1940 call term_sendkeys(bnr, "asdf\<CR>") 1941 call WaitForAssert({-> assert_match('asdf', term_getline(bnr, 2))}) 1942 call term_sendkeys(bnr, "\<C-D>") 1943 call WaitForAssert({-> assert_equal('finished', bnr->term_getstatus())}) 1944 bwipe! 1945endfunc 1946 1947func Test_terminal_switch_mode() 1948 term 1949 let bnr = bufnr('$') 1950 call WaitForAssert({-> assert_equal('running', term_getstatus(bnr))}) 1951 call feedkeys("\<C-W>N", 'xt') 1952 call WaitForAssert({-> assert_equal('running,normal', term_getstatus(bnr))}) 1953 call feedkeys("A", 'xt') 1954 call WaitForAssert({-> assert_equal('running', term_getstatus(bnr))}) 1955 call feedkeys("\<C-W>N", 'xt') 1956 call WaitForAssert({-> assert_equal('running,normal', term_getstatus(bnr))}) 1957 call feedkeys("I", 'xt') 1958 call WaitForAssert({-> assert_equal('running', term_getstatus(bnr))}) 1959 call feedkeys("\<C-W>Nv", 'xt') 1960 call WaitForAssert({-> assert_equal('running,normal', term_getstatus(bnr))}) 1961 call feedkeys("I", 'xt') 1962 call WaitForAssert({-> assert_equal('running', term_getstatus(bnr))}) 1963 call feedkeys("\<C-W>Nv", 'xt') 1964 call WaitForAssert({-> assert_equal('running,normal', term_getstatus(bnr))}) 1965 call feedkeys("A", 'xt') 1966 call WaitForAssert({-> assert_equal('running', term_getstatus(bnr))}) 1967 bwipe! 1968endfunc 1969 1970func Test_terminal_normal_mode() 1971 CheckRunVimInTerminal 1972 1973 " Run Vim in a terminal and open a terminal window to run Vim in. 1974 let lines =<< trim END 1975 call setline(1, range(11111, 11122)) 1976 3 1977 END 1978 call writefile(lines, 'XtermNormal') 1979 let buf = RunVimInTerminal('-S XtermNormal', {'rows': 8}) 1980 call term_wait(buf) 1981 1982 call term_sendkeys(buf, "\<C-W>N") 1983 call term_sendkeys(buf, ":set number cursorline culopt=both\r") 1984 call VerifyScreenDump(buf, 'Test_terminal_normal_1', {}) 1985 1986 call term_sendkeys(buf, ":set culopt=number\r") 1987 call VerifyScreenDump(buf, 'Test_terminal_normal_2', {}) 1988 1989 call term_sendkeys(buf, ":set culopt=line\r") 1990 call VerifyScreenDump(buf, 'Test_terminal_normal_3', {}) 1991 1992 call term_sendkeys(buf, "a:q!\<CR>:q\<CR>:q\<CR>") 1993 call StopVimInTerminal(buf) 1994 call delete('XtermNormal') 1995endfunc 1996 1997func Test_terminal_hidden_and_close() 1998 CheckUnix 1999 2000 call assert_equal(1, winnr('$')) 2001 term ++hidden ++close ls 2002 let bnr = bufnr('$') 2003 call assert_equal('terminal', getbufvar(bnr, '&buftype')) 2004 call WaitForAssert({-> assert_false(bufexists(bnr))}) 2005 call assert_equal(1, winnr('$')) 2006endfunc 2007 2008func Test_terminal_does_not_truncate_last_newlines() 2009 " This test does not pass through ConPTY. 2010 if has('conpty') 2011 return 2012 endif 2013 let contents = [ 2014 \ [ 'One', '', 'X' ], 2015 \ [ 'Two', '', '' ], 2016 \ [ 'Three' ] + repeat([''], 30) 2017 \ ] 2018 2019 for c in contents 2020 call writefile(c, 'Xfile') 2021 if has('win32') 2022 term cmd /c type Xfile 2023 else 2024 term cat Xfile 2025 endif 2026 let bnr = bufnr('$') 2027 call assert_equal('terminal', getbufvar(bnr, '&buftype')) 2028 call WaitForAssert({-> assert_equal('finished', term_getstatus(bnr))}) 2029 sleep 100m 2030 call assert_equal(c, getline(1, line('$'))) 2031 quit 2032 endfor 2033 2034 call delete('Xfile') 2035endfunc 2036 2037func Test_terminal_no_job() 2038 if has('win32') 2039 let cmd = 'cmd /c ""' 2040 else 2041 CheckExecutable false 2042 let cmd = 'false' 2043 endif 2044 let term = term_start(cmd, {'term_finish': 'close'}) 2045 call WaitForAssert({-> assert_equal(v:null, term_getjob(term)) }) 2046endfunc 2047 2048func Test_term_getcursor() 2049 CheckUnix 2050 2051 let buf = Run_shell_in_terminal({}) 2052 2053 " Wait for the shell to display a prompt. 2054 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))}) 2055 2056 " Hide the cursor. 2057 call term_sendkeys(buf, "echo -e '\\033[?25l'\r") 2058 call WaitForAssert({-> assert_equal(0, term_getcursor(buf)[2].visible)}) 2059 2060 " Show the cursor. 2061 call term_sendkeys(buf, "echo -e '\\033[?25h'\r") 2062 call WaitForAssert({-> assert_equal(1, buf->term_getcursor()[2].visible)}) 2063 2064 " Change color of cursor. 2065 call WaitForAssert({-> assert_equal('', term_getcursor(buf)[2].color)}) 2066 call term_sendkeys(buf, "echo -e '\\033]12;blue\\007'\r") 2067 call WaitForAssert({-> assert_equal('blue', term_getcursor(buf)[2].color)}) 2068 call term_sendkeys(buf, "echo -e '\\033]12;green\\007'\r") 2069 call WaitForAssert({-> assert_equal('green', term_getcursor(buf)[2].color)}) 2070 2071 " Make cursor a blinking block. 2072 call term_sendkeys(buf, "echo -e '\\033[1 q'\r") 2073 call WaitForAssert({-> assert_equal([1, 1], 2074 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2075 2076 " Make cursor a steady block. 2077 call term_sendkeys(buf, "echo -e '\\033[2 q'\r") 2078 call WaitForAssert({-> assert_equal([0, 1], 2079 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2080 2081 " Make cursor a blinking underline. 2082 call term_sendkeys(buf, "echo -e '\\033[3 q'\r") 2083 call WaitForAssert({-> assert_equal([1, 2], 2084 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2085 2086 " Make cursor a steady underline. 2087 call term_sendkeys(buf, "echo -e '\\033[4 q'\r") 2088 call WaitForAssert({-> assert_equal([0, 2], 2089 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2090 2091 " Make cursor a blinking vertical bar. 2092 call term_sendkeys(buf, "echo -e '\\033[5 q'\r") 2093 call WaitForAssert({-> assert_equal([1, 3], 2094 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2095 2096 " Make cursor a steady vertical bar. 2097 call term_sendkeys(buf, "echo -e '\\033[6 q'\r") 2098 call WaitForAssert({-> assert_equal([0, 3], 2099 \ [term_getcursor(buf)[2].blink, term_getcursor(buf)[2].shape])}) 2100 2101 call StopShellInTerminal(buf) 2102endfunc 2103 2104func Test_term_gettitle() 2105 " term_gettitle() returns an empty string for a non-terminal buffer 2106 " and for a non-existing buffer. 2107 call assert_equal('', bufnr('%')->term_gettitle()) 2108 call assert_equal('', term_gettitle(bufnr('$') + 1)) 2109 2110 if !has('title') || &title == 0 || empty(&t_ts) 2111 throw "Skipped: can't get/set title" 2112 endif 2113 2114 let term = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile']) 2115 if has('autoservername') 2116 call WaitForAssert({-> assert_match('^\[No Name\] - VIM\d\+$', term_gettitle(term)) }) 2117 call term_sendkeys(term, ":e Xfoo\r") 2118 call WaitForAssert({-> assert_match('^Xfoo (.*[/\\]testdir) - VIM\d\+$', term_gettitle(term)) }) 2119 else 2120 call WaitForAssert({-> assert_equal('[No Name] - VIM', term_gettitle(term)) }) 2121 call term_sendkeys(term, ":e Xfoo\r") 2122 call WaitForAssert({-> assert_match('^Xfoo (.*[/\\]testdir) - VIM$', term_gettitle(term)) }) 2123 endif 2124 2125 call term_sendkeys(term, ":set titlestring=foo\r") 2126 call WaitForAssert({-> assert_equal('foo', term_gettitle(term)) }) 2127 2128 exe term . 'bwipe!' 2129endfunc 2130 2131" When drawing the statusline the cursor position may not have been updated 2132" yet. 2133" 1. create a terminal, make it show 2 lines 2134" 2. 0.5 sec later: leave terminal window, execute "i" 2135" 3. 0.5 sec later: clear terminal window, now it's 1 line 2136" 4. 0.5 sec later: redraw, including statusline (used to trigger bug) 2137" 4. 0.5 sec later: should be done, clean up 2138func Test_terminal_statusline() 2139 CheckUnix 2140 2141 set statusline=x 2142 terminal 2143 let tbuf = bufnr('') 2144 call term_sendkeys(tbuf, "clear; echo a; echo b; sleep 1; clear\n") 2145 call timer_start(500, { tid -> feedkeys("\<C-w>j", 'tx') }) 2146 call timer_start(1500, { tid -> feedkeys("\<C-l>", 'tx') }) 2147 au BufLeave * if &buftype == 'terminal' | silent! normal i | endif 2148 2149 sleep 2 2150 exe tbuf . 'bwipe!' 2151 au! BufLeave 2152 set statusline= 2153endfunc 2154 2155func Test_terminal_getwinpos() 2156 CheckRunVimInTerminal 2157 2158 " split, go to the bottom-right window 2159 split 2160 wincmd j 2161 set splitright 2162 2163 call writefile([ 2164 \ 'echo getwinpos()', 2165 \ ], 'XTest_getwinpos') 2166 let buf = RunVimInTerminal('-S XTest_getwinpos', {'cols': 60}) 2167 call term_wait(buf) 2168 2169 " Find the output of getwinpos() in the bottom line. 2170 let rows = term_getsize(buf)[0] 2171 call WaitForAssert({-> assert_match('\[\d\+, \d\+\]', term_getline(buf, rows))}) 2172 let line = term_getline(buf, rows) 2173 let xpos = str2nr(substitute(line, '\[\(\d\+\), \d\+\]', '\1', '')) 2174 let ypos = str2nr(substitute(line, '\[\d\+, \(\d\+\)\]', '\1', '')) 2175 2176 " Position must be bigger than the getwinpos() result of Vim itself. 2177 " The calculation in the console assumes a 10 x 7 character cell. 2178 " In the GUI it can be more, let's assume a 20 x 14 cell. 2179 " And then add 100 / 200 tolerance. 2180 let [xroot, yroot] = getwinpos() 2181 let winpos = 50->getwinpos() 2182 call assert_equal(xroot, winpos[0]) 2183 call assert_equal(yroot, winpos[1]) 2184 let [winrow, wincol] = win_screenpos('.') 2185 let xoff = wincol * (has('gui_running') ? 14 : 7) + 100 2186 let yoff = winrow * (has('gui_running') ? 20 : 10) + 200 2187 call assert_inrange(xroot + 2, xroot + xoff, xpos) 2188 call assert_inrange(yroot + 2, yroot + yoff, ypos) 2189 2190 call term_wait(buf) 2191 call term_sendkeys(buf, ":q\<CR>") 2192 call StopVimInTerminal(buf) 2193 call delete('XTest_getwinpos') 2194 exe buf . 'bwipe!' 2195 set splitright& 2196 only! 2197endfunc 2198 2199func Test_terminal_altscreen() 2200 " somehow doesn't work on MS-Windows 2201 CheckUnix 2202 let cmd = "cat Xtext\<CR>" 2203 2204 let buf = term_start(&shell, {}) 2205 call writefile(["\<Esc>[?1047h"], 'Xtext') 2206 call term_sendkeys(buf, cmd) 2207 call WaitForAssert({-> assert_equal(1, term_getaltscreen(buf))}) 2208 2209 call writefile(["\<Esc>[?1047l"], 'Xtext') 2210 call term_sendkeys(buf, cmd) 2211 call WaitForAssert({-> assert_equal(0, term_getaltscreen(buf))}) 2212 2213 call term_sendkeys(buf, "exit\r") 2214 exe buf . "bwipe!" 2215 call delete('Xtext') 2216endfunc 2217 2218func Test_terminal_shell_option() 2219 if has('unix') 2220 " exec is a shell builtin command, should fail without a shell. 2221 term exec ls runtest.vim 2222 call WaitForAssert({-> assert_match('job failed', term_getline(bufnr(), 1))}) 2223 bwipe! 2224 2225 term ++shell exec ls runtest.vim 2226 call WaitForAssert({-> assert_match('runtest.vim', term_getline(bufnr(), 1))}) 2227 bwipe! 2228 elseif has('win32') 2229 " dir is a shell builtin command, should fail without a shell. 2230 try 2231 term dir /b runtest.vim 2232 call WaitForAssert({-> assert_match('job failed\|cannot access .*: No such file or directory', term_getline(bufnr(), 1))}) 2233 catch /CreateProcess/ 2234 " ignore 2235 endtry 2236 bwipe! 2237 2238 term ++shell dir /b runtest.vim 2239 call WaitForAssert({-> assert_match('runtest.vim', term_getline(bufnr(), 1))}) 2240 bwipe! 2241 endif 2242endfunc 2243 2244func Test_terminal_setapi_and_call() 2245 if !CanRunVimInTerminal() 2246 return 2247 endif 2248 2249 call WriteApiCall('Tapi_TryThis') 2250 call ch_logfile('Xlog', 'w') 2251 2252 unlet! g:called_bufnum 2253 unlet! g:called_arg 2254 2255 let buf = RunVimInTerminal('-S Xscript', {'term_api': 0}) 2256 call WaitForAssert({-> assert_match('Unpermitted function: Tapi_TryThis', string(readfile('Xlog')))}) 2257 call assert_false(exists('g:called_bufnum')) 2258 call assert_false(exists('g:called_arg')) 2259 2260 call term_setapi(buf, 'Tapi_TryThis') 2261 call term_sendkeys(buf, ":set notitle\<CR>") 2262 call term_sendkeys(buf, ":source Xscript\<CR>") 2263 call WaitFor({-> exists('g:called_bufnum')}) 2264 call assert_equal(buf, g:called_bufnum) 2265 call assert_equal(['hello', 123], g:called_arg) 2266 call StopVimInTerminal(buf) 2267 2268 call delete('Xscript') 2269 call ch_logfile('') 2270 call delete('Xlog') 2271 unlet! g:called_bufnum 2272 unlet! g:called_arg 2273endfunc 2274