|
diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim |
|
index d0748c1..e807e36 100644 |
|
--- a/autoload/fugitive.vim |
|
+++ b/autoload/fugitive.vim |
|
@@ -2592,6 +2592,10 @@ function! s:FormatFile(dict) abort |
|
return a:dict.status . ' ' . a:dict.filename |
|
endfunction |
|
|
|
+function! s:StripDiffStats(text) abort |
|
+ return substitute(a:text, ' \++\d\+ \+-\d\+$', '', '') |
|
+endfunction |
|
+ |
|
function! s:Format(val) abort |
|
if type(a:val) == type({}) |
|
return s:Format{a:val.type}(a:val) |
|
@@ -2617,6 +2621,39 @@ function! s:AddSection(to, label, lines, ...) abort |
|
call extend(a:to.lines, ['', a:label . (len(note) ? ': ' . note : ' (' . len(a:lines) . ')')] + s:Format(a:lines)) |
|
endfunction |
|
|
|
+function! s:DiffStats(diff_section, files) abort |
|
+ call fugitive#Wait(a:diff_section) |
|
+ let headers = {} |
|
+ let stats = [] |
|
+ let i = 0 |
|
+ while i < len(a:files) |
|
+ let file = a:files[i] |
|
+ if file.status ==# 'U' |
|
+ let header = 'diff --cc ' . s:Quote(file.relative[0]) |
|
+ else |
|
+ let header = 'diff --git ' . s:Quote(file.relative[-1]) . ' ' . s:Quote(file.relative[0]) |
|
+ endif |
|
+ let headers[header] = i |
|
+ call add(stats, [0, 0]) |
|
+ let i += 1 |
|
+ endwhile |
|
+ let current = -1 |
|
+ for line in a:diff_section.stdout |
|
+ if line =~# '^diff ' |
|
+ let current = get(headers, line, -1) |
|
+ elseif current < 0 |
|
+ continue |
|
+ elseif line =~# '^+++ \|^--- ' |
|
+ continue |
|
+ elseif line[0:0] ==# '+' |
|
+ let stats[current][0] += 1 |
|
+ elseif line[0:0] ==# '-' |
|
+ let stats[current][1] += 1 |
|
+ endif |
|
+ endfor |
|
+ return stats |
|
+endfunction |
|
+ |
|
function! s:AddDiffSection(to, stat, label, files) abort |
|
if empty(a:files) |
|
return |
|
@@ -2625,8 +2662,20 @@ function! s:AddDiffSection(to, stat, label, files) abort |
|
let expanded = a:stat.expanded[a:label] |
|
let was_expanded = get(getbufvar(a:stat.bufnr, 'fugitive_expanded', {}), a:label, {}) |
|
call extend(a:to.lines, ['', a:label . ' (' . len(a:files) . ')']) |
|
+ let stats = s:DiffStats(diff_section, a:files) |
|
+ let formatted = map(copy(a:files), 's:Format(v:val)') |
|
+ let max_name = max(map(copy(formatted), 'len(v:val)') + [0]) |
|
+ let max_adds = 1 |
|
+ let max_dels = 1 |
|
+ for [adds, dels] in stats |
|
+ let max_adds = max([max_adds, len(string(adds))]) |
|
+ let max_dels = max([max_dels, len(string(dels))]) |
|
+ endfor |
|
+ let i = 0 |
|
for file in a:files |
|
- call add(a:to.lines, s:Format(file)) |
|
+ let suffix = printf('%*s %*s', max_adds + 1, '+' . stats[i][0], max_dels + 1, '-' . stats[i][1]) |
|
+ let line = formatted[i] . repeat(' ', max_name - len(formatted[i]) + 2) . suffix |
|
+ call add(a:to.lines, line) |
|
if has_key(was_expanded, file.filename) |
|
let [diff, start] = s:StageInlineGetDiff(diff_section, file) |
|
if len(diff) |
|
@@ -2634,6 +2683,7 @@ function! s:AddDiffSection(to, stat, label, files) abort |
|
call extend(a:to.lines, diff) |
|
endif |
|
endif |
|
+ let i += 1 |
|
endfor |
|
endfunction |
|
|
|
@@ -4275,7 +4325,7 @@ function! s:StageSeek(info, fallback) abort |
|
endif |
|
let i = 0 |
|
while len(getline(line)) |
|
- let filename = matchstr(getline(line), '^[A-Z?] \zs.*') |
|
+ let filename = s:StripDiffStats(matchstr(getline(line), '^[A-Z?] \zs.*')) |
|
if len(filename) && |
|
\ ((info.filename[-1:-1] ==# '/' && filename[0 : len(info.filename) - 1] ==# info.filename) || |
|
\ (filename[-1:-1] ==# '/' && filename ==# info.filename[0 : len(filename) - 1]) || |
|
@@ -4496,7 +4546,7 @@ function! s:StageInfo(...) abort |
|
let index += 1 |
|
endif |
|
endwhile |
|
- let text = matchstr(getline(lnum), '^[A-Z?] \zs.*') |
|
+ let text = s:StripDiffStats(matchstr(getline(lnum), '^[A-Z?] \zs.*')) |
|
let file = s:StatusSectionFile(heading, text) |
|
let relative = get(file, 'relative', len(text) ? [text] : []) |
|
return {'section': matchstr(heading, '^\u\l\+'), |
|
@@ -4578,7 +4628,7 @@ function! s:Selection(arg1, ...) abort |
|
endif |
|
let results[-1].lnum = lnum |
|
elseif line =~# '^[A-Z?] ' |
|
- let text = matchstr(line, '^[A-Z?] \zs.*') |
|
+ let text = s:StripDiffStats(matchstr(line, '^[A-Z?] \zs.*')) |
|
let file = s:StatusSectionFile(template.heading, text) |
|
let relative = get(file, 'relative', len(text) ? [text] : []) |
|
call add(results, extend(deepcopy(template), { |
|
diff --git a/syntax/fugitive.vim b/syntax/fugitive.vim |
|
index c7fe201..6035093 100644 |
|
--- a/syntax/fugitive.vim |
|
+++ b/syntax/fugitive.vim |
|
@@ -32,6 +32,8 @@ syn region fugitiveHunk start=/^\%(@@\+ -\)\@=/ end=/^\%([A-Za-z?@]\|$\)\@=/ con |
|
for s:section in ['Untracked', 'Unstaged', 'Staged'] |
|
exe 'syn region fugitive' . s:section . 'Section start=/^\%(' . s:section . ' .*(\d\++\=)$\)\@=/ contains=fugitive' . s:section . 'Heading end=/^$/ fold' |
|
exe 'syn match fugitive' . s:section . 'Modifier /^[MADRCU?] / contained containedin=fugitive' . s:section . 'Section' |
|
+ exe 'syn match fugitiveAdded /+\d\+\ze \+-\d\+$/ contained containedin=fugitive' . s:section . 'Section' |
|
+ exe 'syn match fugitiveRemoved /-\d\+$/ contained containedin=fugitive' . s:section . 'Section' |
|
exe 'syn cluster fugitiveSection add=fugitive' . s:section . 'Section' |
|
exe 'syn match fugitive' . s:section . 'Heading /^[A-Z][a-z][^:]*\ze (\d\++\=)$/ contains=fugitivePreposition contained nextgroup=fugitiveCount skipwhite' |
|
endfor |
|
@@ -53,5 +55,7 @@ hi def link fugitiveStop Function |
|
hi def link fugitiveHash Identifier |
|
hi def link fugitiveSymbolicRef Function |
|
hi def link fugitiveCount Number |
|
+hi def fugitiveAdded ctermfg=DarkGreen guifg=#22863a |
|
+hi def fugitiveRemoved ctermfg=DarkRed guifg=#cb2431 |
|
|
|
let b:current_syntax = "fugitive" |