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 183" vim: shiftwidth=2 sts=2 expandtab 184