vim-patch:9.1.1753: defaults: 'diffopt' option value can be improved (#35727)

Problem:  defaults: 'diffopt' option value can be improved
Solution: Update diffopt defaults to include "indent-heuristic" and
          "inline:char" (Yee Cheng Chin)

The default diff options have not been updated much despite new
functionality having been added to Vim.

- indent-heurstic: This has been enabled by default in Git since
  33de716387 in 2017. Given that Vim uses xdiff from Git, it makes sense
  to track the default configuration from Git.

- inline:char: This turns on character-wise inline highlighting which is
  generally much better than the default inline:simple. It has been
  implemented since vim/vim#16881 and we have not seen reports of any issues
  with it, and it has received good feedbacks.

closes: vim/vim#18255

976b365305

Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
This commit is contained in:
zeertzjq
2025-09-12 11:57:05 +08:00
committed by GitHub
parent 4f10e56cc5
commit cf9b7a37cc
11 changed files with 73 additions and 36 deletions

View File

@@ -160,6 +160,7 @@ BUILD
DEFAULTS
• 'diffopt' default value now includes "indent-heuristic" and "inline:char".
• 'statusline' default is exposed as a statusline expression (previously it
was implemented as an internal C routine).
• 'statusline' includes |vim.diagnostic.status()|

View File

@@ -2182,7 +2182,7 @@ A jump table for the options with a short description can be found at |Q_op|.
security reasons.
*'diffopt'* *'dip'*
'diffopt' 'dip' string (default "internal,filler,closeoff,inline:simple,linematch:40")
'diffopt' 'dip' string (default "internal,filler,closeoff,indent-heuristic,inline:char,linematch:40")
global
Option settings for diff mode. It can consist of the following items.
All are optional. Items must be separated by a comma.

View File

@@ -1936,7 +1936,7 @@ vim.go.dex = vim.go.diffexpr
---
---
--- @type string
vim.o.diffopt = "internal,filler,closeoff,inline:simple,linematch:40"
vim.o.diffopt = "internal,filler,closeoff,indent-heuristic,inline:char,linematch:40"
vim.o.dip = vim.o.diffopt
vim.go.diffopt = vim.o.diffopt
vim.go.dip = vim.go.diffopt

View File

@@ -95,9 +95,10 @@ static bool diff_need_update = false; // ex_diffupdate needs to be called
#define ALL_WHITE_DIFF (DIFF_IWHITE | DIFF_IWHITEALL | DIFF_IWHITEEOL)
#define ALL_INLINE (DIFF_INLINE_NONE | DIFF_INLINE_SIMPLE | DIFF_INLINE_CHAR | DIFF_INLINE_WORD)
#define ALL_INLINE_DIFF (DIFF_INLINE_CHAR | DIFF_INLINE_WORD)
static int diff_flags = DIFF_INTERNAL | DIFF_FILLER | DIFF_CLOSE_OFF | DIFF_LINEMATCH;
static int diff_flags = DIFF_INTERNAL | DIFF_FILLER | DIFF_CLOSE_OFF
| DIFF_LINEMATCH | DIFF_INLINE_CHAR;
static int diff_algorithm = 0;
static int diff_algorithm = XDF_INDENT_HEURISTIC;
static int linematch_lines = 40;
#define LBUFLEN 50 // length of line in diff file

View File

@@ -2374,7 +2374,7 @@ local options = {
{
abbreviation = 'dip',
cb = 'did_set_diffopt',
defaults = 'internal,filler,closeoff,inline:simple,linematch:40',
defaults = 'internal,filler,closeoff,indent-heuristic,inline:char,linematch:40',
-- Keep this in sync with diffopt_changed().
values = {
'filler',

View File

@@ -1249,7 +1249,7 @@ end)
it('diff updates line numbers below filler lines', function()
local screen = Screen.new(40, 14)
exec([[
set diffopt=internal,filler,closeoff
set diffopt=internal,filler
call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
vnew
call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])

View File

@@ -1220,7 +1220,7 @@ describe('CursorLine and CursorLineNr highlights', function()
command('windo diffthis')
screen:expect([[
{7: }{9:line 1 some text }│{7: }{9:^line 1 some text }|
{7: }{4:line 2 mo}{27:Re text!}{4: }│{7: }{4:line 2 mo}{27:re text}{4: }|
{7: }{4:line 2 mo}{27:R}{4:e text}{27:!}{4: }│{7: }{4:line 2 mo}{27:r}{4:e text }|
{7: }{22:extra line! }│{7: }{23:----------------------}|
{7: }extra line! │{7: }extra line! |*2
{7: }last line ... │{7: }last line ... |
@@ -1232,7 +1232,7 @@ describe('CursorLine and CursorLineNr highlights', function()
feed('jjjjj')
screen:expect([[
{7: }line 1 some text │{7: }line 1 some text |
{7: }{4:line 2 mo}{27:Re text!}{4: }│{7: }{4:line 2 mo}{27:re text}{4: }|
{7: }{4:line 2 mo}{27:R}{4:e text}{27:!}{4: }│{7: }{4:line 2 mo}{27:r}{4:e text }|
{7: }{22:extra line! }│{7: }{23:----------------------}|
{7: }extra line! │{7: }extra line! |*2
{7: }last line ... │{7: }last line ... |
@@ -1248,7 +1248,7 @@ describe('CursorLine and CursorLineNr highlights', function()
feed('kkkk')
screen:expect([[
{7: }line 1 some text │{7: }line 1 some text |
{7: }{100:line 2 mo}{101:Re text!}{100: }│{7: }{100:^line 2 mo}{101:re text}{100: }|
{7: }{100:line 2 mo}{101:R}{100:e text}{101:!}{100: }│{7: }{100:^line 2 mo}{101:r}{100:e text }|
{7: }{22:extra line! }│{7: }{23:----------------------}|
{7: }extra line! │{7: }extra line! |*2
{7: }last line ... │{7: }last line ... |

View File

@@ -31,7 +31,7 @@ describe('Diff mode screen with 3 diffs open', function()
before_each(function()
clear()
feed(':set diffopt+=linematch:30<cr>')
feed(':set diffopt=internal,filler,linematch:30<cr>')
feed(':e ' .. fname .. '<cr>')
feed(':vnew ' .. fname_2 .. '<cr>')
feed(':vnew ' .. fname_3 .. '<cr>')
@@ -218,7 +218,7 @@ describe('Diff mode screen with 2 diffs open', function()
describe('setup a diff with 2 files and set linematch:30', function()
before_each(function()
feed(':set diffopt+=linematch:30<cr>')
feed(':set diffopt=internal,filler,linematch:30<cr>')
local f1 = [[
common line
@@ -701,7 +701,7 @@ something
end)
describe('setup a diff with 2 files and set linematch:30', function()
before_each(function()
feed(':set diffopt+=linematch:30<cr>')
feed(':set diffopt=internal,filler,linematch:30<cr>')
local f1 = [[
// abc d
// d
@@ -731,7 +731,7 @@ d
end)
describe('setup a diff with 2 files and set linematch:30, with ignore white', function()
before_each(function()
feed(':set diffopt+=linematch:30<cr>:set diffopt+=iwhiteall<cr>')
feed(':set diffopt=internal,filler,linematch:30,iwhiteall<cr>')
local f1 = [[
void testFunction () {
for (int i = 0; i < 10; i++) {
@@ -767,7 +767,7 @@ void testFunction () {
end)
describe('a diff that would result in multiple groups before grouping optimization', function()
before_each(function()
feed(':set diffopt+=linematch:30<cr>')
feed(':set diffopt=internal,filler,linematch:30<cr>')
local f1 = [[
!A
!B
@@ -806,7 +806,7 @@ void testFunction () {
end)
describe('a diff that would result in multiple groups before grouping optimization', function()
before_each(function()
feed(':set diffopt+=linematch:30<cr>')
feed(':set diffopt=internal,filler,linematch:30<cr>')
local f1 = [[
!A
!B
@@ -845,7 +845,7 @@ void testFunction () {
end)
describe('setup a diff with 2 files and set linematch:10', function()
before_each(function()
feed(':set diffopt+=linematch:10<cr>')
feed(':set diffopt=internal,filler,linematch:10<cr>')
local f1 = [[
common line
HIL
@@ -1024,7 +1024,7 @@ describe('regressions', function()
it("doesn't crash with long lines", function()
clear()
feed(':set diffopt+=linematch:30<cr>')
feed(':set diffopt=internal.filler,linematch:30<cr>')
screen = Screen.new(100, 20)
-- line must be greater than MATCH_CHAR_MAX_LEN
n.api.nvim_buf_set_lines(0, 0, -1, false, { string.rep('a', 1000) .. 'hello' })
@@ -1035,7 +1035,7 @@ describe('regressions', function()
it('properly computes filler lines for hunks bigger than linematch limit', function()
clear()
feed(':set diffopt+=linematch:10<cr>')
feed(':set diffopt=internal,filler,linematch:10<cr>')
screen = Screen.new(100, 20)
local lines = {}
for i = 0, 29 do
@@ -1093,7 +1093,7 @@ describe('regressions', function()
n.exec('rightbelow vnew')
n.api.nvim_buf_set_lines(0, 0, -1, false, { 'hijklm', 'nopqr', 'stuv' })
n.exec([[
set diffopt+=linematch:60
set diffopt=internal,filler,linematch:60
windo diffthis | wincmd t
call feedkeys("Aq\<esc>")
call feedkeys("GAklm\<esc>")

View File

@@ -6,7 +6,7 @@ if exists('s:did_load')
set completeopt=menu,preview
endif
set define=^\\s*#\\s*define
set diffopt=internal,filler,closeoff,inline:simple
set diffopt=internal,filler,closeoff,indent-heuristic,inline:char
set directory^=.
set display=
set fillchars=vert:\|,foldsep:\|,fold:-

View File

@@ -850,6 +850,7 @@ func Test_diff_nomodifiable()
endfunc
func Test_diff_hlID()
set diffopt=internal,filler
new
call setline(1, [1, 2, 3, 'Yz', 'a dxxg',])
diffthis
@@ -892,6 +893,7 @@ func Test_diff_hlID()
call assert_equal(synIDattr(diff_hlID(3, 1), "name"), "")
%bwipe!
set diffopt&
endfunc
func Test_diff_filler()
@@ -1060,18 +1062,18 @@ func Test_diff_screen()
call term_sendkeys(buf, ":set diffopt+=algorithm:histogram\<cr>")
call VerifyScreenDump(buf, 'Test_diff_09', {})
" Test 10-11: normal/indent-heuristic
" Test 10-11: with/without indent-heuristic
call term_sendkeys(buf, ":set diffopt&vim\<cr>")
call WriteDiffFiles(buf, ['', ' def finalize(values)', '', ' values.each do |v|', ' v.finalize', ' end'],
\ ['', ' def finalize(values)', '', ' values.each do |v|', ' v.prepare', ' end', '',
\ ' values.each do |v|', ' v.finalize', ' end'])
call term_sendkeys(buf, ":diffupdate!\<cr>")
call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
call VerifyScreenDump(buf, 'Test_diff_10', {})
call term_sendkeys(buf, ":set diffopt+=internal\<cr>:\<cr>")
call VerifyScreenDump(buf, 'Test_diff_11', {})
" Leave trailing : at commandline!
call term_sendkeys(buf, ":set diffopt+=indent-heuristic\<cr>:\<cr>")
call VerifyScreenDump(buf, 'Test_diff_11', {}, 'one')
call term_sendkeys(buf, ":set diffopt-=indent-heuristic\<cr>:\<cr>")
call VerifyScreenDump(buf, 'Test_diff_10', {}, 'one')
" shouldn't matter, if indent-algorithm comes before or after the algorithm
call term_sendkeys(buf, ":set diffopt&\<cr>")
call term_sendkeys(buf, ":set diffopt+=indent-heuristic,algorithm:patience\<cr>:\<cr>")
@@ -1312,6 +1314,7 @@ func Test_diff_with_syntax()
call writefile(lines, 'Xprogram2.c', 'D')
let lines =<< trim END
set diffopt=internal,filler
edit Xprogram1.c
diffsplit Xprogram2.c
END
@@ -1454,9 +1457,7 @@ func Test_diff_rnu()
CheckScreendump
let content =<< trim END
call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
vnew
call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])
set diffopt=internal,filler
call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
vnew
call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])
@@ -1544,6 +1545,7 @@ endfunc
" Test for adding/removing lines inside diff chunks, between diff chunks
" and before diff chunks
func Test_diff_modify_chunks()
set diffopt=internal,filler
enew!
let w2_id = win_getid()
call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
@@ -1623,6 +1625,7 @@ func Test_diff_modify_chunks()
call assert_equal(['', '', '', '', '', '', '', '', ''], hl)
%bw!
set diffopt&
endfunc
func Test_diff_binary()
@@ -2616,7 +2619,7 @@ func Test_linematch_diff()
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
" enable linematch
call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:30\<CR>")
@@ -2644,7 +2647,7 @@ func Test_linematch_diff_iwhite()
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
" setup a diff with 2 files and set linematch:30, with ignore white
call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:30\<CR>")
@@ -2671,7 +2674,7 @@ func Test_linematch_diff_grouping()
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
" a diff that would result in multiple groups before grouping optimization
call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:30\<CR>")
@@ -2709,7 +2712,7 @@ func Test_linematch_diff_scroll()
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
" a diff that would result in multiple groups before grouping optimization
call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:30\<CR>")
@@ -2740,7 +2743,7 @@ func Test_linematch_line_limit_exceeded()
call delete('.Xdifile1.swp')
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:10\<CR>")
@@ -2792,7 +2795,7 @@ func Test_linematch_3diffs()
call delete('.Xdifile3.swp')
call WriteDiffFiles3(0, [], [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
call term_sendkeys(buf, "1\<c-w>w:set autoread\<CR>")
call term_sendkeys(buf, "1\<c-w>w:set autoread\<CR>")
call term_sendkeys(buf, "2\<c-w>w:set autoread\<CR>")
call term_sendkeys(buf, "3\<c-w>w:set autoread\<CR>")
call term_sendkeys(buf, ":set diffopt=internal,filler,linematch:30\<CR>")
@@ -2827,7 +2830,7 @@ func Test_linematch_3diffs_sanity_check()
func Test_linematch_3diffs_sanity_check()
CheckScreendump
call delete('.Xfile_linematch1.swp')
call delete('.Xfile_linematch2.swp')
call delete('.Xfile_linematch2.swp')
call delete('.Xfile_linematch3.swp')
let lines =<< trim END
set diffopt=internal,filler,linematch:60

View File

@@ -302,11 +302,43 @@ func Test_smoothscroll_diff_mode()
call StopVimInTerminal(buf)
endfunc
func Test_smoothscroll_diff_change_line_default()
CheckScreendump
" Uses the new diffopt default with indent-heuristic and inline:char
let lines =<< trim END
set diffopt=internal,filler,closeoff,indent-heuristic,inline:char,followwrap smoothscroll
call setline(1, repeat(' abc', &columns))
call setline(2, 'bar')
call setline(3, repeat(' abc', &columns))
vnew
call setline(1, repeat(' abc', &columns))
call setline(2, 'foo')
call setline(3, 'bar')
call setline(4, repeat(' abc', &columns))
windo exe "normal! 2gg5\<C-E>"
windo diffthis
END
call writefile(lines, 'XSmoothDiffChangeLine', 'D')
let buf = RunVimInTerminal('-S XSmoothDiffChangeLine', #{rows: 20, columns: 55})
call VerifyScreenDump(buf, 'Test_smooth_diff_change_line_1', {})
call term_sendkeys(buf, "Abar")
call VerifyScreenDump(buf, 'Test_smooth_diff_change_line_2', {})
call term_sendkeys(buf, "\<Esc>")
call VerifyScreenDump(buf, 'Test_smooth_diff_change_line_3a', {})
call term_sendkeys(buf, "yyp")
call VerifyScreenDump(buf, 'Test_smooth_diff_change_line_4', {})
call StopVimInTerminal(buf)
endfunc
func Test_smoothscroll_diff_change_line()
CheckScreendump
" Uses the old diffopt default
let lines =<< trim END
set diffopt+=followwrap smoothscroll
set diffopt=internal,filler,closeoff,followwrap,inline:simple smoothscroll
call setline(1, repeat(' abc', &columns))
call setline(2, 'bar')
call setline(3, repeat(' abc', &columns))