diff --git a/README.rdoc b/README.rdoc index ac00c56..dfc1dc3 100644 --- a/README.rdoc +++ b/README.rdoc @@ -12,6 +12,7 @@ Git-vim provides: [:GitLog] Show git-log of current file or repository. [:GitCheckout ] git-checkout. Completes git commits. [:GitDiff ] git-diff. Completes git commits. +[:GitVimDiff ] git-diff in vimdiff mode. [:GitPull ] git-pull. [:GitPullRebase] git-pull --rebase. [:GitPush ] git-push. Defaults to +git push origin +. diff --git a/doc/git-vim.txt b/doc/git-vim.txt index 5fba807..0197f87 100644 --- a/doc/git-vim.txt +++ b/doc/git-vim.txt @@ -37,11 +37,14 @@ Git-vim provides: :GitDiff git-diff. Completes git commits. +:GitVimDiff + git-diff in vimdiff mode. + :GitPull git-pull. :GitPullRebase - git-pull —rebase. + git-pull --rebase. :GitPush git-push. Defaults to +git push origin +. @@ -65,7 +68,7 @@ Git-vim provides: :GitDiff gD - :GitDiff —cached + :GitDiff --cached gs :GitStatus diff --git a/plugin/git.vim b/plugin/git.vim index a88329b..aebbbb7 100644 --- a/plugin/git.vim +++ b/plugin/git.vim @@ -24,6 +24,8 @@ endif if !exists('g:git_no_map_default') || !g:git_no_map_default nnoremap gd :GitDiff + nnoremap gvd :GitVimDiff + nnoremap gvD :GitVimDiff --cached nnoremap gD :GitDiff --cached nnoremap gs :GitStatus nnoremap gl :GitLog @@ -45,6 +47,16 @@ function! s:GetGitDir() return b:git_dir endfunction +" Ensure b:git_dir exists. +function! s:GetRepositoryPath(fname) + let git_dir = fnamemodify(GetGitDir(), ":p:h:h") + let fpath = fnamemodify(a:fname, ":p") + if has('win32') + let fpath = substitute(fpath, '\', '/', 'g') + endif + return strpart(fpath, strlen(git_dir)+1, strlen(fpath) - strlen(git_dir)-1) +endfunction + " Returns current git branch. " Call inside 'statusline' or 'titlestring'. function! GitBranch() @@ -94,16 +106,68 @@ endfunction " Show diff. function! GitDiff(args) - let git_output = s:SystemGit('diff ' . a:args . ' -- ' . s:Expand('%')) + let file = s:Expand('%') + let encoding = &encoding + if &encoding != &termencoding + let file = iconv(file, &encoding, &termencoding) + let &encoding = &termencoding + endif + let git_output = s:SystemGit('diff ' . a:args . ' -- ' . shellescape(file)) + let &encoding = encoding if !strlen(git_output) echo "No output from git command" return endif + let git_output = substitute(git_output, '\r\n','\n', 'g') + if &fenc != &enc + let pos_diff = match(git_output, '\n@@') + let git_output_file = strpart(git_output, 0, pos_diff) + let git_output = iconv(strpart(git_output, pos_diff), &fenc, &enc) + let git_output = git_output_file . git_output + endif call OpenGitBuffer(git_output) setlocal filetype=git-diff endfunction +" Show vimdiff. +function! GitVimDiff(args) + let file = s:Expand('%') + let encoding = &encoding + if &encoding != &termencoding + let file = iconv(file, &encoding, &termencoding) + let &encoding = &termencoding + endif + let git_output = s:SystemGit('cat-file -p ' . a:args . shellescape(':' . s:GetRepositoryPath(file))) + + let &encoding = encoding + echo 'cat-file -p ' . a:args . ':' . s:GetRepositoryPath(s:Expand('%')) + + if !strlen(git_output) + echo "No output from git command" + return + endif + let filetype = &filetype + + diffthis + + let git_command_edit_save = g:git_command_edit + let g:git_command_edit = 'vnew' + + if &encoding != &fenc + let git_output = iconv(git_output, &fenc, &encoding) + endif + let git_output = substitute(git_output, '\r\n','\n', 'g') + let fenc = &fenc + call OpenGitBuffer(git_output) + let g:git_command_edit = git_command_edit_save + let &filetype = filetype + setlocal modifiable + let &fenc=fenc + setlocal nomodifiable + diffthis +endfunction + " Show Status. function! GitStatus() let git_output = s:SystemGit('status') @@ -121,7 +185,14 @@ endfunction " Show Log. function! GitLog(args) - let git_output = s:SystemGit('log ' . a:args . ' -- ' . s:Expand('%')) + let file = s:Expand('%') + let encoding = &encoding + if &encoding != &termencoding + let file = iconv(file, &encoding, &termencoding) + let &encoding = &termencoding + endif + let git_output = s:SystemGit('log ' . a:args . ' -- ' . shellescape(file)) + let &encoding = encoding call OpenGitBuffer(git_output) setlocal filetype=git-log endfunction @@ -129,8 +200,14 @@ endfunction " Add file to index. function! GitAdd(expr) let file = s:Expand(strlen(a:expr) ? a:expr : '%') + let encoding = &encoding + if &encoding != &termencoding + let file = iconv(file, &encoding, &termencoding) + let &encoding = &termencoding + endif - call GitDoCommand('add ' . file) + call GitDoCommand('add ' . shellescape(file)) + let &encoding = encoding endfunction " Commit. @@ -187,18 +264,35 @@ endfunction " Show commit, tree, blobs. function! GitCatFile(file) let file = s:Expand(a:file) - let git_output = s:SystemGit('cat-file -p ' . file) + let encoding = &encoding + if &encoding != &termencoding + let file = iconv(file, &encoding, &termencoding) + let &encoding = &termencoding + endif + let git_output = s:SystemGit('cat-file -p ' . shellescape(file)) + let &encoding = encoding if !strlen(git_output) echo "No output from git command" return endif + if &encoding != &fenc + let git_output = iconv(git_output, &fenc, &encoding) + endif + let git_output = substitute(git_output, '\r\n','\n', 'g') call OpenGitBuffer(git_output) endfunction " Show revision and author for each line. function! GitBlame(...) - let git_output = s:SystemGit('blame -- ' . expand('%')) + let file = s:Expand('%') + let encoding = &encoding + if &encoding != &termencoding + let file = iconv(file, &encoding, &termencoding) + let &encoding = &termencoding + endif + let git_output = s:SystemGit('blame -- ' . shellescape(file)) + let &encoding = encoding if !strlen(git_output) echo "No output from git command" return @@ -358,6 +452,7 @@ endfunction command! -nargs=1 -complete=customlist,ListGitCommits GitCheckout call GitCheckout() command! -nargs=* -complete=customlist,ListGitCommits GitDiff call GitDiff() +command! -nargs=* -complete=customlist,ListGitCommits GitVimDiff call GitVimDiff() command! GitStatus call GitStatus() command! -nargs=? GitAdd call GitAdd() command! -nargs=* GitLog call GitLog()