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 libvterm version response. 886" This must be after other tests, because it has side effects to xterm 887" properties. 888func Test_xx02_libvterm_response() 889 " Termresponse is only parsed when t_RV is not empty. 890 set t_RV=x 891 892 set ttymouse=xterm 893 call test_option_not_set('ttymouse') 894 let seq = "\<Esc>[>0;100;0c" 895 call feedkeys(seq, 'Lx!') 896 call assert_equal(seq, v:termresponse) 897 call assert_equal('sgr', &ttymouse) 898 899 set t_RV= 900endfunc 901 902" This checks the xterm version response. 903" This must be after other tests, because it has side effects to xterm 904" properties. 905func Test_xx03_xterm_response() 906 " Termresponse is only parsed when t_RV is not empty. 907 set t_RV=x 908 909 " xterm < 95: "xterm" (actually unmodified) 910 set ttymouse=xterm 911 call test_option_not_set('ttymouse') 912 let seq = "\<Esc>[>0;94;0c" 913 call feedkeys(seq, 'Lx!') 914 call assert_equal(seq, v:termresponse) 915 call assert_equal('xterm', &ttymouse) 916 917 " xterm >= 95 < 277 "xterm2" 918 set ttymouse=xterm 919 call test_option_not_set('ttymouse') 920 let seq = "\<Esc>[>0;267;0c" 921 call feedkeys(seq, 'Lx!') 922 call assert_equal(seq, v:termresponse) 923 call assert_equal('xterm2', &ttymouse) 924 925 " xterm >= 277: "sgr" 926 set ttymouse=xterm 927 call test_option_not_set('ttymouse') 928 let seq = "\<Esc>[>0;277;0c" 929 call feedkeys(seq, 'Lx!') 930 call assert_equal(seq, v:termresponse) 931 call assert_equal('sgr', &ttymouse) 932 933 set t_RV= 934endfunc 935 936" TODO: check other terminals response 937 938func Test_get_termcode() 939 try 940 let k1 = &t_k1 941 catch /E113/ 942 throw 'Skipped: Unable to query termcodes' 943 endtry 944 set t_k1= 945 set t_k1& 946 call assert_equal(k1, &t_k1) 947 948 " use external termcap first 949 set nottybuiltin 950 set t_k1= 951 set t_k1& 952 " when using external termcap may get something else, but it must not be 953 " empty, since we would fallback to the builtin one. 954 call assert_notequal('', &t_k1) 955 956 if &term =~ 'xterm' 957 " use internal termcap first 958 let term_save = &term 959 let &term = 'builtin_' .. &term 960 set t_k1= 961 set t_k1& 962 call assert_equal(k1, &t_k1) 963 let &term = term_save 964 endif 965 966 set ttybuiltin 967endfunc 968 969func GetEscCodeCSI27(key, modifier) 970 let key = printf("%d", char2nr(a:key)) 971 let mod = printf("%d", a:modifier) 972 return "\<Esc>[27;" .. mod .. ';' .. key .. '~' 973endfunc 974 975func GetEscCodeCSIu(key, modifier) 976 let key = printf("%d", char2nr(a:key)) 977 let mod = printf("%d", a:modifier) 978 return "\<Esc>[" .. key .. ';' .. mod .. 'u' 979endfunc 980 981" This checks the CSI sequences when in modifyOtherKeys mode. 982" The mode doesn't need to be enabled, the codes are always detected. 983func RunTest_modifyOtherKeys(func) 984 new 985 set timeoutlen=10 986 987 " Shift-X is send as 'X' with the shift modifier 988 call feedkeys('a' .. a:func('X', 2) .. "\<Esc>", 'Lx!') 989 call assert_equal('X', getline(1)) 990 991 " Ctrl-i is Tab 992 call setline(1, '') 993 call feedkeys('a' .. a:func('i', 5) .. "\<Esc>", 'Lx!') 994 call assert_equal("\t", getline(1)) 995 996 " Ctrl-I is also Tab 997 call setline(1, '') 998 call feedkeys('a' .. a:func('I', 5) .. "\<Esc>", 'Lx!') 999 call assert_equal("\t", getline(1)) 1000 1001 " Alt-x is ø 1002 call setline(1, '') 1003 call feedkeys('a' .. a:func('x', 3) .. "\<Esc>", 'Lx!') 1004 call assert_equal("ø", getline(1)) 1005 1006 " Meta-x is also ø 1007 call setline(1, '') 1008 call feedkeys('a' .. a:func('x', 9) .. "\<Esc>", 'Lx!') 1009 call assert_equal("ø", getline(1)) 1010 1011 " Alt-X is Ø 1012 call setline(1, '') 1013 call feedkeys('a' .. a:func('X', 3) .. "\<Esc>", 'Lx!') 1014 call assert_equal("Ø", getline(1)) 1015 1016 " Meta-X is ø 1017 call setline(1, '') 1018 call feedkeys('a' .. a:func('X', 9) .. "\<Esc>", 'Lx!') 1019 call assert_equal("Ø", getline(1)) 1020 1021 bwipe! 1022 set timeoutlen& 1023endfunc 1024 1025func Test_modifyOtherKeys_basic() 1026 call RunTest_modifyOtherKeys(function('GetEscCodeCSI27')) 1027 call RunTest_modifyOtherKeys(function('GetEscCodeCSIu')) 1028endfunc 1029 1030func RunTest_mapping_shift(key, func) 1031 call setline(1, '') 1032 if a:key == '|' 1033 exe 'inoremap \| xyz' 1034 else 1035 exe 'inoremap ' .. a:key .. ' xyz' 1036 endif 1037 call feedkeys('a' .. a:func(a:key, 2) .. "\<Esc>", 'Lx!') 1038 call assert_equal("xyz", getline(1)) 1039 if a:key == '|' 1040 exe 'iunmap \|' 1041 else 1042 exe 'iunmap ' .. a:key 1043 endif 1044endfunc 1045 1046func RunTest_mapping_works_with_shift(func) 1047 new 1048 set timeoutlen=10 1049 1050 call RunTest_mapping_shift('@', a:func) 1051 call RunTest_mapping_shift('A', a:func) 1052 call RunTest_mapping_shift('Z', a:func) 1053 call RunTest_mapping_shift('^', a:func) 1054 call RunTest_mapping_shift('_', a:func) 1055 call RunTest_mapping_shift('{', a:func) 1056 call RunTest_mapping_shift('|', a:func) 1057 call RunTest_mapping_shift('}', a:func) 1058 call RunTest_mapping_shift('~', a:func) 1059 1060 bwipe! 1061 set timeoutlen& 1062endfunc 1063 1064func Test_mapping_works_with_shift_plain() 1065 call RunTest_mapping_works_with_shift(function('GetEscCodeCSI27')) 1066 call RunTest_mapping_works_with_shift(function('GetEscCodeCSIu')) 1067endfunc 1068 1069func RunTest_mapping_mods(map, key, func, code) 1070 call setline(1, '') 1071 exe 'inoremap ' .. a:map .. ' xyz' 1072 call feedkeys('a' .. a:func(a:key, a:code) .. "\<Esc>", 'Lx!') 1073 call assert_equal("xyz", getline(1)) 1074 exe 'iunmap ' .. a:map 1075endfunc 1076 1077func RunTest_mapping_works_with_mods(func, mods, code) 1078 new 1079 set timeoutlen=10 1080 1081 if a:mods !~ 'S' 1082 " Shift by itself has no effect 1083 call RunTest_mapping_mods('<' .. a:mods .. '-@>', '@', a:func, a:code) 1084 endif 1085 call RunTest_mapping_mods('<' .. a:mods .. '-A>', 'A', a:func, a:code) 1086 call RunTest_mapping_mods('<' .. a:mods .. '-Z>', 'Z', a:func, a:code) 1087 if a:mods !~ 'S' 1088 " with Shift code is always upper case 1089 call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'a', a:func, a:code) 1090 call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'z', a:func, a:code) 1091 endif 1092 if a:mods != 'A' 1093 " with Alt code is not in upper case 1094 call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'A', a:func, a:code) 1095 call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'Z', a:func, a:code) 1096 endif 1097 call RunTest_mapping_mods('<' .. a:mods .. '-á>', 'á', a:func, a:code) 1098 if a:mods !~ 'S' 1099 " Shift by itself has no effect 1100 call RunTest_mapping_mods('<' .. a:mods .. '-^>', '^', a:func, a:code) 1101 call RunTest_mapping_mods('<' .. a:mods .. '-_>', '_', a:func, a:code) 1102 call RunTest_mapping_mods('<' .. a:mods .. '-{>', '{', a:func, a:code) 1103 call RunTest_mapping_mods('<' .. a:mods .. '-\|>', '|', a:func, a:code) 1104 call RunTest_mapping_mods('<' .. a:mods .. '-}>', '}', a:func, a:code) 1105 call RunTest_mapping_mods('<' .. a:mods .. '-~>', '~', a:func, a:code) 1106 endif 1107 1108 bwipe! 1109 set timeoutlen& 1110endfunc 1111 1112func Test_mapping_works_with_shift() 1113 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S', 2) 1114 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S', 2) 1115endfunc 1116 1117func Test_mapping_works_with_ctrl() 1118 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C', 5) 1119 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C', 5) 1120endfunc 1121 1122func Test_mapping_works_with_shift_ctrl() 1123 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S', 6) 1124 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S', 6) 1125endfunc 1126 1127" Below we also test the "u" code with Alt, This works, but libvterm would not 1128" send the Alt key like this but by prefixing an Esc. 1129 1130func Test_mapping_works_with_alt() 1131 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'A', 3) 1132 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'A', 3) 1133endfunc 1134 1135func Test_mapping_works_with_shift_alt() 1136 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S-A', 4) 1137 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S-A', 4) 1138endfunc 1139 1140func Test_mapping_works_with_ctrl_alt() 1141 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-A', 7) 1142 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-A', 7) 1143endfunc 1144 1145func Test_mapping_works_with_shift_ctrl_alt() 1146 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 8) 1147 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8) 1148endfunc 1149