aboutsummaryrefslogblamecommitdiff
path: root/autoload/diff/prune.vim
blob: 554d65d8b32df5d918f70015a374c8dd2c5dca2d (plain) (tree)
1
2
3
4
5
6
7
8
                      
                                      

                                                    
                                                            
                         
      
                         


                                                                  



                                          
 

                                                                         



                                   

                                                             
                            

                                                               


                            



                                                                             




                                                                   


                                                                           



                                                  

              
                                    


                                                                  


                          



                                                                             



                                                    

              
                                      


                                                                   


                           


                                                                          


                            





                                                                          



                                
         
               

          
           
" 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