From 4b0475f9d84ab9277c57c354deefb7ce5d2ef6b9 Mon Sep 17 00:00:00 2001 From: Tim Pope Date: Wed, 25 Jul 2018 00:29:03 -0400 Subject: [PATCH] Map in blobs to jump to blamed commit --- autoload/fugitive.vim | 95 ++++++++++++++++++++++++++----------------- doc/fugitive.txt | 2 - 2 files changed, 57 insertions(+), 40 deletions(-) diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim index c3c2b58..6eb0770 100644 --- a/autoload/fugitive.vim +++ b/autoload/fugitive.vim @@ -2285,7 +2285,10 @@ augroup fugitive_blame autocmd! autocmd FileType fugitiveblame setlocal nomodeline | if exists('b:git_dir') | let &l:keywordprg = s:Keywordprg() | endif autocmd Syntax fugitiveblame call s:BlameSyntax() - autocmd User Fugitive if s:buffer().type('file', 'blob', 'blame') | exe "command! -buffer -bar -bang -range=0 -nargs=* Gblame :execute s:Blame(0,,,,[])" | endif + autocmd User Fugitive + \ if get(b:, 'fugitive_type') =~# '^\%(file\|blob\|blame\)$' | + \ exe "command! -buffer -bar -bang -range=0 -nargs=* Gblame :execute s:Blame(0,,,,'',[])" | + \ endif autocmd ColorScheme,GUIEnter * call s:RehighlightBlame() autocmd BufWinLeave * execute getwinvar(+bufwinnr(+expand('')), 'fugitive_leave') augroup END @@ -2300,7 +2303,7 @@ function! s:linechars(pattern) abort return chars endfunction -function! s:Blame(bang,line1,line2,count,args) abort +function! s:Blame(bang, line1, line2, count, mods, args) abort if exists('b:fugitive_blamed_bufnr') return 'bdelete' endif @@ -2312,7 +2315,11 @@ function! s:Blame(bang,line1,line2,count,args) abort call s:throw('unsupported option') endif call map(a:args,'s:sub(v:val,"^\\ze[^-]","-")') - let cmd = ['--no-pager', 'blame', '--show-number'] + a:args + let cmd = ['--no-pager', 'blame', '--show-number'] + if a:count + let cmd += ['-L', a:line1 . ',' . a:line1] + endif + let cmd += a:args if s:DirCommitFile(@%)[1] =~# '\D\|..' let cmd += [s:DirCommitFile(@%)[1]] else @@ -2322,27 +2329,29 @@ function! s:Blame(bang,line1,line2,count,args) abort let basecmd = escape(call('fugitive#Prepare', cmd), '!#%') try let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' - if !s:repo().bare() - let dir = getcwd() - execute cd s:fnameescape(s:repo().tree()) + let tree = FugitiveTreeForGitDir(b:git_dir) + if len(tree) && s:cpath(tree) !=# s:cpath(getcwd()) + let cwd = getcwd() + execute cd s:fnameescape(tree) + endif + let error = s:tempname() + let temp = error.'.fugitiveblame' + if &shell =~# 'csh' + silent! execute '%write !('.basecmd.' > '.temp.') >& '.error + else + silent! execute '%write !'.basecmd.' > '.temp.' 2> '.error + endif + if exists('l:cwd') + execute cd s:fnameescape(cwd) + unlet cwd + endif + if v:shell_error + call s:throw(join(readfile(error),"\n")) endif if a:count - execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g') + let edit = substitute(a:mods, '^$', '', '') . get(['edit', 'split', 'pedit'], a:line2 - a:line1, ' split') + return s:BlameCommit(edit, get(readfile(temp), 0, '')) else - let error = s:tempname() - let temp = error.'.fugitiveblame' - if &shell =~# 'csh' - silent! execute '%write !('.basecmd.' > '.temp.') >& '.error - else - silent! execute '%write !'.basecmd.' > '.temp.' 2> '.error - endif - if exists('l:dir') - execute cd s:fnameescape(dir) - unlet dir - endif - if v:shell_error - call s:throw(join(readfile(error),"\n")) - endif for winnr in range(winnr('$'),1,-1) call setwinvar(winnr, '&scrollbind', 0) if exists('+cursorbind') @@ -2408,8 +2417,8 @@ function! s:Blame(bang,line1,line2,count,args) abort syncbind endif finally - if exists('l:dir') - execute cd s:fnameescape(dir) + if exists('l:cwd') + execute cd s:fnameescape(cwd) endif endtry return '' @@ -2418,8 +2427,8 @@ function! s:Blame(bang,line1,line2,count,args) abort endtry endfunction -function! s:BlameCommit(cmd) abort - let line = getline('.') +function! s:BlameCommit(cmd, ...) abort + let line = a:0 ? a:1 : getline('.') if line =~# '^0\{4,40\} ' return 'echoerr ' . string('Not Committed Yet') endif @@ -2430,9 +2439,12 @@ function! s:BlameCommit(cmd) abort let lnum = matchstr(line, ' \zs\d\+\ze\s\+[([:digit:]]') let path = matchstr(line, '^\^\=\x\+\s\+\zs.\{-\}\ze\s*\d\+ ') if path ==# '' - let path = fugitive#Path(bufname(b:fugitive_blamed_bufnr), '') + let path = fugitive#Path(a:0 ? @% : bufname(b:fugitive_blamed_bufnr), '') endif execute cmd + if a:cmd ==# 'pedit' + return '' + endif if search('^diff .* b/\M'.escape(path,'\').'$','W') call search('^+++') let head = line('.') @@ -3087,12 +3099,29 @@ function! s:NavigateUp(count) abort endfunction function! fugitive#MapJumps(...) abort - nnoremap :exe GF("edit") + if get(b:, 'fugitive_type', '') ==# 'blob' + nnoremap :.Gblame + else + nnoremap :exe GF("edit") + endif if !&modifiable nnoremap o :exe GF("split") nnoremap S :exe GF("vsplit") nnoremap O :exe GF("tabedit") - nnoremap p :exe GF("pedit") + nnoremap o :exe GF("split") + nnoremap S :exe GF("vsplit") + nnoremap O :exe GF("tabedit") + if get(b:, 'fugitive_type', '') ==# 'blob' + nnoremap o :.,.+1Gblame + nnoremap S :vertical .,.+1Gblame + nnoremap O :tab .,.+1Gblame + nnoremap p :.,.+2Gblame + else + nnoremap o :exe GF("split") + nnoremap S :exe GF("vsplit") + nnoremap O :exe GF("tabedit") + nnoremap p :exe GF("pedit") + endif nnoremap - :exe Edit('edit',0,'',NavigateUp(v:count1)) if getline(1) =~# '^tree \x\{40\}$' && empty(getline(2))call search('^'.escape(expand('#:t'),'.*[]~\').'/\=$','wc')endif nnoremap P :exe Edit('edit',0,'',ContainingCommit().'^'.v:count1.Relative(':')) nnoremap ~ :exe Edit('edit',0,'',ContainingCommit().'~'.v:count1.Relative(':')) @@ -3152,16 +3181,6 @@ function! s:cfile() abort elseif treebase !~# '^\d\=:' && getline(1) =~# '^tree ' && empty(getline(2)) && line('.') >= 2 return [treebase . s:sub(getline('.'),'/$','')] - elseif get(b:, 'fugitive_type', '') ==# 'blob' - let ref = expand("") - try - let sha1 = s:repo().rev_parse(ref) - catch /^fugitive:/ - endtry - if exists('sha1') - return [ref] - endif - else let dcmds = [] diff --git a/doc/fugitive.txt b/doc/fugitive.txt index fd15f86..3405a1a 100644 --- a/doc/fugitive.txt +++ b/doc/fugitive.txt @@ -235,8 +235,6 @@ that are part of Git repositories). ~ reblame at [count]th first grandparent P reblame at [count]th parent (like HEAD^[count]) -:[range]Gblame [flags] Run git-blame on the given range. - *fugitive-:Gbrowse* :Gbrowse Open the current file, blob, tree, commit, or tag in your browser at the upstream hosting provider.