1" Tests for decoding escape sequences sent by the terminal. 2 3" This only works for Unix in a terminal 4if has('gui_running') || !has('unix') 5 finish 6endif 7 8source shared.vim 9 10" Helper function to emit a terminal escape code. 11func TerminalEscapeCode(code_xterm, code_sgr, row, col, m) 12 if &ttymouse ==# 'xterm2' 13 " need to use byte encoding here. 14 let str = list2str([a:code_xterm, a:col + 0x20, a:row + 0x20]) 15 if has('iconv') 16 let bytes = iconv(str, 'utf-8', 'latin1') 17 else 18 " Hopefully the numbers are not too big. 19 let bytes = str 20 endif 21 call feedkeys("\<Esc>[M" .. bytes, 'Lx!') 22 elseif &ttymouse ==# 'sgr' 23 call feedkeys(printf("\<Esc>[<%d;%d;%d%s", a:code_sgr, a:col, a:row, a:m), 'Lx!') 24 endif 25endfunc 26 27func MouseLeftClick(row, col) 28 call TerminalEscapeCode(0x20, 0, a:row, a:col, 'M') 29endfunc 30 31func MouseMiddleClick(row, col) 32 call TerminalEscapeCode(0x21, 1, a:row, a:col, 'M') 33endfunc 34 35func MouseLeftRelease(row, col) 36 call TerminalEscapeCode(0x23, 3, a:row, a:col, 'm') 37endfunc 38 39func MouseMiddleRelease(row, col) 40 call TerminalEscapeCode(0x23, 3, a:row, a:col, 'm') 41endfunc 42 43func MouseLeftDrag(row, col) 44 call TerminalEscapeCode(0x43, 0x20, a:row, a:col, 'M') 45endfunc 46 47func MouseWheelUp(row, col) 48 call TerminalEscapeCode(0x40, 0x40, a:row, a:col, 'M') 49endfunc 50 51func MouseWheelDown(row, col) 52 call TerminalEscapeCode(0x41, 0x41, a:row, a:col, 'M') 53endfunc 54 55func Test_xterm_mouse_left_click() 56 new 57 let save_mouse = &mouse 58 let save_term = &term 59 let save_ttymouse = &ttymouse 60 set mouse=a term=xterm 61 call setline(1, ['line 1', 'line 2', 'line 3 is a bit longer']) 62 63 for ttymouse_val in ['xterm2', 'sgr'] 64 let msg = 'ttymouse=' .. ttymouse_val 65 exe 'set ttymouse=' . ttymouse_val 66 go 67 call assert_equal([0, 1, 1, 0], getpos('.'), msg) 68 let row = 2 69 let col = 6 70 call MouseLeftClick(row, col) 71 call MouseLeftRelease(row, col) 72 call assert_equal([0, 2, 6, 0], getpos('.'), msg) 73 endfor 74 75 let &mouse = save_mouse 76 let &term = save_term 77 let &ttymouse = save_ttymouse 78 bwipe! 79endfunc 80 81func Test_xterm_mouse_middle_click() 82 if !WorkingClipboard() 83 throw 'Skipped: No working clipboard' 84 endif 85 86 new 87 let save_mouse = &mouse 88 let save_term = &term 89 let save_ttymouse = &ttymouse 90 let save_quotestar = @* 91 let @* = 'abc' 92 set mouse=a term=xterm 93 94 for ttymouse_val in ['xterm2', 'sgr'] 95 let msg = 'ttymouse=' .. ttymouse_val 96 exe 'set ttymouse=' . ttymouse_val 97 call setline(1, ['123456789', '123456789']) 98 99 " Middle-click in the middle of the line pastes text where clicked. 100 let row = 1 101 let col = 6 102 call MouseMiddleClick(row, col) 103 call MouseMiddleRelease(row, col) 104 call assert_equal(['12345abc6789', '123456789'], getline(1, '$'), msg) 105 106 " Middle-click beyond end of the line pastes text at the end of the line. 107 let col = 20 108 call MouseMiddleClick(row, col) 109 call MouseMiddleRelease(row, col) 110 call assert_equal(['12345abc6789abc', '123456789'], getline(1, '$'), msg) 111 112 " Middle-click beyond the last line pastes in the last line. 113 let row = 5 114 let col = 3 115 call MouseMiddleClick(row, col) 116 call MouseMiddleRelease(row, col) 117 call assert_equal(['12345abc6789abc', '12abc3456789'], getline(1, '$'), msg) 118 endfor 119 120 let &mouse = save_mouse 121 let &term = save_term 122 let &ttymouse = save_ttymouse 123 let @* = save_quotestar 124 bwipe! 125endfunc 126 127func Test_xterm_mouse_wheel() 128 new 129 let save_mouse = &mouse 130 let save_term = &term 131 let save_ttymouse = &ttymouse 132 set mouse=a term=xterm 133 call setline(1, range(1, 100)) 134 135 for ttymouse_val in ['xterm2', 'sgr'] 136 let msg = 'ttymouse=' .. ttymouse_val 137 exe 'set ttymouse=' . ttymouse_val 138 go 139 call assert_equal(1, line('w0'), msg) 140 call assert_equal([0, 1, 1, 0], getpos('.'), msg) 141 142 call MouseWheelDown(1, 1) 143 call assert_equal(4, line('w0'), msg) 144 call assert_equal([0, 4, 1, 0], getpos('.'), msg) 145 146 call MouseWheelDown(1, 1) 147 call assert_equal(7, line('w0'), msg) 148 call assert_equal([0, 7, 1, 0], getpos('.'), msg) 149 150 call MouseWheelUp(1, 1) 151 call assert_equal(4, line('w0'), msg) 152 call assert_equal([0, 7, 1, 0], getpos('.'), msg) 153 154 call MouseWheelUp(1, 1) 155 call assert_equal(1, line('w0'), msg) 156 call assert_equal([0, 7, 1, 0], getpos('.'), msg) 157 endfor 158 159 let &mouse = save_mouse 160 let &term = save_term 161 let &ttymouse = save_ttymouse 162 bwipe! 163endfunc 164 165func Test_xterm_mouse_drag_window_separator() 166 let save_mouse = &mouse 167 let save_term = &term 168 let save_ttymouse = &ttymouse 169 set mouse=a term=xterm 170 171 for ttymouse_val in ['xterm2', 'sgr'] 172 let msg = 'ttymouse=' .. ttymouse_val 173 exe 'set ttymouse=' . ttymouse_val 174 175 " Split horizontally and test dragging the horizontal window separator. 176 split 177 let rowseparator = winheight(0) + 1 178 let row = rowseparator 179 let col = 1 180 181 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported. 182 if ttymouse_val !=# 'xterm2' || row <= 223 183 call MouseLeftClick(row, col) 184 let row -= 1 185 call MouseLeftDrag(row, col) 186 call assert_equal(rowseparator - 1, winheight(0) + 1, msg) 187 let row += 1 188 call MouseLeftDrag(row, col) 189 call assert_equal(rowseparator, winheight(0) + 1, msg) 190 call MouseLeftRelease(row, col) 191 call assert_equal(rowseparator, winheight(0) + 1, msg) 192 endif 193 bwipe! 194 195 " Split vertically and test dragging the vertical window separator. 196 vsplit 197 let colseparator = winwidth(0) + 1 198 let row = 1 199 let col = colseparator 200 201 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported. 202 if ttymouse_val !=# 'xterm2' || col <= 223 203 call MouseLeftClick(row, col) 204 let col -= 1 205 call MouseLeftDrag(row, col) 206 call assert_equal(colseparator - 1, winwidth(0) + 1, msg) 207 let col += 1 208 call MouseLeftDrag(row, col) 209 call assert_equal(colseparator, winwidth(0) + 1, msg) 210 call MouseLeftRelease(row, col) 211 call assert_equal(colseparator, winwidth(0) + 1, msg) 212 endif 213 bwipe! 214 endfor 215 216 let &mouse = save_mouse 217 let &term = save_term 218 let &ttymouse = save_ttymouse 219endfunc 220 221func Test_xterm_mouse_drag_statusline() 222 let save_mouse = &mouse 223 let save_term = &term 224 let save_ttymouse = &ttymouse 225 let save_laststatus = &laststatus 226 set mouse=a term=xterm laststatus=2 227 228 for ttymouse_val in ['xterm2', 'sgr'] 229 let msg = 'ttymouse=' .. ttymouse_val 230 exe 'set ttymouse=' . ttymouse_val 231 232 call assert_equal(1, &cmdheight, msg) 233 let rowstatusline = winheight(0) + 1 234 let row = rowstatusline 235 let col = 1 236 237 if ttymouse_val ==# 'xterm2' && row > 223 238 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported. 239 continue 240 endif 241 242 call MouseLeftClick(row, col) 243 let row -= 1 244 call MouseLeftDrag(row, col) 245 call assert_equal(2, &cmdheight, msg) 246 call assert_equal(rowstatusline - 1, winheight(0) + 1, msg) 247 let row += 1 248 call MouseLeftDrag(row, col) 249 call assert_equal(1, &cmdheight, msg) 250 call assert_equal(rowstatusline, winheight(0) + 1, msg) 251 call MouseLeftRelease(row, col) 252 call assert_equal(1, &cmdheight, msg) 253 call assert_equal(rowstatusline, winheight(0) + 1, msg) 254 endfor 255 256 let &mouse = save_mouse 257 let &term = save_term 258 let &ttymouse = save_ttymouse 259 let &laststatus = save_laststatus 260endfunc 261 262func Test_xterm_mouse_click_tab() 263 let save_mouse = &mouse 264 let save_term = &term 265 let save_ttymouse = &ttymouse 266 set mouse=a term=xterm 267 let row = 1 268 269 for ttymouse_val in ['xterm2', 'sgr'] 270 let msg = 'ttymouse=' .. ttymouse_val 271 exe 'set ttymouse=' . ttymouse_val 272 e Xfoo 273 tabnew Xbar 274 275 let a = split(execute(':tabs'), "\n") 276 call assert_equal(['Tab page 1', 277 \ ' Xfoo', 278 \ 'Tab page 2', 279 \ '> Xbar'], a, msg) 280 281 " Test clicking on tab names in the tabline at the top. 282 let col = 2 283 redraw 284 call MouseLeftClick(row, col) 285 call MouseLeftRelease(row, col) 286 let a = split(execute(':tabs'), "\n") 287 call assert_equal(['Tab page 1', 288 \ '> Xfoo', 289 \ 'Tab page 2', 290 \ ' Xbar'], a, msg) 291 292 let col = 9 293 call MouseLeftClick(row, col) 294 call MouseLeftRelease(row, col) 295 let a = split(execute(':tabs'), "\n") 296 call assert_equal(['Tab page 1', 297 \ ' Xfoo', 298 \ 'Tab page 2', 299 \ '> Xbar'], a, msg) 300 301 %bwipe! 302 endfor 303 304 let &mouse = save_mouse 305 let &term = save_term 306 let &ttymouse = save_ttymouse 307endfunc 308 309func Test_xterm_mouse_click_X_to_close_tab() 310 let save_mouse = &mouse 311 let save_term = &term 312 let save_ttymouse = &ttymouse 313 set mouse=a term=xterm 314 let row = 1 315 let col = &columns 316 317 for ttymouse_val in ['xterm2', 'sgr'] 318 if ttymouse_val ==# 'xterm2' && col > 223 319 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported. 320 continue 321 endif 322 let msg = 'ttymouse=' .. ttymouse_val 323 exe 'set ttymouse=' . ttymouse_val 324 e Xtab1 325 tabnew Xtab2 326 tabnew Xtab3 327 tabn 2 328 329 let a = split(execute(':tabs'), "\n") 330 call assert_equal(['Tab page 1', 331 \ ' Xtab1', 332 \ 'Tab page 2', 333 \ '> Xtab2', 334 \ 'Tab page 3', 335 \ ' Xtab3'], a, msg) 336 337 " Click on "X" in tabline to close current tab i.e. Xtab2. 338 redraw 339 call MouseLeftClick(row, col) 340 call MouseLeftRelease(row, col) 341 let a = split(execute(':tabs'), "\n") 342 call assert_equal(['Tab page 1', 343 \ ' Xtab1', 344 \ 'Tab page 2', 345 \ '> Xtab3'], a, msg) 346 347 %bwipe! 348 endfor 349 350 let &mouse = save_mouse 351 let &term = save_term 352 let &ttymouse = save_ttymouse 353endfunc 354 355func Test_xterm_mouse_drag_to_move_tab() 356 let save_mouse = &mouse 357 let save_term = &term 358 let save_ttymouse = &ttymouse 359 " Set 'mousetime' to 1 to avoid recognizing a double-click in the loop 360 set mouse=a term=xterm mousetime=1 361 let row = 1 362 363 for ttymouse_val in ['xterm2', 'sgr'] 364 let msg = 'ttymouse=' .. ttymouse_val 365 exe 'set ttymouse=' . ttymouse_val 366 e Xtab1 367 tabnew Xtab2 368 369 let a = split(execute(':tabs'), "\n") 370 call assert_equal(['Tab page 1', 371 \ ' Xtab1', 372 \ 'Tab page 2', 373 \ '> Xtab2'], a, msg) 374 redraw 375 376 " Click in tab2 and drag it to tab1. 377 " Check getcharmod() to verify that click is not 378 " interpreted as a spurious double-click. 379 call MouseLeftClick(row, 10) 380 call assert_equal(0, getcharmod(), msg) 381 for col in [9, 8, 7, 6] 382 call MouseLeftDrag(row, col) 383 endfor 384 call MouseLeftRelease(row, col) 385 let a = split(execute(':tabs'), "\n") 386 call assert_equal(['Tab page 1', 387 \ '> Xtab2', 388 \ 'Tab page 2', 389 \ ' Xtab1'], a, msg) 390 391 " brief sleep to avoid causing a double-click 392 sleep 20m 393 %bwipe! 394 endfor 395 396 let &mouse = save_mouse 397 let &term = save_term 398 let &ttymouse = save_ttymouse 399 set mousetime& 400endfunc 401 402func Test_xterm_mouse_double_click_to_create_tab() 403 let save_mouse = &mouse 404 let save_term = &term 405 let save_ttymouse = &ttymouse 406 " Set 'mousetime' to a small value, so that double-click works but we don't 407 " have to wait long to avoid a triple-click. 408 set mouse=a term=xterm mousetime=100 409 let row = 1 410 let col = 10 411 412 for ttymouse_val in ['xterm2', 'sgr'] 413 let msg = 'ttymouse=' .. ttymouse_val 414 exe 'set ttymouse=' . ttymouse_val 415 e Xtab1 416 tabnew Xtab2 417 418 let a = split(execute(':tabs'), "\n") 419 call assert_equal(['Tab page 1', 420 \ ' Xtab1', 421 \ 'Tab page 2', 422 \ '> Xtab2'], a, msg) 423 424 redraw 425 call MouseLeftClick(row, col) 426 " Check getcharmod() to verify that first click is not 427 " interpreted as a spurious double-click. 428 call assert_equal(0, getcharmod(), msg) 429 call MouseLeftRelease(row, col) 430 call MouseLeftClick(row, col) 431 call assert_equal(32, getcharmod(), msg) " double-click 432 call MouseLeftRelease(row, col) 433 let a = split(execute(':tabs'), "\n") 434 call assert_equal(['Tab page 1', 435 \ ' Xtab1', 436 \ 'Tab page 2', 437 \ '> [No Name]', 438 \ 'Tab page 3', 439 \ ' Xtab2'], a, msg) 440 441 if ttymouse_val !=# 'sgr' 442 " We need to sleep, or else MouseLeftClick() in next loop 443 " iteration will be interpreted as a spurious triple-click. 444 sleep 100m 445 endif 446 %bwipe! 447 endfor 448 449 let &mouse = save_mouse 450 let &term = save_term 451 let &ttymouse = save_ttymouse 452 set mousetime& 453endfunc 454 455func Test_xterm_mouse_click_in_fold_columns() 456 new 457 let save_mouse = &mouse 458 let save_term = &term 459 let save_ttymouse = &ttymouse 460 let save_foldcolumn = &foldcolumn 461 set mouse=a term=xterm foldcolumn=3 ttymouse=xterm2 462 463 " Create 2 nested folds. 464 call setline(1, range(1, 7)) 465 2,6fold 466 norm! zR 467 4,5fold 468 call assert_equal([-1, -1, -1, 4, 4, -1, -1], 469 \ map(range(1, 7), 'foldclosed(v:val)')) 470 471 " Click in "+" of inner fold in foldcolumn should open it. 472 redraw 473 let row = 4 474 let col = 2 475 call MouseLeftClick(row, col) 476 call MouseLeftRelease(row, col) 477 call assert_equal([-1, -1, -1, -1, -1, -1, -1], 478 \ map(range(1, 7), 'foldclosed(v:val)')) 479 480 " Click in "-" of outer fold in foldcolumn should close it. 481 redraw 482 let row = 2 483 let col = 1 484 call MouseLeftClick(row, col) 485 call MouseLeftRelease(row, col) 486 call assert_equal([-1, 2, 2, 2, 2, 2, -1], 487 \ map(range(1, 7), 'foldclosed(v:val)')) 488 norm! zR 489 490 " Click in "|" of inner fold in foldcolumn should close it. 491 redraw 492 let row = 5 493 let col = 2 494 call MouseLeftClick(row, col) 495 call MouseLeftRelease(row, col) 496 call assert_equal([-1, -1, -1, 4, 4, -1, -1], 497 \ map(range(1, 7), 'foldclosed(v:val)')) 498 499 let &foldcolumn = save_foldcolumn 500 let &ttymouse = save_ttymouse 501 let &term = save_term 502 let &mouse = save_mouse 503 bwipe! 504endfunc 505