blob: ba06f36235655ae12300c4194de7ae0539938dbb [file] [log] [blame]
Bram Moolenaarc6df10e2017-07-29 20:15:08 +02001" Tests for the terminal window.
2
Bram Moolenaarea5d6fa2017-08-18 21:07:11 +02003if !has('terminal')
Bram Moolenaarc6df10e2017-07-29 20:15:08 +02004 finish
5endif
6
7source shared.vim
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01008source screendump.vim
Bram Moolenaarc6df10e2017-07-29 20:15:08 +02009
Bram Moolenaarb81bc772017-08-11 22:45:01 +020010let s:python = PythonProg()
11
Bram Moolenaar94053a52017-08-01 21:44:33 +020012" Open a terminal with a shell, assign the job to g:job and return the buffer
13" number.
Bram Moolenaar05aafed2017-08-11 19:12:11 +020014func Run_shell_in_terminal(options)
Bram Moolenaarba6febd2017-10-30 21:56:23 +010015 if has('win32')
16 let buf = term_start([&shell,'/k'], a:options)
17 else
18 let buf = term_start(&shell, a:options)
19 endif
Bram Moolenaarc6df10e2017-07-29 20:15:08 +020020
21 let termlist = term_list()
22 call assert_equal(1, len(termlist))
23 call assert_equal(buf, termlist[0])
24
25 let g:job = term_getjob(buf)
26 call assert_equal(v:t_job, type(g:job))
27
Bram Moolenaar35422f42017-08-05 16:33:56 +020028 let string = string({'job': term_getjob(buf)})
29 call assert_match("{'job': 'process \\d\\+ run'}", string)
30
Bram Moolenaar94053a52017-08-01 21:44:33 +020031 return buf
32endfunc
33
Bram Moolenaar20e6cd02017-08-01 20:25:22 +020034func Test_terminal_basic()
Bram Moolenaar606cb8b2018-05-03 20:40:20 +020035 au TerminalOpen * let b:done = 'yes'
Bram Moolenaar05aafed2017-08-11 19:12:11 +020036 let buf = Run_shell_in_terminal({})
Bram Moolenaarb00fdf62017-09-21 22:16:21 +020037
Bram Moolenaar7c9aec42017-08-03 13:51:25 +020038 if has("unix")
Bram Moolenaar2dc9d262017-09-08 14:39:30 +020039 call assert_match('^/dev/', job_info(g:job).tty_out)
40 call assert_match('^/dev/', term_gettty(''))
Bram Moolenaar7c9aec42017-08-03 13:51:25 +020041 else
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +010042 " ConPTY works on anonymous pipe.
43 if !has('conpty')
44 call assert_match('^\\\\.\\pipe\\', job_info(g:job).tty_out)
45 call assert_match('^\\\\.\\pipe\\', term_gettty(''))
46 endif
Bram Moolenaar7c9aec42017-08-03 13:51:25 +020047 endif
Bram Moolenaar2bb7b6b2017-08-13 20:58:33 +020048 call assert_equal('t', mode())
Bram Moolenaarb00fdf62017-09-21 22:16:21 +020049 call assert_equal('yes', b:done)
Bram Moolenaar2bb7b6b2017-08-13 20:58:33 +020050 call assert_match('%aR[^\n]*running]', execute('ls'))
Bram Moolenaar0751f512018-03-29 16:37:16 +020051 call assert_match('%aR[^\n]*running]', execute('ls R'))
52 call assert_notmatch('%[^\n]*running]', execute('ls F'))
53 call assert_notmatch('%[^\n]*running]', execute('ls ?'))
Bram Moolenaar2bb7b6b2017-08-13 20:58:33 +020054
Bram Moolenaar94053a52017-08-01 21:44:33 +020055 call Stop_shell_in_terminal(buf)
56 call term_wait(buf)
Bram Moolenaar2bb7b6b2017-08-13 20:58:33 +020057 call assert_equal('n', mode())
58 call assert_match('%aF[^\n]*finished]', execute('ls'))
Bram Moolenaar0751f512018-03-29 16:37:16 +020059 call assert_match('%aF[^\n]*finished]', execute('ls F'))
60 call assert_notmatch('%[^\n]*finished]', execute('ls R'))
61 call assert_notmatch('%[^\n]*finished]', execute('ls ?'))
Bram Moolenaar20e6cd02017-08-01 20:25:22 +020062
Bram Moolenaar94053a52017-08-01 21:44:33 +020063 " closing window wipes out the terminal buffer a with finished job
64 close
65 call assert_equal("", bufname(buf))
66
Bram Moolenaar606cb8b2018-05-03 20:40:20 +020067 au! TerminalOpen
Bram Moolenaar20e6cd02017-08-01 20:25:22 +020068 unlet g:job
69endfunc
70
71func Test_terminal_make_change()
Bram Moolenaar05aafed2017-08-11 19:12:11 +020072 let buf = Run_shell_in_terminal({})
Bram Moolenaar94053a52017-08-01 21:44:33 +020073 call Stop_shell_in_terminal(buf)
Bram Moolenaar20e6cd02017-08-01 20:25:22 +020074 call term_wait(buf)
75
76 setlocal modifiable
77 exe "normal Axxx\<Esc>"
78 call assert_fails(buf . 'bwipe', 'E517')
79 undo
80
Bram Moolenaarc6df10e2017-07-29 20:15:08 +020081 exe buf . 'bwipe'
82 unlet g:job
83endfunc
84
Bram Moolenaar94053a52017-08-01 21:44:33 +020085func Test_terminal_wipe_buffer()
Bram Moolenaar05aafed2017-08-11 19:12:11 +020086 let buf = Run_shell_in_terminal({})
Bram Moolenaareb44a682017-08-03 22:44:55 +020087 call assert_fails(buf . 'bwipe', 'E517')
88 exe buf . 'bwipe!'
Bram Moolenaar50182fa2018-04-28 21:34:40 +020089 call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
Bram Moolenaar94053a52017-08-01 21:44:33 +020090 call assert_equal("", bufname(buf))
91
92 unlet g:job
93endfunc
94
Bram Moolenaar8adb0d02017-09-17 19:08:02 +020095func Test_terminal_split_quit()
96 let buf = Run_shell_in_terminal({})
97 call term_wait(buf)
98 split
99 quit!
100 call term_wait(buf)
101 sleep 50m
102 call assert_equal('run', job_status(g:job))
103
104 quit!
Bram Moolenaar50182fa2018-04-28 21:34:40 +0200105 call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
Bram Moolenaar8adb0d02017-09-17 19:08:02 +0200106
107 exe buf . 'bwipe'
108 unlet g:job
109endfunc
110
Bram Moolenaar94053a52017-08-01 21:44:33 +0200111func Test_terminal_hide_buffer()
Bram Moolenaar05aafed2017-08-11 19:12:11 +0200112 let buf = Run_shell_in_terminal({})
Bram Moolenaar97a80e42017-08-30 13:31:49 +0200113 setlocal bufhidden=hide
Bram Moolenaar94053a52017-08-01 21:44:33 +0200114 quit
115 for nr in range(1, winnr('$'))
116 call assert_notequal(winbufnr(nr), buf)
117 endfor
118 call assert_true(bufloaded(buf))
119 call assert_true(buflisted(buf))
120
121 exe 'split ' . buf . 'buf'
122 call Stop_shell_in_terminal(buf)
123 exe buf . 'bwipe'
124
125 unlet g:job
126endfunc
127
Bram Moolenaar1e115362019-01-09 23:01:02 +0100128func s:Nasty_exit_cb(job, st)
Bram Moolenaar3c3a80d2017-08-03 17:06:45 +0200129 exe g:buf . 'bwipe!'
130 let g:buf = 0
131endfunc
132
Bram Moolenaar9d189612017-09-09 18:11:00 +0200133func Get_cat_123_cmd()
134 if has('win32')
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +0100135 if !has('conpty')
136 return 'cmd /c "cls && color 2 && echo 123"'
137 else
138 " When clearing twice, extra sequence is not output.
139 return 'cmd /c "cls && cls && color 2 && echo 123"'
140 endif
Bram Moolenaar9d189612017-09-09 18:11:00 +0200141 else
142 call writefile(["\<Esc>[32m123"], 'Xtext')
143 return "cat Xtext"
144 endif
145endfunc
146
Bram Moolenaar3c3a80d2017-08-03 17:06:45 +0200147func Test_terminal_nasty_cb()
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200148 let cmd = Get_cat_123_cmd()
Bram Moolenaar3c3a80d2017-08-03 17:06:45 +0200149 let g:buf = term_start(cmd, {'exit_cb': function('s:Nasty_exit_cb')})
150 let g:job = term_getjob(g:buf)
151
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200152 call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
153 call WaitForAssert({-> assert_equal(0, g:buf)})
Bram Moolenaar3c3a80d2017-08-03 17:06:45 +0200154 unlet g:job
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +0100155 unlet g:buf
Bram Moolenaar3c3a80d2017-08-03 17:06:45 +0200156 call delete('Xtext')
157endfunc
158
Bram Moolenaarc6df10e2017-07-29 20:15:08 +0200159func Check_123(buf)
Bram Moolenaar5c838a32017-08-02 22:10:34 +0200160 let l = term_scrape(a:buf, 0)
161 call assert_true(len(l) == 0)
162 let l = term_scrape(a:buf, 999)
163 call assert_true(len(l) == 0)
Bram Moolenaar9c844842017-08-01 18:41:21 +0200164 let l = term_scrape(a:buf, 1)
Bram Moolenaarc6df10e2017-07-29 20:15:08 +0200165 call assert_true(len(l) > 0)
166 call assert_equal('1', l[0].chars)
167 call assert_equal('2', l[1].chars)
168 call assert_equal('3', l[2].chars)
169 call assert_equal('#00e000', l[0].fg)
Bram Moolenaar81df6352018-12-22 18:25:30 +0100170 if has('win32')
171 " On Windows 'background' always defaults to dark, even though the terminal
172 " may use a light background. Therefore accept both white and black.
173 call assert_match('#ffffff\|#000000', l[0].bg)
Bram Moolenaarc6df10e2017-07-29 20:15:08 +0200174 else
Bram Moolenaar81df6352018-12-22 18:25:30 +0100175 if &background == 'light'
176 call assert_equal('#ffffff', l[0].bg)
177 else
178 call assert_equal('#000000', l[0].bg)
179 endif
Bram Moolenaarc6df10e2017-07-29 20:15:08 +0200180 endif
181
Bram Moolenaar5c838a32017-08-02 22:10:34 +0200182 let l = term_getline(a:buf, -1)
183 call assert_equal('', l)
184 let l = term_getline(a:buf, 0)
185 call assert_equal('', l)
186 let l = term_getline(a:buf, 999)
187 call assert_equal('', l)
Bram Moolenaar9c844842017-08-01 18:41:21 +0200188 let l = term_getline(a:buf, 1)
Bram Moolenaarc6df10e2017-07-29 20:15:08 +0200189 call assert_equal('123', l)
190endfunc
191
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200192func Test_terminal_scrape_123()
193 let cmd = Get_cat_123_cmd()
Bram Moolenaarc6df10e2017-07-29 20:15:08 +0200194 let buf = term_start(cmd)
195
196 let termlist = term_list()
197 call assert_equal(1, len(termlist))
198 call assert_equal(buf, termlist[0])
199
Bram Moolenaarf144a3f2017-07-30 18:02:12 +0200200 " Nothing happens with invalid buffer number
201 call term_wait(1234)
202
Bram Moolenaarc6df10e2017-07-29 20:15:08 +0200203 call term_wait(buf)
Bram Moolenaar17833372017-09-04 22:23:19 +0200204 " On MS-Windows we first get a startup message of two lines, wait for the
Bram Moolenaar1bfdc072017-09-05 20:19:42 +0200205 " "cls" to happen, after that we have one line with three characters.
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200206 call WaitForAssert({-> assert_equal(3, len(term_scrape(buf, 1)))})
Bram Moolenaarc6df10e2017-07-29 20:15:08 +0200207 call Check_123(buf)
208
209 " Must still work after the job ended.
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100210 let job = term_getjob(buf)
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200211 call WaitForAssert({-> assert_equal("dead", job_status(job))})
Bram Moolenaarc6df10e2017-07-29 20:15:08 +0200212 call term_wait(buf)
213 call Check_123(buf)
214
215 exe buf . 'bwipe'
Bram Moolenaarf144a3f2017-07-30 18:02:12 +0200216 call delete('Xtext')
Bram Moolenaarc6df10e2017-07-29 20:15:08 +0200217endfunc
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200218
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200219func Test_terminal_scrape_multibyte()
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200220 call writefile(["léttまrs"], 'Xtext')
221 if has('win32')
Bram Moolenaar36783932017-08-14 23:07:30 +0200222 " Run cmd with UTF-8 codepage to make the type command print the expected
223 " multibyte characters.
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100224 let buf = term_start("cmd /K chcp 65001")
225 call term_sendkeys(buf, "type Xtext\<CR>")
226 call term_sendkeys(buf, "exit\<CR>")
227 let line = 4
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200228 else
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100229 let buf = term_start("cat Xtext")
230 let line = 1
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200231 endif
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200232
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100233 call WaitFor({-> len(term_scrape(buf, line)) >= 7 && term_scrape(buf, line)[0].chars == "l"})
234 let l = term_scrape(buf, line)
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200235 call assert_true(len(l) >= 7)
236 call assert_equal('l', l[0].chars)
237 call assert_equal('é', l[1].chars)
238 call assert_equal(1, l[1].width)
239 call assert_equal('t', l[2].chars)
240 call assert_equal('t', l[3].chars)
241 call assert_equal('ま', l[4].chars)
242 call assert_equal(2, l[4].width)
243 call assert_equal('r', l[5].chars)
244 call assert_equal('s', l[6].chars)
245
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100246 let job = term_getjob(buf)
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200247 call WaitForAssert({-> assert_equal("dead", job_status(job))})
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100248 call term_wait(buf)
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200249
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100250 exe buf . 'bwipe'
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200251 call delete('Xtext')
252endfunc
253
Bram Moolenaarf8d57a52017-08-07 20:38:42 +0200254func Test_terminal_scroll()
255 call writefile(range(1, 200), 'Xtext')
256 if has('win32')
257 let cmd = 'cmd /c "type Xtext"'
258 else
259 let cmd = "cat Xtext"
260 endif
261 let buf = term_start(cmd)
262
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100263 let job = term_getjob(buf)
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200264 call WaitForAssert({-> assert_equal("dead", job_status(job))})
Bram Moolenaarf8d57a52017-08-07 20:38:42 +0200265 call term_wait(buf)
266 if has('win32')
267 " TODO: this should not be needed
268 sleep 100m
269 endif
270
Bram Moolenaar82b9ca02017-08-08 23:06:46 +0200271 let scrolled = term_getscrolled(buf)
Bram Moolenaarf8d57a52017-08-07 20:38:42 +0200272 call assert_equal('1', getline(1))
Bram Moolenaar82b9ca02017-08-08 23:06:46 +0200273 call assert_equal('1', term_getline(buf, 1 - scrolled))
Bram Moolenaarf8d57a52017-08-07 20:38:42 +0200274 call assert_equal('49', getline(49))
Bram Moolenaar82b9ca02017-08-08 23:06:46 +0200275 call assert_equal('49', term_getline(buf, 49 - scrolled))
Bram Moolenaarf8d57a52017-08-07 20:38:42 +0200276 call assert_equal('200', getline(200))
Bram Moolenaar82b9ca02017-08-08 23:06:46 +0200277 call assert_equal('200', term_getline(buf, 200 - scrolled))
Bram Moolenaarf8d57a52017-08-07 20:38:42 +0200278
279 exe buf . 'bwipe'
280 call delete('Xtext')
281endfunc
282
Bram Moolenaar6e72cd02018-04-14 21:31:35 +0200283func Test_terminal_scrollback()
Bram Moolenaar33c5e9f2018-05-26 18:58:51 +0200284 let buf = Run_shell_in_terminal({'term_rows': 15})
Bram Moolenaar6d150f72018-04-21 20:03:20 +0200285 set termwinscroll=100
Bram Moolenaar6e72cd02018-04-14 21:31:35 +0200286 call writefile(range(150), 'Xtext')
287 if has('win32')
288 call term_sendkeys(buf, "type Xtext\<CR>")
289 else
290 call term_sendkeys(buf, "cat Xtext\<CR>")
291 endif
292 let rows = term_getsize(buf)[0]
Bram Moolenaar6c672192018-04-15 13:28:42 +0200293 " On MS-Windows there is an empty line, check both last line and above it.
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200294 call WaitForAssert({-> assert_match( '149', term_getline(buf, rows - 1) . term_getline(buf, rows - 2))})
Bram Moolenaar6e72cd02018-04-14 21:31:35 +0200295 let lines = line('$')
Bram Moolenaarac3e8302018-04-15 13:10:44 +0200296 call assert_inrange(91, 100, lines)
Bram Moolenaar6e72cd02018-04-14 21:31:35 +0200297
298 call Stop_shell_in_terminal(buf)
299 call term_wait(buf)
300 exe buf . 'bwipe'
Bram Moolenaar6d150f72018-04-21 20:03:20 +0200301 set termwinscroll&
Bram Moolenaar29ae2232019-02-14 21:22:01 +0100302 call delete('Xtext')
303endfunc
304
305func Test_terminal_postponed_scrollback()
306 if !has('unix')
307 " tail -f only works on Unix
308 return
309 endif
310
311 call writefile(range(50), 'Xtext')
312 call writefile([
313 \ 'terminal',
314 \ 'call feedkeys("tail -n 100 -f Xtext\<CR>", "xt")',
315 \ 'sleep 100m',
316 \ 'call feedkeys("\<C-W>N", "xt")',
317 \ ], 'XTest_postponed')
318 let buf = RunVimInTerminal('-S XTest_postponed', {})
319 " Check that the Xtext lines are displayed and in Terminal-Normal mode
Bram Moolenaar81aa0f52019-02-14 23:23:19 +0100320 call term_wait(buf)
321 " TODO: this sometimes fails
322 "call VerifyScreenDump(buf, 'Test_terminal_01', {})
Bram Moolenaar29ae2232019-02-14 21:22:01 +0100323
324 silent !echo 'one more line' >>Xtext
325 " Sceen will not change, move cursor to get a different dump
326 call term_sendkeys(buf, "k")
Bram Moolenaar81aa0f52019-02-14 23:23:19 +0100327 call term_wait(buf)
328 " TODO: this sometimes fails
329 "call VerifyScreenDump(buf, 'Test_terminal_02', {})
Bram Moolenaar29ae2232019-02-14 21:22:01 +0100330
331 " Back to Terminal-Job mode, text will scroll and show the extra line.
332 call term_sendkeys(buf, "a")
Bram Moolenaar81aa0f52019-02-14 23:23:19 +0100333 call term_wait(buf)
334 " TODO: this sometimes fails
335 "call VerifyScreenDump(buf, 'Test_terminal_03', {})
Bram Moolenaar29ae2232019-02-14 21:22:01 +0100336
337 call term_wait(buf)
338 call term_sendkeys(buf, "\<C-C>")
339 call term_wait(buf)
340 call term_sendkeys(buf, "exit\<CR>")
341 call term_wait(buf)
342 call term_sendkeys(buf, ":q\<CR>")
343 call StopVimInTerminal(buf)
344 call delete('XTest_postponed')
345 call delete('Xtext')
Bram Moolenaar6e72cd02018-04-14 21:31:35 +0200346endfunc
347
Bram Moolenaar81aa0f52019-02-14 23:23:19 +0100348" Run diff on two dumps with different size.
349func Test_terminal_dumpdiff_size()
350 call assert_equal(1, winnr('$'))
351 call term_dumpdiff('dumps/Test_incsearch_search_01.dump', 'dumps/Test_popup_command_01.dump')
352 call assert_equal(2, winnr('$'))
353 call assert_match('Test_incsearch_search_01.dump', getline(10))
354 call assert_match(' +++++$', getline(11))
355 call assert_match('Test_popup_command_01.dump', getline(31))
356 call assert_equal(repeat('+', 75), getline(30))
357 quit
358endfunc
359
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200360func Test_terminal_size()
Bram Moolenaar33a43be2017-08-06 21:36:22 +0200361 let cmd = Get_cat_123_cmd()
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200362
Bram Moolenaarb2412082017-08-20 18:09:14 +0200363 exe 'terminal ++rows=5 ' . cmd
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200364 let size = term_getsize('')
365 bwipe!
366 call assert_equal(5, size[0])
367
Bram Moolenaar08d384f2017-08-11 21:51:23 +0200368 call term_start(cmd, {'term_rows': 6})
369 let size = term_getsize('')
370 bwipe!
371 call assert_equal(6, size[0])
372
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200373 vsplit
Bram Moolenaarb2412082017-08-20 18:09:14 +0200374 exe 'terminal ++rows=5 ++cols=33 ' . cmd
Bram Moolenaara42d3632018-04-14 17:05:38 +0200375 call assert_equal([5, 33], term_getsize(''))
376
377 call term_setsize('', 6, 0)
378 call assert_equal([6, 33], term_getsize(''))
379
380 call term_setsize('', 0, 35)
381 call assert_equal([6, 35], term_getsize(''))
382
383 call term_setsize('', 7, 30)
384 call assert_equal([7, 30], term_getsize(''))
385
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200386 bwipe!
Bram Moolenaar6e72cd02018-04-14 21:31:35 +0200387 call assert_fails("call term_setsize('', 7, 30)", "E955:")
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200388
Bram Moolenaar08d384f2017-08-11 21:51:23 +0200389 call term_start(cmd, {'term_rows': 6, 'term_cols': 36})
390 let size = term_getsize('')
391 bwipe!
392 call assert_equal([6, 36], size)
393
Bram Moolenaarb2412082017-08-20 18:09:14 +0200394 exe 'vertical terminal ++cols=20 ' . cmd
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200395 let size = term_getsize('')
396 bwipe!
397 call assert_equal(20, size[1])
398
Bram Moolenaar08d384f2017-08-11 21:51:23 +0200399 call term_start(cmd, {'vertical': 1, 'term_cols': 26})
400 let size = term_getsize('')
401 bwipe!
402 call assert_equal(26, size[1])
403
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200404 split
Bram Moolenaarb2412082017-08-20 18:09:14 +0200405 exe 'vertical terminal ++rows=6 ++cols=20 ' . cmd
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200406 let size = term_getsize('')
407 bwipe!
408 call assert_equal([6, 20], size)
Bram Moolenaar08d384f2017-08-11 21:51:23 +0200409
410 call term_start(cmd, {'vertical': 1, 'term_rows': 7, 'term_cols': 27})
411 let size = term_getsize('')
412 bwipe!
413 call assert_equal([7, 27], size)
Bram Moolenaar9d654a82017-09-03 19:52:17 +0200414
415 call delete('Xtext')
Bram Moolenaarda43b612017-08-11 22:27:50 +0200416endfunc
417
418func Test_terminal_curwin()
419 let cmd = Get_cat_123_cmd()
420 call assert_equal(1, winnr('$'))
421
422 split dummy
423 exe 'terminal ++curwin ' . cmd
424 call assert_equal(2, winnr('$'))
425 bwipe!
426
427 split dummy
428 call term_start(cmd, {'curwin': 1})
429 call assert_equal(2, winnr('$'))
430 bwipe!
431
432 split dummy
433 call setline(1, 'change')
434 call assert_fails('terminal ++curwin ' . cmd, 'E37:')
435 call assert_equal(2, winnr('$'))
436 exe 'terminal! ++curwin ' . cmd
437 call assert_equal(2, winnr('$'))
438 bwipe!
439
440 split dummy
441 call setline(1, 'change')
442 call assert_fails("call term_start(cmd, {'curwin': 1})", 'E37:')
443 call assert_equal(2, winnr('$'))
444 bwipe!
445
446 split dummy
447 bwipe!
Bram Moolenaar9d654a82017-09-03 19:52:17 +0200448 call delete('Xtext')
Bram Moolenaarcfcc0222017-08-05 17:13:48 +0200449endfunc
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200450
Bram Moolenaarff546792017-11-21 14:47:57 +0100451func s:get_sleep_cmd()
Bram Moolenaarb81bc772017-08-11 22:45:01 +0200452 if s:python != ''
453 let cmd = s:python . " test_short_sleep.py"
Bram Moolenaarc8523e22018-06-03 18:22:02 +0200454 " 500 was not enough for Travis
455 let waittime = 900
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200456 else
Bram Moolenaarb81bc772017-08-11 22:45:01 +0200457 echo 'This will take five seconds...'
458 let waittime = 2000
459 if has('win32')
460 let cmd = $windir . '\system32\timeout.exe 1'
461 else
462 let cmd = 'sleep 1'
463 endif
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200464 endif
Bram Moolenaarff546792017-11-21 14:47:57 +0100465 return [cmd, waittime]
466endfunc
467
468func Test_terminal_finish_open_close()
469 call assert_equal(1, winnr('$'))
470
471 let [cmd, waittime] = s:get_sleep_cmd()
Bram Moolenaarb81bc772017-08-11 22:45:01 +0200472
Bram Moolenaar1dd98332018-03-16 22:54:53 +0100473 " shell terminal closes automatically
474 terminal
475 let buf = bufnr('%')
476 call assert_equal(2, winnr('$'))
477 " Wait for the shell to display a prompt
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200478 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
Bram Moolenaar1dd98332018-03-16 22:54:53 +0100479 call Stop_shell_in_terminal(buf)
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200480 call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime)
Bram Moolenaar1dd98332018-03-16 22:54:53 +0100481
482 " shell terminal that does not close automatically
483 terminal ++noclose
484 let buf = bufnr('%')
485 call assert_equal(2, winnr('$'))
486 " Wait for the shell to display a prompt
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200487 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
Bram Moolenaar1dd98332018-03-16 22:54:53 +0100488 call Stop_shell_in_terminal(buf)
489 call assert_equal(2, winnr('$'))
490 quit
491 call assert_equal(1, winnr('$'))
492
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200493 exe 'terminal ++close ' . cmd
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200494 call assert_equal(2, winnr('$'))
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200495 wincmd p
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200496 call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime)
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200497
498 call term_start(cmd, {'term_finish': 'close'})
499 call assert_equal(2, winnr('$'))
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200500 wincmd p
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200501 call WaitForAssert({-> assert_equal(1, winnr('$'))}, waittime)
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200502 call assert_equal(1, winnr('$'))
503
504 exe 'terminal ++open ' . cmd
Bram Moolenaar97a80e42017-08-30 13:31:49 +0200505 close!
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200506 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200507 bwipe
508
509 call term_start(cmd, {'term_finish': 'open'})
Bram Moolenaar97a80e42017-08-30 13:31:49 +0200510 close!
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200511 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
Bram Moolenaar8cad9302017-08-12 14:32:32 +0200512 bwipe
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200513
Bram Moolenaar8cad9302017-08-12 14:32:32 +0200514 exe 'terminal ++hidden ++open ' . cmd
515 call assert_equal(1, winnr('$'))
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200516 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
Bram Moolenaar8cad9302017-08-12 14:32:32 +0200517 bwipe
518
519 call term_start(cmd, {'term_finish': 'open', 'hidden': 1})
520 call assert_equal(1, winnr('$'))
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200521 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200522 bwipe
Bram Moolenaar37c45832017-08-12 16:01:04 +0200523
524 call assert_fails("call term_start(cmd, {'term_opencmd': 'open'})", 'E475:')
525 call assert_fails("call term_start(cmd, {'term_opencmd': 'split %x'})", 'E475:')
526 call assert_fails("call term_start(cmd, {'term_opencmd': 'split %d and %s'})", 'E475:')
527 call assert_fails("call term_start(cmd, {'term_opencmd': 'split % and %d'})", 'E475:')
528
529 call term_start(cmd, {'term_finish': 'open', 'term_opencmd': '4split | buffer %d'})
Bram Moolenaar97a80e42017-08-30 13:31:49 +0200530 close!
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200531 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
Bram Moolenaar37c45832017-08-12 16:01:04 +0200532 call assert_equal(4, winheight(0))
533 bwipe
Bram Moolenaardd693ce2017-08-10 23:15:19 +0200534endfunc
Bram Moolenaar05aafed2017-08-11 19:12:11 +0200535
536func Test_terminal_cwd()
Bram Moolenaare9f6fd22017-09-10 14:25:49 +0200537 if !executable('pwd')
Bram Moolenaar05aafed2017-08-11 19:12:11 +0200538 return
539 endif
540 call mkdir('Xdir')
541 let buf = term_start('pwd', {'cwd': 'Xdir'})
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200542 call WaitForAssert({-> assert_equal('Xdir', fnamemodify(getline(1), ":t"))})
Bram Moolenaar05aafed2017-08-11 19:12:11 +0200543
544 exe buf . 'bwipe'
545 call delete('Xdir', 'rf')
546endfunc
547
Bram Moolenaar839e81e2018-10-19 16:53:39 +0200548func Test_terminal_cwd_failure()
549 " Case 1: Provided directory is not actually a directory. Attempt to make
550 " the file executable as well.
551 call writefile([], 'Xfile')
552 call setfperm('Xfile', 'rwx------')
553 call assert_fails("call term_start(&shell, {'cwd': 'Xfile'})", 'E475:')
554 call delete('Xfile')
555
556 " Case 2: Directory does not exist.
557 call assert_fails("call term_start(&shell, {'cwd': 'Xdir'})", 'E475:')
558
559 " Case 3: Directory exists but is not accessible.
Bram Moolenaar0b38f542018-11-03 21:47:16 +0100560 " Skip this for root, it will be accessible anyway.
561 if $USER != 'root'
562 call mkdir('XdirNoAccess', '', '0600')
563 " return early if the directory permissions could not be set properly
564 if getfperm('XdirNoAccess')[2] == 'x'
565 call delete('XdirNoAccess', 'rf')
566 return
567 endif
568 call assert_fails("call term_start(&shell, {'cwd': 'XdirNoAccess'})", 'E475:')
569 call delete('XdirNoAccess', 'rf')
Bram Moolenaar839e81e2018-10-19 16:53:39 +0200570 endif
Bram Moolenaar839e81e2018-10-19 16:53:39 +0200571endfunc
572
Bram Moolenaar52dbb5e2017-11-21 18:11:27 +0100573func Test_terminal_servername()
574 if !has('clientserver')
575 return
576 endif
Bram Moolenaard7a137f2018-06-12 18:05:24 +0200577 call s:test_environment("VIM_SERVERNAME", v:servername)
578endfunc
579
580func Test_terminal_version()
581 call s:test_environment("VIM_TERMINAL", string(v:version))
582endfunc
583
584func s:test_environment(name, value)
Bram Moolenaar012eb662018-03-13 17:55:27 +0100585 let buf = Run_shell_in_terminal({})
Bram Moolenaar52dbb5e2017-11-21 18:11:27 +0100586 " Wait for the shell to display a prompt
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200587 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
Bram Moolenaar52dbb5e2017-11-21 18:11:27 +0100588 if has('win32')
Bram Moolenaard7a137f2018-06-12 18:05:24 +0200589 call term_sendkeys(buf, "echo %" . a:name . "%\r")
Bram Moolenaar52dbb5e2017-11-21 18:11:27 +0100590 else
Bram Moolenaard7a137f2018-06-12 18:05:24 +0200591 call term_sendkeys(buf, "echo $" . a:name . "\r")
Bram Moolenaar52dbb5e2017-11-21 18:11:27 +0100592 endif
Bram Moolenaar012eb662018-03-13 17:55:27 +0100593 call term_wait(buf)
594 call Stop_shell_in_terminal(buf)
Bram Moolenaard7a137f2018-06-12 18:05:24 +0200595 call WaitForAssert({-> assert_equal(a:value, getline(2))})
Bram Moolenaar52dbb5e2017-11-21 18:11:27 +0100596
Bram Moolenaar012eb662018-03-13 17:55:27 +0100597 exe buf . 'bwipe'
598 unlet buf
Bram Moolenaar52dbb5e2017-11-21 18:11:27 +0100599endfunc
600
Bram Moolenaar05aafed2017-08-11 19:12:11 +0200601func Test_terminal_env()
Bram Moolenaar012eb662018-03-13 17:55:27 +0100602 let buf = Run_shell_in_terminal({'env': {'TESTENV': 'correct'}})
Bram Moolenaar51c23682017-08-14 21:45:00 +0200603 " Wait for the shell to display a prompt
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200604 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
Bram Moolenaarba6febd2017-10-30 21:56:23 +0100605 if has('win32')
Bram Moolenaar012eb662018-03-13 17:55:27 +0100606 call term_sendkeys(buf, "echo %TESTENV%\r")
Bram Moolenaarba6febd2017-10-30 21:56:23 +0100607 else
Bram Moolenaar012eb662018-03-13 17:55:27 +0100608 call term_sendkeys(buf, "echo $TESTENV\r")
Bram Moolenaarba6febd2017-10-30 21:56:23 +0100609 endif
Bram Moolenaar012eb662018-03-13 17:55:27 +0100610 call term_wait(buf)
611 call Stop_shell_in_terminal(buf)
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200612 call WaitForAssert({-> assert_equal('correct', getline(2))})
Bram Moolenaar05aafed2017-08-11 19:12:11 +0200613
Bram Moolenaar012eb662018-03-13 17:55:27 +0100614 exe buf . 'bwipe'
Bram Moolenaar05aafed2017-08-11 19:12:11 +0200615endfunc
Bram Moolenaar679653e2017-08-13 14:13:19 +0200616
Bram Moolenaardcaa6132017-08-13 17:13:09 +0200617func Test_terminal_list_args()
618 let buf = term_start([&shell, &shellcmdflag, 'echo "123"'])
619 call assert_fails(buf . 'bwipe', 'E517')
620 exe buf . 'bwipe!'
621 call assert_equal("", bufname(buf))
622endfunction
Bram Moolenaar97bd5e62017-08-18 20:50:30 +0200623
624func Test_terminal_noblock()
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100625 let buf = term_start(&shell)
Bram Moolenaar39536dd2019-01-29 22:58:21 +0100626 if has('bsd') || has('mac') || has('sun')
Bram Moolenaard8d85bf2017-09-03 18:08:00 +0200627 " The shell or something else has a problem dealing with more than 1000
628 " characters at the same time.
629 let len = 1000
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +0100630 " NPFS is used in Windows, nonblocking mode does not work properly.
631 elseif has('win32')
632 let len = 1
Bram Moolenaard8d85bf2017-09-03 18:08:00 +0200633 else
634 let len = 5000
635 endif
Bram Moolenaar97bd5e62017-08-18 20:50:30 +0200636
637 for c in ['a','b','c','d','e','f','g','h','i','j','k']
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100638 call term_sendkeys(buf, 'echo ' . repeat(c, len) . "\<cr>")
Bram Moolenaar97bd5e62017-08-18 20:50:30 +0200639 endfor
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100640 call term_sendkeys(buf, "echo done\<cr>")
Bram Moolenaareef05312017-08-20 20:21:23 +0200641
642 " On MS-Windows there is an extra empty line below "done". Find "done" in
643 " the last-but-one or the last-but-two line.
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100644 let lnum = term_getsize(buf)[0] - 1
Bram Moolenaar21810142018-02-02 18:30:36 +0100645 call WaitFor({-> term_getline(buf, lnum) =~ "done" || term_getline(buf, lnum - 1) =~ "done"}, 10000)
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100646 let line = term_getline(buf, lnum)
Bram Moolenaareef05312017-08-20 20:21:23 +0200647 if line !~ 'done'
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100648 let line = term_getline(buf, lnum - 1)
Bram Moolenaareef05312017-08-20 20:21:23 +0200649 endif
650 call assert_match('done', line)
Bram Moolenaar97bd5e62017-08-18 20:50:30 +0200651
Bram Moolenaarab8b1c12017-11-04 19:24:31 +0100652 let g:job = term_getjob(buf)
653 call Stop_shell_in_terminal(buf)
654 call term_wait(buf)
Bram Moolenaard21f8b52017-08-19 15:40:01 +0200655 unlet g:job
Bram Moolenaar97bd5e62017-08-18 20:50:30 +0200656 bwipe
657endfunc
Bram Moolenaar37819ed2017-08-20 19:33:47 +0200658
659func Test_terminal_write_stdin()
Bram Moolenaar3346cc42017-09-02 14:54:21 +0200660 if !executable('wc')
Bram Moolenaardada6d22017-09-02 17:18:35 +0200661 throw 'skipped: wc command not available'
Bram Moolenaar37819ed2017-08-20 19:33:47 +0200662 endif
Bram Moolenaar1580f752018-06-03 15:26:36 +0200663 if has('win32')
664 " TODO: enable once writing to stdin works on MS-Windows
665 return
666 endif
Bram Moolenaar37819ed2017-08-20 19:33:47 +0200667 new
668 call setline(1, ['one', 'two', 'three'])
669 %term wc
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200670 call WaitForAssert({-> assert_match('3', getline("$"))})
Bram Moolenaar3346cc42017-09-02 14:54:21 +0200671 let nrs = split(getline('$'))
Bram Moolenaar37819ed2017-08-20 19:33:47 +0200672 call assert_equal(['3', '3', '14'], nrs)
673 bwipe
674
Bram Moolenaardada6d22017-09-02 17:18:35 +0200675 new
Bram Moolenaar37819ed2017-08-20 19:33:47 +0200676 call setline(1, ['one', 'two', 'three', 'four'])
677 2,3term wc
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200678 call WaitForAssert({-> assert_match('2', getline("$"))})
Bram Moolenaar3346cc42017-09-02 14:54:21 +0200679 let nrs = split(getline('$'))
Bram Moolenaar37819ed2017-08-20 19:33:47 +0200680 call assert_equal(['2', '2', '10'], nrs)
681 bwipe
682
Bram Moolenaardada6d22017-09-02 17:18:35 +0200683 if executable('python')
684 new
685 call setline(1, ['print("hello")'])
686 1term ++eof=exit() python
687 " MS-Windows echoes the input, Unix doesn't.
688 call WaitFor('getline("$") =~ "exit" || getline(1) =~ "hello"')
689 if getline(1) =~ 'hello'
690 call assert_equal('hello', getline(1))
691 else
692 call assert_equal('hello', getline(line('$') - 1))
693 endif
694 bwipe
695
696 if has('win32')
697 new
698 call setline(1, ['print("hello")'])
699 1term ++eof=<C-Z> python
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200700 call WaitForAssert({-> assert_match('Z', getline("$"))})
Bram Moolenaardada6d22017-09-02 17:18:35 +0200701 call assert_equal('hello', getline(line('$') - 1))
702 bwipe
703 endif
704 endif
705
Bram Moolenaar37819ed2017-08-20 19:33:47 +0200706 bwipe!
707endfunc
Bram Moolenaar13ebb032017-08-26 22:02:51 +0200708
709func Test_terminal_no_cmd()
Bram Moolenaar13ebb032017-08-26 22:02:51 +0200710 let buf = term_start('NONE', {})
711 call assert_notequal(0, buf)
712
Bram Moolenaar2dc9d262017-09-08 14:39:30 +0200713 let pty = job_info(term_getjob(buf))['tty_out']
Bram Moolenaar13ebb032017-08-26 22:02:51 +0200714 call assert_notequal('', pty)
Bram Moolenaarcfc15232019-01-23 22:33:18 +0100715 if has('gui_running') && !has('win32')
716 " In the GUI job_start() doesn't work, it does not read from the pty.
Bram Moolenaar2dc9d262017-09-08 14:39:30 +0200717 call system('echo "look here" > ' . pty)
Bram Moolenaarcfc15232019-01-23 22:33:18 +0100718 else
719 " Otherwise using a job works on all systems.
720 call job_start([&shell, &shellcmdflag, 'echo "look here" > ' . pty])
Bram Moolenaar2dc9d262017-09-08 14:39:30 +0200721 endif
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200722 call WaitForAssert({-> assert_match('look here', term_getline(buf, 1))})
Bram Moolenaar2dc9d262017-09-08 14:39:30 +0200723
Bram Moolenaar13ebb032017-08-26 22:02:51 +0200724 bwipe!
725endfunc
Bram Moolenaar9d654a82017-09-03 19:52:17 +0200726
727func Test_terminal_special_chars()
728 " this file name only works on Unix
729 if !has('unix')
730 return
731 endif
732 call mkdir('Xdir with spaces')
733 call writefile(['x'], 'Xdir with spaces/quoted"file')
734 term ls Xdir\ with\ spaces/quoted\"file
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200735 call WaitForAssert({-> assert_match('quoted"file', term_getline('', 1))})
Bram Moolenaar9d654a82017-09-03 19:52:17 +0200736 call term_wait('')
737
738 call delete('Xdir with spaces', 'rf')
739 bwipe
740endfunc
Bram Moolenaare88fc7a2017-09-03 20:59:40 +0200741
742func Test_terminal_wrong_options()
743 call assert_fails('call term_start(&shell, {
744 \ "in_io": "file",
745 \ "in_name": "xxx",
746 \ "out_io": "file",
747 \ "out_name": "xxx",
748 \ "err_io": "file",
749 \ "err_name": "xxx"
750 \ })', 'E474:')
751 call assert_fails('call term_start(&shell, {
752 \ "out_buf": bufnr("%")
753 \ })', 'E474:')
754 call assert_fails('call term_start(&shell, {
755 \ "err_buf": bufnr("%")
756 \ })', 'E474:')
757endfunc
758
759func Test_terminal_redir_file()
Bram Moolenaarf25329c2018-05-06 21:49:32 +0200760 let cmd = Get_cat_123_cmd()
761 let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'})
762 call term_wait(buf)
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +0100763 " ConPTY may precede escape sequence. There are things that are not so.
764 if !has('conpty')
765 call WaitForAssert({-> assert_notequal(0, len(readfile("Xfile")))})
766 call assert_match('123', readfile('Xfile')[0])
767 endif
Bram Moolenaarf25329c2018-05-06 21:49:32 +0200768 let g:job = term_getjob(buf)
769 call WaitForAssert({-> assert_equal("dead", job_status(g:job))})
770 call delete('Xfile')
771 bwipe
Bram Moolenaare88fc7a2017-09-03 20:59:40 +0200772
773 if has('unix')
Bram Moolenaare88fc7a2017-09-03 20:59:40 +0200774 call writefile(['one line'], 'Xfile')
775 let buf = term_start('cat', {'in_io': 'file', 'in_name': 'Xfile'})
776 call term_wait(buf)
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200777 call WaitForAssert({-> assert_equal('one line', term_getline(buf, 1))})
Bram Moolenaar8b53b792017-09-05 20:29:25 +0200778 let g:job = term_getjob(buf)
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200779 call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
Bram Moolenaare88fc7a2017-09-03 20:59:40 +0200780 bwipe
781 call delete('Xfile')
782 endif
783endfunc
Bram Moolenaar69fbc9e2017-09-14 20:37:57 +0200784
785func TerminalTmap(remap)
786 let buf = Run_shell_in_terminal({})
787 call assert_equal('t', mode())
788
789 if a:remap
790 tmap 123 456
791 else
792 tnoremap 123 456
793 endif
Bram Moolenaar461fe502017-12-05 12:30:03 +0100794 " don't use abcde, it's an existing command
795 tmap 456 abxde
Bram Moolenaar69fbc9e2017-09-14 20:37:57 +0200796 call assert_equal('456', maparg('123', 't'))
Bram Moolenaar461fe502017-12-05 12:30:03 +0100797 call assert_equal('abxde', maparg('456', 't'))
Bram Moolenaar69fbc9e2017-09-14 20:37:57 +0200798 call feedkeys("123", 'tx')
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200799 call WaitForAssert({-> assert_match('abxde\|456', term_getline(buf, term_getcursor(buf)[0]))})
Bram Moolenaar69fbc9e2017-09-14 20:37:57 +0200800 let lnum = term_getcursor(buf)[0]
801 if a:remap
Bram Moolenaar461fe502017-12-05 12:30:03 +0100802 call assert_match('abxde', term_getline(buf, lnum))
Bram Moolenaar69fbc9e2017-09-14 20:37:57 +0200803 else
804 call assert_match('456', term_getline(buf, lnum))
805 endif
806
807 call term_sendkeys(buf, "\r")
808 call Stop_shell_in_terminal(buf)
809 call term_wait(buf)
810
811 tunmap 123
812 tunmap 456
813 call assert_equal('', maparg('123', 't'))
814 close
815 unlet g:job
816endfunc
817
818func Test_terminal_tmap()
819 call TerminalTmap(1)
820 call TerminalTmap(0)
821endfunc
Bram Moolenaar059db5c2017-10-15 22:42:23 +0200822
823func Test_terminal_wall()
824 let buf = Run_shell_in_terminal({})
825 wall
826 call Stop_shell_in_terminal(buf)
827 call term_wait(buf)
828 exe buf . 'bwipe'
829 unlet g:job
830endfunc
Bram Moolenaar6daeef12017-10-15 22:56:49 +0200831
Bram Moolenaar7a760922018-02-19 23:10:02 +0100832func Test_terminal_wqall()
833 let buf = Run_shell_in_terminal({})
834 call assert_fails('wqall', 'E948')
835 call Stop_shell_in_terminal(buf)
836 call term_wait(buf)
837 exe buf . 'bwipe'
838 unlet g:job
839endfunc
840
Bram Moolenaar6daeef12017-10-15 22:56:49 +0200841func Test_terminal_composing_unicode()
842 let save_enc = &encoding
843 set encoding=utf-8
844
845 if has('win32')
846 let cmd = "cmd /K chcp 65001"
847 let lnum = [3, 6, 9]
848 else
849 let cmd = &shell
850 let lnum = [1, 3, 5]
851 endif
852
853 enew
854 let buf = term_start(cmd, {'curwin': bufnr('')})
Bram Moolenaar3e1c6172017-11-02 16:58:00 +0100855 let g:job = term_getjob(buf)
Bram Moolenaar6daeef12017-10-15 22:56:49 +0200856 call term_wait(buf, 50)
857
Bram Moolenaarebe74b72018-04-21 23:34:43 +0200858 if has('win32')
859 call assert_equal('cmd', job_info(g:job).cmd[0])
860 else
861 call assert_equal(&shell, job_info(g:job).cmd[0])
862 endif
863
Bram Moolenaar6daeef12017-10-15 22:56:49 +0200864 " ascii + composing
865 let txt = "a\u0308bc"
866 call term_sendkeys(buf, "echo " . txt . "\r")
867 call term_wait(buf, 50)
868 call assert_match("echo " . txt, term_getline(buf, lnum[0]))
869 call assert_equal(txt, term_getline(buf, lnum[0] + 1))
870 let l = term_scrape(buf, lnum[0] + 1)
871 call assert_equal("a\u0308", l[0].chars)
872 call assert_equal("b", l[1].chars)
873 call assert_equal("c", l[2].chars)
874
875 " multibyte + composing
876 let txt = "\u304b\u3099\u304e\u304f\u3099\u3052\u3053\u3099"
877 call term_sendkeys(buf, "echo " . txt . "\r")
878 call term_wait(buf, 50)
879 call assert_match("echo " . txt, term_getline(buf, lnum[1]))
880 call assert_equal(txt, term_getline(buf, lnum[1] + 1))
881 let l = term_scrape(buf, lnum[1] + 1)
882 call assert_equal("\u304b\u3099", l[0].chars)
883 call assert_equal("\u304e", l[1].chars)
884 call assert_equal("\u304f\u3099", l[2].chars)
885 call assert_equal("\u3052", l[3].chars)
886 call assert_equal("\u3053\u3099", l[4].chars)
887
888 " \u00a0 + composing
889 let txt = "abc\u00a0\u0308"
890 call term_sendkeys(buf, "echo " . txt . "\r")
891 call term_wait(buf, 50)
892 call assert_match("echo " . txt, term_getline(buf, lnum[2]))
893 call assert_equal(txt, term_getline(buf, lnum[2] + 1))
894 let l = term_scrape(buf, lnum[2] + 1)
895 call assert_equal("\u00a0\u0308", l[3].chars)
896
897 call term_sendkeys(buf, "exit\r")
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200898 call WaitForAssert({-> assert_equal('dead', job_status(g:job))})
Bram Moolenaar6daeef12017-10-15 22:56:49 +0200899 bwipe!
Bram Moolenaar3e1c6172017-11-02 16:58:00 +0100900 unlet g:job
Bram Moolenaar6daeef12017-10-15 22:56:49 +0200901 let &encoding = save_enc
902endfunc
Bram Moolenaarff546792017-11-21 14:47:57 +0100903
904func Test_terminal_aucmd_on_close()
905 fun Nop()
906 let s:called = 1
907 endfun
908
909 aug repro
910 au!
911 au BufWinLeave * call Nop()
912 aug END
913
914 let [cmd, waittime] = s:get_sleep_cmd()
915
916 call assert_equal(1, winnr('$'))
917 new
918 call setline(1, ['one', 'two'])
919 exe 'term ++close ' . cmd
920 wincmd p
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200921 call WaitForAssert({-> assert_equal(2, winnr('$'))}, waittime)
Bram Moolenaarff546792017-11-21 14:47:57 +0100922 call assert_equal(1, s:called)
923 bwipe!
924
925 unlet s:called
926 au! repro
927 delfunc Nop
928endfunc
Bram Moolenaarede35bb2018-01-26 20:05:18 +0100929
930func Test_terminal_term_start_empty_command()
931 let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})"
932 call assert_fails(cmd, 'E474')
933 let cmd = "call term_start('', {'curwin' : 1, 'term_finish' : 'close'})"
934 call assert_fails(cmd, 'E474')
935 let cmd = "call term_start({}, {'curwin' : 1, 'term_finish' : 'close'})"
936 call assert_fails(cmd, 'E474')
937 let cmd = "call term_start(0, {'curwin' : 1, 'term_finish' : 'close'})"
938 call assert_fails(cmd, 'E474')
939endfunc
Bram Moolenaarb50773c2018-01-30 22:31:19 +0100940
941func Test_terminal_response_to_control_sequence()
942 if !has('unix')
943 return
944 endif
945
946 let buf = Run_shell_in_terminal({})
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200947 call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
Bram Moolenaarb50773c2018-01-30 22:31:19 +0100948
Bram Moolenaar086eb872018-03-25 21:24:12 +0200949 call term_sendkeys(buf, "cat\<CR>")
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200950 call WaitForAssert({-> assert_match('cat', term_getline(buf, 1))})
Bram Moolenaard4a282f2018-02-02 18:22:31 +0100951
Bram Moolenaar086eb872018-03-25 21:24:12 +0200952 " Request the cursor position.
953 call term_sendkeys(buf, "\x1b[6n\<CR>")
Bram Moolenaard4a282f2018-02-02 18:22:31 +0100954
955 " Wait for output from tty to display, below an empty line.
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200956 call WaitForAssert({-> assert_match('3;1R', term_getline(buf, 4))})
Bram Moolenaarb50773c2018-01-30 22:31:19 +0100957
Bram Moolenaar086eb872018-03-25 21:24:12 +0200958 " End "cat" gently.
959 call term_sendkeys(buf, "\<CR>\<C-D>")
960
Bram Moolenaarb50773c2018-01-30 22:31:19 +0100961 call Stop_shell_in_terminal(buf)
Bram Moolenaarb50773c2018-01-30 22:31:19 +0100962 exe buf . 'bwipe'
963 unlet g:job
964endfunc
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100965
Bram Moolenaar3e8d3852018-03-20 17:43:01 +0100966" Run Vim, start a terminal in that Vim with the kill argument,
967" :qall works.
968func Run_terminal_qall_kill(line1, line2)
969 " 1. Open a terminal window and wait for the prompt to appear
970 " 2. set kill using term_setkill()
971 " 3. make Vim exit, it will kill the shell
972 let after = [
973 \ a:line1,
974 \ 'let buf = bufnr("%")',
975 \ 'while term_getline(buf, 1) =~ "^\\s*$"',
976 \ ' sleep 10m',
977 \ 'endwhile',
978 \ a:line2,
979 \ 'au VimLeavePre * call writefile(["done"], "Xdone")',
980 \ 'qall',
981 \ ]
982 if !RunVim([], after, '')
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100983 return
984 endif
Bram Moolenaar3e8d3852018-03-20 17:43:01 +0100985 call assert_equal("done", readfile("Xdone")[0])
986 call delete("Xdone")
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100987endfunc
988
989" Run Vim in a terminal, then start a terminal in that Vim with a kill
990" argument, check that :qall works.
Bram Moolenaar3e8d3852018-03-20 17:43:01 +0100991func Test_terminal_qall_kill_arg()
992 call Run_terminal_qall_kill('term ++kill=kill', '')
993endfunc
994
995" Run Vim, start a terminal in that Vim, set the kill argument with
996" term_setkill(), check that :qall works.
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +0100997func Test_terminal_qall_kill_func()
Bram Moolenaar3e8d3852018-03-20 17:43:01 +0100998 call Run_terminal_qall_kill('term', 'call term_setkill(buf, "kill")')
999endfunc
1000
1001" Run Vim, start a terminal in that Vim without the kill argument,
1002" check that :qall does not exit, :qall! does.
1003func Test_terminal_qall_exit()
1004 let after = [
1005 \ 'term',
1006 \ 'let buf = bufnr("%")',
1007 \ 'while term_getline(buf, 1) =~ "^\\s*$"',
1008 \ ' sleep 10m',
1009 \ 'endwhile',
1010 \ 'set nomore',
1011 \ 'au VimLeavePre * call writefile(["too early"], "Xdone")',
1012 \ 'qall',
1013 \ 'au! VimLeavePre * exe buf . "bwipe!" | call writefile(["done"], "Xdone")',
1014 \ 'cquit',
1015 \ ]
1016 if !RunVim([], after, '')
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01001017 return
1018 endif
Bram Moolenaar3e8d3852018-03-20 17:43:01 +01001019 call assert_equal("done", readfile("Xdone")[0])
1020 call delete("Xdone")
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01001021endfunc
Bram Moolenaar435acdb2018-03-10 20:51:25 +01001022
1023" Run Vim in a terminal, then start a terminal in that Vim without a kill
1024" argument, check that :confirm qall works.
1025func Test_terminal_qall_prompt()
1026 if !CanRunVimInTerminal()
1027 return
1028 endif
1029 let buf = RunVimInTerminal('', {})
1030
1031 " Open a terminal window and wait for the prompt to appear
1032 call term_sendkeys(buf, ":term\<CR>")
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +02001033 call WaitForAssert({-> assert_match('\[running]', term_getline(buf, 10))})
1034 call WaitForAssert({-> assert_notmatch('^\s*$', term_getline(buf, 1))})
Bram Moolenaar435acdb2018-03-10 20:51:25 +01001035
1036 " make Vim exit, it will prompt to kill the shell
1037 call term_sendkeys(buf, "\<C-W>:confirm qall\<CR>")
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +02001038 call WaitForAssert({-> assert_match('ancel:', term_getline(buf, 20))})
Bram Moolenaar435acdb2018-03-10 20:51:25 +01001039 call term_sendkeys(buf, "y")
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +02001040 call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))})
Bram Moolenaar435acdb2018-03-10 20:51:25 +01001041
1042 " close the terminal window where Vim was running
1043 quit
1044endfunc
Bram Moolenaarb852c3e2018-03-11 16:55:36 +01001045
Bram Moolenaar012eb662018-03-13 17:55:27 +01001046func Test_terminal_open_autocmd()
Bram Moolenaarb852c3e2018-03-11 16:55:36 +01001047 augroup repro
1048 au!
1049 au TerminalOpen * let s:called += 1
1050 augroup END
1051
1052 let s:called = 0
1053
1054 " Open a terminal window with :terminal
1055 terminal
1056 call assert_equal(1, s:called)
1057 bwipe!
1058
1059 " Open a terminal window with term_start()
1060 call term_start(&shell)
1061 call assert_equal(2, s:called)
1062 bwipe!
1063
1064 " Open a hidden terminal buffer with :terminal
1065 terminal ++hidden
1066 call assert_equal(3, s:called)
1067 for buf in term_list()
1068 exe buf . "bwipe!"
1069 endfor
1070
1071 " Open a hidden terminal buffer with term_start()
1072 let buf = term_start(&shell, {'hidden': 1})
1073 call assert_equal(4, s:called)
1074 exe buf . "bwipe!"
1075
1076 unlet s:called
1077 au! repro
1078endfunction
Bram Moolenaar45d2a642018-03-24 14:30:32 +01001079
1080func Check_dump01(off)
1081 call assert_equal('one two three four five', trim(getline(a:off + 1)))
1082 call assert_equal('~ Select Word', trim(getline(a:off + 7)))
Bram Moolenaar1834d372018-03-29 17:40:46 +02001083 call assert_equal(':popup PopUp', trim(getline(a:off + 20)))
Bram Moolenaar45d2a642018-03-24 14:30:32 +01001084endfunc
1085
Bram Moolenaarf06b0b62018-03-29 17:22:24 +02001086func Test_terminal_dumpwrite_composing()
1087 if !CanRunVimInTerminal()
1088 return
1089 endif
1090 let save_enc = &encoding
1091 set encoding=utf-8
1092 call assert_equal(1, winnr('$'))
1093
1094 let text = " a\u0300 e\u0302 o\u0308"
1095 call writefile([text], 'Xcomposing')
Bram Moolenaar77bfd752018-04-30 18:03:10 +02001096 let buf = RunVimInTerminal('--cmd "set encoding=utf-8" Xcomposing', {})
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +02001097 call WaitForAssert({-> assert_match(text, term_getline(buf, 1))})
Bram Moolenaarf06b0b62018-03-29 17:22:24 +02001098 call term_dumpwrite(buf, 'Xdump')
1099 let dumpline = readfile('Xdump')[0]
1100 call assert_match('|à| |ê| |ö', dumpline)
1101
1102 call StopVimInTerminal(buf)
1103 call delete('Xcomposing')
1104 call delete('Xdump')
1105 let &encoding = save_enc
1106endfunc
1107
Bram Moolenaar45d2a642018-03-24 14:30:32 +01001108" just testing basic functionality.
1109func Test_terminal_dumpload()
1110 call assert_equal(1, winnr('$'))
1111 call term_dumpload('dumps/Test_popup_command_01.dump')
1112 call assert_equal(2, winnr('$'))
1113 call assert_equal(20, line('$'))
1114 call Check_dump01(0)
1115 quit
1116endfunc
1117
1118func Test_terminal_dumpdiff()
1119 call assert_equal(1, winnr('$'))
1120 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump')
1121 call assert_equal(2, winnr('$'))
1122 call assert_equal(62, line('$'))
1123 call Check_dump01(0)
1124 call Check_dump01(42)
1125 call assert_equal(' bbbbbbbbbbbbbbbbbb ', getline(26)[0:29])
1126 quit
1127endfunc
Bram Moolenaar897e63c2018-03-24 17:16:33 +01001128
1129func Test_terminal_dumpdiff_options()
1130 set laststatus=0
1131 call assert_equal(1, winnr('$'))
1132 let height = winheight(0)
1133 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 1, 'term_cols': 33})
1134 call assert_equal(2, winnr('$'))
1135 call assert_equal(height, winheight(winnr()))
1136 call assert_equal(33, winwidth(winnr()))
1137 call assert_equal('dump diff dumps/Test_popup_command_01.dump', bufname('%'))
1138 quit
1139
1140 call assert_equal(1, winnr('$'))
1141 let width = winwidth(0)
1142 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'vertical': 0, 'term_rows': 13, 'term_name': 'something else'})
1143 call assert_equal(2, winnr('$'))
1144 call assert_equal(width, winwidth(winnr()))
1145 call assert_equal(13, winheight(winnr()))
1146 call assert_equal('something else', bufname('%'))
1147 quit
1148
1149 call assert_equal(1, winnr('$'))
1150 call term_dumpdiff('dumps/Test_popup_command_01.dump', 'dumps/Test_popup_command_02.dump', {'curwin': 1})
1151 call assert_equal(1, winnr('$'))
1152 bwipe
1153
1154 set laststatus&
1155endfunc
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001156
Bram Moolenaar333b80a2018-04-04 22:57:29 +02001157func Api_drop_common(options)
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001158 call assert_equal(1, winnr('$'))
1159
1160 " Use the title termcap entries to output the escape sequence.
1161 call writefile([
Bram Moolenaarcf67a502018-03-25 20:31:32 +02001162 \ 'set title',
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001163 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"',
Bram Moolenaar333b80a2018-04-04 22:57:29 +02001164 \ 'let &titlestring = ''["drop","Xtextfile"' . a:options . ']''',
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001165 \ 'redraw',
1166 \ "set t_ts=",
1167 \ ], 'Xscript')
1168 let buf = RunVimInTerminal('-S Xscript', {})
Bram Moolenaar769e9d22018-04-11 20:53:49 +02001169 call WaitFor({-> bufnr('Xtextfile') > 0})
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001170 call assert_equal('Xtextfile', expand('%:t'))
1171 call assert_true(winnr('$') >= 3)
Bram Moolenaar333b80a2018-04-04 22:57:29 +02001172 return buf
1173endfunc
1174
1175func Test_terminal_api_drop_newwin()
1176 if !CanRunVimInTerminal()
1177 return
1178 endif
1179 let buf = Api_drop_common('')
1180 call assert_equal(0, &bin)
1181 call assert_equal('', &fenc)
1182
1183 call StopVimInTerminal(buf)
1184 call delete('Xscript')
1185 bwipe Xtextfile
1186endfunc
1187
1188func Test_terminal_api_drop_newwin_bin()
1189 if !CanRunVimInTerminal()
1190 return
1191 endif
1192 let buf = Api_drop_common(',{"bin":1}')
1193 call assert_equal(1, &bin)
1194
1195 call StopVimInTerminal(buf)
1196 call delete('Xscript')
1197 bwipe Xtextfile
1198endfunc
1199
1200func Test_terminal_api_drop_newwin_binary()
1201 if !CanRunVimInTerminal()
1202 return
1203 endif
1204 let buf = Api_drop_common(',{"binary":1}')
1205 call assert_equal(1, &bin)
1206
1207 call StopVimInTerminal(buf)
1208 call delete('Xscript')
1209 bwipe Xtextfile
1210endfunc
1211
1212func Test_terminal_api_drop_newwin_nobin()
1213 if !CanRunVimInTerminal()
1214 return
1215 endif
1216 set binary
1217 let buf = Api_drop_common(',{"nobin":1}')
1218 call assert_equal(0, &bin)
1219
1220 call StopVimInTerminal(buf)
1221 call delete('Xscript')
1222 bwipe Xtextfile
1223 set nobinary
1224endfunc
1225
1226func Test_terminal_api_drop_newwin_nobinary()
1227 if !CanRunVimInTerminal()
1228 return
1229 endif
1230 set binary
1231 let buf = Api_drop_common(',{"nobinary":1}')
1232 call assert_equal(0, &bin)
1233
1234 call StopVimInTerminal(buf)
1235 call delete('Xscript')
1236 bwipe Xtextfile
1237 set nobinary
1238endfunc
1239
1240func Test_terminal_api_drop_newwin_ff()
1241 if !CanRunVimInTerminal()
1242 return
1243 endif
1244 let buf = Api_drop_common(',{"ff":"dos"}')
1245 call assert_equal("dos", &ff)
1246
1247 call StopVimInTerminal(buf)
1248 call delete('Xscript')
1249 bwipe Xtextfile
1250endfunc
1251
1252func Test_terminal_api_drop_newwin_fileformat()
1253 if !CanRunVimInTerminal()
1254 return
1255 endif
1256 let buf = Api_drop_common(',{"fileformat":"dos"}')
1257 call assert_equal("dos", &ff)
1258
1259 call StopVimInTerminal(buf)
1260 call delete('Xscript')
1261 bwipe Xtextfile
1262endfunc
1263
1264func Test_terminal_api_drop_newwin_enc()
1265 if !CanRunVimInTerminal()
1266 return
1267 endif
1268 let buf = Api_drop_common(',{"enc":"utf-16"}')
1269 call assert_equal("utf-16", &fenc)
1270
1271 call StopVimInTerminal(buf)
1272 call delete('Xscript')
1273 bwipe Xtextfile
1274endfunc
1275
1276func Test_terminal_api_drop_newwin_encoding()
1277 if !CanRunVimInTerminal()
1278 return
1279 endif
1280 let buf = Api_drop_common(',{"encoding":"utf-16"}')
1281 call assert_equal("utf-16", &fenc)
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001282
1283 call StopVimInTerminal(buf)
1284 call delete('Xscript')
1285 bwipe Xtextfile
1286endfunc
1287
1288func Test_terminal_api_drop_oldwin()
1289 if !CanRunVimInTerminal()
1290 return
1291 endif
1292 let firstwinid = win_getid()
1293 split Xtextfile
1294 let textfile_winid = win_getid()
1295 call assert_equal(2, winnr('$'))
1296 call win_gotoid(firstwinid)
1297
1298 " Use the title termcap entries to output the escape sequence.
1299 call writefile([
Bram Moolenaarcf67a502018-03-25 20:31:32 +02001300 \ 'set title',
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001301 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"',
1302 \ 'let &titlestring = ''["drop","Xtextfile"]''',
1303 \ 'redraw',
1304 \ "set t_ts=",
1305 \ ], 'Xscript')
Bram Moolenaar15a1c3f2018-03-25 18:56:25 +02001306 let buf = RunVimInTerminal('-S Xscript', {'rows': 10})
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +02001307 call WaitForAssert({-> assert_equal('Xtextfile', expand('%:t'))})
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001308 call assert_equal(textfile_winid, win_getid())
1309
1310 call StopVimInTerminal(buf)
1311 call delete('Xscript')
1312 bwipe Xtextfile
1313endfunc
1314
Bram Moolenaar2a77d212018-03-26 21:38:52 +02001315func Tapi_TryThis(bufnum, arg)
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001316 let g:called_bufnum = a:bufnum
1317 let g:called_arg = a:arg
1318endfunc
1319
Bram Moolenaar2a77d212018-03-26 21:38:52 +02001320func WriteApiCall(funcname)
1321 " Use the title termcap entries to output the escape sequence.
1322 call writefile([
1323 \ 'set title',
1324 \ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"',
1325 \ 'let &titlestring = ''["call","' . a:funcname . '",["hello",123]]''',
1326 \ 'redraw',
1327 \ "set t_ts=",
1328 \ ], 'Xscript')
1329endfunc
1330
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001331func Test_terminal_api_call()
1332 if !CanRunVimInTerminal()
1333 return
1334 endif
Bram Moolenaar2de50f82018-03-25 19:09:56 +02001335
Bram Moolenaar2a77d212018-03-26 21:38:52 +02001336 call WriteApiCall('Tapi_TryThis')
Bram Moolenaar8fbaeb12018-03-25 18:20:17 +02001337 let buf = RunVimInTerminal('-S Xscript', {})
1338 call WaitFor({-> exists('g:called_bufnum')})
1339 call assert_equal(buf, g:called_bufnum)
1340 call assert_equal(['hello', 123], g:called_arg)
1341
1342 call StopVimInTerminal(buf)
1343 call delete('Xscript')
1344 unlet g:called_bufnum
1345 unlet g:called_arg
1346endfunc
Bram Moolenaar2a77d212018-03-26 21:38:52 +02001347
1348func Test_terminal_api_call_fails()
1349 if !CanRunVimInTerminal()
1350 return
1351 endif
1352
1353 call WriteApiCall('TryThis')
1354 call ch_logfile('Xlog', 'w')
1355 let buf = RunVimInTerminal('-S Xscript', {})
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +02001356 call WaitForAssert({-> assert_match('Invalid function name: TryThis', string(readfile('Xlog')))})
Bram Moolenaar2a77d212018-03-26 21:38:52 +02001357
1358 call StopVimInTerminal(buf)
1359 call delete('Xscript')
1360 call ch_logfile('', '')
1361 call delete('Xlog')
1362endfunc
Bram Moolenaarf59c6e82018-04-10 15:59:11 +02001363
Bram Moolenaara997b452018-04-17 23:24:06 +02001364let s:caught_e937 = 0
1365
1366func Tapi_Delete(bufnum, arg)
1367 try
1368 execute 'bdelete!' a:bufnum
1369 catch /E937:/
1370 let s:caught_e937 = 1
1371 endtry
1372endfunc
1373
1374func Test_terminal_api_call_fail_delete()
1375 if !CanRunVimInTerminal()
1376 return
1377 endif
1378
1379 call WriteApiCall('Tapi_Delete')
1380 let buf = RunVimInTerminal('-S Xscript', {})
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +02001381 call WaitForAssert({-> assert_equal(1, s:caught_e937)})
Bram Moolenaara997b452018-04-17 23:24:06 +02001382
1383 call StopVimInTerminal(buf)
1384 call delete('Xscript')
1385 call ch_logfile('', '')
1386endfunc
1387
Bram Moolenaarf59c6e82018-04-10 15:59:11 +02001388func Test_terminal_ansicolors_default()
1389 let colors = [
1390 \ '#000000', '#e00000',
1391 \ '#00e000', '#e0e000',
1392 \ '#0000e0', '#e000e0',
1393 \ '#00e0e0', '#e0e0e0',
1394 \ '#808080', '#ff4040',
1395 \ '#40ff40', '#ffff40',
1396 \ '#4040ff', '#ff40ff',
1397 \ '#40ffff', '#ffffff',
1398 \]
1399
1400 let buf = Run_shell_in_terminal({})
1401 call assert_equal(colors, term_getansicolors(buf))
1402 call Stop_shell_in_terminal(buf)
1403 call term_wait(buf)
1404
1405 exe buf . 'bwipe'
1406endfunc
1407
1408let s:test_colors = [
1409 \ '#616e64', '#0d0a79',
1410 \ '#6d610d', '#0a7373',
1411 \ '#690d0a', '#6d696e',
1412 \ '#0d0a6f', '#616e0d',
1413 \ '#0a6479', '#6d0d0a',
1414 \ '#617373', '#0d0a69',
1415 \ '#6d690d', '#0a6e6f',
1416 \ '#610d0a', '#6e6479',
1417 \]
1418
1419func Test_terminal_ansicolors_global()
1420 let g:terminal_ansi_colors = reverse(copy(s:test_colors))
1421 let buf = Run_shell_in_terminal({})
1422 call assert_equal(g:terminal_ansi_colors, term_getansicolors(buf))
1423 call Stop_shell_in_terminal(buf)
1424 call term_wait(buf)
1425
1426 exe buf . 'bwipe'
1427 unlet g:terminal_ansi_colors
1428endfunc
1429
1430func Test_terminal_ansicolors_func()
1431 let g:terminal_ansi_colors = reverse(copy(s:test_colors))
1432 let buf = Run_shell_in_terminal({'ansi_colors': s:test_colors})
1433 call assert_equal(s:test_colors, term_getansicolors(buf))
1434
1435 call term_setansicolors(buf, g:terminal_ansi_colors)
1436 call assert_equal(g:terminal_ansi_colors, term_getansicolors(buf))
1437
1438 let colors = [
1439 \ 'ivory', 'AliceBlue',
1440 \ 'grey67', 'dark goldenrod',
1441 \ 'SteelBlue3', 'PaleVioletRed4',
1442 \ 'MediumPurple2', 'yellow2',
1443 \ 'RosyBrown3', 'OrangeRed2',
1444 \ 'white smoke', 'navy blue',
1445 \ 'grey47', 'gray97',
1446 \ 'MistyRose2', 'DodgerBlue4',
1447 \]
1448 call term_setansicolors(buf, colors)
1449
1450 let colors[4] = 'Invalid'
1451 call assert_fails('call term_setansicolors(buf, colors)', 'E474:')
1452
1453 call Stop_shell_in_terminal(buf)
1454 call term_wait(buf)
1455 exe buf . 'bwipe'
1456endfunc
Bram Moolenaara7eef3d2018-04-15 22:25:54 +02001457
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001458func Test_terminal_termwinsize_option_fixed()
Bram Moolenaara7eef3d2018-04-15 22:25:54 +02001459 if !CanRunVimInTerminal()
1460 return
1461 endif
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001462 set termwinsize=6x40
Bram Moolenaara7eef3d2018-04-15 22:25:54 +02001463 let text = []
1464 for n in range(10)
1465 call add(text, repeat(n, 50))
1466 endfor
1467 call writefile(text, 'Xwinsize')
1468 let buf = RunVimInTerminal('Xwinsize', {})
1469 let win = bufwinid(buf)
1470 call assert_equal([6, 40], term_getsize(buf))
1471 call assert_equal(6, winheight(win))
1472 call assert_equal(40, winwidth(win))
1473
1474 " resizing the window doesn't resize the terminal.
1475 resize 10
1476 vertical resize 60
1477 call assert_equal([6, 40], term_getsize(buf))
1478 call assert_equal(10, winheight(win))
1479 call assert_equal(60, winwidth(win))
1480
1481 call StopVimInTerminal(buf)
1482 call delete('Xwinsize')
1483
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001484 call assert_fails('set termwinsize=40', 'E474')
1485 call assert_fails('set termwinsize=10+40', 'E474')
1486 call assert_fails('set termwinsize=abc', 'E474')
Bram Moolenaara7eef3d2018-04-15 22:25:54 +02001487
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001488 set termwinsize=
Bram Moolenaara7eef3d2018-04-15 22:25:54 +02001489endfunc
Bram Moolenaar498c2562018-04-15 23:45:15 +02001490
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001491func Test_terminal_termwinsize_option_zero()
1492 set termwinsize=0x0
Bram Moolenaar498c2562018-04-15 23:45:15 +02001493 let buf = Run_shell_in_terminal({})
1494 let win = bufwinid(buf)
1495 call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
1496 call Stop_shell_in_terminal(buf)
1497 call term_wait(buf)
1498 exe buf . 'bwipe'
1499
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001500 set termwinsize=7x0
Bram Moolenaar498c2562018-04-15 23:45:15 +02001501 let buf = Run_shell_in_terminal({})
1502 let win = bufwinid(buf)
1503 call assert_equal([7, winwidth(win)], term_getsize(buf))
1504 call Stop_shell_in_terminal(buf)
1505 call term_wait(buf)
1506 exe buf . 'bwipe'
1507
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001508 set termwinsize=0x33
Bram Moolenaar498c2562018-04-15 23:45:15 +02001509 let buf = Run_shell_in_terminal({})
1510 let win = bufwinid(buf)
1511 call assert_equal([winheight(win), 33], term_getsize(buf))
1512 call Stop_shell_in_terminal(buf)
1513 call term_wait(buf)
1514 exe buf . 'bwipe'
1515
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001516 set termwinsize=
Bram Moolenaar498c2562018-04-15 23:45:15 +02001517endfunc
1518
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001519func Test_terminal_termwinsize_mininmum()
1520 set termwinsize=10*50
Bram Moolenaar498c2562018-04-15 23:45:15 +02001521 vsplit
1522 let buf = Run_shell_in_terminal({})
1523 let win = bufwinid(buf)
1524 call assert_inrange(10, 1000, winheight(win))
1525 call assert_inrange(50, 1000, winwidth(win))
1526 call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
1527
1528 resize 15
1529 vertical resize 60
1530 redraw
1531 call assert_equal([15, 60], term_getsize(buf))
1532 call assert_equal(15, winheight(win))
1533 call assert_equal(60, winwidth(win))
1534
1535 resize 7
1536 vertical resize 30
1537 redraw
1538 call assert_equal([10, 50], term_getsize(buf))
1539 call assert_equal(7, winheight(win))
1540 call assert_equal(30, winwidth(win))
1541
1542 call Stop_shell_in_terminal(buf)
1543 call term_wait(buf)
1544 exe buf . 'bwipe'
1545
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001546 set termwinsize=0*0
Bram Moolenaar498c2562018-04-15 23:45:15 +02001547 let buf = Run_shell_in_terminal({})
1548 let win = bufwinid(buf)
1549 call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
1550 call Stop_shell_in_terminal(buf)
1551 call term_wait(buf)
1552 exe buf . 'bwipe'
1553
Bram Moolenaar6d150f72018-04-21 20:03:20 +02001554 set termwinsize=
Bram Moolenaar498c2562018-04-15 23:45:15 +02001555endfunc
Bram Moolenaarb2ac14c2018-05-01 18:47:59 +02001556
1557func Test_terminal_termwinkey()
1558 call assert_equal(1, winnr('$'))
1559 let thiswin = win_getid()
1560
1561 let buf = Run_shell_in_terminal({})
1562 let termwin = bufwinid(buf)
1563 set termwinkey=<C-L>
1564 call feedkeys("\<C-L>w", 'tx')
1565 call assert_equal(thiswin, win_getid())
1566 call feedkeys("\<C-W>w", 'tx')
1567
1568 let job = term_getjob(buf)
1569 call feedkeys("\<C-L>\<C-C>", 'tx')
1570 call WaitForAssert({-> assert_equal("dead", job_status(job))})
Bram Moolenaar29ae2232019-02-14 21:22:01 +01001571
1572 set termwinkey&
Bram Moolenaarb2ac14c2018-05-01 18:47:59 +02001573endfunc
Bram Moolenaarcd8fb442018-05-12 17:42:42 +02001574
1575func Test_terminal_out_err()
1576 if !has('unix')
1577 return
1578 endif
1579 call writefile([
1580 \ '#!/bin/sh',
1581 \ 'echo "this is standard error" >&2',
1582 \ 'echo "this is standard out" >&1',
1583 \ ], 'Xechoerrout.sh')
1584 call setfperm('Xechoerrout.sh', 'rwxrwx---')
1585
1586 let outfile = 'Xtermstdout'
1587 let buf = term_start(['./Xechoerrout.sh'], {'out_io': 'file', 'out_name': outfile})
Bram Moolenaar53191912018-06-19 20:08:14 +02001588
1589 call WaitFor({-> !empty(readfile(outfile)) && !empty(term_getline(buf, 1))})
1590 call assert_equal(['this is standard out'], readfile(outfile))
Bram Moolenaarcd8fb442018-05-12 17:42:42 +02001591 call assert_equal('this is standard error', term_getline(buf, 1))
1592
Bram Moolenaar54c6baf2018-05-12 21:12:12 +02001593 call WaitForAssert({-> assert_equal('dead', job_status(term_getjob(buf)))})
Bram Moolenaarcd8fb442018-05-12 17:42:42 +02001594 exe buf . 'bwipe'
1595 call delete('Xechoerrout.sh')
1596 call delete(outfile)
1597endfunc
Bram Moolenaar4d6cd292018-05-15 23:53:26 +02001598
1599func Test_terminwinscroll()
1600 if !has('unix')
1601 return
1602 endif
1603
1604 " Let the terminal output more than 'termwinscroll' lines, some at the start
1605 " will be dropped.
1606 exe 'set termwinscroll=' . &lines
1607 let buf = term_start('/bin/sh')
1608 for i in range(1, &lines)
1609 call feedkeys("echo " . i . "\<CR>", 'xt')
1610 call WaitForAssert({-> assert_match(string(i), term_getline(buf, term_getcursor(buf)[0] - 1))})
1611 endfor
1612 " Go to Terminal-Normal mode to update the buffer.
1613 call feedkeys("\<C-W>N", 'xt')
1614 call assert_inrange(&lines, &lines * 110 / 100 + winheight(0), line('$'))
1615
1616 " Every "echo nr" must only appear once
1617 let lines = getline(1, line('$'))
1618 for i in range(&lines - len(lines) / 2 + 2, &lines)
1619 let filtered = filter(copy(lines), {idx, val -> val =~ 'echo ' . i . '\>'})
1620 call assert_equal(1, len(filtered), 'for "echo ' . i . '"')
1621 endfor
1622
1623 exe buf . 'bwipe!'
1624endfunc
Bram Moolenaarf9c38832018-06-19 19:59:20 +02001625
Bram Moolenaar875cf872018-07-08 20:49:07 +02001626" Resizing the terminal window caused an ml_get error.
1627" TODO: This does not reproduce the original problem.
1628func Test_terminal_resize()
1629 set statusline=x
1630 terminal
1631 call assert_equal(2, winnr('$'))
1632
1633 " Fill the terminal with text.
1634 if has('win32')
1635 call feedkeys("dir\<CR>", 'xt')
1636 else
1637 call feedkeys("ls\<CR>", 'xt')
1638 endif
1639 " Go to Terminal-Normal mode for a moment.
1640 call feedkeys("\<C-W>N", 'xt')
1641 " Open a new window
1642 call feedkeys("i\<C-W>n", 'xt')
1643 call assert_equal(3, winnr('$'))
1644 redraw
1645
1646 close
1647 call assert_equal(2, winnr('$'))
1648 call feedkeys("exit\<CR>", 'xt')
1649 set statusline&
1650endfunc
1651
Bram Moolenaarf9c38832018-06-19 19:59:20 +02001652" must be nearly the last, we can't go back from GUI to terminal
1653func Test_zz1_terminal_in_gui()
1654 if !CanRunGui()
1655 return
1656 endif
1657
1658 " Ignore the "failed to create input context" error.
1659 call test_ignore_error('E285:')
1660
1661 gui -f
1662
1663 call assert_equal(1, winnr('$'))
1664 let buf = Run_shell_in_terminal({'term_finish': 'close'})
1665 call Stop_shell_in_terminal(buf)
1666 call term_wait(buf)
1667
1668 " closing window wipes out the terminal buffer a with finished job
1669 call WaitForAssert({-> assert_equal(1, winnr('$'))})
1670 call assert_equal("", bufname(buf))
1671
1672 unlet g:job
1673endfunc
1674
1675func Test_zz2_terminal_guioptions_bang()
1676 if !has('gui_running')
1677 return
1678 endif
1679 set guioptions+=!
1680
1681 let filename = 'Xtestscript'
1682 if has('win32')
1683 let filename .= '.bat'
1684 let prefix = ''
1685 let contents = ['@echo off', 'exit %1']
1686 else
1687 let filename .= '.sh'
1688 let prefix = './'
1689 let contents = ['#!/bin/sh', 'exit $1']
1690 endif
1691 call writefile(contents, filename)
1692 call setfperm(filename, 'rwxrwx---')
1693
1694 " Check if v:shell_error is equal to the exit status.
1695 let exitval = 0
1696 execute printf(':!%s%s %d', prefix, filename, exitval)
1697 call assert_equal(exitval, v:shell_error)
1698
1699 let exitval = 9
1700 execute printf(':!%s%s %d', prefix, filename, exitval)
1701 call assert_equal(exitval, v:shell_error)
1702
1703 set guioptions&
1704 call delete(filename)
1705endfunc
Bram Moolenaar7da1fb52018-08-04 16:54:11 +02001706
1707func Test_terminal_hidden()
1708 if !has('unix')
1709 return
1710 endif
1711 term ++hidden cat
1712 let bnr = bufnr('$')
1713 call assert_equal('terminal', getbufvar(bnr, '&buftype'))
1714 exe 'sbuf ' . bnr
1715 call assert_equal('terminal', &buftype)
1716 call term_sendkeys(bnr, "asdf\<CR>")
1717 call WaitForAssert({-> assert_match('asdf', term_getline(bnr, 2))})
1718 call term_sendkeys(bnr, "\<C-D>")
1719 call WaitForAssert({-> assert_equal('finished', term_getstatus(bnr))})
1720 bwipe!
1721endfunc
Bram Moolenaar5db7eec2018-08-07 16:33:18 +02001722
1723func Test_terminal_hidden_and_close()
1724 if !has('unix')
1725 return
1726 endif
1727 call assert_equal(1, winnr('$'))
1728 term ++hidden ++close ls
1729 let bnr = bufnr('$')
1730 call assert_equal('terminal', getbufvar(bnr, '&buftype'))
1731 call WaitForAssert({-> assert_false(bufexists(bnr))})
1732 call assert_equal(1, winnr('$'))
1733endfunc
Bram Moolenaarf3aea592018-11-11 22:18:21 +01001734
1735func Test_terminal_does_not_truncate_last_newlines()
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +01001736 " This test does not pass through ConPTY.
1737 if has('conpty')
1738 return
1739 endif
Bram Moolenaarf3aea592018-11-11 22:18:21 +01001740 let contents = [
1741 \ [ 'One', '', 'X' ],
1742 \ [ 'Two', '', '' ],
1743 \ [ 'Three' ] + repeat([''], 30)
1744 \ ]
1745
1746 for c in contents
1747 call writefile(c, 'Xfile')
Bram Moolenaard3471e52018-11-12 21:42:24 +01001748 if has('win32')
1749 term cmd /c type Xfile
1750 else
1751 term cat Xfile
1752 endif
Bram Moolenaarf3aea592018-11-11 22:18:21 +01001753 let bnr = bufnr('$')
1754 call assert_equal('terminal', getbufvar(bnr, '&buftype'))
1755 call WaitForAssert({-> assert_equal('finished', term_getstatus(bnr))})
Bram Moolenaard3471e52018-11-12 21:42:24 +01001756 sleep 100m
Bram Moolenaarf3aea592018-11-11 22:18:21 +01001757 call assert_equal(c, getline(1, line('$')))
1758 quit
1759 endfor
1760
1761 call delete('Xfile')
1762endfunc
Bram Moolenaare751a5f2018-12-16 16:16:10 +01001763
Bram Moolenaar528ccfb2018-12-21 20:55:22 +01001764func Test_terminal_no_job()
1765 let term = term_start('false', {'term_finish': 'close'})
1766 call WaitForAssert({-> assert_equal(v:null, term_getjob(term)) })
1767endfunc
Bram Moolenaar1e115362019-01-09 23:01:02 +01001768
1769func Test_term_gettitle()
1770 if !has('title') || empty(&t_ts)
1771 return
1772 endif
1773 " TODO: this fails on Travis
1774 return
1775
1776 " term_gettitle() returns an empty string for a non-terminal buffer
1777 " or for a non-existing buffer.
1778 call assert_equal('', term_gettitle(bufnr('%')))
1779 call assert_equal('', term_gettitle(bufnr('$') + 1))
1780
1781 let term = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'])
1782 call WaitForAssert({-> assert_equal('[No Name] - VIM', term_gettitle(term)) })
1783
1784 call term_sendkeys(term, ":e Xfoo\r")
1785 call WaitForAssert({-> assert_match('Xfoo (.*[/\\]testdir) - VIM', term_gettitle(term)) })
1786
1787 call term_sendkeys(term, ":set titlestring=foo\r")
1788 call WaitForAssert({-> assert_equal('foo', term_gettitle(term)) })
1789
1790 exe term . 'bwipe!'
1791endfunc
Bram Moolenaar10772302019-01-20 18:25:54 +01001792
1793" When drawing the statusline the cursor position may not have been updated
1794" yet.
1795" 1. create a terminal, make it show 2 lines
1796" 2. 0.5 sec later: leave terminal window, execute "i"
1797" 3. 0.5 sec later: clear terminal window, now it's 1 line
1798" 4. 0.5 sec later: redraw, including statusline (used to trigger bug)
1799" 4. 0.5 sec later: should be done, clean up
1800func Test_terminal_statusline()
1801 if !has('unix')
1802 return
1803 endif
1804 set statusline=x
1805 terminal
1806 let tbuf = bufnr('')
1807 call term_sendkeys(tbuf, "clear; echo a; echo b; sleep 1; clear\n")
1808 call timer_start(500, { tid -> feedkeys("\<C-w>j", 'tx') })
1809 call timer_start(1500, { tid -> feedkeys("\<C-l>", 'tx') })
1810 au BufLeave * if &buftype == 'terminal' | silent! normal i | endif
1811
1812 sleep 2
1813 exe tbuf . 'bwipe!'
1814 au! BufLeave
1815 set statusline=
1816endfunc