16 Commits
v1.0 ... v1.1

Author SHA1 Message Date
Tim Pope
ccfc60e550 fugitive.vim 1.1 2010-03-21 17:18:43 -04:00
Tim Pope
57393e7956 D in :Gstatus not on a file invokes :Git diff 2010-03-19 21:48:41 -04:00
Tim Pope
4975e76935 D in :Gstatus invokes :Gdiff 2010-03-19 21:23:41 -04:00
Tim Pope
e3e31ce9d7 Fix error in :Gmove 2010-03-19 21:06:08 -04:00
Tim Pope
56b8ad786b Allow double quotes in :Git and :Ggrep arguments
:Git and :Ggrep were defined with the -bar flag, which enables chaining
(`:Ggrep foo | copen`) but also comments (`:Ggrep foo " find foo).  The
former is useful but the latter prevents one from using double quotes
with commands.  Instead, let's disable -bar and fake it in the
implementation.

:Git implements chaining in a way that's hopefully the same as the way
Vim itself chains.  :Ggrep is a little different; it only chains after a
quote or a space so that `:Ggrep -e 'foo|bar'|copen` works as one would
expect.
2010-03-19 19:59:08 -04:00
Tim Pope
6b55a997a9 Finish pending commit even if exiting Vim 2010-03-11 22:15:35 -05:00
Tim Pope
b812cb3bcd Skip duplicate "Signed-off-by" [Wincent Colaiuta] 2010-03-10 19:44:38 -05:00
Tim Pope
13fd856db9 Strip .exe from completed Git commands 2010-03-10 19:37:49 -05:00
Tim Pope
1548f141e0 Fix restoring of $GIT_INDEX_FILE 2010-03-09 19:13:28 -05:00
Tim Pope
f05eb566e6 Use forward slashes in tab complete on Windows 2010-03-09 19:03:44 -05:00
Tim Pope
43290adc85 Fix :Gblame on Windows 2010-03-09 08:43:57 -05:00
Tim Pope
5f64bb35c9 Leave pager enabled on win32 git invocation 2010-03-08 22:57:18 -05:00
Tim Pope
f41e5c9679 Attempt to support 'noshellslash' on Windows 2010-03-08 22:51:10 -05:00
Tim Pope
9c86a7d379 Pass :Gblame flags along to git-blame 2010-03-05 22:28:53 -05:00
Tim Pope
05c0efacab Add a README 2010-02-24 22:48:40 -05:00
Tim Pope
0c99745853 Delete blame buffers when closed 2010-02-16 09:28:00 -05:00
3 changed files with 128 additions and 35 deletions

45
README.markdown Normal file
View File

@@ -0,0 +1,45 @@
fugitive.vim
============
I'm not going to lie to you; fugitive.vim may very well be the best
Git wrapper of all time. Check out these features:
View any blob, tree, commit, or tag in the repository with `:Gedit` (and
`:Gsplit`, `:Gvsplit`, `:Gtabedit`, ...). Edit a file in the index and
write to it to stage the changes. Use `:Gdiff` to bring up the staged
version of the file side by side with the working tree version and use
Vim's diff handling capabilities to stage a subset of the file's
changes.
Bring up the output of `git status` with `:Gstatus`. Use `-` to
`add`/`reset` a file's changes, or `p` to `add`/`reset` `--patch` that
mofo. And guess what `:Gcommit` does!
`:Gblame` brings up an interactive vertical split with `git blame`
output. Press enter on a line to reblame the file as it stood in that
commit, or `o` to open that commit in a split.
`:Gmove` does a `git mv` on a file and simultaneously renames the
buffer. `:Gremove` does a `git rm` on a file and simultaneously deletes
the buffer.
Use `:Ggrep` to search the work tree (or any arbitrary commit) with
`git grep`, skipping over that which is not tracked in the repository.
`:Glog` loads all previous revisions of a file into the quickfix list so
you can iterate over them and watch the file evolve!
`:Gread` is a variant of `git checkout -- filename` that operates on the
buffer rather than the filename. This means you can use `u` to undo it
and you never get any warnings about the file changing outside Vim.
`:Gwrite` writes to both the work tree and index versions of a file,
making it like `git add` when called from a work tree file and like
`git checkout` when called from the index or a blob in history.
Add `%{fugitive#statusline()}` to `'statusline'` to get an indicator
with the current branch in (surprise!) your statusline.
Oh, and of course there's `:Git` for running any arbitrary command.
Like fugitive.vim? Follow the repository on
[GitHub](http://github.com/tpope/vim-fugitive) and vote for it on
[vim.org](http://www.vim.org/scripts/script.php?script_id=2975).

View File

@@ -51,7 +51,8 @@ that are part of Git repositories).
*fugitive-:Gstatus*
:Gstatus Bring up the output of git-status in the preview
window. Press - to stage or unstage the file on the
window. Press D to |:Gdiff| the file on the cursor
line. Press - to stage or unstage the file on the
cursor line. Press p to do so on a per hunk basis
(--patch). Press C to invoke |:Gcommit|.
@@ -139,11 +140,13 @@ that are part of Git repositories).
buffer.
*fugitive-:Gblame*
:Gblame Run git-blame on the file and open the results in a
:Gblame [flags] Run git-blame on the file and open the results in a
scroll bound vertical split. Press enter on a line to
reblame the file as it was in that commit.
reblame the file as it was in that commit. You can
give any of ltwfsMC as flags and they will be passed
along to git-blame.
:[range]Gblame Run git-blame on the given range.
:[range]Gblame [flags] Run git-blame on the given range.
MAPPINGS *fugitive-mappings*

View File

@@ -1,6 +1,6 @@
" fugitive.vim - A Git wrapper so awesome, it should be illegal
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
" Version: 1.0
" Version: 1.1
" GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim
if exists('g:loaded_fugitive') || &cp
@@ -56,6 +56,14 @@ function! s:warn(str)
let v:warningmsg = a:str
endfunction
function! s:shellslash(path)
if exists('+shellslash') && !&shellslash
return s:gsub(a:path,'\\','/')
else
return a:path
endif
endfunction
function! s:add_methods(namespace, method_names) abort
for name in a:method_names
let s:{a:namespace}_prototype[name] = s:function('s:'.a:namespace.'_'.name)
@@ -92,10 +100,11 @@ let s:abstract_prototype = {}
" Initialization {{{1
function! s:ExtractGitDir(path) abort
if a:path =~? '^fugitive://.*//'
return matchstr(a:path,'fugitive://\zs.\{-\}\ze//')
let path = s:shellslash(a:path)
if path =~? '^fugitive://.*//'
return matchstr(path,'fugitive://\zs.\{-\}\ze//')
endif
let fn = fnamemodify(a:path,':s?[\/]$??')
let fn = fnamemodify(path,':s?[\/]$??')
let ofn = ""
let nfn = fn
while fn != ofn
@@ -266,6 +275,7 @@ function! s:repo_superglob(base) dict abort
if !self.bare()
let base = s:sub(a:base,'^/','')
let matches = split(glob(self.tree(s:gsub(base,'/','*&').'*')),"\n")
call map(matches,'s:shellslash(v:val)')
call map(matches,'v:val !~ "/$" && isdirectory(v:val) ? v:val."/" : v:val')
call map(matches,'v:val[ strlen(self.tree())+(a:base !~ "^/") : -1 ]')
let results += matches
@@ -295,7 +305,7 @@ call s:add_methods('repo',['dirglob','superglob'])
function! s:repo_keywordprg() dict abort
let args = ' --git-dir='.escape(self.dir(),"\\\"' ").' show'
if has("gui_running")
if has('gui_running') && !has('win32')
return g:fugitive_git_executable . ' --no-pager' . args
else
return g:fugitive_git_executable . args
@@ -367,7 +377,7 @@ endfunction
function! s:buffer_name() dict abort
let bufname = bufname(self['#'])
return bufname == '' ? '' : fnamemodify(bufname,':p')
return s:shellslash(bufname == '' ? '' : fnamemodify(bufname,':p'))
endfunction
function! s:buffer_commit() dict abort
@@ -438,7 +448,7 @@ call s:add_methods('buffer',['getvar','setvar','getline','repo','type','name','c
" }}}1
" Git {{{1
call s:command("-bar -bang -nargs=? -complete=customlist,s:GitComplete Git :call s:Git(<bang>0,<q-args>)")
call s:command("-bang -nargs=? -complete=customlist,s:GitComplete Git :execute s:Git(<bang>0,<q-args>)")
function! s:ExecuteInTree(cmd) abort
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
@@ -453,18 +463,20 @@ endfunction
function! s:Git(bang,cmd) abort
let git = s:repo().git_command()
if has('gui_running')
if has('gui_running') && !has('win32')
let git .= ' --no-pager'
endif
call s:ExecuteInTree('!'.git.' '.a:cmd)
let cmd = matchstr(a:cmd,'\v\C.{-}%($|\\@<!%(\\\\)*\|)@=')
call s:ExecuteInTree('!'.git.' '.cmd)
call fugitive#reload_status()
return matchstr(a:cmd,'\v\C\\@<!%(\\\\)*\|\zs.*')
endfunction
function! s:GitComplete(A,L,P) abort
if !exists('s:exec_path')
let s:exec_path = s:sub(system(g:fugitive_git_executable.' --exec-path'),'\n$','')
endif
let cmds = map(split(glob(s:exec_path.'/git-*'),"\n"),'v:val[strlen(s:exec_path)+5 : -1]')
let cmds = map(split(glob(s:exec_path.'/git-*'),"\n"),'s:sub(v:val[strlen(s:exec_path)+5 : -1],"\\.exe$","")')
if a:L =~ ' [[:alnum:]-]\+ '
return s:repo().superglob(a:A)
elseif a:A == ''
@@ -526,6 +538,27 @@ function! fugitive#reload_status() abort
endfor
endfunction
function! s:StageDiff() abort
let section = getline(search('^# .*:$','bnW'))
let line = getline('.')
let filename = matchstr(line,'^#\t\%([[:alpha:] ]\+: *\)\=\zs.*')
if filename ==# '' && section == '# Changes to be committed:'
return 'Git diff --cached'
elseif filename ==# ''
return 'Git diff'
elseif line =~# '^#\trenamed:' && filename =~ ' -> '
let [old, new] = split(filename,' -> ')
execute 'Gedit '.s:fnameescape(':0:'.new)
return 'Gdiff HEAD:'.s:fnameescape(old)
elseif section == '# Changes to be committed:'
execute 'Gedit '.s:fnameescape(':0:'.filename)
return 'Gdiff -'
else
execute 'Gedit '.s:fnameescape('/'.filename)
return 'Gdiff'
endif
endfunction
function! s:StageToggle(lnum1,lnum2) abort
try
let output = ''
@@ -660,7 +693,7 @@ function! s:Commit(args) abort
let error = get(readfile(errorfile,'',1),0,'!')
if error =~# "'false'\\.$"
let args = a:args
let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-e|--edit|--interactive)%($| )','')
let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-[se]|--edit|--interactive)%($| )','')
let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-F|--file|-m|--message)%(\s+|\=)%(''[^'']*''|"%(\\.|[^"])*"|\\.|\S)*','')
let args = s:gsub(args,'%(^| )@<=[%#]%(:\w)*','\=expand(submatch(0))')
let args = '-F '.s:shellesc(msgfile).' '.args
@@ -718,7 +751,7 @@ endfunction
augroup fugitive_commit
autocmd!
autocmd BufDelete *.git/COMMIT_EDITMSG execute s:sub(s:FinishCommit(), '^echoerr (.*)', 'echohl ErrorMsg|echo \1|echohl NONE')
autocmd VimLeavePre,BufDelete *.git/COMMIT_EDITMSG execute s:sub(s:FinishCommit(), '^echoerr (.*)', 'echohl ErrorMsg|echo \1|echohl NONE')
augroup END
" }}}1
@@ -728,7 +761,7 @@ if !exists('g:fugitive_summary_format')
let g:fugitive_summary_format = '%s'
endif
call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Ggrep :execute s:Grep(<bang>0,<q-args>)")
call s:command("-bang -nargs=? -complete=customlist,s:EditComplete Ggrep :execute s:Grep(<bang>0,<q-args>)")
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditComplete Glog :execute s:Log('grep<bang>',<f-args>)")
function! s:Grep(bang,arg) abort
@@ -740,7 +773,7 @@ function! s:Grep(bang,arg) abort
execute cd.'`=s:repo().tree()`'
let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n')
let &grepformat = '%f:%l:%m'
exe 'grep! '.a:arg
exe 'grep! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|')
let list = getqflist()
for entry in list
if bufname(entry.bufnr) =~ ':'
@@ -753,9 +786,9 @@ function! s:Grep(bang,arg) abort
endfor
call setqflist(list,'r')
if !a:bang && !empty(list)
return 'cfirst'
return 'cfirst'.matchstr(a:arg,'\v\C[''" ]\zs\|.*')
else
return ''
return matchstr(a:arg,'\v\C[''" ]\|\zs.*')
endif
finally
let &grepprg = grepprg
@@ -1068,7 +1101,7 @@ function! s:Move(force,destination)
if s:buffer().commit() == ''
return 'saveas! '.s:fnameescape(destination)
else
return 'file '.s:fnameescape(s:repo.translate(':0:'.destination)
return 'file '.s:fnameescape(s:repo().translate(':0:'.destination)
endif
endfunction
@@ -1120,16 +1153,20 @@ augroup fugitive_blame
autocmd BufReadPost *.fugitiveblame setfiletype fugitiveblame
autocmd FileType fugitiveblame setlocal nomodeline | if exists('b:git_dir') | let &l:keywordprg = s:repo().keywordprg() | endif
autocmd Syntax fugitiveblame call s:BlameSyntax()
autocmd User Fugitive if s:buffer().type('file', 'blob') | exe "command! -buffer -bar -bang -range=0 Gblame :execute s:Blame(<bang>0,<line1>,<line2>,<count>,<f-args>)" | endif
autocmd User Fugitive if s:buffer().type('file', 'blob') | exe "command! -buffer -bar -bang -range=0 -nargs=* Gblame :execute s:Blame(<bang>0,<line1>,<line2>,<count>,[<f-args>])" | endif
augroup END
function! s:Blame(bang,line1,line2,count) abort
function! s:Blame(bang,line1,line2,count,args) abort
try
if s:buffer().path() == ''
call s:throw('file or blob required')
endif
if filter(copy(a:args),'v:val !~# "^\\%(--root\|--show-name\\|-\\=\\%([ltwfs]\\|[MC]\\d*\\)\\+\\)$"') != []
call s:throw('unsupported option')
endif
call map(a:args,'s:sub(v:val,"^\\ze[^-]","-")')
let git_dir = s:repo().dir()
let cmd = ['--no-pager', 'blame', '--show-number']
let cmd = ['--no-pager', 'blame', '--show-number'] + a:args
if s:buffer().commit() =~# '\D\|..'
let cmd += [s:buffer().commit()]
else
@@ -1145,10 +1182,11 @@ function! s:Blame(bang,line1,line2,count) abort
if a:count
execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g')
else
let temp = tempname().'.fugitiveblame'
silent! exe '%write !'.basecmd.' > '.temp.' 2> '.temp
let error = tempname()
let temp = error.'.fugitiveblame'
silent! exe '%write !'.basecmd.' > '.temp.' 2> '.error
if v:shell_error
call s:throw(join(readfile(temp),"\n"))
call s:throw(join(readfile(error),"\n"))
endif
let bufnr = bufnr('')
let restore = 'call setbufvar('.bufnr.',"&scrollbind",0)'
@@ -1169,12 +1207,13 @@ function! s:Blame(bang,line1,line2,count) abort
let b:fugitive_type = 'blame'
let b:fugitive_blamed_bufnr = bufnr
let b:fugitive_restore = restore
let b:fugitive_blame_arguments = join(a:args,' ')
call s:Detect(expand('%:p'))
execute top
normal! zt
execute current
execute "vertical resize ".(match(getline('.'),'\s\+\d\+)')+1)
setlocal nomodified nomodifiable nonumber scrollbind nowrap foldcolumn=0 nofoldenable filetype=fugitiveblame
setlocal nomodified nomodifiable bufhidden=delete nonumber scrollbind nowrap foldcolumn=0 nofoldenable filetype=fugitiveblame
nnoremap <buffer> <silent> q :<C-U>bdelete<CR>
nnoremap <buffer> <silent> <CR> :<C-U>exe <SID>BlameJump('')<CR>
nnoremap <buffer> <silent> P :<C-U>exe <SID>BlameJump('^'.v:count1)<CR>
@@ -1199,11 +1238,12 @@ function! s:BlameJump(suffix) abort
if commit =~# '^0\+$'
let commit = ':0'
endif
let lnum = matchstr(getline('.'),'\d\+\ze (')
let path = matchstr(getline('.'),'^\^\=\zs\x\+\s\+\zs.\{-\}\ze\s*\d\+ (')
let lnum = matchstr(getline('.'),'\d\+\ze\s\+[([:digit:]]')
let path = matchstr(getline('.'),'^\^\=\zs\x\+\s\+\zs.\{-\}\ze\s*\d\+ ')
if path ==# ''
let path = s:buffer(b:fugitive_blamed_bufnr).path()
endif
let args = b:fugitive_blame_arguments
let offset = line('.') - line('w0')
let bufnr = bufnr('%')
let winnr = bufwinnr(b:fugitive_blamed_bufnr)
@@ -1214,7 +1254,7 @@ function! s:BlameJump(suffix) abort
if winnr > 0
exe bufnr.'bdelete'
endif
Gblame
execute 'Gblame '.args
execute lnum
let delta = line('.') - line('w0') - offset
if delta > 0
@@ -1229,13 +1269,16 @@ endfunction
function! s:BlameSyntax() abort
let b:current_syntax = 'fugitiveblame'
syn match FugitiveblameBoundary "^\^"
syn match FugitiveblameHash "\%(^\^\=\)\@<=\x\{7,40\}\>" nextgroup=FugitiveblameAnnotation,fugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite
syn match FugitiveblameBlank "^\s\+\s\@=" nextgroup=FugitiveblameAnnotation,fugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite
syn match FugitiveblameHash "\%(^\^\=\)\@<=\x\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
syn match FugitiveblameUncommitted "\%(^\^\=\)\@<=0\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
syn region FugitiveblameAnnotation matchgroup=FugitiveblameDelimiter start="(" end="\%( \d\+\)\@<=)" contained keepend oneline
syn match FugitiveblameTime "[0-9:/+-][0-9:/+ -]*[0-9:/+-]\%( \+\d\+)\)\@=" contained containedin=FugitiveblameAnnotation
syn match FugitiveblameLineNumber " \@<=\d\+)\@=" contained containedin=FugitiveblameAnnotation
syn match FugitiveblameOriginalFile " \%(\f\+\D\@<=\|\D\@=\f\+\)\%(\%(\s\+\d\+\)\= (\)\@=" contained nextgroup=FugitiveblameOriginalLineNumber,FugitiveblameAnnotation skipwhite
syn match FugitiveblameOriginalLineNumber " \@<=\d\+\%( (\)\@=" contained nextgroup=FugitiveblameAnnotation skipwhite
syn match FugitiveblameOriginalFile " \%(\f\+\D\@<=\|\D\@=\f\+\)\%(\%(\s\+\d\+\)\=\s\%((\|\s*\d\+)\)\)\@=" contained nextgroup=FugitiveblameOriginalLineNumber,FugitiveblameAnnotation skipwhite
syn match FugitiveblameOriginalLineNumber " \@<=\d\+\%(\s(\)\@=" contained nextgroup=FugitiveblameAnnotation skipwhite
syn match FugitiveblameOriginalLineNumber " \@<=\d\+\%(\s\+\d\+)\)\@=" contained nextgroup=FugitiveblameShort skipwhite
syn match FugitiveblameShort "\d\+)" contained contains=FugitiveblameLineNumber
syn match FugitiveblameNotCommittedYet "(\@<=Not Committed Yet\>" contained containedin=FugitiveblameAnnotation
hi def link FugitiveblameBoundary Keyword
hi def link FugitiveblameHash Identifier
@@ -1244,6 +1287,7 @@ function! s:BlameSyntax() abort
hi def link FugitiveblameLineNumber Number
hi def link FugitiveblameOriginalFile String
hi def link FugitiveblameOriginalLineNumber Float
hi def link FugitiveblameShort FugitiveblameDelimiter
hi def link FugitiveblameDelimiter Delimiter
hi def link FugitiveblameNotCommittedYet Comment
endfunction
@@ -1272,7 +1316,7 @@ function! s:ReplaceCmd(cmd,...) abort
finally
let &autowrite = aw
if exists('old_index')
let $GIT_INDEX_FILE = 'old_index'
let $GIT_INDEX_FILE = old_index
endif
endtry
silent exe 'keepalt file '.tmp
@@ -1313,6 +1357,7 @@ function! s:BufReadIndex()
setlocal ro noma nomod nomodeline bufhidden=delete
nnoremap <buffer> <silent> a :<C-U>let b:fugitive_display_format += 1<Bar>exe <SID>BufReadIndex()<CR>
nnoremap <buffer> <silent> i :<C-U>let b:fugitive_display_format -= 1<Bar>exe <SID>BufReadIndex()<CR>
nnoremap <buffer> <silent> D :<C-U>execute <SID>StageDiff()<CR>
nnoremap <buffer> <silent> - :<C-U>execute <SID>StageToggle(line('.'),line('.')+v:count1-1)<CR>
xnoremap <buffer> <silent> - :<C-U>execute <SID>StageToggle(line("'<"),line("'>"))<CR>
nnoremap <buffer> <silent> p :<C-U>execute <SID>StagePatch(line('.'),line('.')+v:count1-1)<CR>