Skip to content

Instantly share code, notes, and snippets.

@saki7
Created November 11, 2012 12:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saki7/4054780 to your computer and use it in GitHub Desktop.
Save saki7/4054780 to your computer and use it in GitHub Desktop.
<C-g> git blame
function! s:git_commit_count_from_hash(filename,hash) "{{{
let lines = split(system(printf('git log --pretty=oneline %s'
\ ,a:filename)),"\n")
if len(lines) > 0
let commit_count = 0
for line in lines
let commit_count += 1
let line_split = split(line,' ')
let dict = {
\ 'hash' : line_split[0]
\ }
if dict.hash == a:hash
return commit_count
endif
endfor
return 0
else
return 0
endif
endfunction "}}}
function! s:git_blame_info_dict(filename,line_num) "{{{
let lines = split(system(printf('git blame -L%d,%d --line-porcelain %s'
\ ,a:line_num,a:line_num,a:filename)),"\n")
if len(lines) == 13
let dict = {
\ 'hash' : split(lines[0],' '),
\ 'author' : matchstr(lines[1],'author \zs.*'),
\ 'author-mail' : matchstr(lines[2],'author-mail \zs.*'),
\ 'author-time' : matchstr(lines[3],'author-time \zs.*'),
\ 'author-tz' : matchstr(lines[4],'author-tz \zs.*'),
\ 'committer' : matchstr(lines[5],'committer \zs.*'),
\ 'committer-mail' : matchstr(lines[6],'committer-mail \zs.*'),
\ 'committer-time' : matchstr(lines[7],'committer-time \zs.*'),
\ 'committer-tz' : matchstr(lines[8],'committer-tz \zs.*'),
\ 'summary' : matchstr(lines[9],'summary \zs.*'),
\ 'previous' : split(matchstr(lines[10],'previous \zs.*'),' '),
\ 'filename' : matchstr(lines[11],'filename \zs.*'),
\ 'line' : lines[12],
\ }
let dict['author'] = dict['author'] ==# 'Not Committed Yet' ? '' : dict['author']
let dict['author-mail'] = dict['author-mail'] ==# '<not.committed.yet>' ? '' : dict['author-mail']
let dict['committer'] = dict['committer'] ==# 'Not Committed Yet' ? '' : dict['committer']
let dict['committer-mail'] = dict['committer-mail'] ==# '<not.committed.yet>' ? '' : dict['committer-mail']
return dict
else
return {}
endif
endfunction "}}}
function! s:git_blame_info(filename,line_num) "{{{
let ex_fname = fnamemodify(a:filename,':p')
let ex_fname_dir = fnamemodify(a:filename,':p:h')
let tmp_dir = getcwd()
execute 'cd ' . ex_fname_dir
let result = s:git_blame_info_dict(ex_fname,a:line_num)
let commit_count = s:git_commit_count_from_hash(ex_fname, result.hash[0])
execute 'cd ' . tmp_dir
let commit_count_str = commit_count.' commits before'
if commit_count < 1
let commit_count_str = 'specified commit not found in log'
endif
if empty(result)
return 'null'
else
return printf('[%s][%s] %s (%s)',result.hash[0][:6],result.committer,result.summary,commit_count_str)
endif
endfunction "}}}
nnoremap <C-g> :echo <SID>git_blame_info(expand('%'),line('.'))<CR>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment