blob: 19362aafdbf6722928e8d273c7c2daca2501b443 [file] [log] [blame]
Bram Moolenaar7a39dd72019-06-23 00:50:15 +02001" Functions about terminal shared by several tests
2
3" Only load this script once.
4if exists('*CanRunVimInTerminal')
5 finish
6endif
7
Bram Moolenaar6bf1b522020-09-23 17:41:26 +02008source shared.vim
9
Bram Moolenaar7a39dd72019-06-23 00:50:15 +020010" For most tests we need to be able to run terminal Vim with 256 colors. On
11" MS-Windows the console only has 16 colors and the GUI can't run in a
12" terminal.
13func CanRunVimInTerminal()
14 return has('terminal') && !has('win32')
15endfunc
16
17" Skip the rest if there is no terminal feature at all.
18if !has('terminal')
19 finish
20endif
21
22" Stops the shell running in terminal "buf".
23func StopShellInTerminal(buf)
24 call term_sendkeys(a:buf, "exit\r")
25 let job = term_getjob(a:buf)
Bram Moolenaar3a6aadb2021-04-04 15:28:59 +020026 call WaitForAssert({-> assert_equal("dead", job_status(job))})
Bram Moolenaarced2b382022-01-13 15:25:32 +000027 call TermWait(a:buf)
Bram Moolenaar7a39dd72019-06-23 00:50:15 +020028endfunc
29
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +020030" Wrapper around term_wait() to allow more time for re-runs of flaky tests
31" The second argument is the minimum time to wait in msec, 10 if omitted.
32func TermWait(buf, ...)
33 let wait_time = a:0 ? a:1 : 10
Bram Moolenaarceb2e772020-06-18 18:33:59 +020034 if exists('g:run_nr')
35 if g:run_nr == 2
36 let wait_time *= 4
37 elseif g:run_nr > 2
38 let wait_time *= 10
39 endif
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +020040 endif
41 call term_wait(a:buf, wait_time)
42
43 " In case it wasn't set yet.
44 let g:test_is_flaky = 1
45endfunc
46
Bram Moolenaar7a39dd72019-06-23 00:50:15 +020047" Run Vim with "arguments" in a new terminal window.
48" By default uses a size of 20 lines and 75 columns.
49" Returns the buffer number of the terminal.
50"
51" Options is a dictionary, these items are recognized:
Bram Moolenaara45551a2020-06-09 15:57:37 +020052" "keep_t_u7" - when 1 do not make t_u7 empty (resetting t_u7 avoids clearing
53" parts of line 2 and 3 on the display)
Bram Moolenaar7a39dd72019-06-23 00:50:15 +020054" "rows" - height of the terminal window (max. 20)
55" "cols" - width of the terminal window (max. 78)
56" "statusoff" - number of lines the status is offset from default
Bram Moolenaar6bf1b522020-09-23 17:41:26 +020057" "wait_for_ruler" - if zero then don't wait for ruler to show
Bram Moolenaar7ac50232023-03-07 21:05:04 +000058" "no_clean" - if non-zero then remove "--clean" from the command
Aapo Rantalainene2528ae2023-08-31 17:58:13 +020059" "cmd" - run any other command, e.g. "xxd" (used in xxd test)
Christian Brabandt08ea2e12025-01-25 15:01:42 +010060" "env" - additional environment variables, e.g. $TERM variable
Bram Moolenaar7a39dd72019-06-23 00:50:15 +020061func RunVimInTerminal(arguments, options)
62 " If Vim doesn't exit a swap file remains, causing other tests to fail.
63 " Remove it here.
64 call delete(".swp")
65
66 if exists('$COLORFGBG')
67 " Clear $COLORFGBG to avoid 'background' being set to "dark", which will
68 " only be corrected if the response to t_RB is received, which may be too
69 " late.
70 let $COLORFGBG = ''
71 endif
72
73 " Make a horizontal and vertical split, so that we can get exactly the right
74 " size terminal window. Works only when the current window is full width.
75 call assert_equal(&columns, winwidth(0))
76 split
77 vsplit
78
79 " Always do this with 256 colors and a light background.
80 set t_Co=256 background=light
81 hi Normal ctermfg=NONE ctermbg=NONE
82
Bram Moolenaarb936b792020-09-04 18:34:09 +020083 " Make the window 20 lines high and 75 columns, unless told otherwise or
84 " 'termwinsize' is set.
Bram Moolenaar7a39dd72019-06-23 00:50:15 +020085 let rows = get(a:options, 'rows', 20)
86 let cols = get(a:options, 'cols', 75)
87 let statusoff = get(a:options, 'statusoff', 1)
88
Bram Moolenaara45551a2020-06-09 15:57:37 +020089 if get(a:options, 'keep_t_u7', 0)
90 let reset_u7 = ''
91 else
92 let reset_u7 = ' --cmd "set t_u7=" '
93 endif
94
Aapo Rantalainene2528ae2023-08-31 17:58:13 +020095 if empty(get(a:options, 'cmd', ''))
96 let cmd = GetVimCommandCleanTerm() .. reset_u7 .. a:arguments
97 else
98 let cmd = get(a:options, 'cmd')
99 endif
Bram Moolenaar7a39dd72019-06-23 00:50:15 +0200100
Bram Moolenaar7ac50232023-03-07 21:05:04 +0000101 if get(a:options, 'no_clean', 0)
102 let cmd = substitute(cmd, '--clean', '', '')
103 endif
104
Bram Moolenaarb936b792020-09-04 18:34:09 +0200105 let options = #{curwin: 1}
106 if &termwinsize == ''
107 let options.term_rows = rows
108 let options.term_cols = cols
109 endif
110
Bram Moolenaard2842ea2019-09-26 23:08:54 +0200111 " Accept other options whose name starts with 'term_'.
112 call extend(options, filter(copy(a:options), 'v:key =~# "^term_"'))
Christian Brabandt08ea2e12025-01-25 15:01:42 +0100113 " Accept the env dict
114 if !empty(get(a:options, 'env', {}))
115 let options.env = get(a:options, 'env')
116 endif
Bram Moolenaard2842ea2019-09-26 23:08:54 +0200117
118 let buf = term_start(cmd, options)
119
Bram Moolenaar7a39dd72019-06-23 00:50:15 +0200120 if &termwinsize == ''
121 " in the GUI we may end up with a different size, try to set it.
122 if term_getsize(buf) != [rows, cols]
123 call term_setsize(buf, rows, cols)
124 endif
125 call assert_equal([rows, cols], term_getsize(buf))
126 else
127 let rows = term_getsize(buf)[0]
128 let cols = term_getsize(buf)[1]
129 endif
130
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200131 call TermWait(buf)
Bram Moolenaarcde0ff32020-04-04 14:00:39 +0200132
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200133 if get(a:options, 'wait_for_ruler', 1) && empty(get(a:options, 'cmd', ''))
Bram Moolenaar101f4812020-06-16 23:18:51 +0200134 " Wait for "All" or "Top" of the ruler to be shown in the last line or in
135 " the status line of the last window. This can be quite slow (e.g. when
136 " using valgrind).
137 " If it fails then show the terminal contents for debugging.
138 try
139 call WaitFor({-> len(term_getline(buf, rows)) >= cols - 1 || len(term_getline(buf, rows - statusoff)) >= cols - 1})
140 catch /timed out after/
141 let lines = map(range(1, rows), {key, val -> term_getline(buf, val)})
142 call assert_report('RunVimInTerminal() failed, screen contents: ' . join(lines, "<NL>"))
143 endtry
144 endif
Bram Moolenaar7a39dd72019-06-23 00:50:15 +0200145
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100146 " Starting a terminal to run Vim is always considered flaky.
Bram Moolenaar30d53e22020-03-18 21:10:44 +0100147 let g:test_is_flaky = 1
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100148
Bram Moolenaar7a39dd72019-06-23 00:50:15 +0200149 return buf
150endfunc
151
152" Stop a Vim running in terminal buffer "buf".
Bram Moolenaara46765a2020-11-01 20:58:26 +0100153func StopVimInTerminal(buf, kill = 1)
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100154 " Using a terminal to run Vim is always considered flaky.
Bram Moolenaar30d53e22020-03-18 21:10:44 +0100155 let g:test_is_flaky = 1
Bram Moolenaar3cdcb092020-03-18 19:18:10 +0100156
Bram Moolenaar7a39dd72019-06-23 00:50:15 +0200157 call assert_equal("running", term_getstatus(a:buf))
158
James McCoydbe6ef12022-12-31 11:44:57 +0000159 " Wait for all the pending updates to terminal to complete
Yee Cheng Chine70587d2025-02-13 20:55:45 +0100160 call TermWait(a:buf, 1)
James McCoydbe6ef12022-12-31 11:44:57 +0000161
Bram Moolenaar7a39dd72019-06-23 00:50:15 +0200162 " CTRL-O : works both in Normal mode and Insert mode to start a command line.
163 " In Command-line it's inserted, the CTRL-U removes it again.
164 call term_sendkeys(a:buf, "\<C-O>:\<C-U>qa!\<cr>")
165
Bram Moolenaar91689ea2020-05-11 22:04:53 +0200166 " Wait for all the pending updates to terminal to complete
Yee Cheng Chine70587d2025-02-13 20:55:45 +0100167 call TermWait(a:buf, 1)
Bram Moolenaar91689ea2020-05-11 22:04:53 +0200168
Bram Moolenaar645cd3e2020-11-01 20:04:57 +0100169 " Wait for the terminal to end.
Bram Moolenaar7a39dd72019-06-23 00:50:15 +0200170 call WaitForAssert({-> assert_equal("finished", term_getstatus(a:buf))})
Bram Moolenaar645cd3e2020-11-01 20:04:57 +0100171
172 " If the buffer still exists forcefully wipe it.
Bram Moolenaara46765a2020-11-01 20:58:26 +0100173 if a:kill && bufexists(a:buf)
Bram Moolenaar645cd3e2020-11-01 20:04:57 +0100174 exe a:buf .. 'bwipe!'
175 endif
Bram Moolenaar7a39dd72019-06-23 00:50:15 +0200176endfunc
Bram Moolenaarcde0ff32020-04-04 14:00:39 +0200177
Bram Moolenaar1112c0f2020-07-01 21:53:50 +0200178" Open a terminal with a shell, assign the job to g:job and return the buffer
179" number.
180func Run_shell_in_terminal(options)
181 if has('win32')
Milly4f5681d2024-10-20 11:06:00 +0200182 let buf = term_start([&shell, '/D', '/k'], a:options)
Bram Moolenaar1112c0f2020-07-01 21:53:50 +0200183 else
184 let buf = term_start(&shell, a:options)
185 endif
186 let g:test_is_flaky = 1
187
188 let termlist = term_list()
189 call assert_equal(1, len(termlist))
190 call assert_equal(buf, termlist[0])
191
192 let g:job = term_getjob(buf)
193 call assert_equal(v:t_job, type(g:job))
194
195 let string = string({'job': buf->term_getjob()})
196 call assert_match("{'job': 'process \\d\\+ run'}", string)
197
Bram Moolenaarced2b382022-01-13 15:25:32 +0000198 " On slower systems it may take a bit of time before the shell is ready to
199 " accept keys. This mainly matters when using term_sendkeys() next.
200 call TermWait(buf)
201
Bram Moolenaar1112c0f2020-07-01 21:53:50 +0200202 return buf
203endfunc
204
Bram Moolenaar03dfde22021-02-14 13:17:22 +0100205" Return concatenated lines in terminal.
206func Term_getlines(buf, lines)
207 return join(map(a:lines, 'term_getline(a:buf, v:val)'), '')
208endfunc
Bram Moolenaar1112c0f2020-07-01 21:53:50 +0200209
Bram Moolenaar9f145572022-11-27 12:45:41 +0000210
Bram Moolenaarcde0ff32020-04-04 14:00:39 +0200211" vim: shiftwidth=2 sts=2 expandtab