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    " Click elsewhere so that click in next iteration is not
678    " interpreted as unwanted double-click.
679    call MouseLeftClick(row, 11)
680    call MouseLeftRelease(row, 11)
681
682    %bwipe!
683  endfor
684
685  let &mouse = save_mouse
686  let &term = save_term
687  let &ttymouse = save_ttymouse
688  call test_override('no_query_mouse', 0)
689  set mousetime&
690endfunc
691
692func Test_term_mouse_double_click_to_create_tab()
693  let save_mouse = &mouse
694  let save_term = &term
695  let save_ttymouse = &ttymouse
696  call test_override('no_query_mouse', 1)
697  " Set 'mousetime' to a small value, so that double-click works but we don't
698  " have to wait long to avoid a triple-click.
699  set mouse=a term=xterm mousetime=200
700  let row = 1
701  let col = 10
702
703  for ttymouse_val in s:ttymouse_values + s:ttymouse_dec
704    let msg = 'ttymouse=' .. ttymouse_val
705    exe 'set ttymouse=' .. ttymouse_val
706    e Xtab1
707    tabnew Xtab2
708
709    let a = split(execute(':tabs'), "\n")
710    call assert_equal(['Tab page 1',
711        \              '    Xtab1',
712        \              'Tab page 2',
713        \              '>   Xtab2'], a, msg)
714
715    redraw
716    call MouseLeftClick(row, col)
717    " Check getcharmod() to verify that first click is not
718    " interpreted as a spurious double-click.
719    call assert_equal(0, getcharmod(), msg)
720    call MouseLeftRelease(row, col)
721    call MouseLeftClick(row, col)
722    call assert_equal(32, getcharmod(), msg) " double-click
723    call MouseLeftRelease(row, col)
724    let a = split(execute(':tabs'), "\n")
725    call assert_equal(['Tab page 1',
726        \              '    Xtab1',
727        \              'Tab page 2',
728        \              '>   [No Name]',
729        \              'Tab page 3',
730        \              '    Xtab2'], a, msg)
731
732    " Click elsewhere so that click in next iteration is not
733    " interpreted as unwanted double click.
734    call MouseLeftClick(row, col + 1)
735    call MouseLeftRelease(row, col + 1)
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
747" Test double/triple/quadruple click in normal mode to visually select.
748func Test_term_mouse_multiple_clicks_to_visually_select()
749  let save_mouse = &mouse
750  let save_term = &term
751  let save_ttymouse = &ttymouse
752  call test_override('no_query_mouse', 1)
753  set mouse=a term=xterm mousetime=200
754  new
755
756  for ttymouse_val in s:ttymouse_values + s:ttymouse_dec
757    let msg = 'ttymouse=' .. ttymouse_val
758    exe 'set ttymouse=' .. ttymouse_val
759    call setline(1, ['foo [foo bar] foo', 'foo'])
760
761    " Double-click on word should visually select the word.
762    call MouseLeftClick(1, 2)
763    call assert_equal(0, getcharmod(), msg)
764    call MouseLeftRelease(1, 2)
765    call MouseLeftClick(1, 2)
766    call assert_equal(32, getcharmod(), msg) " double-click
767    call MouseLeftRelease(1, 2)
768    call assert_equal('v', mode(), msg)
769    norm! r1
770    call assert_equal(['111 [foo bar] foo', 'foo'], getline(1, '$'), msg)
771
772    " Double-click on opening square bracket should visually
773    " select the whole [foo bar].
774    call MouseLeftClick(1, 5)
775    call assert_equal(0, getcharmod(), msg)
776    call MouseLeftRelease(1, 5)
777    call MouseLeftClick(1, 5)
778    call assert_equal(32, getcharmod(), msg) " double-click
779    call MouseLeftRelease(1, 5)
780    call assert_equal('v', mode(), msg)
781    norm! r2
782    call assert_equal(['111 222222222 foo', 'foo'], getline(1, '$'), msg)
783
784    " Triple-click should visually select the whole line.
785    call MouseLeftClick(1, 3)
786    call assert_equal(0, getcharmod(), msg)
787    call MouseLeftRelease(1, 3)
788    call MouseLeftClick(1, 3)
789    call assert_equal(32, getcharmod(), msg) " double-click
790    call MouseLeftRelease(1, 3)
791    call MouseLeftClick(1, 3)
792    call assert_equal(64, getcharmod(), msg) " triple-click
793    call MouseLeftRelease(1, 3)
794    call assert_equal('V', mode(), msg)
795    norm! r3
796    call assert_equal(['33333333333333333', 'foo'], getline(1, '$'), msg)
797
798    " Quadruple-click should start visual block select.
799    call MouseLeftClick(1, 2)
800    call assert_equal(0, getcharmod(), msg)
801    call MouseLeftRelease(1, 2)
802    call MouseLeftClick(1, 2)
803    call assert_equal(32, getcharmod(), msg) " double-click
804    call MouseLeftRelease(1, 2)
805    call MouseLeftClick(1, 2)
806    call assert_equal(64, getcharmod(), msg) " triple-click
807    call MouseLeftRelease(1, 2)
808    call MouseLeftClick(1, 2)
809    call assert_equal(96, getcharmod(), msg) " quadruple-click
810    call MouseLeftRelease(1, 2)
811    call assert_equal("\<c-v>", mode(), msg)
812    norm! r4
813    call assert_equal(['34333333333333333', 'foo'], getline(1, '$'), msg)
814  endfor
815
816  let &mouse = save_mouse
817  let &term = save_term
818  let &ttymouse = save_ttymouse
819  set mousetime&
820  call test_override('no_query_mouse', 0)
821  bwipe!
822endfunc
823
824func Test_xterm_mouse_click_in_fold_columns()
825  new
826  let save_mouse = &mouse
827  let save_term = &term
828  let save_ttymouse = &ttymouse
829  let save_foldcolumn = &foldcolumn
830  set mouse=a term=xterm foldcolumn=3 ttymouse=xterm2
831
832  " Create 2 nested folds.
833  call setline(1, range(1, 7))
834  2,6fold
835  norm! zR
836  4,5fold
837  call assert_equal([-1, -1, -1, 4, 4, -1, -1],
838        \           map(range(1, 7), 'foldclosed(v:val)'))
839
840  " Click in "+" of inner fold in foldcolumn should open it.
841  redraw
842  let row = 4
843  let col = 2
844  call MouseLeftClick(row, col)
845  call MouseLeftRelease(row, col)
846  call assert_equal([-1, -1, -1, -1, -1, -1, -1],
847        \           map(range(1, 7), 'foldclosed(v:val)'))
848
849  " Click in "-" of outer fold in foldcolumn should close it.
850  redraw
851  let row = 2
852  let col = 1
853  call MouseLeftClick(row, col)
854  call MouseLeftRelease(row, col)
855  call assert_equal([-1, 2, 2, 2, 2, 2, -1],
856        \           map(range(1, 7), 'foldclosed(v:val)'))
857  norm! zR
858
859  " Click in "|" of inner fold in foldcolumn should close it.
860  redraw
861  let row = 5
862  let col = 2
863  call MouseLeftClick(row, col)
864  call MouseLeftRelease(row, col)
865  call assert_equal([-1, -1, -1, 4, 4, -1, -1],
866        \           map(range(1, 7), 'foldclosed(v:val)'))
867
868  let &foldcolumn = save_foldcolumn
869  let &ttymouse = save_ttymouse
870  let &term = save_term
871  let &mouse = save_mouse
872  bwipe!
873endfunc
874
875" This only checks if the sequence is recognized.
876func Test_term_rgb_response()
877  set t_RF=x
878  set t_RB=y
879
880  " response to t_RF, 4 digits
881  let red = 0x12
882  let green = 0x34
883  let blue = 0x56
884  let seq = printf("\<Esc>]10;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
885  call feedkeys(seq, 'Lx!')
886  call assert_equal(seq, v:termrfgresp)
887
888  " response to t_RF, 2 digits
889  let red = 0x78
890  let green = 0x9a
891  let blue = 0xbc
892  let seq = printf("\<Esc>]10;rgb:%02x/%02x/%02x\x07", red, green, blue)
893  call feedkeys(seq, 'Lx!')
894  call assert_equal(seq, v:termrfgresp)
895
896  " response to t_RB, 4 digits, dark
897  set background=light
898  eval 'background'->test_option_not_set()
899  let red = 0x29
900  let green = 0x4a
901  let blue = 0x6b
902  let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
903  call feedkeys(seq, 'Lx!')
904  call assert_equal(seq, v:termrbgresp)
905  call assert_equal('dark', &background)
906
907  " response to t_RB, 4 digits, light
908  set background=dark
909  call test_option_not_set('background')
910  let red = 0x81
911  let green = 0x63
912  let blue = 0x65
913  let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
914  call feedkeys(seq, 'Lx!')
915  call assert_equal(seq, v:termrbgresp)
916  call assert_equal('light', &background)
917
918  " response to t_RB, 2 digits, dark
919  set background=light
920  call test_option_not_set('background')
921  let red = 0x47
922  let green = 0x59
923  let blue = 0x5b
924  let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
925  call feedkeys(seq, 'Lx!')
926  call assert_equal(seq, v:termrbgresp)
927  call assert_equal('dark', &background)
928
929  " response to t_RB, 2 digits, light
930  set background=dark
931  call test_option_not_set('background')
932  let red = 0x83
933  let green = 0xa4
934  let blue = 0xc2
935  let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
936  call feedkeys(seq, 'Lx!')
937  call assert_equal(seq, v:termrbgresp)
938  call assert_equal('light', &background)
939
940  set t_RF= t_RB=
941endfunc
942
943" This only checks if the sequence is recognized.
944" This must be after other tests, because it has side effects to xterm
945" properties.
946func Test_xx01_term_style_response()
947  " Termresponse is only parsed when t_RV is not empty.
948  set t_RV=x
949
950  " send the termresponse to trigger requesting the XT codes
951  let seq = "\<Esc>[>41;337;0c"
952  call feedkeys(seq, 'Lx!')
953  call assert_equal(seq, v:termresponse)
954
955  let seq = "\<Esc>P1$r2 q\<Esc>\\"
956  call feedkeys(seq, 'Lx!')
957  call assert_equal(seq, v:termstyleresp)
958
959  set t_RV=
960endfunc
961
962" This checks the iTerm2 version response.
963" This must be after other tests, because it has side effects to xterm
964" properties.
965func Test_xx02_iTerm2_response()
966  " Termresponse is only parsed when t_RV is not empty.
967  set t_RV=x
968
969  " Old versions of iTerm2 used a different style term response.
970  set ttymouse=xterm
971  call test_option_not_set('ttymouse')
972  let seq = "\<Esc>[>0;95;c"
973  call feedkeys(seq, 'Lx!')
974  call assert_equal(seq, v:termresponse)
975  call assert_equal('xterm', &ttymouse)
976
977  set ttymouse=xterm
978  call test_option_not_set('ttymouse')
979  let seq = "\<Esc>[>0;95;0c"
980  call feedkeys(seq, 'Lx!')
981  call assert_equal(seq, v:termresponse)
982  call assert_equal('sgr', &ttymouse)
983
984  set t_RV=
985endfunc
986
987" This checks the libvterm version response.
988" This must be after other tests, because it has side effects to xterm
989" properties.
990func Test_xx03_libvterm_response()
991  " Termresponse is only parsed when t_RV is not empty.
992  set t_RV=x
993
994  set ttymouse=xterm
995  call test_option_not_set('ttymouse')
996  let seq = "\<Esc>[>0;100;0c"
997  call feedkeys(seq, 'Lx!')
998  call assert_equal(seq, v:termresponse)
999  call assert_equal('sgr', &ttymouse)
1000
1001  set t_RV=
1002endfunc
1003
1004" This checks the Mac Terminal.app version response.
1005" This must be after other tests, because it has side effects to xterm
1006" properties.
1007func Test_xx04_Mac_Terminal_response()
1008  " Termresponse is only parsed when t_RV is not empty.
1009  set t_RV=x
1010
1011  set ttymouse=xterm
1012  call test_option_not_set('ttymouse')
1013  let seq = "\<Esc>[>1;95;0c"
1014  call feedkeys(seq, 'Lx!')
1015  call assert_equal(seq, v:termresponse)
1016  call assert_equal('sgr', &ttymouse)
1017
1018  " Reset is_not_xterm and is_mac_terminal.
1019  set t_RV=
1020  set term=xterm
1021  set t_RV=x
1022endfunc
1023
1024" This checks the mintty version response.
1025" This must be after other tests, because it has side effects to xterm
1026" properties.
1027func Test_xx05_mintty_response()
1028  " Termresponse is only parsed when t_RV is not empty.
1029  set t_RV=x
1030
1031  set ttymouse=xterm
1032  call test_option_not_set('ttymouse')
1033  let seq = "\<Esc>[>77;20905;0c"
1034  call feedkeys(seq, 'Lx!')
1035  call assert_equal(seq, v:termresponse)
1036  call assert_equal('sgr', &ttymouse)
1037
1038  set t_RV=
1039endfunc
1040
1041" This checks the screen version response.
1042" This must be after other tests, because it has side effects to xterm
1043" properties.
1044func Test_xx06_screen_response()
1045  " Termresponse is only parsed when t_RV is not empty.
1046  set t_RV=x
1047
1048  " Old versions of screen don't support SGR mouse mode.
1049  set ttymouse=xterm
1050  call test_option_not_set('ttymouse')
1051  let seq = "\<Esc>[>83;40500;0c"
1052  call feedkeys(seq, 'Lx!')
1053  call assert_equal(seq, v:termresponse)
1054  call assert_equal('xterm', &ttymouse)
1055
1056  " screen supports SGR mouse mode starting in version 4.7.
1057  set ttymouse=xterm
1058  call test_option_not_set('ttymouse')
1059  let seq = "\<Esc>[>83;40700;0c"
1060  call feedkeys(seq, 'Lx!')
1061  call assert_equal(seq, v:termresponse)
1062  call assert_equal('sgr', &ttymouse)
1063
1064  set t_RV=
1065endfunc
1066
1067" This checks the xterm version response.
1068" This must be after other tests, because it has side effects to xterm
1069" properties.
1070func Test_xx07_xterm_response()
1071  " Termresponse is only parsed when t_RV is not empty.
1072  set t_RV=x
1073
1074  " Do Terminal.app first to check that is_mac_terminal is reset.
1075  set ttymouse=xterm
1076  call test_option_not_set('ttymouse')
1077  let seq = "\<Esc>[>1;95;0c"
1078  call feedkeys(seq, 'Lx!')
1079  call assert_equal(seq, v:termresponse)
1080  call assert_equal('sgr', &ttymouse)
1081
1082  " xterm < 95: "xterm" (actually unmodified)
1083  set t_RV=
1084  set term=xterm
1085  set t_RV=x
1086  set ttymouse=xterm
1087  call test_option_not_set('ttymouse')
1088  let seq = "\<Esc>[>0;94;0c"
1089  call feedkeys(seq, 'Lx!')
1090  call assert_equal(seq, v:termresponse)
1091  call assert_equal('xterm', &ttymouse)
1092
1093  " xterm >= 95 < 277 "xterm2"
1094  set ttymouse=xterm
1095  call test_option_not_set('ttymouse')
1096  let seq = "\<Esc>[>0;267;0c"
1097  call feedkeys(seq, 'Lx!')
1098  call assert_equal(seq, v:termresponse)
1099  call assert_equal('xterm2', &ttymouse)
1100
1101  " xterm >= 277: "sgr"
1102  set ttymouse=xterm
1103  call test_option_not_set('ttymouse')
1104  let seq = "\<Esc>[>0;277;0c"
1105  call feedkeys(seq, 'Lx!')
1106  call assert_equal(seq, v:termresponse)
1107  call assert_equal('sgr', &ttymouse)
1108
1109  set t_RV=
1110endfunc
1111
1112func Test_get_termcode()
1113  try
1114    let k1 = &t_k1
1115  catch /E113/
1116    throw 'Skipped: Unable to query termcodes'
1117  endtry
1118  set t_k1=
1119  set t_k1&
1120  call assert_equal(k1, &t_k1)
1121
1122  " use external termcap first
1123  set nottybuiltin
1124  set t_k1=
1125  set t_k1&
1126  " when using external termcap may get something else, but it must not be
1127  " empty, since we would fallback to the builtin one.
1128  call assert_notequal('', &t_k1)
1129
1130  if &term =~ 'xterm'
1131    " use internal termcap first
1132    let term_save = &term
1133    let &term = 'builtin_' .. &term
1134    set t_k1=
1135    set t_k1&
1136    call assert_equal(k1, &t_k1)
1137    let &term = term_save
1138  endif
1139
1140  set ttybuiltin
1141endfunc
1142
1143func GetEscCodeCSI27(key, modifier)
1144  let key = printf("%d", char2nr(a:key))
1145  let mod = printf("%d", a:modifier)
1146  return "\<Esc>[27;" .. mod .. ';' .. key .. '~'
1147endfunc
1148
1149func GetEscCodeCSIu(key, modifier)
1150  let key = printf("%d", char2nr(a:key))
1151  let mod = printf("%d", a:modifier)
1152  return "\<Esc>[" .. key .. ';' .. mod .. 'u'
1153endfunc
1154
1155" This checks the CSI sequences when in modifyOtherKeys mode.
1156" The mode doesn't need to be enabled, the codes are always detected.
1157func RunTest_modifyOtherKeys(func)
1158  new
1159  set timeoutlen=10
1160
1161  " Shift-X is send as 'X' with the shift modifier
1162  call feedkeys('a' .. a:func('X', 2) .. "\<Esc>", 'Lx!')
1163  call assert_equal('X', getline(1))
1164
1165  " Ctrl-i is Tab
1166  call setline(1, '')
1167  call feedkeys('a' .. a:func('i', 5) .. "\<Esc>", 'Lx!')
1168  call assert_equal("\t", getline(1))
1169
1170  " Ctrl-I is also Tab
1171  call setline(1, '')
1172  call feedkeys('a' .. a:func('I', 5) .. "\<Esc>", 'Lx!')
1173  call assert_equal("\t", getline(1))
1174
1175  " Alt-x is ø
1176  call setline(1, '')
1177  call feedkeys('a' .. a:func('x', 3) .. "\<Esc>", 'Lx!')
1178  call assert_equal("ø", getline(1))
1179
1180  " Meta-x is also ø
1181  call setline(1, '')
1182  call feedkeys('a' .. a:func('x', 9) .. "\<Esc>", 'Lx!')
1183  call assert_equal("ø", getline(1))
1184
1185  " Alt-X is Ø
1186  call setline(1, '')
1187  call feedkeys('a' .. a:func('X', 3) .. "\<Esc>", 'Lx!')
1188  call assert_equal("Ø", getline(1))
1189
1190  " Meta-X is ø
1191  call setline(1, '')
1192  call feedkeys('a' .. a:func('X', 9) .. "\<Esc>", 'Lx!')
1193  call assert_equal("Ø", getline(1))
1194
1195  " Ctrl-6 is Ctrl-^
1196  split aaa
1197  edit bbb
1198  call feedkeys(a:func('6', 5), 'Lx!')
1199  call assert_equal("aaa", bufname())
1200  bwipe aaa
1201  bwipe bbb
1202
1203  bwipe!
1204  set timeoutlen&
1205endfunc
1206
1207func Test_modifyOtherKeys_basic()
1208  call RunTest_modifyOtherKeys(function('GetEscCodeCSI27'))
1209  call RunTest_modifyOtherKeys(function('GetEscCodeCSIu'))
1210endfunc
1211
1212func Test_modifyOtherKeys_no_mapping()
1213  set timeoutlen=10
1214
1215  let @a = 'aaa'
1216  call feedkeys(":let x = '" .. GetEscCodeCSI27('R', 5) .. GetEscCodeCSI27('R', 5) .. "a'\<CR>", 'Lx!')
1217  call assert_equal("let x = 'aaa'", @:)
1218
1219  new
1220  call feedkeys("a" .. GetEscCodeCSI27('R', 5) .. GetEscCodeCSI27('R', 5) .. "a\<Esc>", 'Lx!')
1221  call assert_equal("aaa", getline(1))
1222  bwipe!
1223
1224  new
1225  call feedkeys("axx\<CR>yy" .. GetEscCodeCSI27('G', 5) .. GetEscCodeCSI27('K', 5) .. "a\<Esc>", 'Lx!')
1226  call assert_equal("axx", getline(1))
1227  call assert_equal("yy", getline(2))
1228  bwipe!
1229
1230  set timeoutlen&
1231endfunc
1232
1233func RunTest_mapping_shift(key, func)
1234  call setline(1, '')
1235  if a:key == '|'
1236    exe 'inoremap \| xyz'
1237  else
1238    exe 'inoremap ' .. a:key .. ' xyz'
1239  endif
1240  call feedkeys('a' .. a:func(a:key, 2) .. "\<Esc>", 'Lx!')
1241  call assert_equal("xyz", getline(1))
1242  if a:key == '|'
1243    exe 'iunmap \|'
1244  else
1245    exe 'iunmap ' .. a:key
1246  endif
1247endfunc
1248
1249func RunTest_mapping_works_with_shift(func)
1250  new
1251  set timeoutlen=10
1252
1253  call RunTest_mapping_shift('@', a:func)
1254  call RunTest_mapping_shift('A', a:func)
1255  call RunTest_mapping_shift('Z', a:func)
1256  call RunTest_mapping_shift('^', a:func)
1257  call RunTest_mapping_shift('_', a:func)
1258  call RunTest_mapping_shift('{', a:func)
1259  call RunTest_mapping_shift('|', a:func)
1260  call RunTest_mapping_shift('}', a:func)
1261  call RunTest_mapping_shift('~', a:func)
1262
1263  bwipe!
1264  set timeoutlen&
1265endfunc
1266
1267func Test_mapping_works_with_shift_plain()
1268  call RunTest_mapping_works_with_shift(function('GetEscCodeCSI27'))
1269  call RunTest_mapping_works_with_shift(function('GetEscCodeCSIu'))
1270endfunc
1271
1272func RunTest_mapping_mods(map, key, func, code)
1273  call setline(1, '')
1274  exe 'inoremap ' .. a:map .. ' xyz'
1275  call feedkeys('a' .. a:func(a:key, a:code) .. "\<Esc>", 'Lx!')
1276  call assert_equal("xyz", getline(1))
1277  exe 'iunmap ' .. a:map
1278endfunc
1279
1280func RunTest_mapping_works_with_mods(func, mods, code)
1281  new
1282  set timeoutlen=10
1283
1284  if a:mods !~ 'S'
1285    " Shift by itself has no effect
1286    call RunTest_mapping_mods('<' .. a:mods .. '-@>', '@', a:func, a:code)
1287  endif
1288  call RunTest_mapping_mods('<' .. a:mods .. '-A>', 'A', a:func, a:code)
1289  call RunTest_mapping_mods('<' .. a:mods .. '-Z>', 'Z', a:func, a:code)
1290  if a:mods !~ 'S'
1291    " with Shift code is always upper case
1292    call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'a', a:func, a:code)
1293    call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'z', a:func, a:code)
1294  endif
1295  if a:mods != 'A'
1296    " with Alt code is not in upper case
1297    call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'A', a:func, a:code)
1298    call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'Z', a:func, a:code)
1299  endif
1300  call RunTest_mapping_mods('<' .. a:mods .. '-á>', 'á', a:func, a:code)
1301  if a:mods !~ 'S'
1302    " Shift by itself has no effect
1303    call RunTest_mapping_mods('<' .. a:mods .. '-^>', '^', a:func, a:code)
1304    call RunTest_mapping_mods('<' .. a:mods .. '-_>', '_', a:func, a:code)
1305    call RunTest_mapping_mods('<' .. a:mods .. '-{>', '{', a:func, a:code)
1306    call RunTest_mapping_mods('<' .. a:mods .. '-\|>', '|', a:func, a:code)
1307    call RunTest_mapping_mods('<' .. a:mods .. '-}>', '}', a:func, a:code)
1308    call RunTest_mapping_mods('<' .. a:mods .. '-~>', '~', a:func, a:code)
1309  endif
1310
1311  bwipe!
1312  set timeoutlen&
1313endfunc
1314
1315func Test_mapping_works_with_shift()
1316  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S', 2)
1317  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S', 2)
1318endfunc
1319
1320func Test_mapping_works_with_ctrl()
1321  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C', 5)
1322  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C', 5)
1323endfunc
1324
1325func Test_mapping_works_with_shift_ctrl()
1326  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S', 6)
1327  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S', 6)
1328endfunc
1329
1330" Below we also test the "u" code with Alt, This works, but libvterm would not
1331" send the Alt key like this but by prefixing an Esc.
1332
1333func Test_mapping_works_with_alt()
1334  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'A', 3)
1335  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'A', 3)
1336endfunc
1337
1338func Test_mapping_works_with_shift_alt()
1339  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S-A', 4)
1340  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S-A', 4)
1341endfunc
1342
1343func Test_mapping_works_with_ctrl_alt()
1344  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-A', 7)
1345  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-A', 7)
1346endfunc
1347
1348func Test_mapping_works_with_shift_ctrl_alt()
1349  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 8)
1350  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8)
1351endfunc
1352
1353func Test_insert_literal()
1354  set timeoutlen=10
1355  new
1356  " CTRL-V CTRL-X inserts a ^X
1357  call feedkeys('a' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
1358  call assert_equal("\<C-X>", getline(1))
1359
1360  call setline(1, '')
1361  call feedkeys('a' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
1362  call assert_equal("\<C-X>", getline(1))
1363
1364  " CTRL-SHIFT-V CTRL-X inserts escape sequencd
1365  call setline(1, '')
1366  call feedkeys('a' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
1367  call assert_equal("\<Esc>[88;5u", getline(1))
1368
1369  call setline(1, '')
1370  call feedkeys('a' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
1371  call assert_equal("\<Esc>[27;5;88~", getline(1))
1372
1373  bwipe!
1374  set timeoutlen&
1375endfunc
1376
1377func Test_cmdline_literal()
1378  set timeoutlen=10
1379
1380  " CTRL-V CTRL-Y inserts a ^Y
1381  call feedkeys(':' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
1382  call assert_equal("\"\<C-Y>", @:)
1383
1384  call feedkeys(':' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
1385  call assert_equal("\"\<C-Y>", @:)
1386
1387  " CTRL-SHIFT-V CTRL-Y inserts escape sequencd
1388  call feedkeys(':' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
1389  call assert_equal("\"\<Esc>[89;5u", @:)
1390
1391  call setline(1, '')
1392  call feedkeys(':' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
1393  call assert_equal("\"\<Esc>[27;5;89~", @:)
1394
1395  set timeoutlen&
1396endfunc
1397