diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim index f442c8e..4ec7a88 100644 --- a/autoload/fugitive.vim +++ b/autoload/fugitive.vim @@ -1806,7 +1806,6 @@ function! fugitive#BufReadStatus() abort endif let b:dispatch = ':Gfetch --all' call fugitive#MapJumps() - let nowait = v:version >= 704 ? '' : '' call s:Map('n', '-', ":execute Do('Toggle',0)", '') call s:Map('x', '-', ":execute Do('Toggle',1)", '') call s:Map('n', 's', ":execute Do('Stage',0)", '') @@ -2928,19 +2927,19 @@ function! s:StageDiff(diff) abort return 'Git! diff --no-ext-diff' elseif len(info.paths) > 1 execute 'Gedit' . prefix s:fnameescape(':0:' . info.paths[0]) - return a:diff.' HEAD:'.s:fnameescape(info.paths[1]) + return a:diff.'! HEAD:'.s:fnameescape(info.paths[1]) elseif info.section ==# 'Staged' && info.sigil ==# '-' - execute 'Gedit' prefix s:fnameescape('@:'.info.paths[0]) + execute 'Gedit' prefix s:fnameescape(':0:'.info.paths[0]) return a:diff.'! :0:%' elseif info.section ==# 'Staged' execute 'Gedit' prefix s:fnameescape(':0:'.info.paths[0]) - return a:diff . (info.sigil ==# '+' ? '!' : '') . ' @:%' + return a:diff . '! @:%' elseif info.sigil ==# '-' execute 'Gedit' prefix s:fnameescape(':0:'.info.paths[0]) - return a:diff . '!' + return a:diff . '! :(top)%' else execute 'Gedit' prefix s:fnameescape(':(top)'.info.paths[0]) - return a:diff . (info.sigil ==# '+' ? '!' : '') + return a:diff . '!' endif endfunction @@ -4405,23 +4404,37 @@ function! s:Diff(autodir, keepfocus, mods, ...) abort let mods = 'keepalt ' . a:mods endif let back = exists('*win_getid') ? 'call win_gotoid(' . win_getid() . ')' : 'wincmd p' - if (empty(args) || args[0] ==# ':') && commit =~# '^[0-1]\=$' && a:keepfocus && s:IsConflicted() - let mods = (a:autodir ? s:diff_modifier(3) : '') . s:Mods(mods, 'leftabove') + if (empty(args) || args[0] ==# ':') && a:keepfocus + if empty(commit) && s:IsConflicted() + let parents = [s:Relative(':2:'), s:Relative(':3:')] + elseif empty(commit) + let parents = [s:Relative(':0:')] + elseif commit =~# '^\d\=$' + let parents = [s:Relative('HEAD:')] + elseif commit =~# '^\x\x\+$' + let parents = s:LinesError(['rev-parse', commit . '^@'])[0] + call map(parents, 's:Relative(v:val . ":")') + endif + endif + if exists('parents') && len(parents) > 1 + let mods = (a:autodir ? s:diff_modifier(len(parents) + 1) : '') . s:Mods(mods, 'leftabove') let nr = bufnr('') - execute mods 'split' s:fnameescape(s:Generate(s:Relative(':2:'))) + execute mods 'split' s:fnameescape(s:Generate(parents[0])) call s:Map('n', 'dp', ':diffput '.nr.'diffupdate', '') let nr2 = bufnr('') call s:diffthis() exe back - let mods = substitute(mods, '\Cleftabove\|rightbelow\|aboveleft\|belowright', '\=submatch(0) =~# "f" ? "rightbelow" : "leftabove"', '') - execute mods 'split' s:fnameescape(s:Generate(s:Relative(':3:'))) - call s:Map('n', 'dp', ':diffput '.nr.'diffupdate', '') - let nr3 = bufnr('') - call s:diffthis() - exe back - call s:diffthis() call s:Map('n', 'd2o', ':diffget '.nr2.'diffupdate', '') - call s:Map('n', 'd3o', ':diffget '.nr3.'diffupdate', '') + let mods = substitute(mods, '\Cleftabove\|rightbelow\|aboveleft\|belowright', '\=submatch(0) =~# "f" ? "rightbelow" : "leftabove"', '') + for i in range(len(parents)-1, 1, -1) + execute mods 'split' s:fnameescape(s:Generate(parents[i])) + call s:Map('n', 'dp', ':diffput '.nr.'diffupdate', '') + let nrx = bufnr('') + call s:diffthis() + exe back + call s:Map('n', 'd' . (i + 2) . 'o', ':diffget '.nrx.'diffupdate', '') + endfor + call s:diffthis() return post elseif len(args) let arg = join(args, ' ') @@ -4443,6 +4456,8 @@ function! s:Diff(autodir, keepfocus, mods, ...) abort if file !~# ':' && file !~# '^/' && s:TreeChomp('cat-file','-t',file) =~# '^\%(tag\|commit\)$' let file = file.s:Relative(':') endif + elseif exists('parents') && len(parents) + let file = parents[-1] elseif len(commit) let file = s:Relative() elseif s:IsConflicted() diff --git a/doc/fugitive.txt b/doc/fugitive.txt index b30515a..d9f2615 100644 --- a/doc/fugitive.txt +++ b/doc/fugitive.txt @@ -159,12 +159,15 @@ that are part of Git repositories). Vim's |do| and |dp| to stage and unstage changes. *fugitive-:Gdiffsplit!* -:Gdiffsplit! [object] During a merge conflict, do a three-way diff against - both ancestors. Additional d2o and d3o maps are +:Gdiffsplit! Diff against any and all direct ancestors, retaining + focus on the current window. During a merge conflict, + this is a three-way diff against the "ours" and + "theirs" ancestors. Additional d2o and d3o maps are provided to to obtain the hunk from the "ours" or - "theirs" ancestor, respectively. If the file is not - conflicted, behaves the same as if no bang was given, - but keeps focus in the original window. + "theirs" ancestor, respectively. + +:Gdiffsplit! {object} Like |:Gdiffsplit|, but retain focus on the current + window. *fugitive-:Gvdiffsplit* :Gvdiffsplit [object] Like |:Gdiffsplit|, but always split vertically.