aboutsummaryrefslogtreecommitdiffstats
path: root/ftplugin/diff_navigator.vim
blob: fa4f5b124685e7b80284699029c57d9bfbc08909 (plain) (blame)
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
94
95
96
97
98
99
100
101
102
103
104
105
106
" ============================================================================
" File:         diff_navigator.vim
" Description:  Filetype plugin to ease navigation in (unified) diffs
" Maintainer:   Petr Uzel <petr.uzel -at- centrum.cz>
" Version:      0.1
" Last Change:  27 Aug, 2008
" License:      This program is free software. It comes without any warranty,
"               to the extent permitted by applicable law. You can redistribute
"               it and/or modify it under the terms of the Do What The Fuck You
"               Want To Public License, Version 2, as published by Sam Hocevar.
"               See http://sam.zoy.org/wtfpl/COPYING for more details.
"
" Bugs:         Send bugreports/patches directly to me via mail
" Dependencies: filterdiff (part of patchutils project)
"
"
" TODO:         show current hunk in status line
" TODO:         delete hunk/whole file diff - like http://www.vim.org/scripts/script.php?script_id=444)
" TODO:         incorporate more patchutils functionality
" TODO:         something like taglist for diff (shows all files/hunks in the diff)
" TODO:         option for *Next|Prev* funtions to wrap around end of file
" ============================================================================


" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
    finish
endif
let b:did_ftplugin = 1

" Annotate each hunk with it's number and name of the changed file
if !exists("*s:DiffAnnotate")
    function s:DiffAnnotate()
       if !executable('filterdiff') 
           echohl WarningMsg
           echo "You need to install filterdiff first (part of patchutils)"
           echohl None
           return
       endif
       let l:cursorpos = winsaveview()
       %!filterdiff --annotate
       call winrestview(cursorpos) 
    endfunction
endif

" Print annotation of current hunk
if !exists("*s:DiffShowHunk")
    function s:DiffShowHunk()
       " if the current line begins with '+++' or '---', then it makes sense to search
       " forwards
       if getline(".") =~ '^+++ \|^--- '
           let l:lineno = search('^@@[ +-\,\d]*@@.*$', 'ncW')
       else
           let l:lineno = search('^@@[ +-\,\d]*@@.*$', 'bncW')
       endif
       if l:lineno == 0
           return
       endif
       let l:hunk_annotation = substitute(getline(lineno), '^@@[ +-\,\d]*@@\s*\(.*\)$', '\1', '')
       echo l:hunk_annotation
    endfunction
endif

" Skip to next hunk
if !exists("*s:DiffNextHunk")
    function s:DiffNextHunk()
       call search('^@@[ +-\,\d]*@@', 'sW')
    endfunction
endif

" Skip to previous hunk
if !exists("*s:DiffPrevHunk")
    function s:DiffPrevHunk()
       call search('^@@[ +-\,\d]*@@', 'bsW')
    endfunction
endif

" Skip to next changed file
if !exists("*s:DiffNextFile")
    function s:DiffNextFile()
        call search('^--- ', 'sW')
    endfunction
endif

" Skip to previous changed file 
if !exists("*s:DiffPrevFile")
    function s:DiffPrevFile()
        call search('^--- ', 'bsW')
    endfunction
endif

command! -buffer DiffAnnotate call s:DiffAnnotate()
command! -buffer DiffShowHunk call s:DiffShowHunk()
command! -buffer DiffNextHunk call s:DiffNextHunk()
command! -buffer DiffPrevHunk call s:DiffPrevHunk()
command! -buffer DiffNextFile call s:DiffNextFile()
command! -buffer DiffPrevFile call s:DiffPrevFile()


" Default },{,(,) do not make much sense in diffs, so remap them to
" make something useful
nnoremap <buffer> } :DiffNextFile<CR>
nnoremap <buffer> { :DiffPrevFile<CR>
nnoremap <buffer> ) :DiffNextHunk<CR>
nnoremap <buffer> ( :DiffPrevHunk<CR>