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 BufWinEnter * if &buftype == 'terminal' | let b:done = 'yes' | endif 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 call assert_match('^\\\\.\\pipe\\', job_info(g:job).tty_out) 43 call assert_match('^\\\\.\\pipe\\', term_gettty('')) 44 endif 45 call assert_equal('t', mode()) 46 call assert_equal('yes', b:done) 47 call assert_match('%aR[^\n]*running]', execute('ls')) 48 call assert_match('%aR[^\n]*running]', execute('ls R')) 49 call assert_notmatch('%[^\n]*running]', execute('ls F')) 50 call assert_notmatch('%[^\n]*running]', execute('ls ?')) 51 52 call Stop_shell_in_terminal(buf) 53 call term_wait(buf) 54 call assert_equal('n', mode()) 55 call assert_match('%aF[^\n]*finished]', execute('ls')) 56 call assert_match('%aF[^\n]*finished]', execute('ls F')) 57 call assert_notmatch('%[^\n]*finished]', execute('ls R')) 58 call assert_notmatch('%[^\n]*finished]', execute('ls ?')) 59 60 " closing window wipes out the terminal buffer a with finished job 61 close 62 call assert_equal("", bufname(buf)) 63 64 au! BufWinEnter 65 unlet g:job 66endfunc 67 68func Test_terminal_make_change() 69 let buf = Run_shell_in_terminal({}) 70 call Stop_shell_in_terminal(buf) 71 call term_wait(buf) 72 73 setlocal modifiable 74 exe "normal Axxx\<Esc>" 75 call assert_fails(buf . 'bwipe', 'E517') 76 undo 77 78 exe buf . 'bwipe' 79 unlet g:job 80endfunc 81 82func Test_terminal_wipe_buffer() 83 let buf = Run_shell_in_terminal({}) 84 call assert_fails(buf . 'bwipe', 'E517') 85 exe buf . 'bwipe!' 86 call WaitFor('job_status(g:job) == "dead"') 87 call assert_equal('dead', job_status(g:job)) 88 call assert_equal("", bufname(buf)) 89 90 unlet g:job 91endfunc 92 93func Test_terminal_split_quit() 94 let buf = Run_shell_in_terminal({}) 95 call term_wait(buf) 96 split 97 quit! 98 call term_wait(buf) 99 sleep 50m 100 call assert_equal('run', job_status(g:job)) 101 102 quit! 103 call WaitFor('job_status(g:job) == "dead"') 104 call assert_equal('dead', job_status(g:job)) 105 106 exe buf . 'bwipe' 107 unlet g:job 108endfunc 109 110func Test_terminal_hide_buffer() 111 let buf = Run_shell_in_terminal({}) 112 setlocal bufhidden=hide 113 quit 114 for nr in range(1, winnr('$')) 115 call assert_notequal(winbufnr(nr), buf) 116 endfor 117 call assert_true(bufloaded(buf)) 118 call assert_true(buflisted(buf)) 119 120 exe 'split ' . buf . 'buf' 121 call Stop_shell_in_terminal(buf) 122 exe buf . 'bwipe' 123 124 unlet g:job 125endfunc 126 127func! s:Nasty_exit_cb(job, st) 128 exe g:buf . 'bwipe!' 129 let g:buf = 0 130endfunc 131 132func Get_cat_123_cmd() 133 if has('win32') 134 return 'cmd /c "cls && color 2 && echo 123"' 135 else 136 call writefile(["\<Esc>[32m123"], 'Xtext') 137 return "cat Xtext" 138 endif 139endfunc 140 141func Test_terminal_nasty_cb() 142 let cmd = Get_cat_123_cmd() 143 let g:buf = term_start(cmd, {'exit_cb': function('s:Nasty_exit_cb')}) 144 let g:job = term_getjob(g:buf) 145 146 call WaitFor('job_status(g:job) == "dead"') 147 call WaitFor('g:buf == 0') 148 unlet g:buf 149 unlet g:job 150 call delete('Xtext') 151endfunc 152 153func Check_123(buf) 154 let l = term_scrape(a:buf, 0) 155 call assert_true(len(l) == 0) 156 let l = term_scrape(a:buf, 999) 157 call assert_true(len(l) == 0) 158 let l = term_scrape(a:buf, 1) 159 call assert_true(len(l) > 0) 160 call assert_equal('1', l[0].chars) 161 call assert_equal('2', l[1].chars) 162 call assert_equal('3', l[2].chars) 163 call assert_equal('#00e000', l[0].fg) 164 if &background == 'light' 165 call assert_equal('#ffffff', l[0].bg) 166 else 167 call assert_equal('#000000', l[0].bg) 168 endif 169 170 let l = term_getline(a:buf, -1) 171 call assert_equal('', l) 172 let l = term_getline(a:buf, 0) 173 call assert_equal('', l) 174 let l = term_getline(a:buf, 999) 175 call assert_equal('', l) 176 let l = term_getline(a:buf, 1) 177 call assert_equal('123', l) 178endfunc 179 180func Test_terminal_scrape_123() 181 let cmd = Get_cat_123_cmd() 182 let buf = term_start(cmd) 183 184 let termlist = term_list() 185 call assert_equal(1, len(termlist)) 186 call assert_equal(buf, termlist[0]) 187 188 " Nothing happens with invalid buffer number 189 call term_wait(1234) 190 191 call term_wait(buf) 192 " On MS-Windows we first get a startup message of two lines, wait for the 193 " "cls" to happen, after that we have one line with three characters. 194 call WaitFor({-> len(term_scrape(buf, 1)) == 3}) 195 call Check_123(buf) 196 197 " Must still work after the job ended. 198 let job = term_getjob(buf) 199 call WaitFor({-> job_status(job) == "dead"}) 200 call term_wait(buf) 201 call Check_123(buf) 202 203 exe buf . 'bwipe' 204 call delete('Xtext') 205endfunc 206 207func Test_terminal_scrape_multibyte() 208 if !has('multi_byte') 209 return 210 endif 211 call writefile(["léttまrs"], 'Xtext') 212 if has('win32') 213 " Run cmd with UTF-8 codepage to make the type command print the expected 214 " multibyte characters. 215 let buf = term_start("cmd /K chcp 65001") 216 call term_sendkeys(buf, "type Xtext\<CR>") 217 call term_sendkeys(buf, "exit\<CR>") 218 let line = 4 219 else 220 let buf = term_start("cat Xtext") 221 let line = 1 222 endif 223 224 call WaitFor({-> len(term_scrape(buf, line)) >= 7 && term_scrape(buf, line)[0].chars == "l"}) 225 let l = term_scrape(buf, line) 226 call assert_true(len(l) >= 7) 227 call assert_equal('l', l[0].chars) 228 call assert_equal('é', l[1].chars) 229 call assert_equal(1, l[1].width) 230 call assert_equal('t', l[2].chars) 231 call assert_equal('t', l[3].chars) 232 call assert_equal('ま', l[4].chars) 233 call assert_equal(2, l[4].width) 234 call assert_equal('r', l[5].chars) 235 call assert_equal('s', l[6].chars) 236 237 let job = term_getjob(buf) 238 call WaitFor({-> job_status(job) == "dead"}) 239 call term_wait(buf) 240 241 exe buf . 'bwipe' 242 call delete('Xtext') 243endfunc 244 245func Test_terminal_scroll() 246 call writefile(range(1, 200), 'Xtext') 247 if has('win32') 248 let cmd = 'cmd /c "type Xtext"' 249 else 250 let cmd = "cat Xtext" 251 endif 252 let buf = term_start(cmd) 253 254 let job = term_getjob(buf) 255 call WaitFor({-> job_status(job) == "dead"}) 256 call term_wait(buf) 257 if has('win32') 258 " TODO: this should not be needed 259 sleep 100m 260 endif 261 262 let scrolled = term_getscrolled(buf) 263 call assert_equal('1', getline(1)) 264 call assert_equal('1', term_getline(buf, 1 - scrolled)) 265 call assert_equal('49', getline(49)) 266 call assert_equal('49', term_getline(buf, 49 - scrolled)) 267 call assert_equal('200', getline(200)) 268 call assert_equal('200', term_getline(buf, 200 - scrolled)) 269 270 exe buf . 'bwipe' 271 call delete('Xtext') 272endfunc 273 274func Test_terminal_size() 275 let cmd = Get_cat_123_cmd() 276 277 exe 'terminal ++rows=5 ' . cmd 278 let size = term_getsize('') 279 bwipe! 280 call assert_equal(5, size[0]) 281 282 call term_start(cmd, {'term_rows': 6}) 283 let size = term_getsize('') 284 bwipe! 285 call assert_equal(6, size[0]) 286 287 vsplit 288 exe 'terminal ++rows=5 ++cols=33 ' . cmd 289 let size = term_getsize('') 290 bwipe! 291 call assert_equal([5, 33], size) 292 293 call term_start(cmd, {'term_rows': 6, 'term_cols': 36}) 294 let size = term_getsize('') 295 bwipe! 296 call assert_equal([6, 36], size) 297 298 exe 'vertical terminal ++cols=20 ' . cmd 299 let size = term_getsize('') 300 bwipe! 301 call assert_equal(20, size[1]) 302 303 call term_start(cmd, {'vertical': 1, 'term_cols': 26}) 304 let size = term_getsize('') 305 bwipe! 306 call assert_equal(26, size[1]) 307 308 split 309 exe 'vertical terminal ++rows=6 ++cols=20 ' . cmd 310 let size = term_getsize('') 311 bwipe! 312 call assert_equal([6, 20], size) 313 314 call term_start(cmd, {'vertical': 1, 'term_rows': 7, 'term_cols': 27}) 315 let size = term_getsize('') 316 bwipe! 317 call assert_equal([7, 27], size) 318 319 call delete('Xtext') 320endfunc 321 322func Test_terminal_curwin() 323 let cmd = Get_cat_123_cmd() 324 call assert_equal(1, winnr('$')) 325 326 split dummy 327 exe 'terminal ++curwin ' . cmd 328 call assert_equal(2, winnr('$')) 329 bwipe! 330 331 split dummy 332 call term_start(cmd, {'curwin': 1}) 333 call assert_equal(2, winnr('$')) 334 bwipe! 335 336 split dummy 337 call setline(1, 'change') 338 call assert_fails('terminal ++curwin ' . cmd, 'E37:') 339 call assert_equal(2, winnr('$')) 340 exe 'terminal! ++curwin ' . cmd 341 call assert_equal(2, winnr('$')) 342 bwipe! 343 344 split dummy 345 call setline(1, 'change') 346 call assert_fails("call term_start(cmd, {'curwin': 1})", 'E37:') 347 call assert_equal(2, winnr('$')) 348 bwipe! 349 350 split dummy 351 bwipe! 352 call delete('Xtext') 353endfunc 354 355func s:get_sleep_cmd() 356 if s:python != '' 357 let cmd = s:python . " test_short_sleep.py" 358 let waittime = 500 359 else 360 echo 'This will take five seconds...' 361 let waittime = 2000 362 if has('win32') 363 let cmd = $windir . '\system32\timeout.exe 1' 364 else 365 let cmd = 'sleep 1' 366 endif 367 endif 368 return [cmd, waittime] 369endfunc 370 371func Test_terminal_finish_open_close() 372 call assert_equal(1, winnr('$')) 373 374 let [cmd, waittime] = s:get_sleep_cmd() 375 376 " shell terminal closes automatically 377 terminal 378 let buf = bufnr('%') 379 call assert_equal(2, winnr('$')) 380 " Wait for the shell to display a prompt 381 call WaitFor({-> term_getline(buf, 1) != ""}) 382 call Stop_shell_in_terminal(buf) 383 call WaitFor("winnr('$') == 1", waittime) 384 385 " shell terminal that does not close automatically 386 terminal ++noclose 387 let buf = bufnr('%') 388 call assert_equal(2, winnr('$')) 389 " Wait for the shell to display a prompt 390 call WaitFor({-> term_getline(buf, 1) != ""}) 391 call Stop_shell_in_terminal(buf) 392 call assert_equal(2, winnr('$')) 393 quit 394 call assert_equal(1, winnr('$')) 395 396 exe 'terminal ++close ' . cmd 397 call assert_equal(2, winnr('$')) 398 wincmd p 399 call WaitFor("winnr('$') == 1", waittime) 400 401 call term_start(cmd, {'term_finish': 'close'}) 402 call assert_equal(2, winnr('$')) 403 wincmd p 404 call WaitFor("winnr('$') == 1", waittime) 405 call assert_equal(1, winnr('$')) 406 407 exe 'terminal ++open ' . cmd 408 close! 409 call WaitFor("winnr('$') == 2", waittime) 410 call assert_equal(2, winnr('$')) 411 bwipe 412 413 call term_start(cmd, {'term_finish': 'open'}) 414 close! 415 call WaitFor("winnr('$') == 2", waittime) 416 call assert_equal(2, winnr('$')) 417 bwipe 418 419 exe 'terminal ++hidden ++open ' . cmd 420 call assert_equal(1, winnr('$')) 421 call WaitFor("winnr('$') == 2", waittime) 422 call assert_equal(2, winnr('$')) 423 bwipe 424 425 call term_start(cmd, {'term_finish': 'open', 'hidden': 1}) 426 call assert_equal(1, winnr('$')) 427 call WaitFor("winnr('$') == 2", waittime) 428 call assert_equal(2, winnr('$')) 429 bwipe 430 431 call assert_fails("call term_start(cmd, {'term_opencmd': 'open'})", 'E475:') 432 call assert_fails("call term_start(cmd, {'term_opencmd': 'split %x'})", 'E475:') 433 call assert_fails("call term_start(cmd, {'term_opencmd': 'split %d and %s'})", 'E475:') 434 call assert_fails("call term_start(cmd, {'term_opencmd': 'split % and %d'})", 'E475:') 435 436 call term_start(cmd, {'term_finish': 'open', 'term_opencmd': '4split | buffer %d'}) 437 close! 438 call WaitFor("winnr('$') == 2", waittime) 439 call assert_equal(2, winnr('$')) 440 call assert_equal(4, winheight(0)) 441 bwipe 442endfunc 443 444func Test_terminal_cwd() 445 if !executable('pwd') 446 return 447 endif 448 call mkdir('Xdir') 449 let buf = term_start('pwd', {'cwd': 'Xdir'}) 450 call WaitFor('"Xdir" == fnamemodify(getline(1), ":t")') 451 call assert_equal('Xdir', fnamemodify(getline(1), ":t")) 452 453 exe buf . 'bwipe' 454 call delete('Xdir', 'rf') 455endfunc 456 457func Test_terminal_servername() 458 if !has('clientserver') 459 return 460 endif 461 let buf = Run_shell_in_terminal({}) 462 " Wait for the shell to display a prompt 463 call WaitFor({-> term_getline(buf, 1) != ""}) 464 if has('win32') 465 call term_sendkeys(buf, "echo %VIM_SERVERNAME%\r") 466 else 467 call term_sendkeys(buf, "echo $VIM_SERVERNAME\r") 468 endif 469 call term_wait(buf) 470 call Stop_shell_in_terminal(buf) 471 call WaitFor('getline(2) == v:servername') 472 call assert_equal(v:servername, getline(2)) 473 474 exe buf . 'bwipe' 475 unlet buf 476endfunc 477 478func Test_terminal_env() 479 let buf = Run_shell_in_terminal({'env': {'TESTENV': 'correct'}}) 480 " Wait for the shell to display a prompt 481 call WaitFor({-> term_getline(buf, 1) != ""}) 482 if has('win32') 483 call term_sendkeys(buf, "echo %TESTENV%\r") 484 else 485 call term_sendkeys(buf, "echo $TESTENV\r") 486 endif 487 call term_wait(buf) 488 call Stop_shell_in_terminal(buf) 489 call WaitFor('getline(2) == "correct"') 490 call assert_equal('correct', getline(2)) 491 492 exe buf . 'bwipe' 493endfunc 494 495" must be last, we can't go back from GUI to terminal 496func Test_zz_terminal_in_gui() 497 if !CanRunGui() 498 return 499 endif 500 501 " Ignore the "failed to create input context" error. 502 call test_ignore_error('E285:') 503 504 gui -f 505 506 call assert_equal(1, winnr('$')) 507 let buf = Run_shell_in_terminal({'term_finish': 'close'}) 508 call Stop_shell_in_terminal(buf) 509 call term_wait(buf) 510 511 " closing window wipes out the terminal buffer a with finished job 512 call WaitFor("winnr('$') == 1") 513 call assert_equal(1, winnr('$')) 514 call assert_equal("", bufname(buf)) 515 516 unlet g:job 517endfunc 518 519func Test_terminal_list_args() 520 let buf = term_start([&shell, &shellcmdflag, 'echo "123"']) 521 call assert_fails(buf . 'bwipe', 'E517') 522 exe buf . 'bwipe!' 523 call assert_equal("", bufname(buf)) 524endfunction 525 526func Test_terminal_noblock() 527 let buf = term_start(&shell) 528 if has('mac') 529 " The shell or something else has a problem dealing with more than 1000 530 " characters at the same time. 531 let len = 1000 532 else 533 let len = 5000 534 endif 535 536 for c in ['a','b','c','d','e','f','g','h','i','j','k'] 537 call term_sendkeys(buf, 'echo ' . repeat(c, len) . "\<cr>") 538 endfor 539 call term_sendkeys(buf, "echo done\<cr>") 540 541 " On MS-Windows there is an extra empty line below "done". Find "done" in 542 " the last-but-one or the last-but-two line. 543 let lnum = term_getsize(buf)[0] - 1 544 call WaitFor({-> term_getline(buf, lnum) =~ "done" || term_getline(buf, lnum - 1) =~ "done"}, 10000) 545 let line = term_getline(buf, lnum) 546 if line !~ 'done' 547 let line = term_getline(buf, lnum - 1) 548 endif 549 call assert_match('done', line) 550 551 let g:job = term_getjob(buf) 552 call Stop_shell_in_terminal(buf) 553 call term_wait(buf) 554 unlet g:job 555 bwipe 556endfunc 557 558func Test_terminal_write_stdin() 559 if !executable('wc') 560 throw 'skipped: wc command not available' 561 endif 562 new 563 call setline(1, ['one', 'two', 'three']) 564 %term wc 565 call WaitFor('getline("$") =~ "3"') 566 let nrs = split(getline('$')) 567 call assert_equal(['3', '3', '14'], nrs) 568 bwipe 569 570 new 571 call setline(1, ['one', 'two', 'three', 'four']) 572 2,3term wc 573 call WaitFor('getline("$") =~ "2"') 574 let nrs = split(getline('$')) 575 call assert_equal(['2', '2', '10'], nrs) 576 bwipe 577 578 if executable('python') 579 new 580 call setline(1, ['print("hello")']) 581 1term ++eof=exit() python 582 " MS-Windows echoes the input, Unix doesn't. 583 call WaitFor('getline("$") =~ "exit" || getline(1) =~ "hello"') 584 if getline(1) =~ 'hello' 585 call assert_equal('hello', getline(1)) 586 else 587 call assert_equal('hello', getline(line('$') - 1)) 588 endif 589 bwipe 590 591 if has('win32') 592 new 593 call setline(1, ['print("hello")']) 594 1term ++eof=<C-Z> python 595 call WaitFor('getline("$") =~ "Z"') 596 call assert_equal('hello', getline(line('$') - 1)) 597 bwipe 598 endif 599 endif 600 601 bwipe! 602endfunc 603 604func Test_terminal_no_cmd() 605 " Todo: make this work in the GUI 606 if !has('gui_running') 607 return 608 endif 609 let buf = term_start('NONE', {}) 610 call assert_notequal(0, buf) 611 612 let pty = job_info(term_getjob(buf))['tty_out'] 613 call assert_notequal('', pty) 614 if has('win32') 615 silent exe '!start cmd /c "echo look here > ' . pty . '"' 616 else 617 call system('echo "look here" > ' . pty) 618 endif 619 call WaitFor({-> term_getline(buf, 1) =~ "look here"}) 620 621 call assert_match('look here', term_getline(buf, 1)) 622 bwipe! 623endfunc 624 625func Test_terminal_special_chars() 626 " this file name only works on Unix 627 if !has('unix') 628 return 629 endif 630 call mkdir('Xdir with spaces') 631 call writefile(['x'], 'Xdir with spaces/quoted"file') 632 term ls Xdir\ with\ spaces/quoted\"file 633 call WaitFor('term_getline("", 1) =~ "quoted"') 634 call assert_match('quoted"file', term_getline('', 1)) 635 call term_wait('') 636 637 call delete('Xdir with spaces', 'rf') 638 bwipe 639endfunc 640 641func Test_terminal_wrong_options() 642 call assert_fails('call term_start(&shell, { 643 \ "in_io": "file", 644 \ "in_name": "xxx", 645 \ "out_io": "file", 646 \ "out_name": "xxx", 647 \ "err_io": "file", 648 \ "err_name": "xxx" 649 \ })', 'E474:') 650 call assert_fails('call term_start(&shell, { 651 \ "out_buf": bufnr("%") 652 \ })', 'E474:') 653 call assert_fails('call term_start(&shell, { 654 \ "err_buf": bufnr("%") 655 \ })', 'E474:') 656endfunc 657 658func Test_terminal_redir_file() 659 " TODO: this should work on MS-Window 660 if has('unix') 661 let cmd = Get_cat_123_cmd() 662 let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'}) 663 call term_wait(buf) 664 call WaitFor('len(readfile("Xfile")) > 0') 665 call assert_match('123', readfile('Xfile')[0]) 666 let g:job = term_getjob(buf) 667 call WaitFor('job_status(g:job) == "dead"') 668 call delete('Xfile') 669 bwipe 670 endif 671 672 if has('unix') 673 call writefile(['one line'], 'Xfile') 674 let buf = term_start('cat', {'in_io': 'file', 'in_name': 'Xfile'}) 675 call term_wait(buf) 676 call WaitFor('term_getline(' . buf . ', 1) == "one line"') 677 call assert_equal('one line', term_getline(buf, 1)) 678 let g:job = term_getjob(buf) 679 call WaitFor('job_status(g:job) == "dead"') 680 bwipe 681 call delete('Xfile') 682 endif 683endfunc 684 685func TerminalTmap(remap) 686 let buf = Run_shell_in_terminal({}) 687 call assert_equal('t', mode()) 688 689 if a:remap 690 tmap 123 456 691 else 692 tnoremap 123 456 693 endif 694 " don't use abcde, it's an existing command 695 tmap 456 abxde 696 call assert_equal('456', maparg('123', 't')) 697 call assert_equal('abxde', maparg('456', 't')) 698 call feedkeys("123", 'tx') 699 call WaitFor({-> term_getline(buf, term_getcursor(buf)[0]) =~ 'abxde\|456'}) 700 let lnum = term_getcursor(buf)[0] 701 if a:remap 702 call assert_match('abxde', term_getline(buf, lnum)) 703 else 704 call assert_match('456', term_getline(buf, lnum)) 705 endif 706 707 call term_sendkeys(buf, "\r") 708 call Stop_shell_in_terminal(buf) 709 call term_wait(buf) 710 711 tunmap 123 712 tunmap 456 713 call assert_equal('', maparg('123', 't')) 714 close 715 unlet g:job 716endfunc 717 718func Test_terminal_tmap() 719 call TerminalTmap(1) 720 call TerminalTmap(0) 721endfunc 722 723func Test_terminal_wall() 724 let buf = Run_shell_in_terminal({}) 725 wall 726 call Stop_shell_in_terminal(buf) 727 call term_wait(buf) 728 exe buf . 'bwipe' 729 unlet g:job 730endfunc 731 732func Test_terminal_wqall() 733 let buf = Run_shell_in_terminal({}) 734 call assert_fails('wqall', 'E948') 735 call Stop_shell_in_terminal(buf) 736 call term_wait(buf) 737 exe buf . 'bwipe' 738 unlet g:job 739endfunc 740 741func Test_terminal_composing_unicode() 742 let save_enc = &encoding 743 set encoding=utf-8 744 745 if has('win32') 746 let cmd = "cmd /K chcp 65001" 747 let lnum = [3, 6, 9] 748 else 749 let cmd = &shell 750 let lnum = [1, 3, 5] 751 endif 752 753 enew 754 let buf = term_start(cmd, {'curwin': bufnr('')}) 755 let g:job = term_getjob(buf) 756 call term_wait(buf, 50) 757 758 " ascii + composing 759 let txt = "a\u0308bc" 760 call term_sendkeys(buf, "echo " . txt . "\r") 761 call term_wait(buf, 50) 762 call assert_match("echo " . txt, term_getline(buf, lnum[0])) 763 call assert_equal(txt, term_getline(buf, lnum[0] + 1)) 764 let l = term_scrape(buf, lnum[0] + 1) 765 call assert_equal("a\u0308", l[0].chars) 766 call assert_equal("b", l[1].chars) 767 call assert_equal("c", l[2].chars) 768 769 " multibyte + composing 770 let txt = "\u304b\u3099\u304e\u304f\u3099\u3052\u3053\u3099" 771 call term_sendkeys(buf, "echo " . txt . "\r") 772 call term_wait(buf, 50) 773 call assert_match("echo " . txt, term_getline(buf, lnum[1])) 774 call assert_equal(txt, term_getline(buf, lnum[1] + 1)) 775 let l = term_scrape(buf, lnum[1] + 1) 776 call assert_equal("\u304b\u3099", l[0].chars) 777 call assert_equal("\u304e", l[1].chars) 778 call assert_equal("\u304f\u3099", l[2].chars) 779 call assert_equal("\u3052", l[3].chars) 780 call assert_equal("\u3053\u3099", l[4].chars) 781 782 " \u00a0 + composing 783 let txt = "abc\u00a0\u0308" 784 call term_sendkeys(buf, "echo " . txt . "\r") 785 call term_wait(buf, 50) 786 call assert_match("echo " . txt, term_getline(buf, lnum[2])) 787 call assert_equal(txt, term_getline(buf, lnum[2] + 1)) 788 let l = term_scrape(buf, lnum[2] + 1) 789 call assert_equal("\u00a0\u0308", l[3].chars) 790 791 call term_sendkeys(buf, "exit\r") 792 call WaitFor('job_status(g:job) == "dead"') 793 call assert_equal('dead', job_status(g:job)) 794 bwipe! 795 unlet g:job 796 let &encoding = save_enc 797endfunc 798 799func Test_terminal_aucmd_on_close() 800 fun Nop() 801 let s:called = 1 802 endfun 803 804 aug repro 805 au! 806 au BufWinLeave * call Nop() 807 aug END 808 809 let [cmd, waittime] = s:get_sleep_cmd() 810 811 call assert_equal(1, winnr('$')) 812 new 813 call setline(1, ['one', 'two']) 814 exe 'term ++close ' . cmd 815 wincmd p 816 call WaitFor("winnr('$') == 2", waittime) 817 call assert_equal(1, s:called) 818 bwipe! 819 820 unlet s:called 821 au! repro 822 delfunc Nop 823endfunc 824 825func Test_terminal_term_start_empty_command() 826 let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})" 827 call assert_fails(cmd, 'E474') 828 let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})" 829 call assert_fails(cmd, 'E474') 830 let cmd = "call term_start({}, {'curwin' : 1, 'term_finish' : 'close'})" 831 call assert_fails(cmd, 'E474') 832 let cmd = "call term_start(0, {'curwin' : 1, 'term_finish' : 'close'})" 833 call assert_fails(cmd, 'E474') 834endfunc 835 836func Test_terminal_response_to_control_sequence() 837 if !has('unix') 838 return 839 endif 840 841 let buf = Run_shell_in_terminal({}) 842 call WaitFor({-> term_getline(buf, 1) != ''}) 843 844 call term_sendkeys(buf, "cat\<CR>") 845 call WaitFor({-> term_getline(buf, 1) =~ 'cat'}) 846 847 " Request the cursor position. 848 call term_sendkeys(buf, "\x1b[6n\<CR>") 849 850 " Wait for output from tty to display, below an empty line. 851 call WaitFor({-> term_getline(buf, 4) =~ '3;1R'}) 852 853 " End "cat" gently. 854 call term_sendkeys(buf, "\<CR>\<C-D>") 855 856 call Stop_shell_in_terminal(buf) 857 exe buf . 'bwipe' 858 unlet g:job 859endfunc 860 861" Run Vim, start a terminal in that Vim with the kill argument, 862" :qall works. 863func Run_terminal_qall_kill(line1, line2) 864 " 1. Open a terminal window and wait for the prompt to appear 865 " 2. set kill using term_setkill() 866 " 3. make Vim exit, it will kill the shell 867 let after = [ 868 \ a:line1, 869 \ 'let buf = bufnr("%")', 870 \ 'while term_getline(buf, 1) =~ "^\\s*$"', 871 \ ' sleep 10m', 872 \ 'endwhile', 873 \ a:line2, 874 \ 'au VimLeavePre * call writefile(["done"], "Xdone")', 875 \ 'qall', 876 \ ] 877 if !RunVim([], after, '') 878 return 879 endif 880 call assert_equal("done", readfile("Xdone")[0]) 881 call delete("Xdone") 882endfunc 883 884" Run Vim in a terminal, then start a terminal in that Vim with a kill 885" argument, check that :qall works. 886func Test_terminal_qall_kill_arg() 887 call Run_terminal_qall_kill('term ++kill=kill', '') 888endfunc 889 890" Run Vim, start a terminal in that Vim, set the kill argument with 891" term_setkill(), check that :qall works. 892func Test_terminal_qall_kill_func() 893 call Run_terminal_qall_kill('term', 'call term_setkill(buf, "kill")') 894endfunc 895 896" Run Vim, start a terminal in that Vim without the kill argument, 897" check that :qall does not exit, :qall! does. 898func Test_terminal_qall_exit() 899 let after = [ 900 \ 'term', 901 \ 'let buf = bufnr("%")', 902 \ 'while term_getline(buf, 1) =~ "^\\s*$"', 903 \ ' sleep 10m', 904 \ 'endwhile', 905 \ 'set nomore', 906 \ 'au VimLeavePre * call writefile(["too early"], "Xdone")', 907 \ 'qall', 908 \ 'au! VimLeavePre * exe buf . "bwipe!" | call writefile(["done"], "Xdone")', 909 \ 'cquit', 910 \ ] 911 if !RunVim([], after, '') 912 return 913 endif 914 call assert_equal("done", readfile("Xdone")[0]) 915 call delete("Xdone") 916endfunc 917 918" Run Vim in a terminal, then start a terminal in that Vim without a kill 919" argument, check that :confirm qall works. 920func Test_terminal_qall_prompt() 921 if !CanRunVimInTerminal() 922 return 923 endif 924 let buf = RunVimInTerminal('', {}) 925 926 " Open a terminal window and wait for the prompt to appear 927 call term_sendkeys(buf, ":term\<CR>") 928 call WaitFor({-> term_getline(buf, 10) =~ '\[running]'}) 929 call WaitFor({-> term_getline(buf, 1) !~ '^\s*$'}) 930 931 " make Vim exit, it will prompt to kill the shell 932 call term_sendkeys(buf, "\<C-W>:confirm qall\<CR>") 933 call WaitFor({-> term_getline(buf, 20) =~ 'ancel:'}) 934 call term_sendkeys(buf, "y") 935 call WaitFor({-> term_getstatus(buf) == "finished"}) 936 937 " close the terminal window where Vim was running 938 quit 939endfunc 940 941func Test_terminal_open_autocmd() 942 augroup repro 943 au! 944 au TerminalOpen * let s:called += 1 945 augroup END 946 947 let s:called = 0 948 949 " Open a terminal window with :terminal 950 terminal 951 call assert_equal(1, s:called) 952 bwipe! 953 954 " Open a terminal window with term_start() 955 call term_start(&shell) 956 call assert_equal(2, s:called) 957 bwipe! 958 959 " Open a hidden terminal buffer with :terminal 960 terminal ++hidden 961 call assert_equal(3, s:called) 962 for buf in term_list() 963 exe buf . "bwipe!" 964 endfor 965 966 " Open a hidden terminal buffer with term_start() 967 let buf = term_start(&shell, {'hidden': 1}) 968 call assert_equal(4, s:called) 969 exe buf . "bwipe!" 970 971 unlet s:called 972 au! repro 973endfunction 974 975func Check_dump01(off) 976 call assert_equal('one two three four five', trim(getline(a:off + 1))) 977 call assert_equal('~ Select Word', trim(getline(a:off + 7))) 978 call assert_equal(':popup PopUp', trim(getline(a:off + 20))) 979endfunc 980 981func Test_terminal_dumpwrite_composing() 982 if !CanRunVimInTerminal() 983 return 984 endif 985 let save_enc = &encoding 986 set encoding=utf-8 987 call assert_equal(1, winnr('$')) 988 989 let text = " a\u0300 e\u0302 o\u0308" 990 call writefile([text], 'Xcomposing') 991 let buf = RunVimInTerminal('Xcomposing', {}) 992 call WaitFor({-> term_getline(buf, 1) =~ text}) 993 call term_dumpwrite(buf, 'Xdump') 994 let dumpline = readfile('Xdump')[0] 995 call assert_match('|à| |ê| |ö', dumpline) 996 997 call StopVimInTerminal(buf) 998 call delete('Xcomposing') 999 call delete('Xdump') 1000 let &encoding = save_enc 1001endfunc 1002 1003" just testing basic functionality. 1004func Test_terminal_dumpload() 1005 call assert_equal(1, winnr('$')) 1006 call term_dumpload('dumps/Test_popup_command_01.dump') 1007 call assert_equal(2, winnr('$')) 1008 call assert_equal(20, line('$')) 1009 call Check_dump01(0) 1010 quit 1011endfunc 1012 1013func Test_terminal_dumpdiff() 1014 call assert_equal(1, winnr('$')) 1015 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump') 1016 call assert_equal(2, winnr('$')) 1017 call assert_equal(62, line('$')) 1018 call Check_dump01(0) 1019 call Check_dump01(42) 1020 call assert_equal(' bbbbbbbbbbbbbbbbbb ', getline(26)[0:29]) 1021 quit 1022endfunc 1023 1024func Test_terminal_dumpdiff_options() 1025 set laststatus=0 1026 call assert_equal(1, winnr('$')) 1027 let height = winheight(0) 1028 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 1, 'term_cols': 33}) 1029 call assert_equal(2, winnr('$')) 1030 call assert_equal(height, winheight(winnr())) 1031 call assert_equal(33, winwidth(winnr())) 1032 call assert_equal('dump diff dumps/Test_popup_command_01.dump', bufname('%')) 1033 quit 1034 1035 call assert_equal(1, winnr('$')) 1036 let width = winwidth(0) 1037 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 0, 'term_rows': 13, 'term_name': 'something else'}) 1038 call assert_equal(2, winnr('$')) 1039 call assert_equal(width, winwidth(winnr())) 1040 call assert_equal(13, winheight(winnr())) 1041 call assert_equal('something else', bufname('%')) 1042 quit 1043 1044 call assert_equal(1, winnr('$')) 1045 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'curwin': 1}) 1046 call assert_equal(1, winnr('$')) 1047 bwipe 1048 1049 set laststatus& 1050endfunc 1051 1052func Api_drop_common(options) 1053 call assert_equal(1, winnr('$')) 1054 1055 " Use the title termcap entries to output the escape sequence. 1056 call writefile([ 1057 \ 'set title', 1058 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1059 \ 'let &titlestring = ''["drop","Xtextfile"' . a:options . ']''', 1060 \ 'redraw', 1061 \ "set t_ts=", 1062 \ ], 'Xscript') 1063 let buf = RunVimInTerminal('-S Xscript', {}) 1064 call WaitFor({-> bufnr('Xtextfile') > 0}) 1065 call assert_equal('Xtextfile', expand('%:t')) 1066 call assert_true(winnr('$') >= 3) 1067 return buf 1068endfunc 1069 1070func Test_terminal_api_drop_newwin() 1071 if !CanRunVimInTerminal() 1072 return 1073 endif 1074 let buf = Api_drop_common('') 1075 call assert_equal(0, &bin) 1076 call assert_equal('', &fenc) 1077 1078 call StopVimInTerminal(buf) 1079 call delete('Xscript') 1080 bwipe Xtextfile 1081endfunc 1082 1083func Test_terminal_api_drop_newwin_bin() 1084 if !CanRunVimInTerminal() 1085 return 1086 endif 1087 let buf = Api_drop_common(',{"bin":1}') 1088 call assert_equal(1, &bin) 1089 1090 call StopVimInTerminal(buf) 1091 call delete('Xscript') 1092 bwipe Xtextfile 1093endfunc 1094 1095func Test_terminal_api_drop_newwin_binary() 1096 if !CanRunVimInTerminal() 1097 return 1098 endif 1099 let buf = Api_drop_common(',{"binary":1}') 1100 call assert_equal(1, &bin) 1101 1102 call StopVimInTerminal(buf) 1103 call delete('Xscript') 1104 bwipe Xtextfile 1105endfunc 1106 1107func Test_terminal_api_drop_newwin_nobin() 1108 if !CanRunVimInTerminal() 1109 return 1110 endif 1111 set binary 1112 let buf = Api_drop_common(',{"nobin":1}') 1113 call assert_equal(0, &bin) 1114 1115 call StopVimInTerminal(buf) 1116 call delete('Xscript') 1117 bwipe Xtextfile 1118 set nobinary 1119endfunc 1120 1121func Test_terminal_api_drop_newwin_nobinary() 1122 if !CanRunVimInTerminal() 1123 return 1124 endif 1125 set binary 1126 let buf = Api_drop_common(',{"nobinary":1}') 1127 call assert_equal(0, &bin) 1128 1129 call StopVimInTerminal(buf) 1130 call delete('Xscript') 1131 bwipe Xtextfile 1132 set nobinary 1133endfunc 1134 1135func Test_terminal_api_drop_newwin_ff() 1136 if !CanRunVimInTerminal() 1137 return 1138 endif 1139 let buf = Api_drop_common(',{"ff":"dos"}') 1140 call assert_equal("dos", &ff) 1141 1142 call StopVimInTerminal(buf) 1143 call delete('Xscript') 1144 bwipe Xtextfile 1145endfunc 1146 1147func Test_terminal_api_drop_newwin_fileformat() 1148 if !CanRunVimInTerminal() 1149 return 1150 endif 1151 let buf = Api_drop_common(',{"fileformat":"dos"}') 1152 call assert_equal("dos", &ff) 1153 1154 call StopVimInTerminal(buf) 1155 call delete('Xscript') 1156 bwipe Xtextfile 1157endfunc 1158 1159func Test_terminal_api_drop_newwin_enc() 1160 if !CanRunVimInTerminal() 1161 return 1162 endif 1163 let buf = Api_drop_common(',{"enc":"utf-16"}') 1164 call assert_equal("utf-16", &fenc) 1165 1166 call StopVimInTerminal(buf) 1167 call delete('Xscript') 1168 bwipe Xtextfile 1169endfunc 1170 1171func Test_terminal_api_drop_newwin_encoding() 1172 if !CanRunVimInTerminal() 1173 return 1174 endif 1175 let buf = Api_drop_common(',{"encoding":"utf-16"}') 1176 call assert_equal("utf-16", &fenc) 1177 1178 call StopVimInTerminal(buf) 1179 call delete('Xscript') 1180 bwipe Xtextfile 1181endfunc 1182 1183func Test_terminal_api_drop_oldwin() 1184 if !CanRunVimInTerminal() 1185 return 1186 endif 1187 let firstwinid = win_getid() 1188 split Xtextfile 1189 let textfile_winid = win_getid() 1190 call assert_equal(2, winnr('$')) 1191 call win_gotoid(firstwinid) 1192 1193 " Use the title termcap entries to output the escape sequence. 1194 call writefile([ 1195 \ 'set title', 1196 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1197 \ 'let &titlestring = ''["drop","Xtextfile"]''', 1198 \ 'redraw', 1199 \ "set t_ts=", 1200 \ ], 'Xscript') 1201 let buf = RunVimInTerminal('-S Xscript', {'rows': 10}) 1202 call WaitFor({-> expand('%:t') =='Xtextfile'}) 1203 call assert_equal(textfile_winid, win_getid()) 1204 1205 call StopVimInTerminal(buf) 1206 call delete('Xscript') 1207 bwipe Xtextfile 1208endfunc 1209 1210func Tapi_TryThis(bufnum, arg) 1211 let g:called_bufnum = a:bufnum 1212 let g:called_arg = a:arg 1213endfunc 1214 1215func WriteApiCall(funcname) 1216 " Use the title termcap entries to output the escape sequence. 1217 call writefile([ 1218 \ 'set title', 1219 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"', 1220 \ 'let &titlestring = ''["call","' . a:funcname . '",["hello",123]]''', 1221 \ 'redraw', 1222 \ "set t_ts=", 1223 \ ], 'Xscript') 1224endfunc 1225 1226func Test_terminal_api_call() 1227 if !CanRunVimInTerminal() 1228 return 1229 endif 1230 1231 call WriteApiCall('Tapi_TryThis') 1232 let buf = RunVimInTerminal('-S Xscript', {}) 1233 call WaitFor({-> exists('g:called_bufnum')}) 1234 call assert_equal(buf, g:called_bufnum) 1235 call assert_equal(['hello', 123], g:called_arg) 1236 1237 call StopVimInTerminal(buf) 1238 call delete('Xscript') 1239 unlet g:called_bufnum 1240 unlet g:called_arg 1241endfunc 1242 1243func Test_terminal_api_call_fails() 1244 if !CanRunVimInTerminal() 1245 return 1246 endif 1247 1248 call WriteApiCall('TryThis') 1249 call ch_logfile('Xlog', 'w') 1250 let buf = RunVimInTerminal('-S Xscript', {}) 1251 call WaitFor({-> string(readfile('Xlog')) =~ 'Invalid function name: TryThis'}) 1252 1253 call StopVimInTerminal(buf) 1254 call delete('Xscript') 1255 call ch_logfile('', '') 1256 call delete('Xlog') 1257endfunc 1258