blob: 3dbdab5328af126c1e44e7e0c57cad59b3025700 [file] [log] [blame]
Aliaksei Budavei6bff6a22024-08-19 21:33:26 +02001vim9script
2
Aliaksei Budavei5eaacef2025-01-11 17:10:06 +01003# See below on how to configure the git difftool extension
4
5# Extend "git difftool" with the capability for loading screendump files.
6if v:progname =~? '\<g\=vimdiff$'
7 # Let "(g)vimdiff" render other files.
8 if [argv(0), argv(1)]
9 ->filter((_: number, fname: string) =>
10 fname =~? '^\%(/dev/null\|.\+\.dump\)$')
11 ->len() == 2
12 try
13 if argv(0) ==? '/dev/null'
14 term_dumpload(argv(1))
15 elseif argv(1) ==? '/dev/null'
16 term_dumpload(argv(0))
17 else
18 term_dumpdiff(argv(0), argv(1))
19 endif
20 finally
21 silent bwipeout 1 2
22 endtry
23 endif
24
25 # Always stop from further sourcing this script for "(g)vimdiff".
26 finish
27endif
28
29# CONSIDER ALTERNATIVES FOR ENABLING THE ABOVE EXTENSION.
Aliaksei Budavei6bff6a22024-08-19 21:33:26 +020030#
Aliaksei Budavei5eaacef2025-01-11 17:10:06 +010031# For convenience, it is assumed that there is a defined "$VIM_FORK_PATHNAME"
32# environment variable holding an absolute pathname for the root directory of
33# this repository.
34#
35#
36# A. USE Git FOR CONFIGURATION.
37#
38# Define the following Git variables with "git config --edit --local" (where
39# the "vimdumps" name is arbitrary):
40#
41# ------------------------------------------------------------------------------
42# [diff]
43# tool = vimdumps
44# [difftool.vimdumps]
45# cmd = vimdiff -S "${VIM_FORK_PATHNAME:?}"/src/testdir/commondumps.vim -o -- "$LOCAL" "$REMOTE"
46# ------------------------------------------------------------------------------
47#
48# Rendered screendump files (among other files) between revisions can now be
49# compared, two at a time, by using "git difftool", e.g.:
50# git difftool 50423ab8~1 50423ab8
51# git difftool 50423ab8~1 50423ab8 -- '**/*.dump'
52#
53# The raw files can also be examined:
54# :all
55#
56#
57# B. USE Bash FOR CONFIGURATION (on Debian GNU/Linux).
58#
59# 1. Make an alias that sources this file, e.g.:
60# alias git_vimdiff="git difftool -x 'vimdiff -S "${VIM_FORK_PATHNAME:?}"/vim/src/testdir/commondumps.vim -o --'"
61#
62# 2. Enable programmable completion for the alias, e.g.:
63# cat ~/.local/share/bash-completion/completions/git_vimdiff
64#
65# ------------------------------------------------------------------------------
66# ## Consider (un)setting "$BASH_COMPLETION_USER_DIR" and/or "$XDG_DATA_HOME" so
67# ## that this file can be found and sourced; look for these variables in the
68# ## "/usr/share/bash-completion/bash_completion" script.
69# ##
70# ## Look for __git_complete() examples in the header comment of the sourced
71# ## "/usr/share/bash-completion/completions/git" script.
72# [ -r /usr/share/bash-completion/completions/git ] &&
73# . /usr/share/bash-completion/completions/git &&
74# __git_complete git_vimdiff _git_difftool
75# ------------------------------------------------------------------------------
76#
77# Rendered screendump files (among other files) between revisions can now be
78# compared, two at a time, by using the alias, e.g.:
79# git_vimdiff 50423ab8~1 50423ab8
80# git_vimdiff 50423ab8~1 50423ab8 -- '**/*.dump'
81#
82# The raw files can also be examined:
83# :all
84
85
86# Script-local functions
87#
88# Fold the difference part and the bottom part when the top and the bottom
89# parts are identical.
90def FoldDumpDiffCopy()
91 try
92 normal mc
93 # Shape the pattern after get_separator() from "terminal.c".
94 const separator: string = '^\(=\+\)\=\s\S.*\.dump\s\1$'
95 const start_lnum: number = search(separator, 'eW', (line('$') / 2))
96 if start_lnum > 0
97 const end_lnum: number = search(separator, 'eW')
98 if end_lnum > 0 && getline((start_lnum + 1), (end_lnum - 1))
99 ->filter((_: number, line: string) => line !~ '^\s\+$')
100 ->empty()
101 setlocal foldenable foldmethod=manual
102 exec 'normal ' .. start_lnum .. 'GzfG'
103 endif
104 endif
105 finally
106 normal `c
107 endtry
108enddef
109
Aliaksei Budavei6bff6a22024-08-19 21:33:26 +0200110# Render a loaded screendump file or the difference of a loaded screendump
111# file and its namesake file from the "dumps" directory.
112def Render()
113 const failed_fname: string = bufname()
114 try
115 setlocal suffixesadd=.dump
116 const dumps_fname: string = findfile(
117 fnamemodify(failed_fname, ':p:t'),
118 fnamemodify(failed_fname, ':p:h:h') .. '/dumps')
119 if filereadable(dumps_fname)
120 term_dumpdiff(failed_fname, dumps_fname)
Aliaksei Budavei5eaacef2025-01-11 17:10:06 +0100121 FoldDumpDiffCopy()
Aliaksei Budavei6bff6a22024-08-19 21:33:26 +0200122 else
123 term_dumpload(failed_fname)
124 endif
125 finally
126 exec 'bwipeout ' .. failed_fname
127 endtry
128enddef
129
Aliaksei Budavei5eaacef2025-01-11 17:10:06 +0100130# Public functions
131#
Aliaksei Budavei6bff6a22024-08-19 21:33:26 +0200132# Search for the "failed" directory in the passed _subtreedirname_ directories
133# (usually "\<src\>" or "\<syntax\>") and, if found, select its passed _count_
zeertzjq8feed3a2024-09-29 10:37:47 +0200134# occurrence, add all its "*.dump" files to the argument list and list them;
Aliaksei Budavei6bff6a22024-08-19 21:33:26 +0200135# also define a BufRead autocommand that would invoke "Render()" for every
136# "*.dump" file.
137def g:Init(subtreedirname: string, count: number)
138 # Support sourcing this script from any directory in the direct path that
139 # leads to the project's root directory.
140 const failed_path: string = finddir('failed', getcwd() .. '/**', -1)
141 ->filter(((cwdpath: string, parentdirname: string) =>
142 (_: number, dirpath: string) =>
143 cwdpath =~ parentdirname || dirpath =~ parentdirname)(
144 getcwd(),
145 subtreedirname))
146 ->get(count, '') .. '/'
147 var error: string = null_string
148
149 if failed_path == '/'
150 error = 'No such directory: "failed"'
151 else
152 const failed_fnames: string = failed_path .. readdir(failed_path,
153 (fname: string) => fname =~ '^.\+\.dump$')
154 ->join(' ' .. failed_path)
155
156 if failed_fnames =~ 'failed/$'
157 error = 'No such file: "*.dump"'
158 else
159 exec ':0argedit ' .. failed_fnames
160 buffers
161 endif
162 endif
163
164 autocmd_add([{
165 replace: true,
166 group: 'viewdumps',
167 event: 'BufRead',
168 pattern: '*.dump',
169 cmd: 'Render()',
170 }])
171
172 # Unconditionally help, in case a list of filenames is passed to the
173 # command, the first terminal window with its BufRead event.
174 silent doautocmd viewdumps BufRead
175
176 if error != null_string
177 # Instead of sleeping, fill half a window with blanks and prompt
178 # hit-enter.
179 echom error .. repeat("\x20",
180 (winwidth(0) * (winheight(0) / 2) - strlen(error)))
181 endif
182enddef
183
zeertzjq3e5bbb82024-10-22 23:11:27 +0200184# vim:fdm=syntax:sw=2:ts=8:noet:nosta: