Commit: tests(commondumps): Mark and fold lines in screendump views

3 views
Skip to first unread message

Christian Brabandt

unread,
Feb 10, 2026, 5:01:42 PM (17 hours ago) Feb 10
to vim...@googlegroups.com
tests(commondumps): Mark and fold lines in screendump views

Commit: https://github.com/vim/vim/commit/238b0b0587213f999a56cd096da3be920ef2ff1e
Author: Aliaksei Budavei <0x00...@gmail.com>
Date: Tue Feb 10 22:55:36 2026 +0100

tests(commondumps): Mark and fold lines in screendump views

- Dynamically set mark "`" to pair disparate lines and
initially set marks "`a", "`b", etc. for as many lines in
the difference part. Note that users are free to delete
or change any set alphabetic marks without it affecting
the dynamic updating of mark "`"; alphabetic marks only
serve to help with arriving at "summary" lines, e.g.
"`a````".
- Create a fold for the difference part (but defer to users
the closing of it) so that disparate lines that fit real
estate can be viewed at the same time, as an alternative
to the builtin "s" keystroke that swaps top and bottom
parts in place.
- Fold and mark lines with the "git difftool" extension too.

closes: #19380

Signed-off-by: Aliaksei Budavei <0x00...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/testdir/commondumps.vim b/src/testdir/commondumps.vim
index 3dbdab532..cdf56597f 100644
--- a/src/testdir/commondumps.vim
+++ b/src/testdir/commondumps.vim
@@ -1,5 +1,78 @@
vim9script

+# Query the paired position for the cursor line and use it, if available, for
+# mark "`".
+def TryChangingLastJumpMark(marks: dict<list<number>>)
+ const pos: list<number> = get(marks, line('.'), [])
+ if !empty(pos)
+ setpos("'`", [0, pos[0], pos[1], 0])
+ endif
+enddef
+
+# Fold the difference part and the bottom part when the top and the bottom
+# parts are identical; otherwise, create a fold for the difference part and
+# manage marks for disparate lines: dynamically set mark "`" to pair such
+# lines and initially set "`a", "`b", etc. marks for difference part lines.
+def FoldAndMarkDumpDiffParts()
+ defer call('setpos', ['.', getpos('.')])
+ # Shape the pattern after get_separator() from "terminal.c".
+ const separator: string = '^\(=\+\)\=\s\S.*\.dump\s $'
+ const start_lnum: number = search(separator, 'eW', (line('$') / 2))
+ if start_lnum > 0
+ const end_lnum: number = search(separator, 'eW')
+ if end_lnum > 0
+ # Collect [line_nr, col_nr] pairs (matching the first non-blank column)
+ # from the difference part "bs" and assemble corresponding pairs for the
+ # top part "as" and the bottom part "cs".
+ const parts: list<list<list<number>>> =
+ getline((start_lnum + 1), (end_lnum - 1))
+ ->map((idx: number, s: string) =>
+ [matchlist(s, '\(^\s*\S\)')->get(1, '')->strwidth(), idx])
+ ->reduce(((as: list<number>, bs: list<number>, cs: list<number>) =>
+ (xs: list<list<list<number>>>, pair: list<number>) => {
+ const col_nr: number = pair[0]
+ if col_nr != 0
+ const idx: number = pair[1]
+ xs[0]->add([get(as, idx, as[-1]), col_nr])
+ xs[1]->add([bs[idx], col_nr])
+ xs[2]->add([get(cs, idx, cs[-1]), col_nr])
+ endif
+ return xs
+ })(range(1, (start_lnum - 1)),
+ range((start_lnum + 1), (end_lnum - 1)),
+ range((end_lnum + 1), line('$'))),
+ [[], [], []])
+ if empty(parts[1])
+ setlocal foldenable foldmethod=manual
+ exec 'normal ' .. start_lnum .. 'GzfG'
+ else
+ setlocal nofoldenable foldmethod=manual
+ exec ':' .. start_lnum .. ',' .. end_lnum .. 'fold'
+ var marks: dict<list<number>> = {}
+ var names: list<string> = range(97, (97 + 25))
+ ->map((_: number, n: number) => nr2char(n, true))
+ for idx in range(parts[1]->len())
+ if !empty(names)
+ setpos(("'" .. remove(names, 0)),
+ [0, parts[1][idx][0], parts[1][idx][1], 0])
+ endif
+ # Point "bs" to "cs", "cs" to "as", "as" to "cs".
+ marks[parts[1][idx][0]] = parts[2][idx]
+ marks[parts[2][idx][0]] = parts[0][idx]
+ marks[parts[0][idx][0]] = parts[2][idx]
+ endfor
+ autocmd_add([{
+ replace: true,
+ group: 'viewdumps',
+ event: 'CursorMoved',
+ bufnr: bufnr(),
+ cmd: printf('TryChangingLastJumpMark(%s)', string(marks)),
+ }])
+ endif
+ endif
+ endif
+enddef
+
# See below on how to configure the git difftool extension

# Extend "git difftool" with the capability for loading screendump files.
@@ -16,6 +89,7 @@ if v:progname =~? '\<g\=vimdiff$'
term_dumpload(argv(0))
else
term_dumpdiff(argv(0), argv(1))
+ FoldAndMarkDumpDiffParts()
endif
finally
silent bwipeout 1 2
@@ -83,30 +157,6 @@ endif
# :all


-# Script-local functions
-#
-# Fold the difference part and the bottom part when the top and the bottom
-# parts are identical.
-def FoldDumpDiffCopy()
- try
- normal mc
- # Shape the pattern after get_separator() from "terminal.c".
- const separator: string = '^\(=\+\)\=\s\S.*\.dump\s $'
- const start_lnum: number = search(separator, 'eW', (line('$') / 2))
- if start_lnum > 0
- const end_lnum: number = search(separator, 'eW')
- if end_lnum > 0 && getline((start_lnum + 1), (end_lnum - 1))
- ->filter((_: number, line: string) => line !~ '^\s\+$')
- ->empty()
- setlocal foldenable foldmethod=manual
- exec 'normal ' .. start_lnum .. 'GzfG'
- endif
- endif
- finally
- normal `c
- endtry
-enddef
-
# Render a loaded screendump file or the difference of a loaded screendump
# file and its namesake file from the "dumps" directory.
def Render()
@@ -118,7 +168,7 @@ def Render()
fnamemodify(failed_fname, ':p:h:h') .. '/dumps')
if filereadable(dumps_fname)
term_dumpdiff(failed_fname, dumps_fname)
- FoldDumpDiffCopy()
+ FoldAndMarkDumpDiffParts()
else
term_dumpload(failed_fname)
endif
Reply all
Reply to author
Forward
0 new messages