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