Add git blame to vim statusline

This commit is contained in:
Talia 2020-08-17 13:43:24 +02:00
parent c7360af199
commit 4415f562ac
2 changed files with 44 additions and 4 deletions

View file

@ -7,6 +7,8 @@
" ┌┘ Git Stuff └┐ " " ┌┘ Git Stuff └┐ "
" └───────────────────┘ " " └───────────────────┘ "
augroup git
" Find the root of a git repository " Find the root of a git repository
function! s:gitroot() function! s:gitroot()
let l:ret = substitute(system('git rev-parse --show-toplevel'), '\n\_.*', '', '') let l:ret = substitute(system('git rev-parse --show-toplevel'), '\n\_.*', '', '')
@ -139,10 +141,28 @@ function! s:file_at_revision(rev)
call setpos('.', l:pos) call setpos('.', l:pos)
endfun endfun
function s:split_blame_entry(idx, entry)
let l:map = {}
for l:pair in split(a:entry, "\n")[1:]
let l:split = match(l:pair, " ")
let l:map[l:pair[:l:split-1]] = l:pair[l:split+1:]
endfor
let l:map["commit"]=a:entry[:match(a:entry, " ")-1]
let l:map["time"]=strftime("%Y-%d-%m %H:%M:%S", l:map["committer-time"])
let l:map["date"]=strftime("%Y-%d-%m", l:map["committer-time"])
let l:map["short"]=l:map["commit"][1:8]." ".l:map["time"]." ".l:map["author"]
return l:map
endfun
let s:split_blame_entry_ref = funcref("s:split_blame_entry")
function! s:git_blame(first, last) function! s:git_blame(first, last)
let l:input = system('git blame '.expand('%').' --line-porcelain -L '.a:first.','.a:last) let l:input = system('git blame '.expand('%').' --line-porcelain -L '.a:first.','.a:last)
let l:data = map(split(l:input, '\ze\x\{40} \d\+ \d\+'), {idx, elem -> split(elem, '\n')}) if v:shell_error
return map(l:data, {idx, ary -> ary[1][match(ary[1], '\s\+\zs'):]}) throw v:shell_error
else
let l:array = map(split(l:input, '\ze\x\{40} \d\+ \d\+'), s:split_blame_entry_ref)
return l:array
end
endfun endfun
function! s:git_root_to_path() function! s:git_root_to_path()
@ -154,7 +174,25 @@ endfun
call s:git_root_to_path() call s:git_root_to_path()
command! -range Blame echom join(uniq(sort(<sid>git_blame(<line1>, <line2>))), ', ') function! s:blame_command(what, line1, line2)
let l:what=tolower(a:what)
if l:what=="date"
echom join(uniq(sort(map(<sid>git_blame(a:line1, a:line2), { i,a -> a["date"] }))), ', ')
elseif l:what=="adate"
echom join(uniq(sort(map(<sid>git_blame(a:line1, a:line2), { i,a -> a["author"]." @ ".a["date"] }))), ', ')
elseif l:what=="mail"
echom join(uniq(sort(map(<sid>git_blame(a:line1, a:line2), { i,a -> a["committer-mail"] }))), ', ')
elseif l:what=="author" || l:what==""
echom join(uniq(sort(map(<sid>git_blame(a:line1, a:line2), { i,a -> a["author"] }))), ', ')
else
throw "Don't know what '".a:what."' is!"
end
endfun
au BufReadPost * try | let b:blame=<SID>git_blame("","") | catch | unlet! b:blame | endtry
au BufWritePost * try | let b:blame=<SID>git_blame("","") | catch | unlet! b:blame | endtry
command! -range -nargs=? Blame call <SID>blame_command(<q-args>, <line1>, <line2>)
command! -range DBlame !git blame % -L <line1>,<line2> command! -range DBlame !git blame % -L <line1>,<line2>
command! GitNext try command! GitNext try
\| call <sid>gitroot() \| call <sid>gitroot()
@ -180,3 +218,5 @@ command! ShowGitRoot try
\| echo <sid>gitroot() \| echo <sid>gitroot()
\| catch | echo 'Not a git repository' \| catch | echo 'Not a git repository'
\| endtry \| endtry
augroup END

View file

@ -91,7 +91,7 @@ end
set listchars=eol,tab:\│\ ,trail,nbsp:…,space set listchars=eol,tab:\│\ ,trail,nbsp:…,space
set modeline " Allows setting vim options in other files set modeline " Allows setting vim options in other files
set statusline=\ (%n)\ %f\ %a\ [%M%R]\ [%Y]\ %{strlen(@\")}\ %{&autowriteall?'💾\ ':''}\%=0x%B\ [%l/%L,\ %c%V]\ %4.P set statusline=\ (%n)\ %f\ %a\ [%M%R]\ [%Y]\ %{strlen(@\")}\ %{&autowriteall?'💾\ ':''}%#TabLine#%{exists(\"b:blame\")?b:blame[min([getcurpos()[1],len(b:blame)])-1][\"short\"]:\"\"}%#StatusLine#\%=0x%B\ [%l/%L,\ %c%V]\ %4.P
set laststatus=2 set laststatus=2
set cmdheight=1 set cmdheight=1
set timeoutlen=1200 set timeoutlen=1200