Retool diffing
Support mods, rename to match the built-in :diffsplit, and (perhaps controversially) move three-way diffing to the bang variant, so that the default behavior always focuses the other window. Closes https://github.com/tpope/vim-fugitive/pull/715
This commit is contained in:
parent
e49b9a9303
commit
cd78a08543
@ -76,11 +76,12 @@ function! s:DirCheck(...) abort
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:Mods(mods, ...) abort
|
function! s:Mods(mods, ...) abort
|
||||||
let mods = a:mods ==# '<mods>' || empty(a:mods) ? '' : a:mods . ' '
|
let mods = substitute(a:mods, '\C<mods>', '', '')
|
||||||
if a:0 && mods !~# 'aboveleft\|belowright\|leftabove\|rightbelow\|topleft\|botright\|tab'
|
let mods = mods =~# '\S$' ? a:mods . ' ' : a:mods
|
||||||
|
if a:0 && mods !~# '\<\%(aboveleft\|belowright\|leftabove\|rightbelow\|topleft\|botright\|tab\)\>'
|
||||||
let mods = a:1 . ' ' . mods
|
let mods = a:1 . ' ' . mods
|
||||||
endif
|
endif
|
||||||
return mods
|
return substitute(mods, '\s\+', ' ', 'g')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:Slash(path) abort
|
function! s:Slash(path) abort
|
||||||
@ -1710,12 +1711,12 @@ function! fugitive#BufReadStatus() abort
|
|||||||
exe 'xnoremap <buffer> <silent>' nowait "= :<C-U>execute <SID>StageInline('toggle',line(\"'<\"),line(\"'>\")-line(\"'<\")+1)<CR>"
|
exe 'xnoremap <buffer> <silent>' nowait "= :<C-U>execute <SID>StageInline('toggle',line(\"'<\"),line(\"'>\")-line(\"'<\")+1)<CR>"
|
||||||
exe 'xnoremap <buffer> <silent>' nowait "< :<C-U>execute <SID>StageInline('show', line(\"'<\"),line(\"'>\")-line(\"'<\")+1)<CR>"
|
exe 'xnoremap <buffer> <silent>' nowait "< :<C-U>execute <SID>StageInline('show', line(\"'<\"),line(\"'>\")-line(\"'<\")+1)<CR>"
|
||||||
exe 'xnoremap <buffer> <silent>' nowait "> :<C-U>execute <SID>StageInline('hide', line(\"'<\"),line(\"'>\")-line(\"'<\")+1)<CR>"
|
exe 'xnoremap <buffer> <silent>' nowait "> :<C-U>execute <SID>StageInline('hide', line(\"'<\"),line(\"'>\")-line(\"'<\")+1)<CR>"
|
||||||
nnoremap <buffer> <silent> D :<C-U>execute <SID>StageDiff('Gdiff')<CR>
|
nnoremap <buffer> <silent> D :<C-U>execute <SID>StageDiff('Gdiffsplit')<CR>
|
||||||
nnoremap <buffer> <silent> dd :<C-U>execute <SID>StageDiff('Gdiff')<CR>
|
nnoremap <buffer> <silent> dd :<C-U>execute <SID>StageDiff('Gdiffsplit')<CR>
|
||||||
nnoremap <buffer> <silent> dh :<C-U>execute <SID>StageDiff('Gsdiff')<CR>
|
nnoremap <buffer> <silent> dh :<C-U>execute <SID>StageDiff('Ghdiffsplit')<CR>
|
||||||
nnoremap <buffer> <silent> ds :<C-U>execute <SID>StageDiff('Gsdiff')<CR>
|
nnoremap <buffer> <silent> ds :<C-U>execute <SID>StageDiff('Ghdiffsplit')<CR>
|
||||||
nnoremap <buffer> <silent> dp :<C-U>execute <SID>StageDiffEdit()<CR>
|
nnoremap <buffer> <silent> dp :<C-U>execute <SID>StageDiffEdit()<CR>
|
||||||
nnoremap <buffer> <silent> dv :<C-U>execute <SID>StageDiff('Gvdiff')<CR>
|
nnoremap <buffer> <silent> dv :<C-U>execute <SID>StageDiff('Gvdiffsplit')<CR>
|
||||||
nnoremap <buffer> <silent> J :<C-U>execute <SID>StageNext(v:count1)<CR>
|
nnoremap <buffer> <silent> J :<C-U>execute <SID>StageNext(v:count1)<CR>
|
||||||
nnoremap <buffer> <silent> K :<C-U>execute <SID>StagePrevious(v:count1)<CR>
|
nnoremap <buffer> <silent> K :<C-U>execute <SID>StagePrevious(v:count1)<CR>
|
||||||
nnoremap <buffer> <silent> P :<C-U>execute <SID>StagePatch(line('.'),line('.')+v:count1-1)<CR>
|
nnoremap <buffer> <silent> P :<C-U>execute <SID>StagePatch(line('.'),line('.')+v:count1-1)<CR>
|
||||||
@ -3739,9 +3740,9 @@ endfunction
|
|||||||
|
|
||||||
" Section: :Gdiff
|
" Section: :Gdiff
|
||||||
|
|
||||||
call s:command("-bang -bar -nargs=* -complete=customlist,fugitive#CompleteObject Gdiff :execute s:Diff('',<bang>0,<f-args>)")
|
call s:command("-bang -bar -nargs=* -complete=customlist,fugitive#CompleteObject Gdiffsplit :execute s:Diff(1, <bang>0, '<mods>', <f-args>)")
|
||||||
call s:command("-bang -bar -nargs=* -complete=customlist,fugitive#CompleteObject Gvdiff :execute s:Diff('keepalt vert ',<bang>0,<f-args>)")
|
call s:command("-bang -bar -nargs=* -complete=customlist,fugitive#CompleteObject Gvdiffsplit :execute s:Diff(0, <bang>0, 'vertical <mods>', <f-args>)")
|
||||||
call s:command("-bang -bar -nargs=* -complete=customlist,fugitive#CompleteObject Gsdiff :execute s:Diff('keepalt ',<bang>0,<f-args>)")
|
call s:command("-bang -bar -nargs=* -complete=customlist,fugitive#CompleteObject Ghdiffsplit :execute s:Diff(0, <bang>0, '<mods>', <f-args>)")
|
||||||
|
|
||||||
augroup fugitive_diff
|
augroup fugitive_diff
|
||||||
autocmd!
|
autocmd!
|
||||||
@ -3768,13 +3769,13 @@ endfunction
|
|||||||
function! s:diff_modifier(count) abort
|
function! s:diff_modifier(count) abort
|
||||||
let fdc = matchstr(&diffopt, 'foldcolumn:\zs\d\+')
|
let fdc = matchstr(&diffopt, 'foldcolumn:\zs\d\+')
|
||||||
if &diffopt =~# 'horizontal' && &diffopt !~# 'vertical'
|
if &diffopt =~# 'horizontal' && &diffopt !~# 'vertical'
|
||||||
return 'keepalt '
|
return ''
|
||||||
elseif &diffopt =~# 'vertical'
|
elseif &diffopt =~# 'vertical'
|
||||||
return 'keepalt vert '
|
return 'vertical '
|
||||||
elseif winwidth(0) <= a:count * ((&tw ? &tw : 80) + (empty(fdc) ? 2 : fdc))
|
elseif winwidth(0) <= a:count * ((&tw ? &tw : 80) + (empty(fdc) ? 2 : fdc))
|
||||||
return 'keepalt '
|
return ''
|
||||||
else
|
else
|
||||||
return 'keepalt vert '
|
return 'vertical '
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@ -3855,26 +3856,37 @@ function! s:CompareAge(mine, theirs) abort
|
|||||||
return my_time < their_time ? -1 : my_time != their_time
|
return my_time < their_time ? -1 : my_time != their_time
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:Diff(vert,keepfocus,...) abort
|
function! s:IsConflicted() abort
|
||||||
|
return !empty(s:TreeChomp('ls-files', '--unmerged', '--', expand('%:p')))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:Diff(autodir, keepfocus, mods, ...) abort
|
||||||
|
if exists(':DiffGitCached') && !a:0
|
||||||
|
return s:Mods(a:mods) . 'DiffGitCached'
|
||||||
|
endif
|
||||||
let args = copy(a:000)
|
let args = copy(a:000)
|
||||||
let post = ''
|
let post = ''
|
||||||
if get(args, 0) =~# '^+'
|
if get(args, 0) =~# '^+'
|
||||||
let post = remove(args, 0)[1:-1]
|
let post = remove(args, 0)[1:-1]
|
||||||
endif
|
endif
|
||||||
let vert = empty(a:vert) ? s:diff_modifier(2) : a:vert
|
|
||||||
let commit = s:DirCommitFile(@%)[1]
|
let commit = s:DirCommitFile(@%)[1]
|
||||||
|
if a:mods =~# '\<tab\>'
|
||||||
|
let mods = substitute(a:mods, '\<tab\>', '', 'g')
|
||||||
|
tab split
|
||||||
|
else
|
||||||
|
let mods = 'keepalt ' . a:mods
|
||||||
|
endif
|
||||||
let back = exists('*win_getid') ? 'call win_gotoid(' . win_getid() . ')' : 'wincmd p'
|
let back = exists('*win_getid') ? 'call win_gotoid(' . win_getid() . ')' : 'wincmd p'
|
||||||
if exists(':DiffGitCached')
|
if (empty(args) || args[0] ==# ':') && commit =~# '^[0-1]\=$' && a:keepfocus && s:IsConflicted()
|
||||||
return 'DiffGitCached'
|
let mods = (a:autodir ? s:diff_modifier(3) : '') . s:Mods(mods, 'leftabove')
|
||||||
elseif (empty(args) || args[0] ==# ':') && commit =~# '^[0-1]\=$' && !empty(s:TreeChomp('ls-files', '--unmerged', '--', expand('%:p')))
|
|
||||||
let vert = empty(a:vert) ? s:diff_modifier(3) : a:vert
|
|
||||||
let nr = bufnr('')
|
let nr = bufnr('')
|
||||||
execute 'leftabove '.vert.'split' s:fnameescape(s:Generate(s:Relative(':2:')))
|
execute mods 'split' s:fnameescape(s:Generate(s:Relative(':2:')))
|
||||||
execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
|
execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
|
||||||
let nr2 = bufnr('')
|
let nr2 = bufnr('')
|
||||||
call s:diffthis()
|
call s:diffthis()
|
||||||
exe back
|
exe back
|
||||||
execute 'rightbelow '.vert.'split' s:fnameescape(s:Generate(s:Relative(':3:')))
|
let mods = substitute(mods, '\Cleftabove\|rightbelow\|aboveleft\|belowright', '\=submatch(0) =~# "f" ? "rightbelow" : "leftabove"', '')
|
||||||
|
execute mods 'split' s:fnameescape(s:Generate(s:Relative(':3:')))
|
||||||
execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
|
execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
|
||||||
let nr3 = bufnr('')
|
let nr3 = bufnr('')
|
||||||
call s:diffthis()
|
call s:diffthis()
|
||||||
@ -3903,8 +3915,13 @@ function! s:Diff(vert,keepfocus,...) abort
|
|||||||
if file !~# ':' && file !~# '^/' && s:TreeChomp('cat-file','-t',file) =~# '^\%(tag\|commit\)$'
|
if file !~# ':' && file !~# '^/' && s:TreeChomp('cat-file','-t',file) =~# '^\%(tag\|commit\)$'
|
||||||
let file = file.s:Relative(':')
|
let file = file.s:Relative(':')
|
||||||
endif
|
endif
|
||||||
|
elseif len(commit)
|
||||||
|
let file = s:Relative()
|
||||||
|
elseif s:IsConflicted()
|
||||||
|
let file = s:Relative(':1:')
|
||||||
|
let post = 'echohl WarningMsg|echo "Use :Gdiffsplit! for 3 way diff"|echohl NONE|' . post
|
||||||
else
|
else
|
||||||
let file = empty(commit) ? s:Relative(':0:') : s:Relative()
|
let file = s:Relative(':0:')
|
||||||
endif
|
endif
|
||||||
try
|
try
|
||||||
let spec = s:Generate(file)
|
let spec = s:Generate(file)
|
||||||
@ -3914,10 +3931,12 @@ function! s:Diff(vert,keepfocus,...) abort
|
|||||||
endif
|
endif
|
||||||
let w:fugitive_diff_restore = restore
|
let w:fugitive_diff_restore = restore
|
||||||
if s:CompareAge(commit, s:DirCommitFile(spec)[1]) < 0
|
if s:CompareAge(commit, s:DirCommitFile(spec)[1]) < 0
|
||||||
execute 'rightbelow '.vert.'diffsplit '.s:fnameescape(spec)
|
let mods = s:Mods(mods, 'rightbelow')
|
||||||
else
|
else
|
||||||
execute 'leftabove '.vert.'diffsplit '.s:fnameescape(spec)
|
let mods = s:Mods(mods, 'leftabove')
|
||||||
endif
|
endif
|
||||||
|
let mods = (a:autodir ? s:diff_modifier(2) : '') . mods
|
||||||
|
execute mods 'diffsplit' s:fnameescape(spec)
|
||||||
let &l:readonly = &l:readonly
|
let &l:readonly = &l:readonly
|
||||||
redraw
|
redraw
|
||||||
let w:fugitive_diff_restore = restore
|
let w:fugitive_diff_restore = restore
|
||||||
@ -4789,18 +4808,18 @@ function! s:cfile() abort
|
|||||||
|
|
||||||
let dref = matchstr(diff, '\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)')
|
let dref = matchstr(diff, '\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)')
|
||||||
let ref = matchstr(diff, '\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)')
|
let ref = matchstr(diff, '\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)')
|
||||||
let dcmd = 'Gdiff! +'.offset
|
let dcmd = 'Gdiffsplit! +'.offset
|
||||||
|
|
||||||
elseif getline('.') =~# '^diff --git \%([abciow12]/.*\|/dev/null\) \%([abciow12]/.*\|/dev/null\)'
|
elseif getline('.') =~# '^diff --git \%([abciow12]/.*\|/dev/null\) \%([abciow12]/.*\|/dev/null\)'
|
||||||
let dref = matchstr(getline('.'),'\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)')
|
let dref = matchstr(getline('.'),'\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)')
|
||||||
let ref = matchstr(getline('.'),'\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)')
|
let ref = matchstr(getline('.'),'\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)')
|
||||||
let dcmd = 'Gdiff!'
|
let dcmd = 'Gdiffsplit!'
|
||||||
|
|
||||||
elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%([abciow12]/.*\|/dev/null\) \%([abciow12]/.*\|/dev/null\)'
|
elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%([abciow12]/.*\|/dev/null\) \%([abciow12]/.*\|/dev/null\)'
|
||||||
let line = getline(line('.')-1)
|
let line = getline(line('.')-1)
|
||||||
let dref = matchstr(line,'\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)')
|
let dref = matchstr(line,'\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)')
|
||||||
let ref = matchstr(line,'\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)')
|
let ref = matchstr(line,'\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)')
|
||||||
let dcmd = 'Gdiff!'
|
let dcmd = 'Gdiffsplit!'
|
||||||
|
|
||||||
elseif line('$') == 1 && getline('.') =~ '^\x\{40,\}$'
|
elseif line('$') == 1 && getline('.') =~ '^\x\{40,\}$'
|
||||||
let ref = getline('.')
|
let ref = getline('.')
|
||||||
|
@ -143,25 +143,28 @@ that are part of Git repositories).
|
|||||||
:Gwq! [path] Like |:Gwrite|! followed by |:quit|! if the write
|
:Gwq! [path] Like |:Gwrite|! followed by |:quit|! if the write
|
||||||
succeeded.
|
succeeded.
|
||||||
|
|
||||||
*fugitive-:Gdiff*
|
*fugitive-:Gdiffsplit*
|
||||||
:Gdiff [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 is used
|
With no argument, the version in the index or work
|
||||||
(which means a three-way diff during a merge conflict,
|
tree is used. The newer of the two files is placed to
|
||||||
making it a git-mergetool alternative). The newer of
|
the right or bottom, depending on 'diffopt' and the
|
||||||
the two files is placed to the right or bottom,
|
width of the window relative to 'textwidth'. Use
|
||||||
depending on 'diffopt', and the width of the window
|
Vim's |do| and |dp| to stage and unstage changes.
|
||||||
relative to 'textwidth'. Use |do| and |dp| and write
|
|
||||||
to the index file to simulate "git add --patch". For
|
|
||||||
the three-way diff, there is also d2o and d3o pulling
|
|
||||||
the hunk to the middle from the left or the right
|
|
||||||
window, respectively.
|
|
||||||
|
|
||||||
*fugitive-:Gsdiff*
|
*fugitive-:Gdiffsplit!*
|
||||||
:Gsdiff [object] Like |:Gdiff|, but always split horizontally.
|
:Gdiffsplit! [object] During a merge conflict, do a three-way diff against
|
||||||
|
both 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.
|
||||||
|
|
||||||
*fugitive-:Gvdiff*
|
*fugitive-:Gvdiffsplit*
|
||||||
:Gvdiff [object] Like |:Gdiff|, but always split vertically.
|
:Gvdiffsplit [object] Like |:Gdiffsplit|, but always split vertically.
|
||||||
|
|
||||||
|
*fugitive-:Ghdiffsplit* *fugitive-:Gsdiff*
|
||||||
|
:Ghdiffsplit [object] Like |:Gdiffsplit|, but always split horizontally.
|
||||||
|
|
||||||
*fugitive-:Gmove*
|
*fugitive-:Gmove*
|
||||||
:Gmove {destination} Wrapper around git-mv that renames the buffer
|
:Gmove {destination} Wrapper around git-mv that renames the buffer
|
||||||
@ -276,13 +279,14 @@ i On untracked files, call |:Git| add --intent-to-add.
|
|||||||
automatically.
|
automatically.
|
||||||
|
|
||||||
*fugitive_dd*
|
*fugitive_dd*
|
||||||
dd Perform a |:Gdiff| on the file under the cursor.
|
dd Perform a |:Gdiffsplit| on the file under the cursor.
|
||||||
|
|
||||||
*fugitive_ds*
|
|
||||||
ds Perform a |:Gsdiff| on the file under the cursor.
|
|
||||||
|
|
||||||
*fugitive_dv*
|
*fugitive_dv*
|
||||||
dv Perform a |:Gvdiff| on the file under the cursor.
|
dv Perform a |:Gvdiffsplit| on the file under the cursor.
|
||||||
|
|
||||||
|
*fugitive_ds* *fugitive_dh*
|
||||||
|
ds Perform a |:Ghdiffsplit| on the file under the cursor.
|
||||||
|
dh
|
||||||
|
|
||||||
*fugitive_dp*
|
*fugitive_dp*
|
||||||
dp Invoke |:Git!| diff on the file under the cursor.
|
dp Invoke |:Git!| diff on the file under the cursor.
|
||||||
|
Loading…
Reference in New Issue
Block a user