Respect 'splitbelow' on :Gdiffsplit with argument

When calling :Gdiffsplit with no argument, we always end up with the
work tree version as half of the diff, and it is helpful to position
that consistently.  I generalized this to a consistent older versus
newer ordering when given an argument, but I don't think that has proven
very useful in practice.

This also introduces a minor behavior change where calling the bang
variant in the initial commit now loads an empty version of the buffer,
rather than falling back to the work tree.
This commit is contained in:
Tim Pope
2021-08-28 08:34:40 -04:00
parent 4603d77424
commit d523feebe9
2 changed files with 13 additions and 34 deletions

View File

@@ -6116,28 +6116,6 @@ function! s:diffoff_all(dir) abort
diffoff! diffoff!
endfunction endfunction
function! s:CompareAge(mine, theirs) abort
let scores = {':0': 1, ':1': 2, ':2': 3, ':': 4, ':3': 5}
let mine = substitute(a:mine, '^:', '', '')
let theirs = substitute(a:theirs, '^:', '', '')
let my_score = get(scores, ':'.mine, 0)
let their_score = get(scores, ':'.theirs, 0)
if my_score || their_score
return my_score < their_score ? -1 : my_score != their_score
elseif mine ==# theirs
return 0
endif
let base = s:TreeChomp('merge-base', mine, theirs)
if base ==# mine
return -1
elseif base ==# theirs
return 1
endif
let my_time = +s:TreeChomp('log', '--max-count=1', '--pretty=format:%at', a:mine, '--')
let their_time = +s:TreeChomp('log', '--max-count=1', '--pretty=format:%at', a:theirs, '--')
return my_time < their_time ? -1 : my_time != their_time
endfunction
function! s:IsConflicted() abort function! s:IsConflicted() abort
return len(@%) && !empty(s:ChompDefault('', ['ls-files', '--unmerged', '--', expand('%:p')])) return len(@%) && !empty(s:ChompDefault('', ['ls-files', '--unmerged', '--', expand('%:p')]))
endfunction endfunction
@@ -6218,7 +6196,7 @@ function! fugitive#Diffsplit(autodir, keepfocus, mods, arg, args) abort
let file = s:Relative() let file = s:Relative()
elseif arg ==# ':' elseif arg ==# ':'
exe s:DirCheck() exe s:DirCheck()
let file = s:Relative(':0:') let file = len(commit) ? s:Relative() : s:Relative(s:IsConflicted() ? ':1:' : ':0:')
elseif arg =~# '^:\d$' elseif arg =~# '^:\d$'
exe s:DirCheck() exe s:DirCheck()
let file = s:Relative(arg . ':') let file = s:Relative(arg . ':')
@@ -6231,18 +6209,23 @@ function! fugitive#Diffsplit(autodir, keepfocus, mods, arg, args) abort
return 'echoerr ' . string(v:exception) return 'echoerr ' . string(v:exception)
endtry endtry
endif endif
elseif exists('parents') && len(parents) let mods = s:Mods(a:mods)
let file = parents[-1] elseif exists('parents')
let file = get(parents, -1, s:Relative(repeat('0', 40). ':'))
let mods = s:Mods(a:mods, 'leftabove')
elseif len(commit) elseif len(commit)
let file = s:Relative() let file = s:Relative()
let mods = s:Mods(a:mods, 'rightbelow')
elseif s:IsConflicted() elseif s:IsConflicted()
let file = s:Relative(':1:') let file = s:Relative(':1:')
let mods = s:Mods(a:mods, 'leftabove')
if get(g:, 'fugitive_legacy_commands', 1) if get(g:, 'fugitive_legacy_commands', 1)
let post = 'echohl WarningMsg|echo "Use :Gdiffsplit! for 3 way diff"|echohl NONE|' . post let post = 'echohl WarningMsg|echo "Use :Gdiffsplit! for 3 way diff"|echohl NONE|' . post
endif endif
else else
exe s:DirCheck() exe s:DirCheck()
let file = s:Relative(':0:') let file = s:Relative(':0:')
let mods = s:Mods(a:mods, 'leftabove')
endif endif
let spec = s:Generate(file) let spec = s:Generate(file)
if spec =~# '^fugitive:' && empty(s:DirCommitFile(spec)[2]) if spec =~# '^fugitive:' && empty(s:DirCommitFile(spec)[2])
@@ -6251,11 +6234,6 @@ function! fugitive#Diffsplit(autodir, keepfocus, mods, arg, args) abort
exe pre exe pre
let restore = s:diff_restore() let restore = s:diff_restore()
let w:fugitive_diff_restore = restore let w:fugitive_diff_restore = restore
if len(spec) && s:CompareAge(commit, s:DirCommitFile(spec)[1]) < 0
let mods = s:Mods(mods, 'rightbelow')
else
let mods = s:Mods(mods, 'leftabove')
endif
let mods = (autodir ? s:diff_modifier(2) : '') . mods let mods = (autodir ? s:diff_modifier(2) : '') . mods
if &diffopt =~# 'vertical' if &diffopt =~# 'vertical'
let diffopt = &diffopt let diffopt = &diffopt

View File

@@ -184,10 +184,11 @@ that are part of Git repositories).
:Gdiffsplit [object] Perform a |vimdiff| against the given file, or if a :Gdiffsplit [object] Perform a |vimdiff| against the given file, or if a
commit is given, the current file in that commit. commit is given, the current file in that commit.
With no argument, the version in the index or work With no argument, the version in the index or work
tree is used. The newer of the two files is placed to tree is used, and the work tree version is always
the right or bottom, depending on 'diffopt' and the placed to the right or bottom. A vertical split is
width of the window relative to 'textwidth'. Use used if space permits, and if 'diffopt' does not
Vim's |do| and |dp| to stage and unstage changes. otherwise specify. Use Vim's |do| and |dp| to stage
and unstage changes.
*:Gdiffsplit!* *:Gdiffsplit!*
:Gdiffsplit! Diff against any and all direct ancestors, retaining :Gdiffsplit! Diff against any and all direct ancestors, retaining