public
Description: Vim script to highlight lines changed from a base version in SCM
Homepage:
Clone URL: git://github.com/ghewgill/vim-scmdiff.git
vim-scmdiff / scmdiff.vim
100644 172 lines (135 sloc) 4.902 kb
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
" Vim script to show file differences from a base version in SCM.
" Home: http://github.com/ghewgill/vim-scmdiff
 
" Default commands:
" \d Toggle diff view on/off
" :D rev Difference between current and rev
"
" You can change the highlighting by adding the following to your
" .vimrc file and customizing as necessary. (or just uncomment them here):
" highlight DiffAdd ctermbg=DarkBlue ctermfg=white cterm=NONE
" highlight DiffChange ctermbg=DarkBlue ctermfg=white cterm=NONE
" highlight DiffText ctermbg=DarkBlue ctermfg=white cterm=underline
" highlight DiffDelete ctermbg=red ctermfg=white
 
if exists("loadedScmDiff") || &cp
    finish
endif
 
let loadedScmDiff = 1
 
map <silent> <Leader>d :call <SID>scmToggle()<CR>
noremap <unique> <script> <plug>Dh :call <SID>scmDiff("h")<CR>
com! -bar -nargs=? D :call s:scmDiff(<f-args>)
 
let g:scmDiffRev = ''
 
function! s:scmToggle()
 
    if exists('b:scmDiffOn') && b:scmDiffOn == 1
        let b:scmDiffOn = 0
        set nodiff
        exe 'bdelete ' . b:scmDiffTmpfile
        echohl DiffDelete | echon "scmdiff Disabled" | echohl None
    else
        call s:scmDiff()
        if exists('b:scmDiffOn') && b:scmDiffOn == 1
            echohl DiffAdd | echon "scmdiff Enabled" | echohl None
        endif
    endif
 
endfunction
 
function! s:scmRefresh()
 
    if exists('b:scmDiffOn') && b:scmDiffOn == 1
        call s:scmDiff()
    endif
 
endfunction
 
function! s:detectSCM()
 
" Cache the results we find here to save time
    if exists("g:scmBufPath") && g:scmBufPath == expand("%:p:h") && exists("g:scmDiffCommand")
        return
    endif
    let g:scmBufPath = expand("%:p:h")
 
" Detect CVS, SCCS(bitkeeper) or .svn directories in current path
    if !exists("g:scmDiffCommand") && isdirectory(g:scmBufPath."/.svn")
        let g:scmDiffCommand = "svn diff"
        return
    endif
 
    if !exists("g:scmDiffCommand") && isdirectory(g:scmBufPath."/CVS")
        let g:scmDiffCommand = "cvs diff"
        return
    endif
 
    if !exists("g:scmDiffCommand") && isdirectory(g:scmBufPath."/SCCS")
        let g:scmDiffCommand = "bk diffs"
        return
    endif
 
" Detect .git, SCCS(bitkeeper), .hg(mercurial), _darcs(darcs) directories recursively in reverse
    let my_path = g:scmBufPath
    while my_path != "/"
        if !exists("g:scmDiffCommand") && isdirectory(my_path."/.git")
            let g:scmDiffCommand = "git diff"
            return
        endif
        if !exists("g:scmDiffCommand") && isdirectory(my_path."/.hg")
            let g:scmDiffCommand = "hg diff"
            return
        endif
        if !exists("g:scmDiffCommand") && isdirectory(my_path."/_darcs")
            let g:scmDiffCommand = "darcs diff -u"
            return
        endif
        let my_path = simplify(my_path."/../")
    endwhile
 
endfunction
 
function! s:scmDiff(...)
 
    call s:detectSCM()
    if (!exists("g:scmDiffCommand"))
        echohl WarningMsg | echon "Could not find .git, .svn, .hg, _darcs, SCCS, or CVS directories, are you under a supported SCM repository path?" | echohl None
        return
    endif
 
    if exists('b:scmDiffOn') && b:scmDiffOn == 1
        let b:scmDiffOn = 0
        set nodiff
        exe 'bdelete ' . b:scmDiffTmpfile
    endif
 
    let b:scmDiffOn = 1
    let view = winsaveview()
 
    if a:0 == 1
        if a:1 == 'none'
            let g:scmDiffRev = ''
        else
            let g:scmDiffRev = a:1
            if (match(g:scmDiffCommand, 'darcs'))
                g:scmDiffRev = '--from-patch=' . g:scmDiffRev
            endif
        endif
    endif
 
    let ftype = &filetype
    let b:scmDiffTmpfile = tempname()
    let cmd = 'cat ' . bufname('%') . ' > ' . b:scmDiffTmpfile
    let cmdOutput = system(cmd)
    let tmpdiff = tempname()
    let cmd = 'cd ' . g:scmBufPath . ' && ' . g:scmDiffCommand . ' ' . g:scmDiffRev . ' ' . expand('%:t') . ' > ' . tmpdiff
    let cmdOutput = system(cmd)
    let doWrap = &wrap " Save the current state of wrap for later
 
    if v:shell_error && cmdOutput != ''
        echohl WarningMsg | echon cmdOutput | echohl None
        return
    endif
 
    let cmd = 'patch -R -p0 ' . b:scmDiffTmpfile . ' ' . tmpdiff
    let cmdOutput = system(cmd)
 
    if v:shell_error && cmdOutput != ''
        echohl WarningMsg | echon cmdOutput | echohl None
        return
    endif
 
    if a:0 > 0 && a:1 == 'h'
        exe 'diffsplit' . b:scmDiffTmpfile
    else
        exe 'vert diffsplit' . b:scmDiffTmpfile
    endif
 
    exe 'set filetype=' . ftype
 
    hide
    if doWrap == 1
        set wrap "Restore the state of wrap
    endif
 
    set foldcolumn=0
    set foldlevel=100
    set diffopt= " removed filler so we don't show deleted lines
    set noscrollbind
 
    call winrestview(view)
 
endfunction
 
autocmd CursorHold * call s:scmRefresh()
 
 
" vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
" vim<600: expandtab sw=4 ts=4 sts=4