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