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