blob: 055ed8b65ec24b3427d2bcd8f8e412977363db6c [file] [log] [blame]
Bram Moolenaar905dd902019-04-07 14:21:47 +02001" Tests for decoding escape sequences sent by the terminal.
2
3" This only works for Unix in a terminal
Bram Moolenaar8c5a2782019-08-07 23:07:07 +02004source check.vim
5CheckNotGui
6CheckUnix
Bram Moolenaar905dd902019-04-07 14:21:47 +02007
Bram Moolenaar564344a2019-04-28 13:00:12 +02008source shared.vim
Bram Moolenaar515545e2020-03-22 14:08:59 +01009source mouse.vim
Bram Moolenaarecd34bf2020-08-04 20:17:31 +020010source view_util.vim
Bram Moolenaare46a2ed2020-08-04 21:04:57 +020011source term_util.vim
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +020012
Bram Moolenaar92fd5992019-05-02 23:00:22 +020013func Test_term_mouse_left_click()
Bram Moolenaar905dd902019-04-07 14:21:47 +020014 new
15 let save_mouse = &mouse
16 let save_term = &term
17 let save_ttymouse = &ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +020018 call test_override('no_query_mouse', 1)
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +020019 set mouse=a term=xterm
Bram Moolenaar905dd902019-04-07 14:21:47 +020020 call setline(1, ['line 1', 'line 2', 'line 3 is a bit longer'])
Bram Moolenaar905dd902019-04-07 14:21:47 +020021
Bram Moolenaar515545e2020-03-22 14:08:59 +010022 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
Bram Moolenaar49452192019-04-17 16:27:02 +020023 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar1ee36d62019-05-01 23:13:56 +020024 exe 'set ttymouse=' .. ttymouse_val
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +020025 go
Bram Moolenaar49452192019-04-17 16:27:02 +020026 call assert_equal([0, 1, 1, 0], getpos('.'), msg)
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +020027 let row = 2
28 let col = 6
29 call MouseLeftClick(row, col)
30 call MouseLeftRelease(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +020031 call assert_equal([0, 2, 6, 0], getpos('.'), msg)
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +020032 endfor
Bram Moolenaar905dd902019-04-07 14:21:47 +020033
34 let &mouse = save_mouse
35 let &term = save_term
36 let &ttymouse = save_ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +020037 call test_override('no_query_mouse', 0)
Bram Moolenaar905dd902019-04-07 14:21:47 +020038 bwipe!
39endfunc
40
Bram Moolenaar6aa75232019-10-13 21:01:34 +020041func Test_xterm_mouse_right_click_extends_visual()
42 if has('mac')
43 throw "Skipped: test right click in visual mode does not work on macOs (why?)"
44 endif
45 let save_mouse = &mouse
46 let save_term = &term
47 let save_ttymouse = &ttymouse
48 call test_override('no_query_mouse', 1)
49 set mouse=a term=xterm
50
51 for visual_mode in ["v", "V", "\<C-V>"]
Bram Moolenaar515545e2020-03-22 14:08:59 +010052 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
Bram Moolenaar6aa75232019-10-13 21:01:34 +020053 let msg = 'visual=' .. visual_mode .. ' ttymouse=' .. ttymouse_val
54 exe 'set ttymouse=' .. ttymouse_val
55
56 call setline(1, repeat([repeat('-', 7)], 7))
57 call MouseLeftClick(4, 4)
58 call MouseLeftRelease(4, 4)
59 exe "norm! " .. visual_mode
60
61 " Right click extends top left of visual area.
62 call MouseRightClick(2, 2)
63 call MouseRightRelease(2, 2)
64
Bram Moolenaarf19f8d12019-12-18 19:36:23 +010065 " Right click extends bottom right of visual area.
Bram Moolenaar6aa75232019-10-13 21:01:34 +020066 call MouseRightClick(6, 6)
67 call MouseRightRelease(6, 6)
68 norm! r1gv
69
70 " Right click shrinks top left of visual area.
71 call MouseRightClick(3, 3)
72 call MouseRightRelease(3, 3)
73
74 " Right click shrinks bottom right of visual area.
75 call MouseRightClick(5, 5)
76 call MouseRightRelease(5, 5)
77 norm! r2
78
79 if visual_mode ==# 'v'
80 call assert_equal(['-------',
81 \ '-111111',
82 \ '1122222',
83 \ '2222222',
84 \ '2222211',
85 \ '111111-',
86 \ '-------'], getline(1, '$'), msg)
87 elseif visual_mode ==# 'V'
88 call assert_equal(['-------',
89 \ '1111111',
90 \ '2222222',
91 \ '2222222',
92 \ '2222222',
93 \ '1111111',
94 \ '-------'], getline(1, '$'), msg)
95 else
96 call assert_equal(['-------',
97 \ '-11111-',
98 \ '-12221-',
99 \ '-12221-',
100 \ '-12221-',
101 \ '-11111-',
102 \ '-------'], getline(1, '$'), msg)
103 endif
104 endfor
105 endfor
106
107 let &mouse = save_mouse
108 let &term = save_term
109 let &ttymouse = save_ttymouse
110 call test_override('no_query_mouse', 0)
111 bwipe!
112endfunc
113
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200114" Test that <C-LeftMouse> jumps to help tag and <C-RightMouse> jumps back.
Bram Moolenaar297bec02020-07-14 22:11:04 +0200115" Also test for g<LeftMouse> and g<RightMouse>.
116func Test_xterm_mouse_tagjump()
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200117 let save_mouse = &mouse
118 let save_term = &term
119 let save_ttymouse = &ttymouse
120 set mouse=a term=xterm
121
Bram Moolenaar515545e2020-03-22 14:08:59 +0100122 for ttymouse_val in g:Ttymouse_values
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200123 let msg = 'ttymouse=' .. ttymouse_val
124 exe 'set ttymouse=' .. ttymouse_val
125 help
126 /usr_02.txt
127 norm! zt
Bram Moolenaar297bec02020-07-14 22:11:04 +0200128
129 " CTRL-left click to jump to a tag
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200130 let row = 1
131 let col = 1
132 call MouseCtrlLeftClick(row, col)
133 call MouseLeftRelease(row, col)
134 call assert_match('usr_02.txt$', bufname('%'), msg)
Bram Moolenaarb4367b72019-10-01 14:19:07 +0200135 call assert_equal('*usr_02.txt*', expand('<cWORD>'), msg)
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200136
Bram Moolenaar297bec02020-07-14 22:11:04 +0200137 " CTRL-right click to pop a tag
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200138 call MouseCtrlRightClick(row, col)
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200139 call MouseRightRelease(row, col)
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200140 call assert_match('help.txt$', bufname('%'), msg)
Bram Moolenaarb4367b72019-10-01 14:19:07 +0200141 call assert_equal('|usr_02.txt|', expand('<cWORD>'), msg)
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200142
Bram Moolenaar297bec02020-07-14 22:11:04 +0200143 " Jump to a tag
144 exe "normal \<C-]>"
145 call assert_match('usr_02.txt$', bufname('%'), msg)
146 call assert_equal('*usr_02.txt*', expand('<cWORD>'), msg)
147
148 " Use CTRL-right click in insert mode to pop the tag
149 new
150 let str = 'iHello' .. MouseCtrlRightClickCode(row, col)
151 \ .. MouseRightReleaseCode(row, col) .. "\<C-C>"
Bram Moolenaar2764d062020-07-18 12:59:19 +0200152 call assert_fails('call feedkeys(str, "Lx!")', 'E37:', msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +0200153 close!
154
155 " CTRL-right click with a count
156 let str = "4" .. MouseCtrlRightClickCode(row, col)
157 \ .. MouseRightReleaseCode(row, col)
Bram Moolenaar2764d062020-07-18 12:59:19 +0200158 call assert_fails('call feedkeys(str, "Lx!")', 'E555:', msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +0200159 call assert_match('help.txt$', bufname('%'), msg)
160 call assert_equal(1, line('.'), msg)
161
162 " g<LeftMouse> to jump to a tag
163 /usr_02.txt
164 norm! zt
165 call test_setmouse(row, col)
166 exe "normal g\<LeftMouse>"
167 call assert_match('usr_02.txt$', bufname('%'), msg)
168 call assert_equal('*usr_02.txt*', expand('<cWORD>'), msg)
169
170 " g<RightMouse> to pop to a tag
171 call test_setmouse(row, col)
172 exe "normal g\<RightMouse>"
173 call assert_match('help.txt$', bufname('%'), msg)
174 call assert_equal('|usr_02.txt|', expand('<cWORD>'), msg)
175
176 %bw!
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200177 endfor
178
179 let &mouse = save_mouse
180 let &term = save_term
181 let &ttymouse = save_ttymouse
182endfunc
183
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200184func Test_term_mouse_middle_click()
Bram Moolenaar52992fe2019-08-12 14:20:33 +0200185 CheckFeature clipboard_working
Bram Moolenaar564344a2019-04-28 13:00:12 +0200186
Bram Moolenaarc1b81602019-04-27 19:11:35 +0200187 new
188 let save_mouse = &mouse
189 let save_term = &term
190 let save_ttymouse = &ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200191 call test_override('no_query_mouse', 1)
Bram Moolenaarc1b81602019-04-27 19:11:35 +0200192 let save_quotestar = @*
Bram Moolenaar297bec02020-07-14 22:11:04 +0200193 let save_quoteplus = @+
Bram Moolenaarc1b81602019-04-27 19:11:35 +0200194 set mouse=a term=xterm
195
Bram Moolenaar515545e2020-03-22 14:08:59 +0100196 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
Bram Moolenaarc1b81602019-04-27 19:11:35 +0200197 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200198 exe 'set ttymouse=' .. ttymouse_val
Bram Moolenaarc1b81602019-04-27 19:11:35 +0200199 call setline(1, ['123456789', '123456789'])
Bram Moolenaar297bec02020-07-14 22:11:04 +0200200 let @* = 'abc'
Bram Moolenaarc1b81602019-04-27 19:11:35 +0200201
202 " Middle-click in the middle of the line pastes text where clicked.
203 let row = 1
204 let col = 6
205 call MouseMiddleClick(row, col)
206 call MouseMiddleRelease(row, col)
207 call assert_equal(['12345abc6789', '123456789'], getline(1, '$'), msg)
208
209 " Middle-click beyond end of the line pastes text at the end of the line.
210 let col = 20
211 call MouseMiddleClick(row, col)
212 call MouseMiddleRelease(row, col)
213 call assert_equal(['12345abc6789abc', '123456789'], getline(1, '$'), msg)
214
215 " Middle-click beyond the last line pastes in the last line.
216 let row = 5
217 let col = 3
218 call MouseMiddleClick(row, col)
219 call MouseMiddleRelease(row, col)
220 call assert_equal(['12345abc6789abc', '12abc3456789'], getline(1, '$'), msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +0200221
222 " Middle mouse click in operator pending mode beeps
223 call assert_beeps('exe "normal c\<MiddleMouse>"')
224
225 " Clicking middle mouse in visual mode, yanks the selection and pastes the
226 " clipboard contents
227 let save_clipboard = &clipboard
228 set clipboard=
229 let @" = ''
230 call cursor(1, 1)
231 call feedkeys("v3l" ..
232 \ MouseMiddleClickCode(2, 7) .. MouseMiddleReleaseCode(2, 7), 'Lx!')
233 call assert_equal(['12345abc6789abc', '12abc3abc456789'],
234 \ getline(1, '$'), msg)
Bram Moolenaar2764d062020-07-18 12:59:19 +0200235 call assert_equal('1234', @", msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +0200236 let &clipboard = save_clipboard
237
238 " Clicking middle mouse in select mode, replaces the selected text with
239 " the clipboard contents
240 let @+ = 'xyz'
241 call cursor(1, 3)
242 exe "normal gh\<Right>\<Right>\<MiddleMouse>"
243 call assert_equal(['12xyzabc6789abc', '12abc3abc456789'],
244 \ getline(1, '$'), msg)
Bram Moolenaar2764d062020-07-18 12:59:19 +0200245
246 " Prefixing middle click with [ or ] fixes the indent after pasting.
247 %d
248 call setline(1, " one two")
249 call setreg('r', 'red blue', 'l')
250 call test_setmouse(1, 5)
251 exe "normal \"r[\<MiddleMouse>"
252 call assert_equal(' red blue', getline(1), msg)
253 call test_setmouse(2, 5)
254 exe "normal \"r]\<MiddleMouse>"
255 call assert_equal(' red blue', getline(3), msg)
256 %d
Bram Moolenaarc1b81602019-04-27 19:11:35 +0200257 endfor
258
259 let &mouse = save_mouse
260 let &term = save_term
261 let &ttymouse = save_ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200262 call test_override('no_query_mouse', 0)
Bram Moolenaarc1b81602019-04-27 19:11:35 +0200263 let @* = save_quotestar
Bram Moolenaar297bec02020-07-14 22:11:04 +0200264 let @+ = save_quotestar
Bram Moolenaarc1b81602019-04-27 19:11:35 +0200265 bwipe!
266endfunc
267
Bram Moolenaar297bec02020-07-14 22:11:04 +0200268" If clipboard is not working, then clicking the middle mouse button in visual
269" mode, will copy and paste the selected text.
270func Test_term_mouse_middle_click_no_clipboard()
271 if has('clipboard_working')
272 throw 'Skipped: clipboard support works'
Bram Moolenaar297bec02020-07-14 22:11:04 +0200273 endif
274 new
275 let save_mouse = &mouse
276 let save_term = &term
277 let save_ttymouse = &ttymouse
278 call test_override('no_query_mouse', 1)
279 set mouse=a term=xterm
280
281 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
282 let msg = 'ttymouse=' .. ttymouse_val
283 exe 'set ttymouse=' .. ttymouse_val
284 call setline(1, ['123456789', '123456789'])
285
286 " Clicking middle mouse in visual mode, yanks the selection and pastes it
287 call cursor(1, 1)
288 call feedkeys("v3l" ..
289 \ MouseMiddleClickCode(2, 7) .. MouseMiddleReleaseCode(2, 7), 'Lx!')
290 call assert_equal(['123456789', '1234561234789'],
291 \ getline(1, '$'), msg)
292 endfor
293
294 call test_override('no_query_mouse', 0)
295 let &ttymouse = save_ttymouse
296 let &term = save_term
297 let &mouse = save_mouse
298 close!
299endfunc
300
301func Test_term_mouse_middle_click_insert_mode()
302 CheckFeature clipboard_working
303
304 new
305 let save_mouse = &mouse
306 let save_term = &term
307 let save_ttymouse = &ttymouse
308 call test_override('no_query_mouse', 1)
309 set mouse=a term=xterm
310
311 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
312 let msg = 'ttymouse=' .. ttymouse_val
313 exe 'set ttymouse=' .. ttymouse_val
314 call setline(1, ['123456789', '123456789'])
315 let @* = 'abc'
316
317 " Middle-click in inesrt mode doesn't move the cursor but inserts the
318 " contents of aregister
319 call cursor(1, 4)
320 call feedkeys('i' ..
321 \ MouseMiddleClickCode(2, 7) .. MouseMiddleReleaseCode(2, 7) ..
322 \ "\<C-C>", 'Lx!')
323 call assert_equal(['123abc456789', '123456789'],
324 \ getline(1, '$'), msg)
Bram Moolenaar2764d062020-07-18 12:59:19 +0200325 call assert_equal([1, 6], [line('.'), col('.')], msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +0200326
327 " Middle-click in replace mode
328 call cursor(1, 1)
329 call feedkeys('$R' ..
330 \ MouseMiddleClickCode(2, 7) .. MouseMiddleReleaseCode(2, 7) ..
331 \ "\<C-C>", 'Lx!')
332 call assert_equal(['123abc45678abc', '123456789'],
333 \ getline(1, '$'), msg)
Bram Moolenaar2764d062020-07-18 12:59:19 +0200334 call assert_equal([1, 14], [line('.'), col('.')], msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +0200335 endfor
336
337 let &mouse = save_mouse
338 let &term = save_term
339 let &ttymouse = save_ttymouse
340 call test_override('no_query_mouse', 0)
341 close!
342endfunc
343
344" Test for switching window using mouse in insert mode
345func Test_term_mouse_switch_win_insert_mode()
346 5new
347 let save_mouse = &mouse
348 let save_term = &term
349 let save_ttymouse = &ttymouse
350 call test_override('no_query_mouse', 1)
351 set mouse=a term=xterm ttymouse=xterm2
352
353 call feedkeys('ivim' ..
354 \ MouseLeftClickCode(8, 6) .. MouseLeftReleaseCode(8, 6) ..
355 \ "\<C-C>", 'Lx!')
356 call assert_equal(2, winnr())
357 wincmd w
358 call assert_equal('n', mode())
359 call assert_equal(['vim'], getline(1, '$'))
360
361 let &mouse = save_mouse
362 let &term = save_term
363 let &ttymouse = save_ttymouse
364 call test_override('no_query_mouse', 0)
365 close!
366endfunc
367
368" Test for using the mouse to increaes the height of the cmdline window
369func Test_mouse_cmdwin_resize()
370 let save_mouse = &mouse
371 let save_term = &term
372 let save_ttymouse = &ttymouse
373 call test_override('no_query_mouse', 1)
374 set mouse=a term=xterm ttymouse=xterm2
375 5new
376 redraw!
377
378 let h = 0
379 let row = &lines - &cmdwinheight - 2
380 call feedkeys("q:" ..
381 \ MouseLeftClickCode(row, 1) ..
382 \ MouseLeftDragCode(row - 1, 1) ..
383 \ MouseLeftReleaseCode(row - 2, 1) ..
384 \ "alet h = \<C-R>=winheight(0)\<CR>\<CR>", 'Lx!')
385 call assert_equal(&cmdwinheight + 2, h)
386
387 let &mouse = save_mouse
388 let &term = save_term
389 let &ttymouse = save_ttymouse
390 call test_override('no_query_mouse', 0)
391 close!
392endfunc
393
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200394" TODO: for unclear reasons this test fails if it comes after
395" Test_xterm_mouse_ctrl_click()
396func Test_1xterm_mouse_wheel()
Bram Moolenaar049736f2019-04-07 21:55:07 +0200397 new
398 let save_mouse = &mouse
399 let save_term = &term
Bram Moolenaard58d4f92020-07-01 15:49:29 +0200400 let save_wrap = &wrap
Bram Moolenaar049736f2019-04-07 21:55:07 +0200401 let save_ttymouse = &ttymouse
Bram Moolenaard58d4f92020-07-01 15:49:29 +0200402 set mouse=a term=xterm nowrap
403 call setline(1, range(100000000000000, 100000000000100))
Bram Moolenaar049736f2019-04-07 21:55:07 +0200404
Bram Moolenaar515545e2020-03-22 14:08:59 +0100405 for ttymouse_val in g:Ttymouse_values
Bram Moolenaar49452192019-04-17 16:27:02 +0200406 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200407 exe 'set ttymouse=' .. ttymouse_val
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200408 go
Bram Moolenaar49452192019-04-17 16:27:02 +0200409 call assert_equal(1, line('w0'), msg)
410 call assert_equal([0, 1, 1, 0], getpos('.'), msg)
Bram Moolenaar049736f2019-04-07 21:55:07 +0200411
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200412 call MouseWheelDown(1, 1)
Bram Moolenaar49452192019-04-17 16:27:02 +0200413 call assert_equal(4, line('w0'), msg)
414 call assert_equal([0, 4, 1, 0], getpos('.'), msg)
Bram Moolenaar049736f2019-04-07 21:55:07 +0200415
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200416 call MouseWheelDown(1, 1)
Bram Moolenaar49452192019-04-17 16:27:02 +0200417 call assert_equal(7, line('w0'), msg)
418 call assert_equal([0, 7, 1, 0], getpos('.'), msg)
Bram Moolenaar049736f2019-04-07 21:55:07 +0200419
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200420 call MouseWheelUp(1, 1)
Bram Moolenaar49452192019-04-17 16:27:02 +0200421 call assert_equal(4, line('w0'), msg)
422 call assert_equal([0, 7, 1, 0], getpos('.'), msg)
Bram Moolenaar049736f2019-04-07 21:55:07 +0200423
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200424 call MouseWheelUp(1, 1)
Bram Moolenaar49452192019-04-17 16:27:02 +0200425 call assert_equal(1, line('w0'), msg)
426 call assert_equal([0, 7, 1, 0], getpos('.'), msg)
Bram Moolenaard58d4f92020-07-01 15:49:29 +0200427
428 if has('gui')
429 " Horizontal wheel scrolling currently only works when vim is
430 " compiled with gui enabled.
431 call MouseWheelRight(1, 1)
432 call assert_equal(7, 1 + virtcol(".") - wincol(), msg)
433 call assert_equal([0, 7, 7, 0], getpos('.'), msg)
434
435 call MouseWheelRight(1, 1)
436 call assert_equal(13, 1 + virtcol(".") - wincol(), msg)
437 call assert_equal([0, 7, 13, 0], getpos('.'), msg)
438
439 call MouseWheelLeft(1, 1)
440 call assert_equal(7, 1 + virtcol(".") - wincol(), msg)
441 call assert_equal([0, 7, 13, 0], getpos('.'), msg)
442
443 call MouseWheelLeft(1, 1)
444 call assert_equal(1, 1 + virtcol(".") - wincol(), msg)
445 call assert_equal([0, 7, 13, 0], getpos('.'), msg)
446 endif
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200447 endfor
Bram Moolenaar049736f2019-04-07 21:55:07 +0200448
449 let &mouse = save_mouse
450 let &term = save_term
Bram Moolenaard58d4f92020-07-01 15:49:29 +0200451 let &wrap = save_wrap
Bram Moolenaar049736f2019-04-07 21:55:07 +0200452 let &ttymouse = save_ttymouse
453 bwipe!
454endfunc
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200455
Bram Moolenaarb4367b72019-10-01 14:19:07 +0200456" Test that dragging beyond the window (at the bottom and at the top)
Bram Moolenaarf19f8d12019-12-18 19:36:23 +0100457" scrolls window content by the number of lines beyond the window.
Bram Moolenaarb4367b72019-10-01 14:19:07 +0200458func Test_term_mouse_drag_beyond_window()
459 let save_mouse = &mouse
460 let save_term = &term
461 let save_ttymouse = &ttymouse
462 call test_override('no_query_mouse', 1)
463 set mouse=a term=xterm
464 let col = 1
465 call setline(1, range(1, 100))
466
467 " Split into 3 windows, and go into the middle window
468 " so we test dragging mouse below and above the window.
469 2split
470 wincmd j
471 2split
472
Bram Moolenaar515545e2020-03-22 14:08:59 +0100473 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
Bram Moolenaarb4367b72019-10-01 14:19:07 +0200474 let msg = 'ttymouse=' .. ttymouse_val
475 exe 'set ttymouse=' .. ttymouse_val
476
477 " Line #10 at the top.
478 norm! 10zt
479 redraw
480 call assert_equal(10, winsaveview().topline, msg)
481 call assert_equal(2, winheight(0), msg)
482
483 let row = 4
484 call MouseLeftClick(row, col)
485 call assert_equal(10, winsaveview().topline, msg)
486
487 " Drag downwards. We're still in the window so topline should
488 " not change yet.
489 let row += 1
490 call MouseLeftDrag(row, col)
491 call assert_equal(10, winsaveview().topline, msg)
492
493 " We now leave the window at the bottom, so the window content should
494 " scroll by 1 line, then 2 lines (etc) as we drag further away.
495 let row += 1
496 call MouseLeftDrag(row, col)
497 call assert_equal(11, winsaveview().topline, msg)
498
499 let row += 1
500 call MouseLeftDrag(row, col)
501 call assert_equal(13, winsaveview().topline, msg)
502
503 " Now drag upwards.
504 let row -= 1
505 call MouseLeftDrag(row, col)
506 call assert_equal(14, winsaveview().topline, msg)
507
508 " We're now back in the window so the topline should not change.
509 let row -= 1
510 call MouseLeftDrag(row, col)
511 call assert_equal(14, winsaveview().topline, msg)
512
513 let row -= 1
514 call MouseLeftDrag(row, col)
515 call assert_equal(14, winsaveview().topline, msg)
516
517 " We now leave the window at the top so the window content should
518 " scroll by 1 line, then 2, then 3 (etc) in the opposite direction.
519 let row -= 1
520 call MouseLeftDrag(row, col)
521 call assert_equal(13, winsaveview().topline, msg)
522
523 let row -= 1
524 call MouseLeftDrag(row, col)
525 call assert_equal(11, winsaveview().topline, msg)
526
527 let row -= 1
528 call MouseLeftDrag(row, col)
529 call assert_equal(8, winsaveview().topline, msg)
530
531 call MouseLeftRelease(row, col)
532 call assert_equal(8, winsaveview().topline, msg)
533 call assert_equal(2, winheight(0), 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 bwipe!
541endfunc
542
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200543func Test_term_mouse_drag_window_separator()
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200544 let save_mouse = &mouse
545 let save_term = &term
546 let save_ttymouse = &ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200547 call test_override('no_query_mouse', 1)
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200548 set mouse=a term=xterm
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200549
Bram Moolenaar515545e2020-03-22 14:08:59 +0100550 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
Bram Moolenaar49452192019-04-17 16:27:02 +0200551 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200552 exe 'set ttymouse=' .. ttymouse_val
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200553
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200554 " Split horizontally and test dragging the horizontal window separator.
555 split
556 let rowseparator = winheight(0) + 1
557 let row = rowseparator
558 let col = 1
Bram Moolenaarc8b3dda2019-04-12 21:42:52 +0200559
Bram Moolenaar2b00b9b2019-04-17 17:08:27 +0200560 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
561 if ttymouse_val !=# 'xterm2' || row <= 223
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200562 call MouseLeftClick(row, col)
563 let row -= 1
564 call MouseLeftDrag(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +0200565 call assert_equal(rowseparator - 1, winheight(0) + 1, msg)
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200566 let row += 1
567 call MouseLeftDrag(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +0200568 call assert_equal(rowseparator, winheight(0) + 1, msg)
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200569 call MouseLeftRelease(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +0200570 call assert_equal(rowseparator, winheight(0) + 1, msg)
Bram Moolenaarc8b3dda2019-04-12 21:42:52 +0200571 endif
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200572 bwipe!
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200573
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200574 " Split vertically and test dragging the vertical window separator.
575 vsplit
576 let colseparator = winwidth(0) + 1
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200577 let row = 1
578 let col = colseparator
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200579
Bram Moolenaar2b00b9b2019-04-17 17:08:27 +0200580 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
581 if ttymouse_val !=# 'xterm2' || col <= 223
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200582 call MouseLeftClick(row, col)
583 let col -= 1
584 call MouseLeftDrag(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +0200585 call assert_equal(colseparator - 1, winwidth(0) + 1, msg)
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200586 let col += 1
587 call MouseLeftDrag(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +0200588 call assert_equal(colseparator, winwidth(0) + 1, msg)
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200589 call MouseLeftRelease(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +0200590 call assert_equal(colseparator, winwidth(0) + 1, msg)
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200591 endif
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200592 bwipe!
593 endfor
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200594
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200595 let &mouse = save_mouse
596 let &term = save_term
597 let &ttymouse = save_ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200598 call test_override('no_query_mouse', 0)
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200599endfunc
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200600
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200601func Test_term_mouse_drag_statusline()
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200602 let save_mouse = &mouse
603 let save_term = &term
604 let save_ttymouse = &ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200605 call test_override('no_query_mouse', 1)
Bram Moolenaarca57ab52019-04-13 14:53:16 +0200606 let save_laststatus = &laststatus
607 set mouse=a term=xterm laststatus=2
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200608
Bram Moolenaar515545e2020-03-22 14:08:59 +0100609 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
Bram Moolenaar49452192019-04-17 16:27:02 +0200610 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200611 exe 'set ttymouse=' .. ttymouse_val
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200612
Bram Moolenaar49452192019-04-17 16:27:02 +0200613 call assert_equal(1, &cmdheight, msg)
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200614 let rowstatusline = winheight(0) + 1
615 let row = rowstatusline
616 let col = 1
Bram Moolenaarc8b3dda2019-04-12 21:42:52 +0200617
Bram Moolenaar2b00b9b2019-04-17 17:08:27 +0200618 if ttymouse_val ==# 'xterm2' && row > 223
619 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
Bram Moolenaarc8b3dda2019-04-12 21:42:52 +0200620 continue
621 endif
622
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200623 call MouseLeftClick(row, col)
624 let row -= 1
625 call MouseLeftDrag(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +0200626 call assert_equal(2, &cmdheight, msg)
627 call assert_equal(rowstatusline - 1, winheight(0) + 1, msg)
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200628 let row += 1
629 call MouseLeftDrag(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +0200630 call assert_equal(1, &cmdheight, msg)
631 call assert_equal(rowstatusline, winheight(0) + 1, msg)
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200632 call MouseLeftRelease(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +0200633 call assert_equal(1, &cmdheight, msg)
634 call assert_equal(rowstatusline, winheight(0) + 1, msg)
Bram Moolenaar3fbd2d72019-04-11 23:56:16 +0200635 endfor
636
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200637 let &mouse = save_mouse
638 let &term = save_term
639 let &ttymouse = save_ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200640 call test_override('no_query_mouse', 0)
Bram Moolenaarca57ab52019-04-13 14:53:16 +0200641 let &laststatus = save_laststatus
642endfunc
643
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200644func Test_term_mouse_click_tab()
Bram Moolenaarca57ab52019-04-13 14:53:16 +0200645 let save_mouse = &mouse
646 let save_term = &term
647 let save_ttymouse = &ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200648 call test_override('no_query_mouse', 1)
Bram Moolenaarca57ab52019-04-13 14:53:16 +0200649 set mouse=a term=xterm
650 let row = 1
651
Bram Moolenaar515545e2020-03-22 14:08:59 +0100652 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
Bram Moolenaar49452192019-04-17 16:27:02 +0200653 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200654 exe 'set ttymouse=' .. ttymouse_val
Bram Moolenaarca57ab52019-04-13 14:53:16 +0200655 e Xfoo
656 tabnew Xbar
657
658 let a = split(execute(':tabs'), "\n")
659 call assert_equal(['Tab page 1',
660 \ ' Xfoo',
661 \ 'Tab page 2',
Bram Moolenaar49452192019-04-17 16:27:02 +0200662 \ '> Xbar'], a, msg)
Bram Moolenaarca57ab52019-04-13 14:53:16 +0200663
664 " Test clicking on tab names in the tabline at the top.
665 let col = 2
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200666 redraw
Bram Moolenaarca57ab52019-04-13 14:53:16 +0200667 call MouseLeftClick(row, col)
668 call MouseLeftRelease(row, col)
669 let a = split(execute(':tabs'), "\n")
670 call assert_equal(['Tab page 1',
671 \ '> Xfoo',
672 \ 'Tab page 2',
Bram Moolenaar49452192019-04-17 16:27:02 +0200673 \ ' Xbar'], a, msg)
Bram Moolenaarca57ab52019-04-13 14:53:16 +0200674
675 let col = 9
676 call MouseLeftClick(row, col)
677 call MouseLeftRelease(row, col)
678 let a = split(execute(':tabs'), "\n")
679 call assert_equal(['Tab page 1',
680 \ ' Xfoo',
681 \ 'Tab page 2',
Bram Moolenaar49452192019-04-17 16:27:02 +0200682 \ '> Xbar'], a, msg)
Bram Moolenaarca57ab52019-04-13 14:53:16 +0200683
684 %bwipe!
685 endfor
686
687 let &mouse = save_mouse
688 let &term = save_term
689 let &ttymouse = save_ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200690 call test_override('no_query_mouse', 0)
Bram Moolenaar3fb01a52019-04-09 21:52:02 +0200691endfunc
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200692
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200693func Test_term_mouse_click_X_to_close_tab()
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200694 let save_mouse = &mouse
695 let save_term = &term
696 let save_ttymouse = &ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200697 call test_override('no_query_mouse', 1)
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200698 set mouse=a term=xterm
699 let row = 1
700 let col = &columns
701
Bram Moolenaar515545e2020-03-22 14:08:59 +0100702 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
Bram Moolenaar2b00b9b2019-04-17 17:08:27 +0200703 if ttymouse_val ==# 'xterm2' && col > 223
704 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200705 continue
706 endif
Bram Moolenaar49452192019-04-17 16:27:02 +0200707 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200708 exe 'set ttymouse=' .. ttymouse_val
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200709 e Xtab1
710 tabnew Xtab2
711 tabnew Xtab3
712 tabn 2
713
714 let a = split(execute(':tabs'), "\n")
715 call assert_equal(['Tab page 1',
716 \ ' Xtab1',
717 \ 'Tab page 2',
718 \ '> Xtab2',
719 \ 'Tab page 3',
Bram Moolenaar49452192019-04-17 16:27:02 +0200720 \ ' Xtab3'], a, msg)
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200721
722 " Click on "X" in tabline to close current tab i.e. Xtab2.
723 redraw
724 call MouseLeftClick(row, col)
725 call MouseLeftRelease(row, col)
726 let a = split(execute(':tabs'), "\n")
727 call assert_equal(['Tab page 1',
728 \ ' Xtab1',
729 \ 'Tab page 2',
Bram Moolenaar49452192019-04-17 16:27:02 +0200730 \ '> Xtab3'], a, msg)
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200731
732 %bwipe!
733 endfor
734
735 let &mouse = save_mouse
736 let &term = save_term
737 let &ttymouse = save_ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200738 call test_override('no_query_mouse', 0)
Bram Moolenaar39f76c62019-04-13 22:13:23 +0200739endfunc
Bram Moolenaare3e38282019-04-15 20:55:31 +0200740
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200741func Test_term_mouse_drag_to_move_tab()
Bram Moolenaare3e38282019-04-15 20:55:31 +0200742 let save_mouse = &mouse
743 let save_term = &term
744 let save_ttymouse = &ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200745 call test_override('no_query_mouse', 1)
Bram Moolenaare3e38282019-04-15 20:55:31 +0200746 " Set 'mousetime' to 1 to avoid recognizing a double-click in the loop
747 set mouse=a term=xterm mousetime=1
748 let row = 1
749
Bram Moolenaar515545e2020-03-22 14:08:59 +0100750 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
Bram Moolenaar49452192019-04-17 16:27:02 +0200751 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200752 exe 'set ttymouse=' .. ttymouse_val
Bram Moolenaare3e38282019-04-15 20:55:31 +0200753 e Xtab1
754 tabnew Xtab2
755
756 let a = split(execute(':tabs'), "\n")
757 call assert_equal(['Tab page 1',
758 \ ' Xtab1',
759 \ 'Tab page 2',
Bram Moolenaar49452192019-04-17 16:27:02 +0200760 \ '> Xtab2'], a, msg)
Bram Moolenaare3e38282019-04-15 20:55:31 +0200761 redraw
762
763 " Click in tab2 and drag it to tab1.
764 " Check getcharmod() to verify that click is not
765 " interpreted as a spurious double-click.
766 call MouseLeftClick(row, 10)
Bram Moolenaar49452192019-04-17 16:27:02 +0200767 call assert_equal(0, getcharmod(), msg)
Bram Moolenaare3e38282019-04-15 20:55:31 +0200768 for col in [9, 8, 7, 6]
769 call MouseLeftDrag(row, col)
770 endfor
771 call MouseLeftRelease(row, col)
772 let a = split(execute(':tabs'), "\n")
773 call assert_equal(['Tab page 1',
774 \ '> Xtab2',
775 \ 'Tab page 2',
Bram Moolenaar49452192019-04-17 16:27:02 +0200776 \ ' Xtab1'], a, msg)
Bram Moolenaare3e38282019-04-15 20:55:31 +0200777
Bram Moolenaarf36a2c72019-11-16 18:57:16 +0100778 " Click elsewhere so that click in next iteration is not
779 " interpreted as unwanted double-click.
780 call MouseLeftClick(row, 11)
781 call MouseLeftRelease(row, 11)
782
Bram Moolenaare3e38282019-04-15 20:55:31 +0200783 %bwipe!
784 endfor
785
786 let &mouse = save_mouse
787 let &term = save_term
788 let &ttymouse = save_ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200789 call test_override('no_query_mouse', 0)
Bram Moolenaare3e38282019-04-15 20:55:31 +0200790 set mousetime&
791endfunc
792
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200793func Test_term_mouse_double_click_to_create_tab()
Bram Moolenaare3e38282019-04-15 20:55:31 +0200794 let save_mouse = &mouse
795 let save_term = &term
796 let save_ttymouse = &ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200797 call test_override('no_query_mouse', 1)
Bram Moolenaare3e38282019-04-15 20:55:31 +0200798 " Set 'mousetime' to a small value, so that double-click works but we don't
799 " have to wait long to avoid a triple-click.
Bram Moolenaarf36a2c72019-11-16 18:57:16 +0100800 set mouse=a term=xterm mousetime=200
Bram Moolenaare3e38282019-04-15 20:55:31 +0200801 let row = 1
802 let col = 10
803
Bram Moolenaar515545e2020-03-22 14:08:59 +0100804 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
Bram Moolenaar49452192019-04-17 16:27:02 +0200805 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar1ee36d62019-05-01 23:13:56 +0200806 exe 'set ttymouse=' .. ttymouse_val
Bram Moolenaare3e38282019-04-15 20:55:31 +0200807 e Xtab1
808 tabnew Xtab2
809
810 let a = split(execute(':tabs'), "\n")
811 call assert_equal(['Tab page 1',
812 \ ' Xtab1',
813 \ 'Tab page 2',
Bram Moolenaar49452192019-04-17 16:27:02 +0200814 \ '> Xtab2'], a, msg)
Bram Moolenaare3e38282019-04-15 20:55:31 +0200815
816 redraw
817 call MouseLeftClick(row, col)
818 " Check getcharmod() to verify that first click is not
819 " interpreted as a spurious double-click.
Bram Moolenaar49452192019-04-17 16:27:02 +0200820 call assert_equal(0, getcharmod(), msg)
Bram Moolenaare3e38282019-04-15 20:55:31 +0200821 call MouseLeftRelease(row, col)
822 call MouseLeftClick(row, col)
Bram Moolenaar49452192019-04-17 16:27:02 +0200823 call assert_equal(32, getcharmod(), msg) " double-click
Bram Moolenaare3e38282019-04-15 20:55:31 +0200824 call MouseLeftRelease(row, col)
825 let a = split(execute(':tabs'), "\n")
826 call assert_equal(['Tab page 1',
827 \ ' Xtab1',
828 \ 'Tab page 2',
829 \ '> [No Name]',
830 \ 'Tab page 3',
Bram Moolenaar49452192019-04-17 16:27:02 +0200831 \ ' Xtab2'], a, msg)
Bram Moolenaare3e38282019-04-15 20:55:31 +0200832
Bram Moolenaarf36a2c72019-11-16 18:57:16 +0100833 " Click elsewhere so that click in next iteration is not
834 " interpreted as unwanted double click.
835 call MouseLeftClick(row, col + 1)
836 call MouseLeftRelease(row, col + 1)
837
Bram Moolenaare3e38282019-04-15 20:55:31 +0200838 %bwipe!
839 endfor
840
841 let &mouse = save_mouse
842 let &term = save_term
843 let &ttymouse = save_ttymouse
Bram Moolenaar92fd5992019-05-02 23:00:22 +0200844 call test_override('no_query_mouse', 0)
Bram Moolenaare3e38282019-04-15 20:55:31 +0200845 set mousetime&
846endfunc
Bram Moolenaar696d6372019-04-17 16:33:46 +0200847
Bram Moolenaarf36a2c72019-11-16 18:57:16 +0100848" Test double/triple/quadruple click in normal mode to visually select.
849func Test_term_mouse_multiple_clicks_to_visually_select()
850 let save_mouse = &mouse
851 let save_term = &term
852 let save_ttymouse = &ttymouse
853 call test_override('no_query_mouse', 1)
Bram Moolenaar2a5c61a2020-12-30 14:59:23 +0100854
855 " 'mousetime' must be sufficiently large, or else the test is flaky when
856 " using a ssh connection with X forwarding; i.e. ssh -X (issue #7563).
857 set mouse=a term=xterm mousetime=600
Bram Moolenaarf36a2c72019-11-16 18:57:16 +0100858 new
859
Bram Moolenaar515545e2020-03-22 14:08:59 +0100860 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
Bram Moolenaarf36a2c72019-11-16 18:57:16 +0100861 let msg = 'ttymouse=' .. ttymouse_val
862 exe 'set ttymouse=' .. ttymouse_val
863 call setline(1, ['foo [foo bar] foo', 'foo'])
864
865 " Double-click on word should visually select the word.
866 call MouseLeftClick(1, 2)
867 call assert_equal(0, getcharmod(), msg)
868 call MouseLeftRelease(1, 2)
869 call MouseLeftClick(1, 2)
870 call assert_equal(32, getcharmod(), msg) " double-click
871 call MouseLeftRelease(1, 2)
872 call assert_equal('v', mode(), msg)
873 norm! r1
874 call assert_equal(['111 [foo bar] foo', 'foo'], getline(1, '$'), msg)
875
876 " Double-click on opening square bracket should visually
877 " select the whole [foo bar].
878 call MouseLeftClick(1, 5)
879 call assert_equal(0, getcharmod(), msg)
880 call MouseLeftRelease(1, 5)
881 call MouseLeftClick(1, 5)
882 call assert_equal(32, getcharmod(), msg) " double-click
883 call MouseLeftRelease(1, 5)
884 call assert_equal('v', mode(), msg)
885 norm! r2
886 call assert_equal(['111 222222222 foo', 'foo'], getline(1, '$'), msg)
887
888 " Triple-click should visually select the whole line.
889 call MouseLeftClick(1, 3)
890 call assert_equal(0, getcharmod(), msg)
891 call MouseLeftRelease(1, 3)
892 call MouseLeftClick(1, 3)
893 call assert_equal(32, getcharmod(), msg) " double-click
894 call MouseLeftRelease(1, 3)
895 call MouseLeftClick(1, 3)
896 call assert_equal(64, getcharmod(), msg) " triple-click
897 call MouseLeftRelease(1, 3)
898 call assert_equal('V', mode(), msg)
899 norm! r3
900 call assert_equal(['33333333333333333', 'foo'], getline(1, '$'), msg)
901
902 " Quadruple-click should start visual block select.
903 call MouseLeftClick(1, 2)
904 call assert_equal(0, getcharmod(), msg)
905 call MouseLeftRelease(1, 2)
906 call MouseLeftClick(1, 2)
907 call assert_equal(32, getcharmod(), msg) " double-click
908 call MouseLeftRelease(1, 2)
909 call MouseLeftClick(1, 2)
910 call assert_equal(64, getcharmod(), msg) " triple-click
911 call MouseLeftRelease(1, 2)
912 call MouseLeftClick(1, 2)
913 call assert_equal(96, getcharmod(), msg) " quadruple-click
914 call MouseLeftRelease(1, 2)
915 call assert_equal("\<c-v>", mode(), msg)
916 norm! r4
917 call assert_equal(['34333333333333333', 'foo'], getline(1, '$'), msg)
Bram Moolenaar2764d062020-07-18 12:59:19 +0200918
919 " Double-click on a space character should visually select all the
920 " consecutive space characters.
921 %d
922 call setline(1, ' one two')
923 call MouseLeftClick(1, 2)
924 call MouseLeftRelease(1, 2)
925 call MouseLeftClick(1, 2)
926 call MouseLeftRelease(1, 2)
927 call assert_equal('v', mode(), msg)
928 norm! r1
929 call assert_equal(['1111one two'], getline(1, '$'), msg)
930
931 " Double-click on a word with exclusive selection
932 set selection=exclusive
933 let @" = ''
934 call MouseLeftClick(1, 10)
935 call MouseLeftRelease(1, 10)
936 call MouseLeftClick(1, 10)
937 call MouseLeftRelease(1, 10)
938 norm! y
939 call assert_equal('two', @", msg)
940
941 " Double click to select a block of text with exclusive selection
942 %d
943 call setline(1, 'one (two) three')
944 call MouseLeftClick(1, 5)
945 call MouseLeftRelease(1, 5)
946 call MouseLeftClick(1, 5)
947 call MouseLeftRelease(1, 5)
948 norm! y
949 call assert_equal(5, col("'<"), msg)
950 call assert_equal(10, col("'>"), msg)
951
952 call MouseLeftClick(1, 9)
953 call MouseLeftRelease(1, 9)
954 call MouseLeftClick(1, 9)
955 call MouseLeftRelease(1, 9)
956 norm! y
957 call assert_equal(5, col("'<"), msg)
958 call assert_equal(10, col("'>"), msg)
959 set selection&
960
961 " Click somewhere else so that the clicks above is not combined with the
962 " clicks in the next iteration.
963 call MouseRightClick(3, 10)
964 call MouseRightRelease(3, 10)
Bram Moolenaarf36a2c72019-11-16 18:57:16 +0100965 endfor
966
967 let &mouse = save_mouse
968 let &term = save_term
969 let &ttymouse = save_ttymouse
970 set mousetime&
971 call test_override('no_query_mouse', 0)
972 bwipe!
973endfunc
974
Bram Moolenaar2764d062020-07-18 12:59:19 +0200975" Test for selecting text in visual blockwise mode using Alt-LeftClick
976func Test_mouse_alt_leftclick()
977 let save_mouse = &mouse
978 let save_term = &term
979 let save_ttymouse = &ttymouse
980 call test_override('no_query_mouse', 1)
981 set mouse=a term=xterm mousetime=200
982 set mousemodel=popup
983 new
984 call setline(1, 'one (two) three')
985
986 for ttymouse_val in g:Ttymouse_values
987 let msg = 'ttymouse=' .. ttymouse_val
988 exe 'set ttymouse=' .. ttymouse_val
989
990 " Left click with the Alt modifier key should extend the selection in
991 " blockwise visual mode.
992 let @" = ''
993 call MouseLeftClick(1, 3)
994 call MouseLeftRelease(1, 3)
995 call MouseAltLeftClick(1, 11)
996 call MouseLeftRelease(1, 11)
997 call assert_equal("\<C-V>", mode(), msg)
998 normal! y
999 call assert_equal('e (two) t', @")
1000 endfor
1001
1002 let &mouse = save_mouse
1003 let &term = save_term
1004 let &ttymouse = save_ttymouse
1005 set mousetime& mousemodel&
1006 call test_override('no_query_mouse', 0)
1007 close!
1008endfunc
1009
Bram Moolenaar696d6372019-04-17 16:33:46 +02001010func Test_xterm_mouse_click_in_fold_columns()
1011 new
1012 let save_mouse = &mouse
1013 let save_term = &term
1014 let save_ttymouse = &ttymouse
1015 let save_foldcolumn = &foldcolumn
Bram Moolenaar2b00b9b2019-04-17 17:08:27 +02001016 set mouse=a term=xterm foldcolumn=3 ttymouse=xterm2
Bram Moolenaar696d6372019-04-17 16:33:46 +02001017
1018 " Create 2 nested folds.
1019 call setline(1, range(1, 7))
1020 2,6fold
1021 norm! zR
1022 4,5fold
1023 call assert_equal([-1, -1, -1, 4, 4, -1, -1],
1024 \ map(range(1, 7), 'foldclosed(v:val)'))
1025
1026 " Click in "+" of inner fold in foldcolumn should open it.
1027 redraw
1028 let row = 4
1029 let col = 2
1030 call MouseLeftClick(row, col)
1031 call MouseLeftRelease(row, col)
1032 call assert_equal([-1, -1, -1, -1, -1, -1, -1],
1033 \ map(range(1, 7), 'foldclosed(v:val)'))
1034
1035 " Click in "-" of outer fold in foldcolumn should close it.
1036 redraw
1037 let row = 2
1038 let col = 1
1039 call MouseLeftClick(row, col)
1040 call MouseLeftRelease(row, col)
1041 call assert_equal([-1, 2, 2, 2, 2, 2, -1],
1042 \ map(range(1, 7), 'foldclosed(v:val)'))
1043 norm! zR
1044
1045 " Click in "|" of inner fold in foldcolumn should close it.
1046 redraw
1047 let row = 5
1048 let col = 2
1049 call MouseLeftClick(row, col)
1050 call MouseLeftRelease(row, col)
1051 call assert_equal([-1, -1, -1, 4, 4, -1, -1],
1052 \ map(range(1, 7), 'foldclosed(v:val)'))
1053
1054 let &foldcolumn = save_foldcolumn
1055 let &ttymouse = save_ttymouse
1056 let &term = save_term
1057 let &mouse = save_mouse
1058 bwipe!
1059endfunc
Bram Moolenaar66761db2019-06-05 22:07:51 +02001060
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01001061" Left or right click in Ex command line sets position of the cursor.
1062func Test_term_mouse_click_in_cmdline_to_set_pos()
1063 let save_mouse = &mouse
1064 let save_term = &term
1065 let save_ttymouse = &ttymouse
1066 call test_override('no_query_mouse', 1)
1067 set mouse=a term=xterm
1068 let row = &lines
1069
Bram Moolenaar515545e2020-03-22 14:08:59 +01001070 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
Bram Moolenaarab505b12020-03-23 19:28:44 +01001071 " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
1072 if ttymouse_val !=# 'xterm2' || row <= 223
1073 let msg = 'ttymouse=' .. ttymouse_val
1074 exe 'set ttymouse=' .. ttymouse_val
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01001075
Bram Moolenaarab505b12020-03-23 19:28:44 +01001076
1077 call feedkeys(':"3456789'
1078 \ .. MouseLeftClickCode(row, 7)
1079 \ .. MouseLeftReleaseCode(row, 7) .. 'L'
1080 \ .. MouseRightClickCode(row, 4)
1081 \ .. MouseRightReleaseCode(row, 4) .. 'R'
1082 \ .. "\<CR>", 'Lx!')
1083 call assert_equal('"3R456L789', @:, msg)
1084 endif
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01001085 endfor
1086
1087 let &mouse = save_mouse
1088 let &term = save_term
1089 let &ttymouse = save_ttymouse
1090 set mousetime&
1091 call test_override('no_query_mouse', 0)
1092endfunc
1093
1094" Middle click in command line pastes at position of cursor.
1095func Test_term_mouse_middle_click_in_cmdline_to_paste()
1096 CheckFeature clipboard_working
1097 let save_mouse = &mouse
1098 let save_term = &term
1099 let save_ttymouse = &ttymouse
1100 call test_override('no_query_mouse', 1)
1101 set mouse=a term=xterm
1102 let row = &lines
1103 " Column values does not matter, paste is done at position of cursor.
1104 let col = 1
1105 let @* = 'paste'
1106
Bram Moolenaar515545e2020-03-22 14:08:59 +01001107 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01001108 let msg = 'ttymouse=' .. ttymouse_val
1109 exe 'set ttymouse=' .. ttymouse_val
1110
1111 call feedkeys(":\"->"
1112 \ .. MouseMiddleReleaseCode(row, col)
1113 \ .. MouseMiddleClickCode(row, col)
1114 \ .. "<-"
1115 \ .. MouseMiddleReleaseCode(row, col)
1116 \ .. MouseMiddleClickCode(row, col)
1117 \ .. "\<CR>", 'Lx!')
1118 call assert_equal('"->paste<-paste', @:, msg)
1119 endfor
1120
1121 let &mouse = save_mouse
1122 let &term = save_term
1123 let &ttymouse = save_ttymouse
1124 let @* = ''
1125 call test_override('no_query_mouse', 0)
1126endfunc
1127
Bram Moolenaar297bec02020-07-14 22:11:04 +02001128" Test for making sure S-Middlemouse doesn't do anything
1129func Test_term_mouse_shift_middle_click()
1130 new
1131 let save_mouse = &mouse
1132 let save_term = &term
1133 let save_ttymouse = &ttymouse
1134 call test_override('no_query_mouse', 1)
1135 set mouse=a term=xterm ttymouse=xterm2 mousemodel=
1136
1137 call test_setmouse(1, 1)
1138 exe "normal \<S-MiddleMouse>"
1139 call assert_equal([''], getline(1, '$'))
1140 call assert_equal(1, winnr())
1141
1142 let &mouse = save_mouse
1143 let &term = save_term
1144 let &ttymouse = save_ttymouse
1145 set mousemodel&
1146 call test_override('no_query_mouse', 0)
1147 close!
1148endfunc
1149
1150" Test for using mouse in visual mode
1151func Test_term_mouse_visual_mode()
1152 new
1153 let save_mouse = &mouse
1154 let save_term = &term
1155 let save_ttymouse = &ttymouse
1156 call test_override('no_query_mouse', 1)
1157 set term=xterm ttymouse=xterm2
1158
1159 " If visual mode is not present in 'mouse', then left click should not
1160 " do anything in visal mode.
1161 call setline(1, ['one two three four'])
1162 set mouse=nci
1163 call cursor(1, 5)
1164 let @" = ''
1165 call feedkeys("ve"
1166 \ .. MouseLeftClickCode(1, 15) .. MouseLeftReleaseCode(1, 15)
1167 \ .. 'y', 'Lx!')
1168 call assert_equal(5, col('.'))
1169 call assert_equal('two', @")
1170
1171 " Pressing right click in visual mode should change the visual selection
1172 " if 'mousemodel' doesn't contain popup.
1173 " Right click after the visual selection
1174 set mousemodel=
1175 set mouse=a
1176 call test_setmouse(1, 13)
1177 exe "normal 5|ve\<RightMouse>y"
1178 call assert_equal('two three', @")
1179 call assert_equal(5, col('.'))
1180
1181 " Right click before the visual selection
1182 call test_setmouse(1, 9)
1183 exe "normal 15|ve\<RightMouse>y"
1184 call assert_equal('three four', @")
1185 call assert_equal(9, col('.'))
1186
Bram Moolenaar2764d062020-07-18 12:59:19 +02001187 " Right click inside the selection closer to the start of the selection
1188 call test_setmouse(1, 7)
1189 exe "normal 5|vee\<RightMouse>lly"
1190 call assert_equal('three', @")
1191 call assert_equal(9, col('.'))
1192 call assert_equal(9, col("'<"))
1193 call assert_equal(13, col("'>"))
1194
1195 " Right click inside the selection closer to the end of the selection
1196 call test_setmouse(1, 11)
1197 exe "normal 5|vee\<RightMouse>ly"
1198 call assert_equal('two thre', @")
1199 call assert_equal(5, col('.'))
1200 call assert_equal(5, col("'<"))
1201 call assert_equal(12, col("'>"))
1202
1203 " Multi-line selection. Right click inside thse selection.
1204 call setline(1, repeat(['aaaaaa'], 7))
Bram Moolenaar297bec02020-07-14 22:11:04 +02001205 call test_setmouse(3, 1)
1206 exe "normal ggVG\<RightMouse>y"
1207 call assert_equal(3, line("'<"))
Bram Moolenaar2764d062020-07-18 12:59:19 +02001208 call test_setmouse(5, 1)
Bram Moolenaar297bec02020-07-14 22:11:04 +02001209 exe "normal ggVG\<RightMouse>y"
Bram Moolenaar2764d062020-07-18 12:59:19 +02001210 call assert_equal(5, line("'>"))
1211
1212 " Click right in the middle line of the selection
1213 call test_setmouse(4, 3)
1214 exe "normal ggVG$\<RightMouse>y"
1215 call assert_equal(4, line("'<"))
1216 call test_setmouse(4, 4)
1217 exe "normal ggVG$\<RightMouse>y"
Bram Moolenaar297bec02020-07-14 22:11:04 +02001218 call assert_equal(4, line("'>"))
1219
1220 set mousemodel&
1221 let &mouse = save_mouse
1222 let &term = save_term
1223 let &ttymouse = save_ttymouse
1224 call test_override('no_query_mouse', 0)
1225 close!
1226endfunc
1227
Bram Moolenaar0eabd4d2020-03-15 16:13:53 +01001228" Test for displaying the popup menu using the right mouse click
Bram Moolenaar297bec02020-07-14 22:11:04 +02001229func Test_term_mouse_popup_menu()
Bram Moolenaar0eabd4d2020-03-15 16:13:53 +01001230 CheckFeature menu
1231 new
1232 call setline(1, 'popup menu test')
1233 let save_mouse = &mouse
1234 let save_term = &term
1235 let save_ttymouse = &ttymouse
1236 let save_mousemodel = &mousemodel
1237 call test_override('no_query_mouse', 1)
1238 set mouse=a term=xterm mousemodel=popup
1239
1240 menu PopUp.foo :let g:menustr = 'foo'<CR>
1241 menu PopUp.bar :let g:menustr = 'bar'<CR>
1242 menu PopUp.baz :let g:menustr = 'baz'<CR>
1243
Bram Moolenaar515545e2020-03-22 14:08:59 +01001244 for ttymouse_val in g:Ttymouse_values
Bram Moolenaar2764d062020-07-18 12:59:19 +02001245 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar0eabd4d2020-03-15 16:13:53 +01001246 exe 'set ttymouse=' .. ttymouse_val
1247 let g:menustr = ''
1248 call feedkeys(MouseRightClickCode(1, 4)
1249 \ .. MouseRightReleaseCode(1, 4) .. "\<Down>\<Down>\<CR>", "x")
Bram Moolenaar2764d062020-07-18 12:59:19 +02001250 call assert_equal('bar', g:menustr, msg)
Bram Moolenaar0eabd4d2020-03-15 16:13:53 +01001251 endfor
1252
1253 unmenu PopUp
1254 let &mouse = save_mouse
1255 let &term = save_term
1256 let &ttymouse = save_ttymouse
1257 let &mousemodel = save_mousemodel
1258 call test_override('no_query_mouse', 0)
1259 close!
1260endfunc
1261
Bram Moolenaar297bec02020-07-14 22:11:04 +02001262" Test for 'mousemodel' set to popup_setpos to move the cursor where the popup
1263" menu is displayed.
1264func Test_term_mouse_popup_menu_setpos()
1265 CheckFeature menu
1266 5new
1267 call setline(1, ['the dish ran away with the spoon',
1268 \ 'the cow jumped over the moon' ])
1269 let save_mouse = &mouse
1270 let save_term = &term
1271 let save_ttymouse = &ttymouse
1272 let save_mousemodel = &mousemodel
1273 call test_override('no_query_mouse', 1)
1274 set mouse=a term=xterm mousemodel=popup_setpos
1275
1276 nmenu PopUp.foo :let g:menustr = 'foo'<CR>
1277 nmenu PopUp.bar :let g:menustr = 'bar'<CR>
1278 nmenu PopUp.baz :let g:menustr = 'baz'<CR>
1279 vmenu PopUp.foo y:<C-U>let g:menustr = 'foo'<CR>
1280 vmenu PopUp.bar y:<C-U>let g:menustr = 'bar'<CR>
1281 vmenu PopUp.baz y:<C-U>let g:menustr = 'baz'<CR>
1282
1283 for ttymouse_val in g:Ttymouse_values
Bram Moolenaar2764d062020-07-18 12:59:19 +02001284 let msg = 'ttymouse=' .. ttymouse_val
Bram Moolenaar297bec02020-07-14 22:11:04 +02001285 exe 'set ttymouse=' .. ttymouse_val
1286 let g:menustr = ''
1287 call cursor(1, 1)
1288 call feedkeys(MouseRightClickCode(1, 5)
1289 \ .. MouseRightReleaseCode(1, 5) .. "\<Down>\<Down>\<CR>", "x")
Bram Moolenaar2764d062020-07-18 12:59:19 +02001290 call assert_equal('bar', g:menustr, msg)
1291 call assert_equal([1, 5], [line('.'), col('.')], msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +02001292
1293 " Test for right click in visual mode inside the selection
1294 let @" = ''
1295 call cursor(1, 10)
1296 call feedkeys('vee' .. MouseRightClickCode(1, 12)
1297 \ .. MouseRightReleaseCode(1, 12) .. "\<Down>\<CR>", "x")
Bram Moolenaar2764d062020-07-18 12:59:19 +02001298 call assert_equal([1, 10], [line('.'), col('.')], msg)
1299 call assert_equal('ran away', @", msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +02001300
1301 " Test for right click in visual mode before the selection
1302 let @" = ''
1303 call cursor(1, 10)
1304 call feedkeys('vee' .. MouseRightClickCode(1, 2)
1305 \ .. MouseRightReleaseCode(1, 2) .. "\<Down>\<CR>", "x")
Bram Moolenaar2764d062020-07-18 12:59:19 +02001306 call assert_equal([1, 2], [line('.'), col('.')], msg)
1307 call assert_equal('', @", msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +02001308
1309 " Test for right click in visual mode after the selection
1310 let @" = ''
1311 call cursor(1, 10)
1312 call feedkeys('vee' .. MouseRightClickCode(1, 20)
1313 \ .. MouseRightReleaseCode(1, 20) .. "\<Down>\<CR>", "x")
Bram Moolenaar2764d062020-07-18 12:59:19 +02001314 call assert_equal([1, 20], [line('.'), col('.')], msg)
1315 call assert_equal('', @", msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +02001316
1317 " Test for right click in block-wise visual mode inside the selection
1318 let @" = ''
1319 call cursor(1, 16)
1320 call feedkeys("\<C-V>j3l" .. MouseRightClickCode(2, 17)
1321 \ .. MouseRightReleaseCode(2, 17) .. "\<Down>\<CR>", "x")
Bram Moolenaar2764d062020-07-18 12:59:19 +02001322 call assert_equal([1, 16], [line('.'), col('.')], msg)
1323 call assert_equal("\<C-V>4", getregtype('"'), msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +02001324
1325 " Test for right click in block-wise visual mode outside the selection
1326 let @" = ''
1327 call cursor(1, 16)
1328 call feedkeys("\<C-V>j3l" .. MouseRightClickCode(2, 2)
1329 \ .. MouseRightReleaseCode(2, 2) .. "\<Down>\<CR>", "x")
Bram Moolenaar2764d062020-07-18 12:59:19 +02001330 call assert_equal([2, 2], [line('.'), col('.')], msg)
1331 call assert_equal('v', getregtype('"'), msg)
1332 call assert_equal('', @", msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +02001333
1334 " Try clicking on the status line
1335 let @" = ''
1336 call cursor(1, 10)
1337 call feedkeys('vee' .. MouseRightClickCode(6, 2)
1338 \ .. MouseRightReleaseCode(6, 2) .. "\<Down>\<CR>", "x")
Bram Moolenaar2764d062020-07-18 12:59:19 +02001339 call assert_equal([1, 10], [line('.'), col('.')], msg)
1340 call assert_equal('ran away', @", msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +02001341
1342 " Try clicking outside the window
1343 let @" = ''
1344 call cursor(7, 2)
1345 call feedkeys('vee' .. MouseRightClickCode(7, 2)
1346 \ .. MouseRightReleaseCode(7, 2) .. "\<Down>\<CR>", "x")
Bram Moolenaar2764d062020-07-18 12:59:19 +02001347 call assert_equal(2, winnr(), msg)
1348 call assert_equal('', @", msg)
Bram Moolenaar297bec02020-07-14 22:11:04 +02001349 wincmd w
1350 endfor
1351
1352 unmenu PopUp
1353 let &mouse = save_mouse
1354 let &term = save_term
1355 let &ttymouse = save_ttymouse
1356 let &mousemodel = save_mousemodel
1357 call test_override('no_query_mouse', 0)
1358 close!
1359endfunc
1360
1361" Test for searching for the word under the cursor using Shift-Right or
1362" Shift-Left click.
1363func Test_term_mouse_search()
1364 new
1365 let save_mouse = &mouse
1366 let save_term = &term
1367 let save_ttymouse = &ttymouse
1368 call test_override('no_query_mouse', 1)
1369 set mouse=a term=xterm ttymouse=xterm2
1370 set mousemodel=
1371
1372 " In normal mode, Shift-Left or Shift-Right click should search for the word
1373 " under the cursor.
1374 call setline(1, ['one two three four', 'four three two one'])
1375 call test_setmouse(1, 4)
1376 exe "normal \<S-LeftMouse>"
1377 call assert_equal([2, 12], [line('.'), col('.')])
1378 call test_setmouse(2, 16)
1379 exe "normal \<S-RightMouse>"
1380 call assert_equal([1, 1], [line('.'), col('.')])
1381
1382 " In visual mode, Shift-Left or Shift-Right click should search for the word
1383 " under the cursor and extend the selection.
1384 call test_setmouse(1, 4)
1385 exe "normal 4|ve\<S-LeftMouse>y"
1386 call assert_equal([2, 12], [line("'>"), col("'>")])
1387 call test_setmouse(2, 16)
1388 exe "normal 2G16|ve\<S-RightMouse>y"
1389 call assert_equal([1, 1], [line("'<"), col("'<")])
1390
1391 set mousemodel&
1392 let &mouse = save_mouse
1393 let &term = save_term
1394 let &ttymouse = save_ttymouse
1395 call test_override('no_query_mouse', 0)
1396 close!
1397endfunc
1398
1399" Test for selecting an entry in the quickfix/location list window using the
1400" mouse.
1401func Test_term_mouse_quickfix_window()
1402 let save_mouse = &mouse
1403 let save_term = &term
1404 let save_ttymouse = &ttymouse
1405 call test_override('no_query_mouse', 1)
1406 set mouse=a term=xterm ttymouse=xterm2
1407 set mousemodel=
1408
1409 cgetexpr "Xfile1:1:L1"
1410 copen 5
1411 call test_setmouse(&lines - 7, 1)
1412 exe "normal \<2-LeftMouse>"
1413 call assert_equal('Xfile1', @%)
1414 %bw!
1415
1416 lgetexpr "Xfile2:1:L1"
1417 lopen 5
1418 call test_setmouse(&lines - 7, 1)
1419 exe "normal \<2-LeftMouse>"
1420 call assert_equal('Xfile2', @%)
1421 %bw!
1422
1423 set mousemodel&
1424 let &mouse = save_mouse
1425 let &term = save_term
1426 let &ttymouse = save_ttymouse
1427 call test_override('no_query_mouse', 0)
1428endfunc
1429
Bram Moolenaar2764d062020-07-18 12:59:19 +02001430" Test for the 'h' flag in the 'mouse' option. Using mouse in the help window.
1431func Test_term_mouse_help_window()
1432 let save_mouse = &mouse
1433 let save_term = &term
1434 let save_ttymouse = &ttymouse
1435 call test_override('no_query_mouse', 1)
1436 set mouse=h term=xterm mousetime=200
1437
1438 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
1439 let msg = 'ttymouse=' .. ttymouse_val
1440 exe 'set ttymouse=' .. ttymouse_val
1441 help
1442 let @" = ''
1443 call MouseLeftClick(2, 5)
1444 call MouseLeftRelease(2, 5)
1445 call MouseLeftClick(1, 1)
1446 call MouseLeftDrag(1, 10)
1447 call MouseLeftRelease(1, 10)
1448 norm! y
1449 call assert_equal('*help.txt*', @", msg)
1450 helpclose
1451
1452 " Click somewhere else to make sure the left click above is not combined
1453 " with the next left click and treated as a double click
1454 call MouseRightClick(5, 10)
1455 call MouseRightRelease(5, 10)
1456 endfor
1457
1458 let &mouse = save_mouse
1459 let &term = save_term
1460 let &ttymouse = save_ttymouse
1461 set mousetime&
1462 call test_override('no_query_mouse', 0)
1463 %bw!
1464endfunc
1465
1466" Test for the translation of various mouse terminal codes
1467func Test_mouse_termcodes()
1468 let save_mouse = &mouse
1469 let save_term = &term
1470 let save_ttymouse = &ttymouse
1471 call test_override('no_query_mouse', 1)
1472 set mouse=a term=xterm mousetime=200
1473
1474 new
1475 for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
1476 let msg = 'ttymouse=' .. ttymouse_val
1477 exe 'set ttymouse=' .. ttymouse_val
1478
1479 let mouse_codes = [
1480 \ ["\<LeftMouse>", "<LeftMouse>"],
1481 \ ["\<MiddleMouse>", "<MiddleMouse>"],
1482 \ ["\<RightMouse>", "<RightMouse>"],
1483 \ ["\<S-LeftMouse>", "<S-LeftMouse>"],
1484 \ ["\<S-MiddleMouse>", "<S-MiddleMouse>"],
1485 \ ["\<S-RightMouse>", "<S-RightMouse>"],
1486 \ ["\<C-LeftMouse>", "<C-LeftMouse>"],
1487 \ ["\<C-MiddleMouse>", "<C-MiddleMouse>"],
1488 \ ["\<C-RightMouse>", "<C-RightMouse>"],
1489 \ ["\<M-LeftMouse>", "<M-LeftMouse>"],
1490 \ ["\<M-MiddleMouse>", "<M-MiddleMouse>"],
1491 \ ["\<M-RightMouse>", "<M-RightMouse>"],
1492 \ ["\<2-LeftMouse>", "<2-LeftMouse>"],
1493 \ ["\<2-MiddleMouse>", "<2-MiddleMouse>"],
1494 \ ["\<2-RightMouse>", "<2-RightMouse>"],
1495 \ ["\<3-LeftMouse>", "<3-LeftMouse>"],
1496 \ ["\<3-MiddleMouse>", "<3-MiddleMouse>"],
1497 \ ["\<3-RightMouse>", "<3-RightMouse>"],
1498 \ ["\<4-LeftMouse>", "<4-LeftMouse>"],
1499 \ ["\<4-MiddleMouse>", "<4-MiddleMouse>"],
1500 \ ["\<4-RightMouse>", "<4-RightMouse>"],
1501 \ ["\<LeftDrag>", "<LeftDrag>"],
1502 \ ["\<MiddleDrag>", "<MiddleDrag>"],
1503 \ ["\<RightDrag>", "<RightDrag>"],
1504 \ ["\<LeftRelease>", "<LeftRelease>"],
1505 \ ["\<MiddleRelease>", "<MiddleRelease>"],
1506 \ ["\<RightRelease>", "<RightRelease>"],
1507 \ ["\<ScrollWheelUp>", "<ScrollWheelUp>"],
1508 \ ["\<S-ScrollWheelUp>", "<S-ScrollWheelUp>"],
1509 \ ["\<C-ScrollWheelUp>", "<C-ScrollWheelUp>"],
1510 \ ["\<ScrollWheelDown>", "<ScrollWheelDown>"],
1511 \ ["\<S-ScrollWheelDown>", "<S-ScrollWheelDown>"],
1512 \ ["\<C-ScrollWheelDown>", "<C-ScrollWheelDown>"],
1513 \ ["\<ScrollWheelLeft>", "<ScrollWheelLeft>"],
1514 \ ["\<S-ScrollWheelLeft>", "<S-ScrollWheelLeft>"],
1515 \ ["\<C-ScrollWheelLeft>", "<C-ScrollWheelLeft>"],
1516 \ ["\<ScrollWheelRight>", "<ScrollWheelRight>"],
1517 \ ["\<S-ScrollWheelRight>", "<S-ScrollWheelRight>"],
1518 \ ["\<C-ScrollWheelRight>", "<C-ScrollWheelRight>"]
1519 \ ]
1520
1521 for [code, outstr] in mouse_codes
1522 exe "normal ggC\<C-K>" . code
1523 call assert_equal(outstr, getline(1), msg)
1524 endfor
1525 endfor
1526
1527 let &mouse = save_mouse
1528 let &term = save_term
1529 let &ttymouse = save_ttymouse
1530 set mousetime&
1531 call test_override('no_query_mouse', 0)
1532 %bw!
1533endfunc
1534
Bram Moolenaar66761db2019-06-05 22:07:51 +02001535" This only checks if the sequence is recognized.
Bram Moolenaar66761db2019-06-05 22:07:51 +02001536func Test_term_rgb_response()
1537 set t_RF=x
1538 set t_RB=y
1539
1540 " response to t_RF, 4 digits
1541 let red = 0x12
1542 let green = 0x34
1543 let blue = 0x56
1544 let seq = printf("\<Esc>]10;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
1545 call feedkeys(seq, 'Lx!')
1546 call assert_equal(seq, v:termrfgresp)
1547
1548 " response to t_RF, 2 digits
1549 let red = 0x78
1550 let green = 0x9a
1551 let blue = 0xbc
1552 let seq = printf("\<Esc>]10;rgb:%02x/%02x/%02x\x07", red, green, blue)
1553 call feedkeys(seq, 'Lx!')
1554 call assert_equal(seq, v:termrfgresp)
1555
Bram Moolenaar32e19772019-06-05 22:57:04 +02001556 " response to t_RB, 4 digits, dark
1557 set background=light
Bram Moolenaarce90e362019-09-08 18:58:44 +02001558 eval 'background'->test_option_not_set()
Bram Moolenaar32e19772019-06-05 22:57:04 +02001559 let red = 0x29
1560 let green = 0x4a
1561 let blue = 0x6b
1562 let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
1563 call feedkeys(seq, 'Lx!')
1564 call assert_equal(seq, v:termrbgresp)
1565 call assert_equal('dark', &background)
1566
1567 " response to t_RB, 4 digits, light
1568 set background=dark
1569 call test_option_not_set('background')
1570 let red = 0x81
1571 let green = 0x63
Bram Moolenaar66761db2019-06-05 22:07:51 +02001572 let blue = 0x65
1573 let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
1574 call feedkeys(seq, 'Lx!')
1575 call assert_equal(seq, v:termrbgresp)
Bram Moolenaar32e19772019-06-05 22:57:04 +02001576 call assert_equal('light', &background)
Bram Moolenaar66761db2019-06-05 22:07:51 +02001577
Bram Moolenaar32e19772019-06-05 22:57:04 +02001578 " response to t_RB, 2 digits, dark
1579 set background=light
1580 call test_option_not_set('background')
1581 let red = 0x47
1582 let green = 0x59
1583 let blue = 0x5b
Bram Moolenaar66761db2019-06-05 22:07:51 +02001584 let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
1585 call feedkeys(seq, 'Lx!')
1586 call assert_equal(seq, v:termrbgresp)
Bram Moolenaar32e19772019-06-05 22:57:04 +02001587 call assert_equal('dark', &background)
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01001588
Bram Moolenaar32e19772019-06-05 22:57:04 +02001589 " response to t_RB, 2 digits, light
1590 set background=dark
1591 call test_option_not_set('background')
1592 let red = 0x83
1593 let green = 0xa4
1594 let blue = 0xc2
1595 let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
1596 call feedkeys(seq, 'Lx!')
1597 call assert_equal(seq, v:termrbgresp)
1598 call assert_equal('light', &background)
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01001599
Bram Moolenaar66761db2019-06-05 22:07:51 +02001600 set t_RF= t_RB=
1601endfunc
1602
1603" This only checks if the sequence is recognized.
Bram Moolenaar1a4cbb12019-10-12 13:25:44 +02001604" This must be after other tests, because it has side effects to xterm
1605" properties.
1606func Test_xx01_term_style_response()
Bram Moolenaar66761db2019-06-05 22:07:51 +02001607 " Termresponse is only parsed when t_RV is not empty.
1608 set t_RV=x
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001609 call test_override('term_props', 1)
Bram Moolenaar66761db2019-06-05 22:07:51 +02001610
1611 " send the termresponse to trigger requesting the XT codes
1612 let seq = "\<Esc>[>41;337;0c"
1613 call feedkeys(seq, 'Lx!')
1614 call assert_equal(seq, v:termresponse)
1615
1616 let seq = "\<Esc>P1$r2 q\<Esc>\\"
1617 call feedkeys(seq, 'Lx!')
1618 call assert_equal(seq, v:termstyleresp)
1619
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001620 call assert_equal(#{
1621 \ cursor_style: 'u',
1622 \ cursor_blink_mode: 'u',
1623 \ underline_rgb: 'u',
1624 \ mouse: 's'
1625 \ }, terminalprops())
1626
Bram Moolenaar66761db2019-06-05 22:07:51 +02001627 set t_RV=
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001628 call test_override('term_props', 0)
Bram Moolenaar66761db2019-06-05 22:07:51 +02001629endfunc
Bram Moolenaarde6dbb42019-06-06 11:59:18 +02001630
Bram Moolenaar89577b32019-10-18 21:26:05 +02001631" This checks the iTerm2 version response.
1632" This must be after other tests, because it has side effects to xterm
1633" properties.
1634func Test_xx02_iTerm2_response()
1635 " Termresponse is only parsed when t_RV is not empty.
1636 set t_RV=x
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001637 call test_override('term_props', 1)
Bram Moolenaar89577b32019-10-18 21:26:05 +02001638
1639 " Old versions of iTerm2 used a different style term response.
1640 set ttymouse=xterm
1641 call test_option_not_set('ttymouse')
1642 let seq = "\<Esc>[>0;95;c"
1643 call feedkeys(seq, 'Lx!')
1644 call assert_equal(seq, v:termresponse)
1645 call assert_equal('xterm', &ttymouse)
1646
1647 set ttymouse=xterm
1648 call test_option_not_set('ttymouse')
1649 let seq = "\<Esc>[>0;95;0c"
1650 call feedkeys(seq, 'Lx!')
1651 call assert_equal(seq, v:termresponse)
1652 call assert_equal('sgr', &ttymouse)
1653
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001654 call assert_equal(#{
1655 \ cursor_style: 'n',
1656 \ cursor_blink_mode: 'u',
1657 \ underline_rgb: 'u',
1658 \ mouse: 's'
1659 \ }, terminalprops())
1660
Bram Moolenaar89577b32019-10-18 21:26:05 +02001661 set t_RV=
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001662 call test_override('term_props', 0)
Bram Moolenaar89577b32019-10-18 21:26:05 +02001663endfunc
1664
Bram Moolenaar1a4cbb12019-10-12 13:25:44 +02001665" This checks the libvterm version response.
1666" This must be after other tests, because it has side effects to xterm
1667" properties.
Bram Moolenaar89577b32019-10-18 21:26:05 +02001668func Test_xx03_libvterm_response()
Bram Moolenaar1a4cbb12019-10-12 13:25:44 +02001669 " Termresponse is only parsed when t_RV is not empty.
1670 set t_RV=x
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001671 call test_override('term_props', 1)
Bram Moolenaar03b00472019-10-14 22:22:03 +02001672
Bram Moolenaar1a4cbb12019-10-12 13:25:44 +02001673 set ttymouse=xterm
1674 call test_option_not_set('ttymouse')
Bram Moolenaar1a4cbb12019-10-12 13:25:44 +02001675 let seq = "\<Esc>[>0;100;0c"
1676 call feedkeys(seq, 'Lx!')
1677 call assert_equal(seq, v:termresponse)
1678 call assert_equal('sgr', &ttymouse)
1679
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001680 call assert_equal(#{
1681 \ cursor_style: 'n',
1682 \ cursor_blink_mode: 'u',
1683 \ underline_rgb: 'u',
1684 \ mouse: 's'
1685 \ }, terminalprops())
1686
Bram Moolenaar1a4cbb12019-10-12 13:25:44 +02001687 set t_RV=
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001688 call test_override('term_props', 0)
Bram Moolenaar1a4cbb12019-10-12 13:25:44 +02001689endfunc
1690
Bram Moolenaar89577b32019-10-18 21:26:05 +02001691" This checks the Mac Terminal.app version response.
1692" This must be after other tests, because it has side effects to xterm
1693" properties.
1694func Test_xx04_Mac_Terminal_response()
1695 " Termresponse is only parsed when t_RV is not empty.
1696 set t_RV=x
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001697 call test_override('term_props', 1)
Bram Moolenaar89577b32019-10-18 21:26:05 +02001698
1699 set ttymouse=xterm
Bram Moolenaar8dff4cb2020-06-14 14:34:16 +02001700 " t_8u is not reset
1701 let &t_8u = "\<Esc>[58;2;%lu;%lu;%lum"
Bram Moolenaar89577b32019-10-18 21:26:05 +02001702 call test_option_not_set('ttymouse')
1703 let seq = "\<Esc>[>1;95;0c"
1704 call feedkeys(seq, 'Lx!')
1705 call assert_equal(seq, v:termresponse)
1706 call assert_equal('sgr', &ttymouse)
1707
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001708 call assert_equal(#{
1709 \ cursor_style: 'n',
1710 \ cursor_blink_mode: 'u',
1711 \ underline_rgb: 'y',
1712 \ mouse: 's'
1713 \ }, terminalprops())
Bram Moolenaar8dff4cb2020-06-14 14:34:16 +02001714 call assert_equal("\<Esc>[58;2;%lu;%lu;%lum", &t_8u)
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001715
Bram Moolenaar89577b32019-10-18 21:26:05 +02001716 " Reset is_not_xterm and is_mac_terminal.
1717 set t_RV=
1718 set term=xterm
1719 set t_RV=x
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001720 call test_override('term_props', 0)
Bram Moolenaar89577b32019-10-18 21:26:05 +02001721endfunc
1722
1723" This checks the mintty version response.
1724" This must be after other tests, because it has side effects to xterm
1725" properties.
1726func Test_xx05_mintty_response()
1727 " Termresponse is only parsed when t_RV is not empty.
1728 set t_RV=x
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001729 call test_override('term_props', 1)
Bram Moolenaar89577b32019-10-18 21:26:05 +02001730
1731 set ttymouse=xterm
1732 call test_option_not_set('ttymouse')
1733 let seq = "\<Esc>[>77;20905;0c"
1734 call feedkeys(seq, 'Lx!')
1735 call assert_equal(seq, v:termresponse)
1736 call assert_equal('sgr', &ttymouse)
1737
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001738 call assert_equal(#{
1739 \ cursor_style: 'n',
1740 \ cursor_blink_mode: 'u',
1741 \ underline_rgb: 'y',
1742 \ mouse: 's'
1743 \ }, terminalprops())
1744
Bram Moolenaar89577b32019-10-18 21:26:05 +02001745 set t_RV=
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001746 call test_override('term_props', 0)
Bram Moolenaar89577b32019-10-18 21:26:05 +02001747endfunc
1748
1749" This checks the screen version response.
1750" This must be after other tests, because it has side effects to xterm
1751" properties.
1752func Test_xx06_screen_response()
1753 " Termresponse is only parsed when t_RV is not empty.
1754 set t_RV=x
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001755 call test_override('term_props', 1)
Bram Moolenaar89577b32019-10-18 21:26:05 +02001756
1757 " Old versions of screen don't support SGR mouse mode.
1758 set ttymouse=xterm
1759 call test_option_not_set('ttymouse')
1760 let seq = "\<Esc>[>83;40500;0c"
1761 call feedkeys(seq, 'Lx!')
1762 call assert_equal(seq, v:termresponse)
1763 call assert_equal('xterm', &ttymouse)
1764
1765 " screen supports SGR mouse mode starting in version 4.7.
1766 set ttymouse=xterm
1767 call test_option_not_set('ttymouse')
1768 let seq = "\<Esc>[>83;40700;0c"
1769 call feedkeys(seq, 'Lx!')
1770 call assert_equal(seq, v:termresponse)
1771 call assert_equal('sgr', &ttymouse)
1772
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001773 call assert_equal(#{
1774 \ cursor_style: 'n',
1775 \ cursor_blink_mode: 'n',
1776 \ underline_rgb: 'y',
1777 \ mouse: 's'
1778 \ }, terminalprops())
1779
Bram Moolenaar89577b32019-10-18 21:26:05 +02001780 set t_RV=
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001781 call test_override('term_props', 0)
Bram Moolenaar89577b32019-10-18 21:26:05 +02001782endfunc
1783
Bram Moolenaar03b00472019-10-14 22:22:03 +02001784" This checks the xterm version response.
1785" This must be after other tests, because it has side effects to xterm
1786" properties.
Bram Moolenaar89577b32019-10-18 21:26:05 +02001787func Test_xx07_xterm_response()
Bram Moolenaar03b00472019-10-14 22:22:03 +02001788 " Termresponse is only parsed when t_RV is not empty.
1789 set t_RV=x
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001790 call test_override('term_props', 1)
Bram Moolenaar03b00472019-10-14 22:22:03 +02001791
Bram Moolenaar3cea8a92019-10-17 21:55:24 +02001792 " Do Terminal.app first to check that is_mac_terminal is reset.
1793 set ttymouse=xterm
1794 call test_option_not_set('ttymouse')
1795 let seq = "\<Esc>[>1;95;0c"
1796 call feedkeys(seq, 'Lx!')
1797 call assert_equal(seq, v:termresponse)
1798 call assert_equal('sgr', &ttymouse)
1799
Bram Moolenaar03b00472019-10-14 22:22:03 +02001800 " xterm < 95: "xterm" (actually unmodified)
Bram Moolenaar3cea8a92019-10-17 21:55:24 +02001801 set t_RV=
1802 set term=xterm
1803 set t_RV=x
Bram Moolenaar03b00472019-10-14 22:22:03 +02001804 set ttymouse=xterm
1805 call test_option_not_set('ttymouse')
1806 let seq = "\<Esc>[>0;94;0c"
1807 call feedkeys(seq, 'Lx!')
1808 call assert_equal(seq, v:termresponse)
1809 call assert_equal('xterm', &ttymouse)
1810
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001811 call assert_equal(#{
1812 \ cursor_style: 'n',
1813 \ cursor_blink_mode: 'u',
1814 \ underline_rgb: 'y',
1815 \ mouse: 'u'
1816 \ }, terminalprops())
1817
Bram Moolenaar03b00472019-10-14 22:22:03 +02001818 " xterm >= 95 < 277 "xterm2"
1819 set ttymouse=xterm
1820 call test_option_not_set('ttymouse')
1821 let seq = "\<Esc>[>0;267;0c"
1822 call feedkeys(seq, 'Lx!')
1823 call assert_equal(seq, v:termresponse)
1824 call assert_equal('xterm2', &ttymouse)
1825
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001826 call assert_equal(#{
1827 \ cursor_style: 'n',
1828 \ cursor_blink_mode: 'u',
1829 \ underline_rgb: 'u',
1830 \ mouse: '2'
1831 \ }, terminalprops())
1832
Bram Moolenaar03b00472019-10-14 22:22:03 +02001833 " xterm >= 277: "sgr"
1834 set ttymouse=xterm
1835 call test_option_not_set('ttymouse')
1836 let seq = "\<Esc>[>0;277;0c"
1837 call feedkeys(seq, 'Lx!')
1838 call assert_equal(seq, v:termresponse)
1839 call assert_equal('sgr', &ttymouse)
1840
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001841 call assert_equal(#{
1842 \ cursor_style: 'n',
1843 \ cursor_blink_mode: 'u',
1844 \ underline_rgb: 'u',
1845 \ mouse: 's'
1846 \ }, terminalprops())
1847
Bram Moolenaar8dff4cb2020-06-14 14:34:16 +02001848 " xterm >= 279: "sgr" and cursor_style not reset; also check t_8u reset
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001849 set ttymouse=xterm
1850 call test_option_not_set('ttymouse')
Bram Moolenaar8dff4cb2020-06-14 14:34:16 +02001851 let &t_8u = "\<Esc>[58;2;%lu;%lu;%lum"
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001852 let seq = "\<Esc>[>0;279;0c"
1853 call feedkeys(seq, 'Lx!')
1854 call assert_equal(seq, v:termresponse)
1855 call assert_equal('sgr', &ttymouse)
1856
1857 call assert_equal(#{
1858 \ cursor_style: 'u',
1859 \ cursor_blink_mode: 'u',
1860 \ underline_rgb: 'u',
1861 \ mouse: 's'
1862 \ }, terminalprops())
Bram Moolenaar8dff4cb2020-06-14 14:34:16 +02001863 call assert_equal('', &t_8u)
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001864
Bram Moolenaar03b00472019-10-14 22:22:03 +02001865 set t_RV=
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +02001866 call test_override('term_props', 0)
Bram Moolenaar03b00472019-10-14 22:22:03 +02001867endfunc
1868
Bram Moolenaarde6dbb42019-06-06 11:59:18 +02001869func Test_get_termcode()
Bram Moolenaareb663282019-10-06 12:02:15 +02001870 try
1871 let k1 = &t_k1
1872 catch /E113/
1873 throw 'Skipped: Unable to query termcodes'
1874 endtry
Bram Moolenaarde6dbb42019-06-06 11:59:18 +02001875 set t_k1=
1876 set t_k1&
1877 call assert_equal(k1, &t_k1)
Bram Moolenaar9aeb3362019-06-06 12:36:15 +02001878
1879 " use external termcap first
1880 set nottybuiltin
1881 set t_k1=
1882 set t_k1&
1883 " when using external termcap may get something else, but it must not be
1884 " empty, since we would fallback to the builtin one.
1885 call assert_notequal('', &t_k1)
1886
1887 if &term =~ 'xterm'
1888 " use internal termcap first
1889 let term_save = &term
1890 let &term = 'builtin_' .. &term
1891 set t_k1=
1892 set t_k1&
1893 call assert_equal(k1, &t_k1)
1894 let &term = term_save
1895 endif
1896
1897 set ttybuiltin
Bram Moolenaarde6dbb42019-06-06 11:59:18 +02001898endfunc
Bram Moolenaar18a79a62019-10-12 15:36:11 +02001899
Bram Moolenaarecd34bf2020-08-04 20:17:31 +02001900func Test_list_builtin_terminals()
Bram Moolenaare46a2ed2020-08-04 21:04:57 +02001901 CheckRunVimInTerminal
Bram Moolenaar4d05af02020-11-27 20:55:00 +01001902 call RunVimInTerminal('', #{rows: 14})
1903 call term_sendkeys('', ":set cmdheight=3\<CR>")
1904 call TermWait('', 100)
1905 call term_sendkeys('', ":set term=xxx\<CR>")
1906 call TermWait('', 100)
1907 call assert_match('builtin_dumb', term_getline('', 11))
1908 call assert_match('Not found in termcap', term_getline('', 12))
1909 call StopVimInTerminal('')
Bram Moolenaarecd34bf2020-08-04 20:17:31 +02001910endfunc
1911
Bram Moolenaar18a79a62019-10-12 15:36:11 +02001912func GetEscCodeCSI27(key, modifier)
1913 let key = printf("%d", char2nr(a:key))
1914 let mod = printf("%d", a:modifier)
1915 return "\<Esc>[27;" .. mod .. ';' .. key .. '~'
1916endfunc
1917
1918func GetEscCodeCSIu(key, modifier)
1919 let key = printf("%d", char2nr(a:key))
1920 let mod = printf("%d", a:modifier)
1921 return "\<Esc>[" .. key .. ';' .. mod .. 'u'
1922endfunc
1923
1924" This checks the CSI sequences when in modifyOtherKeys mode.
1925" The mode doesn't need to be enabled, the codes are always detected.
1926func RunTest_modifyOtherKeys(func)
1927 new
Bram Moolenaar459fd782019-10-13 16:43:39 +02001928 set timeoutlen=10
Bram Moolenaar18a79a62019-10-12 15:36:11 +02001929
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01001930 " Shift-X is sent as 'X' with the shift modifier
Bram Moolenaar18a79a62019-10-12 15:36:11 +02001931 call feedkeys('a' .. a:func('X', 2) .. "\<Esc>", 'Lx!')
1932 call assert_equal('X', getline(1))
1933
1934 " Ctrl-i is Tab
1935 call setline(1, '')
1936 call feedkeys('a' .. a:func('i', 5) .. "\<Esc>", 'Lx!')
1937 call assert_equal("\t", getline(1))
1938
1939 " Ctrl-I is also Tab
1940 call setline(1, '')
1941 call feedkeys('a' .. a:func('I', 5) .. "\<Esc>", 'Lx!')
1942 call assert_equal("\t", getline(1))
1943
1944 " Alt-x is ø
1945 call setline(1, '')
1946 call feedkeys('a' .. a:func('x', 3) .. "\<Esc>", 'Lx!')
1947 call assert_equal("ø", getline(1))
1948
1949 " Meta-x is also ø
1950 call setline(1, '')
1951 call feedkeys('a' .. a:func('x', 9) .. "\<Esc>", 'Lx!')
1952 call assert_equal("ø", getline(1))
1953
1954 " Alt-X is Ø
1955 call setline(1, '')
1956 call feedkeys('a' .. a:func('X', 3) .. "\<Esc>", 'Lx!')
1957 call assert_equal("Ø", getline(1))
1958
1959 " Meta-X is ø
1960 call setline(1, '')
1961 call feedkeys('a' .. a:func('X', 9) .. "\<Esc>", 'Lx!')
1962 call assert_equal("Ø", getline(1))
1963
Bram Moolenaar828ffd52019-11-21 23:24:00 +01001964 " Ctrl-6 is Ctrl-^
1965 split aaa
1966 edit bbb
1967 call feedkeys(a:func('6', 5), 'Lx!')
1968 call assert_equal("aaa", bufname())
1969 bwipe aaa
1970 bwipe bbb
1971
Bram Moolenaar0684e362020-12-03 19:54:42 +01001972 " Ctrl-V X 33 is 3
1973 call setline(1, '')
1974 call feedkeys("a\<C-V>" .. a:func('X', 2) .. "33\<Esc>", 'Lx!')
1975 call assert_equal("3", getline(1))
1976
1977 " Ctrl-V U 12345 is Unicode 12345
1978 call setline(1, '')
1979 call feedkeys("a\<C-V>" .. a:func('U', 2) .. "12345\<Esc>", 'Lx!')
1980 call assert_equal("\U12345", getline(1))
1981
Bram Moolenaar18a79a62019-10-12 15:36:11 +02001982 bwipe!
1983 set timeoutlen&
1984endfunc
1985
Bram Moolenaar459fd782019-10-13 16:43:39 +02001986func Test_modifyOtherKeys_basic()
Bram Moolenaar18a79a62019-10-12 15:36:11 +02001987 call RunTest_modifyOtherKeys(function('GetEscCodeCSI27'))
Bram Moolenaar18a79a62019-10-12 15:36:11 +02001988 call RunTest_modifyOtherKeys(function('GetEscCodeCSIu'))
1989endfunc
Bram Moolenaard1e2f392019-10-12 18:22:50 +02001990
Bram Moolenaar38571a02019-11-26 14:28:15 +01001991func Test_modifyOtherKeys_no_mapping()
1992 set timeoutlen=10
1993
1994 let @a = 'aaa'
1995 call feedkeys(":let x = '" .. GetEscCodeCSI27('R', 5) .. GetEscCodeCSI27('R', 5) .. "a'\<CR>", 'Lx!')
1996 call assert_equal("let x = 'aaa'", @:)
1997
1998 new
1999 call feedkeys("a" .. GetEscCodeCSI27('R', 5) .. GetEscCodeCSI27('R', 5) .. "a\<Esc>", 'Lx!')
2000 call assert_equal("aaa", getline(1))
2001 bwipe!
2002
2003 new
2004 call feedkeys("axx\<CR>yy" .. GetEscCodeCSI27('G', 5) .. GetEscCodeCSI27('K', 5) .. "a\<Esc>", 'Lx!')
2005 call assert_equal("axx", getline(1))
2006 call assert_equal("yy", getline(2))
2007 bwipe!
2008
2009 set timeoutlen&
2010endfunc
2011
Bram Moolenaard1e2f392019-10-12 18:22:50 +02002012func RunTest_mapping_shift(key, func)
2013 call setline(1, '')
2014 if a:key == '|'
2015 exe 'inoremap \| xyz'
2016 else
2017 exe 'inoremap ' .. a:key .. ' xyz'
2018 endif
2019 call feedkeys('a' .. a:func(a:key, 2) .. "\<Esc>", 'Lx!')
2020 call assert_equal("xyz", getline(1))
2021 if a:key == '|'
2022 exe 'iunmap \|'
2023 else
2024 exe 'iunmap ' .. a:key
2025 endif
2026endfunc
2027
Bram Moolenaar975a8802020-06-06 22:36:24 +02002028func Test_modifyOtherKeys_mapped()
2029 set timeoutlen=10
2030 imap ' <C-W>
2031 imap <C-W><C-A> c-a
2032 call setline(1, '')
2033
2034 " single quote is turned into single byte CTRL-W
2035 " CTRL-A is added with a separate modifier, and needs to be simplified before
2036 " the mapping can match.
2037 call feedkeys("a'" .. GetEscCodeCSI27('A', 5) .. "\<Esc>", 'Lx!')
2038 call assert_equal('c-a', getline(1))
2039
2040 iunmap '
2041 iunmap <C-W><C-A>
2042 set timeoutlen&
2043endfunc
2044
Bram Moolenaar749bc952020-10-31 16:33:47 +01002045" Whether Shift-Tab sends "ESC [ Z" or "ESC [ 27 ; 2 ; 9 ~" is unpredictable,
2046" both should work.
2047func Test_modifyOtherKeys_shift_tab()
2048 set timeoutlen=10
2049
2050 call setline(1, '')
2051 call feedkeys("a\<C-K>" .. GetEscCodeCSI27("\t", '2') .. "\<Esc>", 'Lx!')
2052 eval getline(1)->assert_equal('<S-Tab>')
2053
2054 call setline(1, '')
2055 call feedkeys("a\<C-K>\<Esc>[Z\<Esc>", 'Lx!')
2056 eval getline(1)->assert_equal('<S-Tab>')
2057
2058 set timeoutlen&
2059 bwipe!
2060endfunc
2061
Bram Moolenaard1e2f392019-10-12 18:22:50 +02002062func RunTest_mapping_works_with_shift(func)
2063 new
Bram Moolenaar459fd782019-10-13 16:43:39 +02002064 set timeoutlen=10
Bram Moolenaard1e2f392019-10-12 18:22:50 +02002065
2066 call RunTest_mapping_shift('@', a:func)
2067 call RunTest_mapping_shift('A', a:func)
2068 call RunTest_mapping_shift('Z', a:func)
2069 call RunTest_mapping_shift('^', a:func)
2070 call RunTest_mapping_shift('_', a:func)
2071 call RunTest_mapping_shift('{', a:func)
2072 call RunTest_mapping_shift('|', a:func)
2073 call RunTest_mapping_shift('}', a:func)
2074 call RunTest_mapping_shift('~', a:func)
2075
2076 bwipe!
2077 set timeoutlen&
2078endfunc
2079
Bram Moolenaar459fd782019-10-13 16:43:39 +02002080func Test_mapping_works_with_shift_plain()
Bram Moolenaard1e2f392019-10-12 18:22:50 +02002081 call RunTest_mapping_works_with_shift(function('GetEscCodeCSI27'))
2082 call RunTest_mapping_works_with_shift(function('GetEscCodeCSIu'))
2083endfunc
Bram Moolenaar459fd782019-10-13 16:43:39 +02002084
2085func RunTest_mapping_mods(map, key, func, code)
2086 call setline(1, '')
2087 exe 'inoremap ' .. a:map .. ' xyz'
2088 call feedkeys('a' .. a:func(a:key, a:code) .. "\<Esc>", 'Lx!')
2089 call assert_equal("xyz", getline(1))
2090 exe 'iunmap ' .. a:map
2091endfunc
2092
2093func RunTest_mapping_works_with_mods(func, mods, code)
2094 new
2095 set timeoutlen=10
2096
2097 if a:mods !~ 'S'
2098 " Shift by itself has no effect
2099 call RunTest_mapping_mods('<' .. a:mods .. '-@>', '@', a:func, a:code)
2100 endif
2101 call RunTest_mapping_mods('<' .. a:mods .. '-A>', 'A', a:func, a:code)
2102 call RunTest_mapping_mods('<' .. a:mods .. '-Z>', 'Z', a:func, a:code)
2103 if a:mods !~ 'S'
2104 " with Shift code is always upper case
2105 call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'a', a:func, a:code)
2106 call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'z', a:func, a:code)
2107 endif
2108 if a:mods != 'A'
2109 " with Alt code is not in upper case
2110 call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'A', a:func, a:code)
2111 call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'Z', a:func, a:code)
2112 endif
2113 call RunTest_mapping_mods('<' .. a:mods .. '-á>', 'á', a:func, a:code)
2114 if a:mods !~ 'S'
2115 " Shift by itself has no effect
2116 call RunTest_mapping_mods('<' .. a:mods .. '-^>', '^', a:func, a:code)
2117 call RunTest_mapping_mods('<' .. a:mods .. '-_>', '_', a:func, a:code)
2118 call RunTest_mapping_mods('<' .. a:mods .. '-{>', '{', a:func, a:code)
2119 call RunTest_mapping_mods('<' .. a:mods .. '-\|>', '|', a:func, a:code)
2120 call RunTest_mapping_mods('<' .. a:mods .. '-}>', '}', a:func, a:code)
2121 call RunTest_mapping_mods('<' .. a:mods .. '-~>', '~', a:func, a:code)
2122 endif
2123
2124 bwipe!
2125 set timeoutlen&
2126endfunc
2127
2128func Test_mapping_works_with_shift()
2129 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S', 2)
2130 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S', 2)
2131endfunc
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01002132
Bram Moolenaar459fd782019-10-13 16:43:39 +02002133func Test_mapping_works_with_ctrl()
2134 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C', 5)
2135 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C', 5)
Bram Moolenaar4e2114e2020-10-07 16:12:37 +02002136
2137 new
2138 set timeoutlen=10
2139
2140 " CTRL-@ actually produces the code for CTRL-2, which is converted
2141 call RunTest_mapping_mods('<C-@>', '2', function('GetEscCodeCSI27'), 5)
2142 call RunTest_mapping_mods('<C-@>', '2', function('GetEscCodeCSIu'), 5)
2143
2144 " CTRL-^ actually produces the code for CTRL-6, which is converted
2145 call RunTest_mapping_mods('<C-^>', '6', function('GetEscCodeCSI27'), 5)
2146 call RunTest_mapping_mods('<C-^>', '6', function('GetEscCodeCSIu'), 5)
2147
2148 " CTRL-_ actually produces the code for CTRL--, which is converted
2149 call RunTest_mapping_mods('<C-_>', '-', function('GetEscCodeCSI27'), 5)
2150 call RunTest_mapping_mods('<C-_>', '-', function('GetEscCodeCSIu'), 5)
2151
2152 bwipe!
2153 set timeoutlen&
Bram Moolenaar459fd782019-10-13 16:43:39 +02002154endfunc
2155
2156func Test_mapping_works_with_shift_ctrl()
2157 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S', 6)
2158 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S', 6)
Bram Moolenaar9a033d72020-10-07 17:29:48 +02002159
2160 new
2161 set timeoutlen=10
2162
2163 " Ctrl-Shift-[ actually produces CTRL-Shift-{ which is mapped as <C-{>
2164 call RunTest_mapping_mods('<C-{>', '{', function('GetEscCodeCSI27'), 6)
2165 call RunTest_mapping_mods('<C-{>', '{', function('GetEscCodeCSIu'), 6)
2166
2167 " Ctrl-Shift-] actually produces CTRL-Shift-} which is mapped as <C-}>
2168 call RunTest_mapping_mods('<C-{>', '{', function('GetEscCodeCSI27'), 6)
2169 call RunTest_mapping_mods('<C-{>', '{', function('GetEscCodeCSIu'), 6)
2170
2171 " Ctrl-Shift-\ actually produces CTRL-Shift-| which is mapped as <C-|>
2172 call RunTest_mapping_mods('<C-\|>', '|', function('GetEscCodeCSI27'), 6)
2173 call RunTest_mapping_mods('<C-\|>', '|', function('GetEscCodeCSIu'), 6)
2174
2175 bwipe!
2176 set timeoutlen&
Bram Moolenaar459fd782019-10-13 16:43:39 +02002177endfunc
2178
2179" Below we also test the "u" code with Alt, This works, but libvterm would not
2180" send the Alt key like this but by prefixing an Esc.
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01002181
Bram Moolenaar459fd782019-10-13 16:43:39 +02002182func Test_mapping_works_with_alt()
2183 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'A', 3)
2184 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'A', 3)
2185endfunc
2186
2187func Test_mapping_works_with_shift_alt()
2188 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S-A', 4)
2189 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S-A', 4)
2190endfunc
2191
Bram Moolenaardaff0fb2020-09-27 13:16:46 +02002192func Test_mapping_works_with_alt_and_shift()
2193 new
2194 set timeoutlen=10
2195
2196 " mapping <A-?> works even though the code is A-S-?
2197 for c in ['!', '$', '+', ':', '?', '^', '~']
2198 call RunTest_mapping_mods('<A-' .. c .. '>', c, function('GetEscCodeCSI27'), 4)
2199 call RunTest_mapping_mods('<A-' .. c .. '>', c, function('GetEscCodeCSIu'), 4)
2200 endfor
2201
2202 bwipe!
2203 set timeoutlen&
2204endfunc
2205
Bram Moolenaar459fd782019-10-13 16:43:39 +02002206func Test_mapping_works_with_ctrl_alt()
2207 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-A', 7)
2208 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-A', 7)
2209endfunc
2210
2211func Test_mapping_works_with_shift_ctrl_alt()
2212 call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 8)
2213 call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8)
2214endfunc
Bram Moolenaarfc4ea2a2019-11-26 19:33:22 +01002215
2216func Test_insert_literal()
2217 set timeoutlen=10
2218 new
2219 " CTRL-V CTRL-X inserts a ^X
2220 call feedkeys('a' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
2221 call assert_equal("\<C-X>", getline(1))
2222
2223 call setline(1, '')
2224 call feedkeys('a' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
2225 call assert_equal("\<C-X>", getline(1))
2226
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01002227 " CTRL-SHIFT-V CTRL-X inserts escape sequence
Bram Moolenaarfc4ea2a2019-11-26 19:33:22 +01002228 call setline(1, '')
2229 call feedkeys('a' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
2230 call assert_equal("\<Esc>[88;5u", getline(1))
2231
2232 call setline(1, '')
2233 call feedkeys('a' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
2234 call assert_equal("\<Esc>[27;5;88~", getline(1))
2235
2236 bwipe!
2237 set timeoutlen&
2238endfunc
2239
2240func Test_cmdline_literal()
2241 set timeoutlen=10
2242
2243 " CTRL-V CTRL-Y inserts a ^Y
2244 call feedkeys(':' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2245 call assert_equal("\"\<C-Y>", @:)
2246
2247 call feedkeys(':' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2248 call assert_equal("\"\<C-Y>", @:)
2249
Bram Moolenaarf19f8d12019-12-18 19:36:23 +01002250 " CTRL-SHIFT-V CTRL-Y inserts escape sequence
Bram Moolenaarfc4ea2a2019-11-26 19:33:22 +01002251 call feedkeys(':' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2252 call assert_equal("\"\<Esc>[89;5u", @:)
2253
2254 call setline(1, '')
2255 call feedkeys(':' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2256 call assert_equal("\"\<Esc>[27;5;89~", @:)
2257
2258 set timeoutlen&
2259endfunc
Bram Moolenaar0eabd4d2020-03-15 16:13:53 +01002260
Bram Moolenaar0ff5ded2020-05-07 18:43:44 +02002261" Test for translation of special key codes (<xF1>, <xF2>, etc.)
2262func Test_Keycode_Tranlsation()
2263 let keycodes = [
2264 \ ["<xUp>", "<Up>"],
2265 \ ["<xDown>", "<Down>"],
2266 \ ["<xLeft>", "<Left>"],
2267 \ ["<xRight>", "<Right>"],
2268 \ ["<xHome>", "<Home>"],
2269 \ ["<xEnd>", "<End>"],
2270 \ ["<zHome>", "<Home>"],
2271 \ ["<zEnd>", "<End>"],
2272 \ ["<xF1>", "<F1>"],
2273 \ ["<xF2>", "<F2>"],
2274 \ ["<xF3>", "<F3>"],
2275 \ ["<xF4>", "<F4>"],
2276 \ ["<S-xF1>", "<S-F1>"],
2277 \ ["<S-xF2>", "<S-F2>"],
2278 \ ["<S-xF3>", "<S-F3>"],
2279 \ ["<S-xF4>", "<S-F4>"]]
2280 for [k1, k2] in keycodes
2281 exe "nnoremap " .. k1 .. " 2wx"
2282 call assert_true(maparg(k1, 'n', 0, 1).lhs == k2)
2283 exe "nunmap " .. k1
2284 endfor
2285endfunc
2286
Bram Moolenaar0eabd4d2020-03-15 16:13:53 +01002287" vim: shiftwidth=2 sts=2 expandtab