xref: /vim-8.2.3635/src/testdir/term_util.vim (revision 9faec4e3)
1" Functions about terminal shared by several tests
2
3" Only load this script once.
4if exists('*CanRunVimInTerminal')
5  finish
6endif
7
8source shared.vim
9
10" 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)
26  call WaitFor({-> job_status(job) == "dead"})
27endfunc
28
29" Wrapper around term_wait() to allow more time for re-runs of flaky tests
30" The second argument is the minimum time to wait in msec, 10 if omitted.
31func TermWait(buf, ...)
32  let wait_time = a:0 ? a:1 : 10
33  if exists('g:run_nr')
34    if g:run_nr == 2
35      let wait_time *= 4
36    elseif g:run_nr > 2
37      let wait_time *= 10
38    endif
39  endif
40  call term_wait(a:buf, wait_time)
41
42  " In case it wasn't set yet.
43  let g:test_is_flaky = 1
44endfunc
45
46" Run Vim with "arguments" in a new terminal window.
47" By default uses a size of 20 lines and 75 columns.
48" Returns the buffer number of the terminal.
49"
50" Options is a dictionary, these items are recognized:
51" "keep_t_u7" - when 1 do not make t_u7 empty (resetting t_u7 avoids clearing
52"               parts of line 2 and 3 on the display)
53" "rows" - height of the terminal window (max. 20)
54" "cols" - width of the terminal window (max. 78)
55" "statusoff" - number of lines the status is offset from default
56" "wait_for_ruler" - if zero then don't wait for ruler to show
57func RunVimInTerminal(arguments, options)
58  " If Vim doesn't exit a swap file remains, causing other tests to fail.
59  " Remove it here.
60  call delete(".swp")
61
62  if exists('$COLORFGBG')
63    " Clear $COLORFGBG to avoid 'background' being set to "dark", which will
64    " only be corrected if the response to t_RB is received, which may be too
65    " late.
66    let $COLORFGBG = ''
67  endif
68
69  " Make a horizontal and vertical split, so that we can get exactly the right
70  " size terminal window.  Works only when the current window is full width.
71  call assert_equal(&columns, winwidth(0))
72  split
73  vsplit
74
75  " Always do this with 256 colors and a light background.
76  set t_Co=256 background=light
77  hi Normal ctermfg=NONE ctermbg=NONE
78
79  " Make the window 20 lines high and 75 columns, unless told otherwise or
80  " 'termwinsize' is set.
81  let rows = get(a:options, 'rows', 20)
82  let cols = get(a:options, 'cols', 75)
83  let statusoff = get(a:options, 'statusoff', 1)
84
85  if get(a:options, 'keep_t_u7', 0)
86    let reset_u7 = ''
87  else
88    let reset_u7 = ' --cmd "set t_u7=" '
89  endif
90
91  let cmd = GetVimCommandCleanTerm() .. reset_u7 .. a:arguments
92
93  let options = #{curwin: 1}
94  if &termwinsize == ''
95    let options.term_rows = rows
96    let options.term_cols = cols
97  endif
98
99  " Accept other options whose name starts with 'term_'.
100  call extend(options, filter(copy(a:options), 'v:key =~# "^term_"'))
101
102  let buf = term_start(cmd, options)
103
104  if &termwinsize == ''
105    " in the GUI we may end up with a different size, try to set it.
106    if term_getsize(buf) != [rows, cols]
107      call term_setsize(buf, rows, cols)
108    endif
109    call assert_equal([rows, cols], term_getsize(buf))
110  else
111    let rows = term_getsize(buf)[0]
112    let cols = term_getsize(buf)[1]
113  endif
114
115  call TermWait(buf)
116
117  if get(a:options, 'wait_for_ruler', 1)
118    " Wait for "All" or "Top" of the ruler to be shown in the last line or in
119    " the status line of the last window. This can be quite slow (e.g. when
120    " using valgrind).
121    " If it fails then show the terminal contents for debugging.
122    try
123      call WaitFor({-> len(term_getline(buf, rows)) >= cols - 1 || len(term_getline(buf, rows - statusoff)) >= cols - 1})
124    catch /timed out after/
125      let lines = map(range(1, rows), {key, val -> term_getline(buf, val)})
126      call assert_report('RunVimInTerminal() failed, screen contents: ' . join(lines, "<NL>"))
127    endtry
128  endif
129
130  " Starting a terminal to run Vim is always considered flaky.
131  let g:test_is_flaky = 1
132
133  return buf
134endfunc
135
136" Stop a Vim running in terminal buffer "buf".
137func StopVimInTerminal(buf, kill = 1)
138  " Using a terminal to run Vim is always considered flaky.
139  let g:test_is_flaky = 1
140
141  call assert_equal("running", term_getstatus(a:buf))
142
143  " CTRL-O : works both in Normal mode and Insert mode to start a command line.
144  " In Command-line it's inserted, the CTRL-U removes it again.
145  call term_sendkeys(a:buf, "\<C-O>:\<C-U>qa!\<cr>")
146
147  " Wait for all the pending updates to terminal to complete
148  call TermWait(a:buf)
149
150  " Wait for the terminal to end.
151  call WaitForAssert({-> assert_equal("finished", term_getstatus(a:buf))})
152
153  " If the buffer still exists forcefully wipe it.
154  if a:kill && bufexists(a:buf)
155    exe a:buf .. 'bwipe!'
156  endif
157endfunc
158
159" Open a terminal with a shell, assign the job to g:job and return the buffer
160" number.
161func Run_shell_in_terminal(options)
162  if has('win32')
163    let buf = term_start([&shell,'/k'], a:options)
164  else
165    let buf = term_start(&shell, a:options)
166  endif
167  let g:test_is_flaky = 1
168
169  let termlist = term_list()
170  call assert_equal(1, len(termlist))
171  call assert_equal(buf, termlist[0])
172
173  let g:job = term_getjob(buf)
174  call assert_equal(v:t_job, type(g:job))
175
176  let string = string({'job': buf->term_getjob()})
177  call assert_match("{'job': 'process \\d\\+ run'}", string)
178
179  return buf
180endfunc
181
182" Return concatenated lines in terminal.
183func Term_getlines(buf, lines)
184  return join(map(a:lines, 'term_getline(a:buf, v:val)'), '')
185endfunc
186
187" vim: shiftwidth=2 sts=2 expandtab
188