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