1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
" Undo some diff lines
function! diff#prune#Prune(type) abort
" Choose appropriate line ranges depending on mode
if a:type ==# 'v' || a:type ==# 'V' || a:type ==# "\<C-V>"
let range = '''<,''>'
else
let range = '''[,'']'
endif
" Reinstate removals and remove addenda; preserve search pattern
let search_save = @/
silent execute range.'substitute/^-/ /e'
silent execute range.'global/^+/d'
let @/ = search_save
" Now we need to look for any blocks or files to remove if they have no
" changes in them anymore
let file_changes = 0
let block_changes = 0
let deletions = {}
for li in range(1, line('$') + 1)
" Flag for the end of the buffer (one past the last line)
let eof = li > line('$')
" If this index corresponds to a real line, cache its value
if !eof
let line = getline(li)
let deletions[li] = 0
endif
" Flags for whether this iteration constitutes the start of a new file, a
" new block, or a changed line
let file = stridx(line, 'diff') == 0 && !eof
let block = stridx(line, '@@') == 0 && !eof
let change = (stridx(line, '+') == 0 || stridx(line, '-') == 0)
\ && !eof
\ && exists('block_start')
" End of old file: flag previous file lines for deletion if no changes,
" clear file start and changes variables
if file || eof
if exists('file_start') && file_changes == 0
for di in range(file_start, li - 1)
let deletions[di] = 1
endfor
endif
unlet! file_start file_changes
endif
" Start of new file: set start line, start new changes counter
if file
let file_start = li
let file_changes = 0
endif
" End of old block: flag previous block lines for deletion if no changes,
" clear block start and changes variables
if block || file || eof
if exists('block_start') && block_changes == 0
for di in range(block_start, li - 1)
let deletions[di] = 1
endfor
endif
unlet! block_start block_changes
endif
" Start of new block: set start line, start new changes counter
if block
let block_start = li
let block_changes = 0
endif
" If this is a changed line, bump the counters for this file and block
if change
let file_changes += 1
let block_changes += 1
endif
endfor
" Delete any flagged lines, going in reverse order so we don't reset any
" indices as we go
let di = line('$')
while di > 0
if deletions[di]
silent execute di.'delete'
endif
let di -= 1
endwhile
endfunction
|