1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-24 05:30:07 +08:00
SpaceVim/bundle/git.vim/autoload/git/blame.vim
2021-01-02 18:15:08 +08:00

162 lines
4.8 KiB
VimL

let s:JOB = SpaceVim#api#import('job')
let s:BUFFER = SpaceVim#api#import('vim#buffer')
let s:STRING = SpaceVim#api#import('data#string')
let s:blame_buffer_nr = -1
let s:blame_show_buffer_nr = -1
function! git#blame#run(...)
if len(a:1) == 0
let cmd = ['git', 'blame', '--line-porcelain', expand('%')]
else
let cmd = ['git', 'blame', '--line-porcelain'] + a:1
endif
let s:lines = []
call git#logger#info('git-blame cmd:' . string(cmd))
call s:JOB.start(cmd,
\ {
\ 'on_stderr' : function('s:on_stderr'),
\ 'on_stdout' : function('s:on_stdout'),
\ 'on_exit' : function('s:on_exit'),
\ }
\ )
endfunction
function! s:on_stdout(id, data, event) abort
for data in a:data
call git#logger#info('git-blame stdout:' . data)
endfor
let s:lines += a:data
endfunction
function! s:on_stderr(id, data, event) abort
for data in a:data
call git#logger#info('git-blame stderr:' . data)
endfor
endfunction
function! s:on_exit(id, data, event) abort
call git#logger#info('git-blame exit data:' . string(a:data))
let rst = s:parser(s:lines)
if !empty(rst)
if !bufexists(s:blame_buffer_nr)
let s:blame_buffer_nr = s:openBlameWindow()
endif
call setbufvar(s:blame_buffer_nr, 'git_blame_info', rst)
call s:BUFFER.buf_set_lines(s:blame_buffer_nr, 0 , -1, 0, map(deepcopy(rst), 's:STRING.fill(v:val.summary, 40) . repeat(" ", 4) . strftime("%Y %b %d %X", v:val.time)'))
let fname = rst[0].filename
if !bufexists(s:blame_show_buffer_nr)
let s:blame_show_buffer_nr = s:openBlameShowWindow(fname)
endif
call s:BUFFER.buf_set_lines(s:blame_show_buffer_nr, 0 , -1, 0, map(deepcopy(rst), 'v:val.line'))
endif
endfunction
function! s:openBlameWindow() abort
tabedit git://blame
normal! "_dd
setl nobuflisted
setl nomodifiable
setl nonumber norelativenumber
setl buftype=nofile
setl scrollbind
setf git-blame
setlocal bufhidden=wipe
nnoremap <buffer><silent> <Cr> :call <SID>open_previous()<CR>
nnoremap <buffer><silent> <BS> :call <SID>back()<CR>
nnoremap <buffer><silent> q :call <SID>close_blame_win()<CR>
return bufnr('%')
endfunction
function! s:openBlameShowWindow(fname) abort
exe 'rightbelow vsplit git://blame:show/' . a:fname
normal! "_dd
setl nobuflisted
setl nomodifiable
setl scrollbind
setl buftype=nofile
setlocal bufhidden=wipe
nnoremap <buffer><silent> q :bd!<CR>
return bufnr('%')
endfunction
function! s:close_blame_win() abort
let s:blame_history = []
call s:closeBlameShowWindow()
q
endfunction
function! s:closeBlameShowWindow() abort
if bufexists(s:blame_show_buffer_nr)
exe 'bd ' . s:blame_show_buffer_nr
endif
endfunction
" revision
" 1cca0b8676d664d2ea2f9b0756d41967fc8481fb 1 1 5
" author Shidong Wang
" author-mail <wsdjeg@outlook.com>
" author-time 1578202864
" author-tz +0800
" committer Shidong Wang
" committer-mail <wsdjeg@outlook.com>
" committer-time 1578202864
" committer-tz +0800
" summary Add git blame support
" filename autoload/git/blame.vim
" let s:JOB = SpaceVim#api#import('job')
function! s:parser(lines) abort
let rst = []
let obj = {}
for line in a:lines
if line =~# '^[a-zA-Z0-9]\{40}'
call extend(obj, {'revision' : line[:39]})
elseif line =~# '^summary'
call extend(obj, {'summary' : line[8:]})
elseif line =~# '^filename'
call extend(obj, {'filename' : line[9:]})
elseif line =~# '^previous'
call extend(obj, {'previous' : line[9:48]})
elseif line =~# '^committer-time'
call extend(obj, {'time' : str2nr(line[15:])})
elseif line =~# '^\t'
call extend(obj, {'line' : line[1:]})
if !empty(obj) && has_key(obj, 'summary') && has_key(obj, 'line')
call add(rst, obj)
endif
let obj = {}
endif
endfor
return rst
endfunction
let s:blame_history = []
function! s:back() abort
if empty(s:blame_history)
echo 'No navigational history is found'
return
endif
let [rev, fname] = remove(s:blame_history, -1)
exe 'Git blame' rev fname
endfunction
function! s:open_previous() abort
let rst = get(b:, 'git_blame_info', [])
if empty(rst)
return
endif
let blame_info = rst[line('.') - 1]
if has_key(blame_info, 'previous')
call add(s:blame_history, [blame_info.revision, blame_info.filename])
exe 'Git blame' blame_info.previous blame_info.filename
else
echo 'No related parent commit exists'
endif
endfunction
function! git#blame#complete(ArgLead, CmdLine, CursorPos)
return "%\n" . join(getcompletion(a:ArgLead, 'file'), "\n")
endfunction