1" Tests for decoding escape sequences sent by the terminal. 2 3" This only works for Unix in a terminal 4source check.vim 5CheckNotGui 6CheckUnix 7 8source shared.vim 9 10" xterm2 and sgr always work, urxvt is optional. 11let s:ttymouse_values = ['xterm2', 'sgr'] 12if has('mouse_urxvt') 13 call add(s:ttymouse_values, 'urxvt') 14endif 15 16" dec doesn't support all the functionality 17if has('mouse_dec') 18 let s:ttymouse_dec = ['dec'] 19else 20 let s:ttymouse_dec = [] 21endif 22 23" netterm only supports left click 24if has('mouse_netterm') 25 let s:ttymouse_netterm = ['netterm'] 26else 27 let s:ttymouse_netterm = [] 28endif 29 30" Helper function to emit a terminal escape code. 31func TerminalEscapeCode(code, row, col, m) 32 if &ttymouse ==# 'xterm2' 33 " need to use byte encoding here. 34 let str = list2str([a:code + 0x20, a:col + 0x20, a:row + 0x20]) 35 if has('iconv') 36 let bytes = str->iconv('utf-8', 'latin1') 37 else 38 " Hopefully the numbers are not too big. 39 let bytes = str 40 endif 41 call feedkeys("\<Esc>[M" .. bytes, 'Lx!') 42 elseif &ttymouse ==# 'sgr' 43 call feedkeys(printf("\<Esc>[<%d;%d;%d%s", a:code, a:col, a:row, a:m), 'Lx!') 44 elseif &ttymouse ==# 'urxvt' 45 call feedkeys(printf("\<Esc>[%d;%d;%dM", a:code + 0x20, a:col, a:row), 'Lx!') 46 endif 47endfunc 48 49func DecEscapeCode(code, down, row, col) 50 call feedkeys(printf("\<Esc>[%d;%d;%d;%d&w", a:code, a:down, a:row, a:col), 'Lx!') 51endfunc 52 53func NettermEscapeCode(row, col) 54 call feedkeys(printf("\<Esc>}%d,%d\r", a:row, a:col), 'Lx!') 55endfunc 56 57func MouseLeftClick(row, col) 58 if &ttymouse ==# 'dec' 59 call DecEscapeCode(2, 4, a:row, a:col) 60 elseif &ttymouse ==# 'netterm' 61 call NettermEscapeCode(a:row, a:col) 62 else 63 call TerminalEscapeCode(0, a:row, a:col, 'M') 64 endif 65endfunc 66 67func MouseMiddleClick(row, col) 68 if &ttymouse ==# 'dec' 69 call DecEscapeCode(4, 2, a:row, a:col) 70 else 71 call TerminalEscapeCode(1, a:row, a:col, 'M') 72 endif 73endfunc 74 75func MouseRightClick(row, col) 76 if &ttymouse ==# 'dec' 77 call DecEscapeCode(6, 1, a:row, a:col) 78 else 79 call TerminalEscapeCode(2, a:row, a:col, 'M') 80 endif 81endfunc 82 83func MouseCtrlLeftClick(row, col) 84 let ctrl = 0x10 85 call TerminalEscapeCode(0 + ctrl, a:row, a:col, 'M') 86endfunc 87 88func MouseCtrlRightClick(row, col) 89 let ctrl = 0x10 90 call TerminalEscapeCode(2 + ctrl, a:row, a:col, 'M') 91endfunc 92 93func MouseLeftRelease(row, col) 94 if &ttymouse ==# 'dec' 95 call DecEscapeCode(3, 0, a:row, a:col) 96 elseif &ttymouse ==# 'netterm' 97 " send nothing 98 else 99 call TerminalEscapeCode(3, a:row, a:col, 'm') 100 endif 101endfunc 102 103func MouseMiddleRelease(row, col) 104 if &ttymouse ==# 'dec' 105 call DecEscapeCode(5, 0, a:row, a:col) 106 else 107 call TerminalEscapeCode(3, a:row, a:col, 'm') 108 endif 109endfunc 110 111func MouseRightRelease(row, col) 112 if &ttymouse ==# 'dec' 113 call DecEscapeCode(7, 0, a:row, a:col) 114 else 115 call TerminalEscapeCode(3, a:row, a:col, 'm') 116 endif 117endfunc 118 119func MouseLeftDrag(row, col) 120 if &ttymouse ==# 'dec' 121 call DecEscapeCode(1, 4, a:row, a:col) 122 else 123 call TerminalEscapeCode(0x20, a:row, a:col, 'M') 124 endif 125endfunc 126 127func MouseWheelUp(row, col) 128 call TerminalEscapeCode(0x40, a:row, a:col, 'M') 129endfunc 130 131func MouseWheelDown(row, col) 132 call TerminalEscapeCode(0x41, a:row, a:col, 'M') 133endfunc 134 135func Test_term_mouse_left_click() 136 new 137 let save_mouse = &mouse 138 let save_term = &term 139 let save_ttymouse = &ttymouse 140 call test_override('no_query_mouse', 1) 141 set mouse=a term=xterm 142 call setline(1, ['line 1', 'line 2', 'line 3 is a bit longer']) 143 144 for ttymouse_val in s:ttymouse_values + s:ttymouse_dec + s:ttymouse_netterm 145 let msg = 'ttymouse=' .. ttymouse_val 146 exe 'set ttymouse=' .. ttymouse_val 147 go 148 call assert_equal([0, 1, 1, 0], getpos('.'), msg) 149 let row = 2 150 let col = 6 151 call MouseLeftClick(row, col) 152 call MouseLeftRelease(row, col) 153 call assert_equal([0, 2, 6, 0], getpos('.'), msg) 154 endfor 155 156 let &mouse = save_mouse 157 let &term = save_term 158 let &ttymouse = save_ttymouse 159 call test_override('no_query_mouse', 0) 160 bwipe! 161endfunc 162 163func Test_xterm_mouse_right_click_extends_visual() 164 if has('mac') 165 throw "Skipped: test right click in visual mode does not work on macOs (why?)" 166 endif 167 let save_mouse = &mouse 168 let save_term = &term 169 let save_ttymouse = &ttymouse 170 call test_override('no_query_mouse', 1) 171 set mouse=a term=xterm 172 173 for visual_mode in ["v", "V", "\<C-V>"] 174 for ttymouse_val in s:ttymouse_values + s:ttymouse_dec 175 let msg = 'visual=' .. visual_mode .. ' ttymouse=' .. ttymouse_val 176 exe 'set ttymouse=' .. ttymouse_val 177 178 call setline(1, repeat([repeat('-', 7)], 7)) 179 call MouseLeftClick(4, 4) 180 call MouseLeftRelease(4, 4) 181 exe "norm! " .. visual_mode 182 183 " Right click extends top left of visual area. 184 call MouseRightClick(2, 2) 185 call MouseRightRelease(2, 2) 186 187 " Right click extends bottom bottom right of visual area. 188 call MouseRightClick(6, 6) 189 call MouseRightRelease(6, 6) 190 norm! r1gv 191 192 " Right click shrinks top left of visual area. 193 call MouseRightClick(3, 3) 194 call MouseRightRelease(3, 3) 195 196 " Right click shrinks bottom right of visual area. 197 call MouseRightClick(5, 5) 198 call MouseRightRelease(5, 5) 199 norm! r2 200 201 if visual_mode ==# 'v' 202 call assert_equal(['-------', 203 \ '-111111', 204 \ '1122222', 205 \ '2222222', 206 \ '2222211', 207 \ '111111-', 208 \ '-------'], getline(1, '$'), msg) 209 elseif visual_mode ==# 'V' 210 call assert_equal(['-------', 211 \ '1111111', 212 \ '2222222', 213 \ '2222222', 214 \ '2222222', 215 \ '1111111', 216 \ '-------'], getline(1, '$'), msg) 217 else 218 call assert_equal(['-------', 219 \ '-11111-', 220 \ '-12221-', 221 \ '-12221-', 222 \ '-12221-', 223 \ '-11111-', 224 \ '-------'], getline(1, '$'), msg) 225 endif 226 endfor 227 endfor 228 229 let &mouse = save_mouse 230 let &term = save_term 231 let &ttymouse = save_ttymouse 232 call test_override('no_query_mouse', 0) 233 bwipe! 234endfunc 235 236" Test that <C-LeftMouse> jumps to help tag and <C-RightMouse> jumps back. 237func Test_xterm_mouse_ctrl_click() 238 let save_mouse = &mouse 239 let save_term = &term 240 let save_ttymouse = &ttymouse 241 set mouse=a term=xterm 242 243 for ttymouse_val in s:ttymouse_values 244 let msg = 'ttymouse=' .. ttymouse_val 245 exe 'set ttymouse=' .. ttymouse_val 246 help 247 /usr_02.txt 248 norm! zt 249 let row = 1 250 let col = 1 251 call MouseCtrlLeftClick(row, col) 252 call MouseLeftRelease(row, col) 253 call assert_match('usr_02.txt$', bufname('%'), msg) 254 call assert_equal('*usr_02.txt*', expand('<cWORD>'), msg) 255 256 call MouseCtrlRightClick(row, col) 257 call MouseRightRelease(row, col) 258 call assert_match('help.txt$', bufname('%'), msg) 259 call assert_equal('|usr_02.txt|', expand('<cWORD>'), msg) 260 261 helpclose 262 endfor 263 264 let &mouse = save_mouse 265 let &term = save_term 266 let &ttymouse = save_ttymouse 267endfunc 268 269func Test_term_mouse_middle_click() 270 CheckFeature clipboard_working 271 272 new 273 let save_mouse = &mouse 274 let save_term = &term 275 let save_ttymouse = &ttymouse 276 call test_override('no_query_mouse', 1) 277 let save_quotestar = @* 278 let @* = 'abc' 279 set mouse=a term=xterm 280 281 for ttymouse_val in s:ttymouse_values + s:ttymouse_dec 282 let msg = 'ttymouse=' .. ttymouse_val 283 exe 'set ttymouse=' .. ttymouse_val 284 call setline(1, ['123456789', '123456789']) 285 286 " Middle-click in the middle of the line pastes text where clicked. 287 let row = 1 288 let col = 6 289 call MouseMiddleClick(row, col) 290 call MouseMiddleRelease(row, col) 291 call assert_equal(['12345abc6789', '123456789'], getline(1, '$'), msg) 292 293 " Middle-click beyond end of the line pastes text at the end of the line. 294 let col = 20 295 call MouseMiddleClick(row, col) 296 call MouseMiddleRelease(row, col) 297 call assert_equal(['12345abc6789abc', '123456789'], getline(1, '$'), msg) 298 299 " Middle-click beyond the last line pastes in the last line. 300 let row = 5 301 let col = 3 302 call MouseMiddleClick(row, col) 303 call MouseMiddleRelease(row, col) 304 call assert_equal(['12345abc6789abc', '12abc3456789'], getline(1, '$'), msg) 305 endfor 306 307 let &mouse = save_mouse 308 let &term = save_term 309 let &ttymouse = save_ttymouse 310 call test_override('no_query_mouse', 0) 311 let @* = save_quotestar 312 bwipe! 313endfunc 314 315" TODO: for unclear reasons this test fails if it comes after 316" Test_xterm_mouse_ctrl_click() 317func Test_1xterm_mouse_wheel() 318 new 319 let save_mouse = &mouse 320 let save_term = &term 321 let save_ttymouse = &ttymouse 322 set mouse=a term=xterm 323 call setline(1, range(1, 100)) 324 325 for ttymouse_val in s:ttymouse_values 326 let msg = 'ttymouse=' .. ttymouse_val 327 exe 'set ttymouse=' .. ttymouse_val 328 go 329 call assert_equal(1, line('w0'), msg) 330 call assert_equal([0, 1, 1, 0], getpos('.'), msg) 331 332 call MouseWheelDown(1, 1) 333 call assert_equal(4, line('w0'), msg) 334 call assert_equal([0, 4, 1, 0], getpos('.'), msg) 335 336 call MouseWheelDown(1, 1) 337 call assert_equal(7, line('w0'), msg) 338 call assert_equal([0, 7, 1, 0], getpos('.'), msg) 339 340 call MouseWheelUp(1, 1) 341 call assert_equal(4, line('w0'), msg) 342 call assert_equal([0, 7, 1, 0], getpos('.'), msg) 343 344 call MouseWheelUp(1, 1) 345 call assert_equal(1, line('w0'), msg) 346 call assert_equal([0, 7, 1, 0], getpos('.'), msg) 347 endfor 348 349 let &mouse = save_mouse 350 let &term = save_term 351 let &ttymouse = save_ttymouse 352 bwipe! 353endfunc 354 355" Test that dragging beyond the window (at the bottom and at the top) 356" scrolls window content by the number of of lines beyond the window. 357func Test_term_mouse_drag_beyond_window() 358 let save_mouse = &mouse 359 let save_term = &term 360 let save_ttymouse = &ttymouse 361 call test_override('no_query_mouse', 1) 362 set mouse=a term=xterm 363 let col = 1 364 call setline(1, range(1, 100)) 365 366 " Split into 3 windows, and go into the middle window 367 " so we test dragging mouse below and above the window. 368 2split 369 wincmd j 370 2split 371 372 for ttymouse_val in s:ttymouse_values + s:ttymouse_dec 373 let msg = 'ttymouse=' .. ttymouse_val 374 exe 'set ttymouse=' .. ttymouse_val 375 376 " Line #10 at the top. 377 norm! 10zt 378 redraw 379 call assert_equal(10, winsaveview().topline, msg) 380 call assert_equal(2, winheight(0), msg) 381 382 let row = 4 383 call MouseLeftClick(row, col) 384 call assert_equal(10, winsaveview().topline, msg) 385 386 " Drag downwards. We're still in the window so topline should 387 " not change yet. 388 let row += 1 389 call MouseLeftDrag(row, col) 390 call assert_equal(10, winsaveview().topline, msg) 391 392 " We now leave the window at the bottom, so the window content should 393 " scroll by 1 line, then 2 lines (etc) as we drag further away. 394 let row += 1 395 call MouseLeftDrag(row, col) 396 call assert_equal(11, winsaveview().topline, msg) 397 398 let row += 1 399 call MouseLeftDrag(row, col) 400 call assert_equal(13, winsaveview().topline, msg) 401 402 " Now drag upwards. 403 let row -= 1 404 call MouseLeftDrag(row, col) 405 call assert_equal(14, winsaveview().topline, msg) 406 407 " We're now back in the window so the topline should not change. 408 let row -= 1 409 call MouseLeftDrag(row, col) 410 call assert_equal(14, winsaveview().topline, msg) 411 412 let row -= 1 413 call MouseLeftDrag(row, col) 414 call assert_equal(14, winsaveview().topline, msg) 415 416 " We now leave the window at the top so the window content should 417 " scroll by 1 line, then 2, then 3 (etc) in the opposite direction. 418 let row -= 1 419 call MouseLeftDrag(row, col) 420 call assert_equal(13, winsaveview().topline, msg) 421 422 let row -= 1 423 call MouseLeftDrag(row, col) 424 call assert_equal(11, winsaveview().topline, msg) 425 426 let row -= 1 427 call MouseLeftDrag(row, col) 428 call assert_equal(8, winsaveview().topline, msg) 429 430 call MouseLeftRelease(row, col) 431 call assert_equal(8, winsaveview().topline, msg) 432 call assert_equal(2, winheight(0), msg) 433 endfor 434 435 let &mouse = save_mouse 436 let &term = save_term 437 let &ttymouse = save_ttymouse 438 call test_override('no_query_mouse', 0) 439 bwipe! 440endfunc 441 442func Test_term_mouse_drag_window_separator() 443 let save_mouse = &mouse 444 let save_term = &term 445 let save_ttymouse = &ttymouse 446 call test_override('no_query_mouse', 1) 447 set mouse=a term=xterm 448 449 for ttymouse_val in s:ttymouse_values + s:ttymouse_dec 450 let msg = 'ttymouse=' .. ttymouse_val 451 exe 'set ttymouse=' .. ttymouse_val 452 453 " Split horizontally and test dragging the horizontal window separator. 454 split 455 let rowseparator = winheight(0) + 1 456 let row = rowseparator 457 let col = 1 458 459 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported. 460 if ttymouse_val !=# 'xterm2' || row <= 223 461 call MouseLeftClick(row, col) 462 let row -= 1 463 call MouseLeftDrag(row, col) 464 call assert_equal(rowseparator - 1, winheight(0) + 1, msg) 465 let row += 1 466 call MouseLeftDrag(row, col) 467 call assert_equal(rowseparator, winheight(0) + 1, msg) 468 call MouseLeftRelease(row, col) 469 call assert_equal(rowseparator, winheight(0) + 1, msg) 470 endif 471 bwipe! 472 473 " Split vertically and test dragging the vertical window separator. 474 vsplit 475 let colseparator = winwidth(0) + 1 476 let row = 1 477 let col = colseparator 478 479 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported. 480 if ttymouse_val !=# 'xterm2' || col <= 223 481 call MouseLeftClick(row, col) 482 let col -= 1 483 call MouseLeftDrag(row, col) 484 call assert_equal(colseparator - 1, winwidth(0) + 1, msg) 485 let col += 1 486 call MouseLeftDrag(row, col) 487 call assert_equal(colseparator, winwidth(0) + 1, msg) 488 call MouseLeftRelease(row, col) 489 call assert_equal(colseparator, winwidth(0) + 1, msg) 490 endif 491 bwipe! 492 endfor 493 494 let &mouse = save_mouse 495 let &term = save_term 496 let &ttymouse = save_ttymouse 497 call test_override('no_query_mouse', 0) 498endfunc 499 500func Test_term_mouse_drag_statusline() 501 let save_mouse = &mouse 502 let save_term = &term 503 let save_ttymouse = &ttymouse 504 call test_override('no_query_mouse', 1) 505 let save_laststatus = &laststatus 506 set mouse=a term=xterm laststatus=2 507 508 for ttymouse_val in s:ttymouse_values + s:ttymouse_dec 509 let msg = 'ttymouse=' .. ttymouse_val 510 exe 'set ttymouse=' .. ttymouse_val 511 512 call assert_equal(1, &cmdheight, msg) 513 let rowstatusline = winheight(0) + 1 514 let row = rowstatusline 515 let col = 1 516 517 if ttymouse_val ==# 'xterm2' && row > 223 518 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported. 519 continue 520 endif 521 522 call MouseLeftClick(row, col) 523 let row -= 1 524 call MouseLeftDrag(row, col) 525 call assert_equal(2, &cmdheight, msg) 526 call assert_equal(rowstatusline - 1, winheight(0) + 1, msg) 527 let row += 1 528 call MouseLeftDrag(row, col) 529 call assert_equal(1, &cmdheight, msg) 530 call assert_equal(rowstatusline, winheight(0) + 1, msg) 531 call MouseLeftRelease(row, col) 532 call assert_equal(1, &cmdheight, msg) 533 call assert_equal(rowstatusline, winheight(0) + 1, msg) 534 endfor 535 536 let &mouse = save_mouse 537 let &term = save_term 538 let &ttymouse = save_ttymouse 539 call test_override('no_query_mouse', 0) 540 let &laststatus = save_laststatus 541endfunc 542 543func Test_term_mouse_click_tab() 544 let save_mouse = &mouse 545 let save_term = &term 546 let save_ttymouse = &ttymouse 547 call test_override('no_query_mouse', 1) 548 set mouse=a term=xterm 549 let row = 1 550 551 for ttymouse_val in s:ttymouse_values + s:ttymouse_dec + s:ttymouse_netterm 552 let msg = 'ttymouse=' .. ttymouse_val 553 exe 'set ttymouse=' .. ttymouse_val 554 e Xfoo 555 tabnew Xbar 556 557 let a = split(execute(':tabs'), "\n") 558 call assert_equal(['Tab page 1', 559 \ ' Xfoo', 560 \ 'Tab page 2', 561 \ '> Xbar'], a, msg) 562 563 " Test clicking on tab names in the tabline at the top. 564 let col = 2 565 redraw 566 call MouseLeftClick(row, col) 567 call MouseLeftRelease(row, col) 568 let a = split(execute(':tabs'), "\n") 569 call assert_equal(['Tab page 1', 570 \ '> Xfoo', 571 \ 'Tab page 2', 572 \ ' Xbar'], a, msg) 573 574 let col = 9 575 call MouseLeftClick(row, col) 576 call MouseLeftRelease(row, col) 577 let a = split(execute(':tabs'), "\n") 578 call assert_equal(['Tab page 1', 579 \ ' Xfoo', 580 \ 'Tab page 2', 581 \ '> Xbar'], a, msg) 582 583 %bwipe! 584 endfor 585 586 let &mouse = save_mouse 587 let &term = save_term 588 let &ttymouse = save_ttymouse 589 call test_override('no_query_mouse', 0) 590endfunc 591 592func Test_term_mouse_click_X_to_close_tab() 593 let save_mouse = &mouse 594 let save_term = &term 595 let save_ttymouse = &ttymouse 596 call test_override('no_query_mouse', 1) 597 set mouse=a term=xterm 598 let row = 1 599 let col = &columns 600 601 for ttymouse_val in s:ttymouse_values + s:ttymouse_dec + s:ttymouse_netterm 602 if ttymouse_val ==# 'xterm2' && col > 223 603 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported. 604 continue 605 endif 606 let msg = 'ttymouse=' .. ttymouse_val 607 exe 'set ttymouse=' .. ttymouse_val 608 e Xtab1 609 tabnew Xtab2 610 tabnew Xtab3 611 tabn 2 612 613 let a = split(execute(':tabs'), "\n") 614 call assert_equal(['Tab page 1', 615 \ ' Xtab1', 616 \ 'Tab page 2', 617 \ '> Xtab2', 618 \ 'Tab page 3', 619 \ ' Xtab3'], a, msg) 620 621 " Click on "X" in tabline to close current tab i.e. Xtab2. 622 redraw 623 call MouseLeftClick(row, col) 624 call MouseLeftRelease(row, col) 625 let a = split(execute(':tabs'), "\n") 626 call assert_equal(['Tab page 1', 627 \ ' Xtab1', 628 \ 'Tab page 2', 629 \ '> Xtab3'], a, msg) 630 631 %bwipe! 632 endfor 633 634 let &mouse = save_mouse 635 let &term = save_term 636 let &ttymouse = save_ttymouse 637 call test_override('no_query_mouse', 0) 638endfunc 639 640func Test_term_mouse_drag_to_move_tab() 641 let save_mouse = &mouse 642 let save_term = &term 643 let save_ttymouse = &ttymouse 644 call test_override('no_query_mouse', 1) 645 " Set 'mousetime' to 1 to avoid recognizing a double-click in the loop 646 set mouse=a term=xterm mousetime=1 647 let row = 1 648 649 for ttymouse_val in s:ttymouse_values + s:ttymouse_dec 650 let msg = 'ttymouse=' .. ttymouse_val 651 exe 'set ttymouse=' .. ttymouse_val 652 e Xtab1 653 tabnew Xtab2 654 655 let a = split(execute(':tabs'), "\n") 656 call assert_equal(['Tab page 1', 657 \ ' Xtab1', 658 \ 'Tab page 2', 659 \ '> Xtab2'], a, msg) 660 redraw 661 662 " Click in tab2 and drag it to tab1. 663 " Check getcharmod() to verify that click is not 664 " interpreted as a spurious double-click. 665 call MouseLeftClick(row, 10) 666 call assert_equal(0, getcharmod(), msg) 667 for col in [9, 8, 7, 6] 668 call MouseLeftDrag(row, col) 669 endfor 670 call MouseLeftRelease(row, col) 671 let a = split(execute(':tabs'), "\n") 672 call assert_equal(['Tab page 1', 673 \ '> Xtab2', 674 \ 'Tab page 2', 675 \ ' Xtab1'], a, msg) 676 677 " brief sleep to avoid causing a double-click 678 sleep 20m 679 %bwipe! 680 endfor 681 682 let &mouse = save_mouse 683 let &term = save_term 684 let &ttymouse = save_ttymouse 685 call test_override('no_query_mouse', 0) 686 set mousetime& 687endfunc 688 689func Test_term_mouse_double_click_to_create_tab() 690 let save_mouse = &mouse 691 let save_term = &term 692 let save_ttymouse = &ttymouse 693 call test_override('no_query_mouse', 1) 694 " Set 'mousetime' to a small value, so that double-click works but we don't 695 " have to wait long to avoid a triple-click. 696 set mouse=a term=xterm mousetime=100 697 let row = 1 698 let col = 10 699 700 let round = 0 701 for ttymouse_val in s:ttymouse_values + s:ttymouse_dec 702 let msg = 'ttymouse=' .. ttymouse_val 703 exe 'set ttymouse=' .. ttymouse_val 704 e Xtab1 705 tabnew Xtab2 706 707 if round > 0 708 " We need to sleep, or else the first MouseLeftClick() will be 709 " interpreted as a spurious triple-click. 710 sleep 100m 711 endif 712 let round += 1 713 714 let a = split(execute(':tabs'), "\n") 715 call assert_equal(['Tab page 1', 716 \ ' Xtab1', 717 \ 'Tab page 2', 718 \ '> Xtab2'], a, msg) 719 720 redraw 721 call MouseLeftClick(row, col) 722 " Check getcharmod() to verify that first click is not 723 " interpreted as a spurious double-click. 724 call assert_equal(0, getcharmod(), msg) 725 call MouseLeftRelease(row, col) 726 call MouseLeftClick(row, col) 727 call assert_equal(32, getcharmod(), msg) " double-click 728 call MouseLeftRelease(row, col) 729 let a = split(execute(':tabs'), "\n") 730 call assert_equal(['Tab page 1', 731 \ ' Xtab1', 732 \ 'Tab page 2', 733 \ '> [No Name]', 734 \ 'Tab page 3', 735 \ ' Xtab2'], a, msg) 736 737 %bwipe! 738 endfor 739 740 let &mouse = save_mouse 741 let &term = save_term 742 let &ttymouse = save_ttymouse 743 call test_override('no_query_mouse', 0) 744 set mousetime& 745endfunc 746 747func Test_xterm_mouse_click_in_fold_columns() 748 new 749 let save_mouse = &mouse 750 let save_term = &term 751 let save_ttymouse = &ttymouse 752 let save_foldcolumn = &foldcolumn 753 set mouse=a term=xterm foldcolumn=3 ttymouse=xterm2 754 755 " Create 2 nested folds. 756 call setline(1, range(1, 7)) 757 2,6fold 758 norm! zR 759 4,5fold 760 call assert_equal([-1, -1, -1, 4, 4, -1, -1], 761 \ map(range(1, 7), 'foldclosed(v:val)')) 762 763 " Click in "+" of inner fold in foldcolumn should open it. 764 redraw 765 let row = 4 766 let col = 2 767 call MouseLeftClick(row, col) 768 call MouseLeftRelease(row, col) 769 call assert_equal([-1, -1, -1, -1, -1, -1, -1], 770 \ map(range(1, 7), 'foldclosed(v:val)')) 771 772 " Click in "-" of outer fold in foldcolumn should close it. 773 redraw 774 let row = 2 775 let col = 1 776 call MouseLeftClick(row, col) 777 call MouseLeftRelease(row, col) 778 call assert_equal([-1, 2, 2, 2, 2, 2, -1], 779 \ map(range(1, 7), 'foldclosed(v:val)')) 780 norm! zR 781 782 " Click in "|" of inner fold in foldcolumn should close it. 783 redraw 784 let row = 5 785 let col = 2 786 call MouseLeftClick(row, col) 787 call MouseLeftRelease(row, col) 788 call assert_equal([-1, -1, -1, 4, 4, -1, -1], 789 \ map(range(1, 7), 'foldclosed(v:val)')) 790 791 let &foldcolumn = save_foldcolumn 792 let &ttymouse = save_ttymouse 793 let &term = save_term 794 let &mouse = save_mouse 795 bwipe! 796endfunc 797 798" This only checks if the sequence is recognized. 799func Test_term_rgb_response() 800 set t_RF=x 801 set t_RB=y 802 803 " response to t_RF, 4 digits 804 let red = 0x12 805 let green = 0x34 806 let blue = 0x56 807 let seq = printf("\<Esc>]10;rgb:%02x00/%02x00/%02x00\x07", red, green, blue) 808 call feedkeys(seq, 'Lx!') 809 call assert_equal(seq, v:termrfgresp) 810 811 " response to t_RF, 2 digits 812 let red = 0x78 813 let green = 0x9a 814 let blue = 0xbc 815 let seq = printf("\<Esc>]10;rgb:%02x/%02x/%02x\x07", red, green, blue) 816 call feedkeys(seq, 'Lx!') 817 call assert_equal(seq, v:termrfgresp) 818 819 " response to t_RB, 4 digits, dark 820 set background=light 821 eval 'background'->test_option_not_set() 822 let red = 0x29 823 let green = 0x4a 824 let blue = 0x6b 825 let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue) 826 call feedkeys(seq, 'Lx!') 827 call assert_equal(seq, v:termrbgresp) 828 call assert_equal('dark', &background) 829 830 " response to t_RB, 4 digits, light 831 set background=dark 832 call test_option_not_set('background') 833 let red = 0x81 834 let green = 0x63 835 let blue = 0x65 836 let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue) 837 call feedkeys(seq, 'Lx!') 838 call assert_equal(seq, v:termrbgresp) 839 call assert_equal('light', &background) 840 841 " response to t_RB, 2 digits, dark 842 set background=light 843 call test_option_not_set('background') 844 let red = 0x47 845 let green = 0x59 846 let blue = 0x5b 847 let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue) 848 call feedkeys(seq, 'Lx!') 849 call assert_equal(seq, v:termrbgresp) 850 call assert_equal('dark', &background) 851 852 " response to t_RB, 2 digits, light 853 set background=dark 854 call test_option_not_set('background') 855 let red = 0x83 856 let green = 0xa4 857 let blue = 0xc2 858 let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue) 859 call feedkeys(seq, 'Lx!') 860 call assert_equal(seq, v:termrbgresp) 861 call assert_equal('light', &background) 862 863 set t_RF= t_RB= 864endfunc 865 866" This only checks if the sequence is recognized. 867" This must be after other tests, because it has side effects to xterm 868" properties. 869func Test_xx01_term_style_response() 870 " Termresponse is only parsed when t_RV is not empty. 871 set t_RV=x 872 873 " send the termresponse to trigger requesting the XT codes 874 let seq = "\<Esc>[>41;337;0c" 875 call feedkeys(seq, 'Lx!') 876 call assert_equal(seq, v:termresponse) 877 878 let seq = "\<Esc>P1$r2 q\<Esc>\\" 879 call feedkeys(seq, 'Lx!') 880 call assert_equal(seq, v:termstyleresp) 881 882 set t_RV= 883endfunc 884 885" This checks the iTerm2 version response. 886" This must be after other tests, because it has side effects to xterm 887" properties. 888func Test_xx02_iTerm2_response() 889 " Termresponse is only parsed when t_RV is not empty. 890 set t_RV=x 891 892 " Old versions of iTerm2 used a different style term response. 893 set ttymouse=xterm 894 call test_option_not_set('ttymouse') 895 let seq = "\<Esc>[>0;95;c" 896 call feedkeys(seq, 'Lx!') 897 call assert_equal(seq, v:termresponse) 898 call assert_equal('xterm', &ttymouse) 899 900 set ttymouse=xterm 901 call test_option_not_set('ttymouse') 902 let seq = "\<Esc>[>0;95;0c" 903 call feedkeys(seq, 'Lx!') 904 call assert_equal(seq, v:termresponse) 905 call assert_equal('sgr', &ttymouse) 906 907 set t_RV= 908endfunc 909 910" This checks the libvterm version response. 911" This must be after other tests, because it has side effects to xterm 912" properties. 913func Test_xx03_libvterm_response() 914 " Termresponse is only parsed when t_RV is not empty. 915 set t_RV=x 916 917 set ttymouse=xterm 918 call test_option_not_set('ttymouse') 919 let seq = "\<Esc>[>0;100;0c" 920 call feedkeys(seq, 'Lx!') 921 call assert_equal(seq, v:termresponse) 922 call assert_equal('sgr', &ttymouse) 923 924 set t_RV= 925endfunc 926 927" This checks the Mac Terminal.app version response. 928" This must be after other tests, because it has side effects to xterm 929" properties. 930func Test_xx04_Mac_Terminal_response() 931 " Termresponse is only parsed when t_RV is not empty. 932 set t_RV=x 933 934 set ttymouse=xterm 935 call test_option_not_set('ttymouse') 936 let seq = "\<Esc>[>1;95;0c" 937 call feedkeys(seq, 'Lx!') 938 call assert_equal(seq, v:termresponse) 939 call assert_equal('sgr', &ttymouse) 940 941 " Reset is_not_xterm and is_mac_terminal. 942 set t_RV= 943 set term=xterm 944 set t_RV=x 945endfunc 946 947" This checks the mintty version response. 948" This must be after other tests, because it has side effects to xterm 949" properties. 950func Test_xx05_mintty_response() 951 " Termresponse is only parsed when t_RV is not empty. 952 set t_RV=x 953 954 set ttymouse=xterm 955 call test_option_not_set('ttymouse') 956 let seq = "\<Esc>[>77;20905;0c" 957 call feedkeys(seq, 'Lx!') 958 call assert_equal(seq, v:termresponse) 959 call assert_equal('sgr', &ttymouse) 960 961 set t_RV= 962endfunc 963 964" This checks the screen version response. 965" This must be after other tests, because it has side effects to xterm 966" properties. 967func Test_xx06_screen_response() 968 " Termresponse is only parsed when t_RV is not empty. 969 set t_RV=x 970 971 " Old versions of screen don't support SGR mouse mode. 972 set ttymouse=xterm 973 call test_option_not_set('ttymouse') 974 let seq = "\<Esc>[>83;40500;0c" 975 call feedkeys(seq, 'Lx!') 976 call assert_equal(seq, v:termresponse) 977 call assert_equal('xterm', &ttymouse) 978 979 " screen supports SGR mouse mode starting in version 4.7. 980 set ttymouse=xterm 981 call test_option_not_set('ttymouse') 982 let seq = "\<Esc>[>83;40700;0c" 983 call feedkeys(seq, 'Lx!') 984 call assert_equal(seq, v:termresponse) 985 call assert_equal('sgr', &ttymouse) 986 987 set t_RV= 988endfunc 989 990" This checks the xterm version response. 991" This must be after other tests, because it has side effects to xterm 992" properties. 993func Test_xx07_xterm_response() 994 " Termresponse is only parsed when t_RV is not empty. 995 set t_RV=x 996 997 " Do Terminal.app first to check that is_mac_terminal is reset. 998 set ttymouse=xterm 999 call test_option_not_set('ttymouse') 1000 let seq = "\<Esc>[>1;95;0c" 1001 call feedkeys(seq, 'Lx!') 1002 call assert_equal(seq, v:termresponse) 1003 call assert_equal('sgr', &ttymouse) 1004 1005 " xterm < 95: "xterm" (actually unmodified) 1006 set t_RV= 1007 set term=xterm 1008 set t_RV=x 1009 set ttymouse=xterm 1010 call test_option_not_set('ttymouse') 1011 let seq = "\<Esc>[>0;94;0c" 1012 call feedkeys(seq, 'Lx!') 1013 call assert_equal(seq, v:termresponse) 1014 call assert_equal('xterm', &ttymouse) 1015 1016 " xterm >= 95 < 277 "xterm2" 1017 set ttymouse=xterm 1018 call test_option_not_set('ttymouse') 1019 let seq = "\<Esc>[>0;267;0c" 1020 call feedkeys(seq, 'Lx!') 1021 call assert_equal(seq, v:termresponse) 1022 call assert_equal('xterm2', &ttymouse) 1023 1024 " xterm >= 277: "sgr" 1025 set ttymouse=xterm 1026 call test_option_not_set('ttymouse') 1027 let seq = "\<Esc>[>0;277;0c" 1028 call feedkeys(seq, 'Lx!') 1029 call assert_equal(seq, v:termresponse) 1030 call assert_equal('sgr', &ttymouse) 1031 1032 set t_RV= 1033endfunc 1034 1035func Test_get_termcode() 1036 try 1037 let k1 = &t_k1 1038 catch /E113/ 1039 throw 'Skipped: Unable to query termcodes' 1040 endtry 1041 set t_k1= 1042 set t_k1& 1043 call assert_equal(k1, &t_k1) 1044 1045 " use external termcap first 1046 set nottybuiltin 1047 set t_k1= 1048 set t_k1& 1049 " when using external termcap may get something else, but it must not be 1050 " empty, since we would fallback to the builtin one. 1051 call assert_notequal('', &t_k1) 1052 1053 if &term =~ 'xterm' 1054 " use internal termcap first 1055 let term_save = &term 1056 let &term = 'builtin_' .. &term 1057 set t_k1= 1058 set t_k1& 1059 call assert_equal(k1, &t_k1) 1060 let &term = term_save 1061 endif 1062 1063 set ttybuiltin 1064endfunc 1065 1066func GetEscCodeCSI27(key, modifier) 1067 let key = printf("%d", char2nr(a:key)) 1068 let mod = printf("%d", a:modifier) 1069 return "\<Esc>[27;" .. mod .. ';' .. key .. '~' 1070endfunc 1071 1072func GetEscCodeCSIu(key, modifier) 1073 let key = printf("%d", char2nr(a:key)) 1074 let mod = printf("%d", a:modifier) 1075 return "\<Esc>[" .. key .. ';' .. mod .. 'u' 1076endfunc 1077 1078" This checks the CSI sequences when in modifyOtherKeys mode. 1079" The mode doesn't need to be enabled, the codes are always detected. 1080func RunTest_modifyOtherKeys(func) 1081 new 1082 set timeoutlen=10 1083 1084 " Shift-X is send as 'X' with the shift modifier 1085 call feedkeys('a' .. a:func('X', 2) .. "\<Esc>", 'Lx!') 1086 call assert_equal('X', getline(1)) 1087 1088 " Ctrl-i is Tab 1089 call setline(1, '') 1090 call feedkeys('a' .. a:func('i', 5) .. "\<Esc>", 'Lx!') 1091 call assert_equal("\t", getline(1)) 1092 1093 " Ctrl-I is also Tab 1094 call setline(1, '') 1095 call feedkeys('a' .. a:func('I', 5) .. "\<Esc>", 'Lx!') 1096 call assert_equal("\t", getline(1)) 1097 1098 " Alt-x is ø 1099 call setline(1, '') 1100 call feedkeys('a' .. a:func('x', 3) .. "\<Esc>", 'Lx!') 1101 call assert_equal("ø", getline(1)) 1102 1103 " Meta-x is also ø 1104 call setline(1, '') 1105 call feedkeys('a' .. a:func('x', 9) .. "\<Esc>", 'Lx!') 1106 call assert_equal("ø", getline(1)) 1107 1108 " Alt-X is Ø 1109 call setline(1, '') 1110 call feedkeys('a' .. a:func('X', 3) .. "\<Esc>", 'Lx!') 1111 call assert_equal("Ø", getline(1)) 1112 1113 " Meta-X is ø 1114 call setline(1, '') 1115 call feedkeys('a' .. a:func('X', 9) .. "\<Esc>", 'Lx!') 1116 call assert_equal("Ø", getline(1)) 1117 1118 bwipe! 1119 set timeoutlen& 1120endfunc 1121 1122func Test_modifyOtherKeys_basic() 1123 call RunTest_modifyOtherKeys(function('GetEscCodeCSI27')) 1124 call RunTest_modifyOtherKeys(function('GetEscCodeCSIu')) 1125endfunc 1126 1127func RunTest_mapping_shift(key, func) 1128 call setline(1, '') 1129 if a:key == '|' 1130 exe 'inoremap \| xyz' 1131 else 1132 exe 'inoremap ' .. a:key .. ' xyz' 1133 endif 1134 call feedkeys('a' .. a:func(a:key, 2) .. "\<Esc>", 'Lx!') 1135 call assert_equal("xyz", getline(1)) 1136 if a:key == '|' 1137 exe 'iunmap \|' 1138 else 1139 exe 'iunmap ' .. a:key 1140 endif 1141endfunc 1142 1143func RunTest_mapping_works_with_shift(func) 1144 new 1145 set timeoutlen=10 1146 1147 call RunTest_mapping_shift('@', a:func) 1148 call RunTest_mapping_shift('A', a:func) 1149 call RunTest_mapping_shift('Z', a:func) 1150 call RunTest_mapping_shift('^', a:func) 1151 call RunTest_mapping_shift('_', a:func) 1152 call RunTest_mapping_shift('{', a:func) 1153 call RunTest_mapping_shift('|', a:func) 1154 call RunTest_mapping_shift('}', a:func) 1155 call RunTest_mapping_shift('~', a:func) 1156 1157 bwipe! 1158 set timeoutlen& 1159endfunc 1160 1161func Test_mapping_works_with_shift_plain() 1162 call RunTest_mapping_works_with_shift(function('GetEscCodeCSI27')) 1163 call RunTest_mapping_works_with_shift(function('GetEscCodeCSIu')) 1164endfunc 1165 1166func RunTest_mapping_mods(map, key, func, code) 1167 call setline(1, '') 1168 exe 'inoremap ' .. a:map .. ' xyz' 1169 call feedkeys('a' .. a:func(a:key, a:code) .. "\<Esc>", 'Lx!') 1170 call assert_equal("xyz", getline(1)) 1171 exe 'iunmap ' .. a:map 1172endfunc 1173 1174func RunTest_mapping_works_with_mods(func, mods, code) 1175 new 1176 set timeoutlen=10 1177 1178 if a:mods !~ 'S' 1179 " Shift by itself has no effect 1180 call RunTest_mapping_mods('<' .. a:mods .. '-@>', '@', a:func, a:code) 1181 endif 1182 call RunTest_mapping_mods('<' .. a:mods .. '-A>', 'A', a:func, a:code) 1183 call RunTest_mapping_mods('<' .. a:mods .. '-Z>', 'Z', a:func, a:code) 1184 if a:mods !~ 'S' 1185 " with Shift code is always upper case 1186 call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'a', a:func, a:code) 1187 call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'z', a:func, a:code) 1188 endif 1189 if a:mods != 'A' 1190 " with Alt code is not in upper case 1191 call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'A', a:func, a:code) 1192 call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'Z', a:func, a:code) 1193 endif 1194 call RunTest_mapping_mods('<' .. a:mods .. '-á>', 'á', a:func, a:code) 1195 if a:mods !~ 'S' 1196 " Shift by itself has no effect 1197 call RunTest_mapping_mods('<' .. a:mods .. '-^>', '^', a:func, a:code) 1198 call RunTest_mapping_mods('<' .. a:mods .. '-_>', '_', a:func, a:code) 1199 call RunTest_mapping_mods('<' .. a:mods .. '-{>', '{', a:func, a:code) 1200 call RunTest_mapping_mods('<' .. a:mods .. '-\|>', '|', a:func, a:code) 1201 call RunTest_mapping_mods('<' .. a:mods .. '-}>', '}', a:func, a:code) 1202 call RunTest_mapping_mods('<' .. a:mods .. '-~>', '~', a:func, a:code) 1203 endif 1204 1205 bwipe! 1206 set timeoutlen& 1207endfunc 1208 1209func Test_mapping_works_with_shift() 1210 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S', 2) 1211 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S', 2) 1212endfunc 1213 1214func Test_mapping_works_with_ctrl() 1215 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C', 5) 1216 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C', 5) 1217endfunc 1218 1219func Test_mapping_works_with_shift_ctrl() 1220 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S', 6) 1221 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S', 6) 1222endfunc 1223 1224" Below we also test the "u" code with Alt, This works, but libvterm would not 1225" send the Alt key like this but by prefixing an Esc. 1226 1227func Test_mapping_works_with_alt() 1228 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'A', 3) 1229 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'A', 3) 1230endfunc 1231 1232func Test_mapping_works_with_shift_alt() 1233 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S-A', 4) 1234 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S-A', 4) 1235endfunc 1236 1237func Test_mapping_works_with_ctrl_alt() 1238 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-A', 7) 1239 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-A', 7) 1240endfunc 1241 1242func Test_mapping_works_with_shift_ctrl_alt() 1243 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 8) 1244 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8) 1245endfunc 1246