if !exists('g:git_command_edit') let g:git_command_edit = 'new' endif if !exists('g:git_bufhidden') let g:git_bufhidden = '' endif nnoremap gd :GitDiff nnoremap gD :GitDiff --cached nnoremap gs :GitStatus nnoremap gl :GitLog nnoremap ga :GitAdd nnoremap gA :GitAdd nnoremap gc :GitCommit nnoremap gg :GitGrep -e '=getreg('/')' " Returns current git branch. " Call inside 'statusline' or 'titlestring'. function! GitBranch() if !exists('b:git_dir') let b:git_dir = finddir('.git', expand('%:p:h') . ';/') echo 'git_dir := ' . b:git_dir if strlen(b:git_dir) let b:git_dir = fnamemodify(b:git_dir, ':p') echo 'git_dir := ' . b:git_dir endif endif let len = strlen(b:git_dir) if len && b:git_dir[len-1] != '/' let b:git_dir .= '/' end if strlen(b:git_dir) && filereadable(b:git_dir . 'HEAD') let lines = readfile(b:git_dir . 'HEAD') return len(lines) ? matchstr(lines[0], '[^/]*$') : '' else return '' endif endfunction " List all git local branches. function! ListGitBranches(arg_lead, cmd_line, cursor_pos) let branches = split(system('git branch'), '\n') if v:shell_error return [] endif return map(branches, 'matchstr(v:val, ''^[* ] \zs.*'')') endfunction " List all git commits. function! ListGitCommits(arg_lead, cmd_line, cursor_pos) let commits = split(system('git log --pretty=format:%h')) if v:shell_error return [] endif let commits = ['HEAD'] + ListGitBranches(a:arg_lead, a:cmd_line, a:cursor_pos) + commits if a:cmd_line =~ '^GitDiff' " GitDiff accepts .. if a:arg_lead =~ '\.\.' let pre = matchstr(a:arg_lead, '.*\.\.\ze') let commits = map(commits, 'pre . v:val') endif endif return filter(commits, 'match(v:val, ''\v'' . a:arg_lead) == 0') endfunction " Show diff. function! GitDiff(args) let git_output = system('git diff ' . a:args . ' -- ' . s:Expand('%')) if !strlen(git_output) echo "No output from git command" return endif call OpenGitBuffer(git_output) setlocal filetype=diff endfunction " Show Status. function! GitStatus() let git_output = system('git status') call OpenGitBuffer(git_output) setlocal filetype=git-status nnoremap :GitAdd endfunction " Show Log. function! GitLog() let git_output = system('git log -- ' . s:Expand('%')) call OpenGitBuffer(git_output) setlocal filetype=git-log endfunction " Show Grep. function! GitGrep(args) echo 'git grep ' . a:args let git_output = system('git grep -n ' . a:args) if !strlen(git_output) echo "no output from git command" return endif "call OpenGitBuffer(git_output) "set filetype=git-grep call OpenGitGrepQickFix(git_output) endfunction " Add file to index. function! GitAdd(expr) let file = s:Expand(strlen(a:expr) ? a:expr : '%') call GitDoCommand('add ' . file) endfunction " Commit. function! GitCommit(args) " Create COMMIT_EDITMSG file let editor_save = $EDITOR let $EDITOR = '' call system('git commit ' . a:args) let $EDITOR = editor_save execute printf('%s %sCOMMIT_EDITMSG', g:git_command_edit, b:git_dir) setlocal filetype=git-status bufhidden=wipe augroup GitCommit autocmd BufWritePre g/^#\|^\s*$/d | setlocal fileencoding=utf-8 execute printf("autocmd BufWritePost call GitDoCommand('commit %s -F ' . expand('%%')) | autocmd! GitCommit * ", a:args) augroup END endfunction " Checkout. function! GitCheckout(args) call GitDoCommand('checkout ' . a:args) endfunction " Show commit, tree, blobs. function! GitCatFile(file) let file = s:Expand(a:file) "let file_type = system('git cat-file -t ' . file) let git_output = system('git cat-file -p ' . file) if !strlen(git_output) echo "No output from git command" return endif call OpenGitBuffer(git_output) endfunction function! GitDoCommand(args) let git_output = system('git ' . a:args) let git_output = substitute(git_output, '\n*$', '', '') if v:shell_error echohl Error echo git_output echohl None else echo git_output endif endfunction " Show vimdiff for merge. (experimental) function! GitVimDiffMerge() let file = s:Expand('%') let filetype = &filetype let t:git_vimdiff_original_bufnr = bufnr('%') let t:git_vimdiff_buffers = [] topleft new setlocal buftype=nofile file `=':2:' . file` call add(t:git_vimdiff_buffers, bufnr('%')) execute 'silent read!git show :2:' . file 0d diffthis let &filetype = filetype rightbelow vnew setlocal buftype=nofile file `=':3:' . file` call add(t:git_vimdiff_buffers, bufnr('%')) execute 'silent read!git show :3:' . file 0d diffthis let &filetype = filetype endfunction function! GitVimDiffMergeDone() if exists('t:git_vimdiff_original_bufnr') && exists('t:git_vimdiff_buffers') if getbufline(t:git_vimdiff_buffers[0], 1, '$') == getbufline(t:git_vimdiff_buffers[1], 1, '$') execute 'sbuffer ' . t:git_vimdiff_original_bufnr 0put=getbufline(t:git_vimdiff_buffers[0], 1, '$') normal! jdG update execute 'bdelete ' . t:git_vimdiff_buffers[0] execute 'bdelete ' . t:git_vimdiff_buffers[1] close else echohl Error echo 'There still remains conflict' echohl None endif endif endfunction function! s:OpenGitBuffer(content) if exists('b:is_git_msg_buffer') && b:is_git_msg_buffer enew! else execute g:git_command_edit endif setlocal buftype=nofile readonly modifiable execute 'setlocal bufhidden=' . g:git_bufhidden silent put=a:content keepjumps 0d setlocal nomodifiable let b:is_git_msg_buffer = 1 endfunction function! s:OpenGitGrepQickFix(content) let list = [] for l:line in split(a:content, "\n") let l:parts = matchlist(l:line, '\([^:]\+\):\(\d\+\):\(.*\)') call add(list, { 'filename': l:parts[1], 'lnum': l:parts[2], 'text': l:parts[3] }) endfor call setqflist(list) endfunction function! s:Expand(expr) if has('win32') return substitute(expand(a:expr), '\', '/', 'g') else return expand(a:expr) endif endfunction command! -nargs=1 -complete=customlist,ListGitCommits GitCheckout call GitCheckout() command! -nargs=* -complete=customlist,ListGitCommits GitDiff call GitDiff() command! GitStatus call GitStatus() command! -nargs=? GitAdd call GitAdd() command! GitLog call GitLog() command! -nargs=* GitCommit call GitCommit() command! -nargs=1 GitCatFile call GitCatFile() command! -nargs=+ Git call GitDoCommand() command! GitVimDiffMerge call GitVimDiffMerge() command! GitVimDiffMergeDone call GitVimDiffMergeDone() command! -nargs=* GitGrep :call GitGrep() " vim: set et sw=4 ts=4: