mirror of
https://github.com/neovim/neovim.git
synced 2025-10-05 01:16:31 +00:00
vim-patch:9.1.1557: not possible to anchor specific lines in diff mode (#34967)
Problem: not possible to anchor specific lines in diff mode
Solution: Add support for the anchoring lines in diff mode using the
'diffanchor' option (Yee Cheng Chin).
Adds support for anchoring specific lines to each other while viewing a
diff. While lines are anchored, they are guaranteed to be aligned to
each other in a diff view, allowing the user to control and inform the
diff algorithm what the desired alignment is. Internally, this is done
by splitting up the buffer at each anchor and run the diff algorithm on
each split section separately, and then merge the results back for a
logically consistent diff result.
To do this, add a new "diffanchors" option that takes a list of
`{address}`, and a new "diffopt" option value "anchor". Each address
specified will be an anchor, and the user can choose to use any type of
address, including marks, line numbers, or pattern search. Anchors are
sorted by line number in each file, and it's possible to have multiple
anchors on the same line (this is useful when doing multi-buffer diff).
Update documentation to provide examples.
This is similar to Git diff's `--anchored` flag. Other diff tools like
Meld/Araxis Merge also have similar features (called "synchronization
points" or "synchronization links"). We are not using Git/Xdiff's
`--anchored` implementation here because it has a very limited API
(it requires usage of the Patience algorithm, and can only anchor
unique lines that are the same across both files).
Because the user could anchor anywhere, diff anchors could result in
adjacent diff blocks (one block is directly touching another without a
gap), if there is a change right above the anchor point. We don't want
to merge these diff blocks because we want to line up the change at the
anchor. Adjacent diff blocks were first allowed when linematch was
added, but the existing code had a lot of branched paths where
line-matched diff blocks were handled differently. As a part of this
change, refactor them to have a more unified code path that is
generalized enough to handle adjacent diff blocks correctly and without
needing to carve in exceptions all over the place.
closes: vim/vim#17615
0d9160e11c
Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
This commit is contained in:
@@ -2244,6 +2244,36 @@ local options = {
|
||||
short_desc = N_('diff mode for the current window'),
|
||||
type = 'boolean',
|
||||
},
|
||||
{
|
||||
abbreviation = 'dia',
|
||||
cb = 'did_set_diffanchors',
|
||||
defaults = '',
|
||||
desc = [=[
|
||||
List of {address} in each buffer, separated by commas, that are
|
||||
considered anchors when used for diffing. It's valid to specify "$+1"
|
||||
for 1 past the last line. "%" cannot be used for this option. There
|
||||
can be at most 20 anchors set for each buffer.
|
||||
|
||||
Each anchor line splits the buffer (the split happens above the
|
||||
anchor), with each part being diff'ed separately before the final
|
||||
result is joined. When more than one {address} are provided, the
|
||||
anchors will be sorted interally by line number. If using buffer
|
||||
local options, each buffer should have the same number of anchors
|
||||
(extra anchors will be ignored). This option is only used when
|
||||
'diffopt' has "anchor" set. See |diff-anchors| for more details and
|
||||
examples.
|
||||
*E1550*
|
||||
If some of the {address} do not resolve to a line in each buffer (e.g.
|
||||
a pattern search that does not match anything), none of the anchors
|
||||
will be used.
|
||||
]=],
|
||||
full_name = 'diffanchors',
|
||||
list = 'onecomma',
|
||||
scope = { 'global', 'buf' },
|
||||
short_desc = N_('list of addresses for anchoring a diff'),
|
||||
type = 'string',
|
||||
varname = 'p_dia',
|
||||
},
|
||||
{
|
||||
abbreviation = 'dex',
|
||||
cb = 'did_set_optexpr',
|
||||
@@ -2269,6 +2299,7 @@ local options = {
|
||||
-- Keep this in sync with diffopt_changed().
|
||||
values = {
|
||||
'filler',
|
||||
'anchor',
|
||||
'context:',
|
||||
'iblank',
|
||||
'icase',
|
||||
@@ -2301,6 +2332,10 @@ local options = {
|
||||
patience patience diff algorithm
|
||||
histogram histogram diff algorithm
|
||||
|
||||
anchor Anchor specific lines in each buffer to be
|
||||
aligned with each other if 'diffanchors' is
|
||||
set. See |diff-anchors|.
|
||||
|
||||
closeoff When a window is closed where 'diff' is set
|
||||
and there is only one window remaining in the
|
||||
same tab page with 'diff' set, execute
|
||||
@@ -2403,6 +2438,7 @@ local options = {
|
||||
"linematch:60", as this will enable alignment
|
||||
for a 2 buffer diff hunk of 30 lines each,
|
||||
or a 3 buffer diff hunk of 20 lines each.
|
||||
Implicitly sets "filler" when this is set.
|
||||
|
||||
vertical Start diff mode with vertical splits (unless
|
||||
explicitly specified otherwise).
|
||||
|
Reference in New Issue
Block a user