runtime(syntax-tests): Allow for folded and wrapped lines in syntax test files
The current implementation falls short for syntax test files
on two accounts:
1. With folded lines -- some lines before folded lines are
unnecessarily repeated in generated dump files because
closed folded lines are always treated as opened for the
cursor to move _in_ instead of to move _over_ them.
2. With wrapped lines (longer than 75 columns) -- some lines
are omitted in generated dump files because calculations
for the cursor progress and its movement commands only
refer to file lines and not their layout within a 20x75
buffer (less &cmdheight).
As an alternative, we abandon deterministic (and inaccurate
at times) calculations for the cursor progress and, instead,
advance the cursor by as much as before for a single dump
file, but now rely on marking the last visible line and
additional movement to position lines at desired offsets,
carefully preserving compatibility for the &scrolloff and
&ruler values inherited from defaults.vim. The parent Vim
process will keep track of progress through a syntax test
file made by its child process ("terminal") by reading the
rightmost end of the ruler line from the terminal buffer,
looking for " All " or " Bot " for its cue to finish dump
file generation.
With these changes applied, the lossless line length limit
will be raised from 75 to 1425 (for a 19x75 view) columns.
Also, prefer "lastline" to "truncate" for &display; hiding
the content of any last _long_ line in a view goes against
the purpose of syntax file testing -- all lines should be
recorded.
related: #15150
fixes: #14245
Signed-off-by: Aliaksei Budavei <0x000c70@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/runtime/syntax/testdir/runtest.vim b/runtime/syntax/testdir/runtest.vim
index e1cfdcf..32b1663 100644
--- a/runtime/syntax/testdir/runtest.vim
+++ b/runtime/syntax/testdir/runtest.vim
@@ -85,6 +85,28 @@
endif
endfunc
+def IsWinNumOneAtEOF(in_name_and_out_name: string): bool
+ # Expect defaults from term_util#RunVimInTerminal().
+ if winwidth(1) != 75 || winheight(1) != 20
+ ch_log(printf('Aborting for %s: (75 x 20) != (%d x %d)',
+ in_name_and_out_name,
+ winwidth(1),
+ winheight(1)))
+ return true
+ endif
+ # A two-fold role: (1) redraw whenever the first test file is of 19 lines or
+ # less long (not applicable to c.c); (2) redraw in case the terminal buffer
+ # cannot redraw itself just yet (else expect extra files generated).
+ redraw
+ const pos: string = join([
+ screenstring(20, 71),
+ screenstring(20, 72),
+ screenstring(20, 73),
+ screenstring(20, 74),
+ screenstring(20, 75)], '')
+ return (pos == ' All ' || pos == ' Bot ')
+enddef
+
func RunTest()
let ok_count = 0
let failed_tests = []
@@ -100,7 +122,6 @@
continue
endif
- let linecount = readfile(fname)->len()
let root = fnamemodify(fname, ':t:r')
let filetype = substitute(root, '\([^_.]*\)[_.].*', '\1', '')
let failed_root = 'failed/' .. root
@@ -160,11 +181,93 @@
call cursor(1, 1)
" BEGIN [runtime/defaults.vim]
" Also, disable italic highlighting to avoid issues on some terminals.
- set display=truncate ruler scrolloff=5 t_ZH= t_ZR=
+ set display=lastline ruler scrolloff=5 t_ZH= t_ZR=
syntax on
" END [runtime/defaults.vim]
redraw!
endfunc
+
+ def ScrollToSecondPage(estate: number, op_wh: number, op_so: number)
+ if line('.') != 1 || line('w$') >= line('$')
+ return
+ endif
+ try
+ set scrolloff=0
+ # Advance mark "c"[ursor] along with the cursor.
+ norm! Lmc
+ if foldclosed('.') < 0 &&
+ (strdisplaywidth(getline('.')) + &l:fdc * winheight(1)) >= estate
+ # Make for an exit for a screenful long line.
+ norm! j^
+ return
+ else
+ # Place the cursor on the actually last visible line.
+ while winline() < op_wh
+ const lastnum: number = winline()
+ norm! gjmc
+ if lastnum > winline()
+ break
+ endif
+ endwhile
+ norm! zt
+ endif
+ finally
+ # COMPATIBILITY: Scroll up around "scrolloff" lines.
+ &scrolloff = max([1, op_so])
+ endtry
+ norm! ^
+ enddef
+
+ def ScrollToNextPage(estate: number, op_wh: number, op_so: number)
+ if line('.') == 1 || line('w$') >= line('$')
+ return
+ endif
+ try
+ set scrolloff=0
+ # Advance mark "c"[ursor] along with the cursor.
+ norm! Lmc
+ if foldclosed('.') < 0 &&
+ (strdisplaywidth(getline('.')) + &l:fdc * winheight(1)) >= estate
+ # Make for an exit for a screenful long line.
+ norm! j^
+ return
+ else
+ # Place the cursor on the actually last visible line.
+ while winline() < op_wh
+ const lastnum: number = winline()
+ norm! gjmc
+ if lastnum > winline()
+ break
+ endif
+ endwhile
+ endif
+ finally
+ # COMPATIBILITY: Scroll up/down around "scrolloff" lines.
+ &scrolloff = max([1, op_so])
+ endtry
+ norm! zt
+ const marknum: number = line("'c")
+ # Eschew &smoothscroll since line("`c") is not supported.
+ # Remember that "w0" can point to the first line of a _closed_ fold
+ # whereas the last line of a _closed_ fold can be marked.
+ if line('w0') > marknum
+ while line('w0') > marknum
+ exe "norm! \<C-y>"
+ endwhile
+ if line('w0') != marknum
+ exe "norm! \<C-e>H"
+ endif
+ # Handle non-wrapped lines.
+ elseif line('w0') < marknum
+ while line('w0') < marknum
+ exe "norm! \<C-e>"
+ endwhile
+ if line('w0') != marknum
+ exe "norm! \<C-y>H"
+ endif
+ endif
+ norm! ^
+ enddef
END
call writefile(lines, 'Xtestscript')
@@ -198,25 +301,37 @@
" Screendump at the start of the file: failed/root_00.dump
let root_00 = root .. '_00'
- call ch_log('First screendump for ' .. fname .. ': failed/' .. root_00 .. '.dump')
+ let in_name_and_out_name = fname .. ': failed/' .. root_00 .. '.dump'
+ call ch_log('First screendump for ' .. in_name_and_out_name)
let fail = VerifyScreenDump(buf, root_00, {})
- " clear the shell info if there are not enough lines to cause a scroll
- if filetype == 'sh' && linecount <= 19
+ " Clear the shell info if there are not enough lines to cause a scroll
+ if filetype == 'sh' && IsWinNumOneAtEOF(in_name_and_out_name)
call term_sendkeys(buf, ":redraw\<CR>")
endif
" Make a Screendump every 18 lines of the file: failed/root_NN.dump
- let topline = 1
let nr = 1
- while linecount - topline > 20
- let topline += 18
- call term_sendkeys(buf, printf("%dGzt", topline))
- let root_next = root .. printf('_%02d', nr)
- call ch_log('Next screendump for ' .. fname .. ': failed/' .. root_next .. '.dump')
+ let root_next = printf('%s_%02d', root, nr)
+ let in_name_and_out_name = fname .. ': failed/' .. root_next .. '.dump'
+
+ if !IsWinNumOneAtEOF(in_name_and_out_name)
+ call term_sendkeys(buf, ":call ScrollToSecondPage((18 * 75 + 1), 19, 5) | redraw!\<CR>")
+ call ch_log('Next screendump for ' .. in_name_and_out_name)
let fail += VerifyScreenDump(buf, root_next, {})
let nr += 1
- endwhile
+ let root_next = printf('%s_%02d', root, nr)
+ let in_name_and_out_name = fname .. ': failed/' .. root_next .. '.dump'
+
+ while !IsWinNumOneAtEOF(in_name_and_out_name)
+ call term_sendkeys(buf, ":call ScrollToNextPage((18 * 75 + 1), 19, 5) | redraw!\<CR>")
+ call ch_log('Next screendump for ' .. in_name_and_out_name)
+ let fail += VerifyScreenDump(buf, root_next, {})
+ let nr += 1
+ let root_next = printf('%s_%02d', root, nr)
+ let in_name_and_out_name = fname .. ': failed/' .. root_next .. '.dump'
+ endwhile
+ endif
" Screendump at the end of the file: failed/root_99.dump
call term_sendkeys(buf, 'Gzb')