1 " perforceutils.vim: Please see perforce/perforceutils.vim
3 " Make sure line-continuations won't cause any problem. This will be restored
8 " Determine the script id.
9 function! s:MyScriptId()
11 let s:sid = maparg("<SID>xx")
13 return substitute(s:sid, "xx$", "", "")
15 let s:myScriptId = s:MyScriptId()
16 delfunction s:MyScriptId " This is not needed anymore.
18 " CAUTION: Don't assume the existence of plugin/perforce.vim (or any other
19 " plugins) at the time this file is sourced.
23 " Open the source line for the current line from the diff.
24 function! perforceutils#DiffOpenSrc(preview) " {{{
25 let s:EMPTY_STR = perforce#PFEval('s:EMPTY_STR')
26 if perforce#PFEval('s:GetCurrentItem()') !~# s:EMPTY_STR
29 call genutils#SaveHardPosition('DiffOpenSrc')
30 " Move to the end of next line (if possible), so that the search will work
31 " correctly when the cursor is ON the header (should find the current line).
33 let filePat = '\zs[^#]\+\%(#\d\+\)\=\ze\%( ([^)]\+)\)\='
34 let diffHdr = '^diff \%(-\S\+\s\+\)*'
35 " Search backwards to find the header for this diff (could contain two
36 " depot files or one depot file with or without a local file).
37 if search('^==== '.filePat.'\%( - '.filePat.'\)\= ====', 'bW')
38 let firstFile = matchstr(getline('.'), '^==== \zs'.filePat.
40 let secondFile = matchstr(getline('.'), ' - '.filePat.' ====',
41 \ strlen(firstFile)+5)
45 elseif search('^--- '.filePat.'.*\n\_^+++ '.filePat, 'bW')
46 let firstFile = matchstr(getline(line('.')-1), '^--- \zs.\{-}\ze\t')
47 let secondFile = matchstr(getline('.'), '^+++ \zs.\{-}\ze\t')
50 " Another GNU diff header, for default output (typically for -r option).
51 elseif search(diffHdr.filePat.' '.filePat, 'bW')
52 exec substitute(substitute(getline('.'),
53 \ diffHdr.'\('.filePat.'\) \('.filePat.'\)',
54 \ ":::let firstFile = '\\1' | let secondFile = '\\2'", ''),
61 call genutils#RestoreHardPosition('DiffOpenSrc')
62 if firstFile =~# s:EMPTY_STR
64 elseif secondFile =~# s:EMPTY_STR
65 " When there is only one file, then it is treated as the secondFile.
66 let secondFile = firstFile
70 " Search for the start of the diff segment. We could be in default,
71 " context or unified mode. Determine context, stLine and offset.
72 if search('^\d\+\%(,\d\+\)\=[adc]\d\+\%(,\d\+\)\=$', 'bW') " default.
73 let segStLine = line('.')
74 let segHeader = getline('.')
75 call genutils#RestoreHardPosition('DiffOpenSrc')
78 if getline('.') =~# '^>'
81 if search('^---$', 'bW') && line('.') > segStLine
82 let segStLine = line('.')
85 let stLine = matchstr(segHeader, regPre.'\zs\d\+\ze')
86 call genutils#RestoreHardPosition('DiffOpenSrc')
87 let offset = line('.') - segStLine - 1
88 elseif search('\([*-]\)\1\1 \d\+,\d\+ \1\{4}', 'bW') " context.
89 if getline('.') =~# '^-'
94 let stLine = matchstr(getline('.'), '^[*-]\{3} \zs\d\+\ze,')
95 let segStLine = line('.')
96 call genutils#RestoreHardPosition('DiffOpenSrc')
97 let offset = line('.') - segStLine - 1
98 elseif search('^@@ -\=\d\+,\d\+ +\=\d\+,\d\+ @@$', 'bW') " unified
99 let segStLine = line('.')
100 let segHeader = getline('.')
101 call genutils#RestoreHardPosition('DiffOpenSrc')
102 let context = 'local'
104 if getline('.') =~# '^-'
105 let context = 'depot'
108 let stLine = matchstr(segHeader, ' '.sign.'\zs\d\+\ze,\d\+')
109 let _ma = &l:modifiable
112 " Count the number of lines that come from the other side (those lines
113 " that start with an opposite sign).
114 let _ss = @/ | let @/ = '^'.substitute('-+', sign, '', '') |
115 \ let offOffset = matchstr(genutils#GetVimCmdOutput( segStLine.',.s//&/'),
116 \ '\d\+\ze substitutions\? on \d\+ lines\?') + 0 | let @/ = _ss
119 call genutils#RestoreHardPosition('DiffOpenSrc')
121 let offset = line('.') - segStLine - 1 - offOffset
123 let &l:modifiable = _ma
125 else " Not inside a diff context, just use 1.
126 let context = 'local'
132 if context ==# 'depot' && firstFile =~# s:EMPTY_STR
133 " Assume previous revision as the "before" file if none specified.
134 if perforce#PFCall('s:IsDepotPath', secondFile) && secondFile =~# '#\d\+'
135 let depotRev = s:GetFileRevision(secondFile)
139 let firstFile = substitute(secondFile, '#\d\+', '', '').'#'.(depotRev-1)
144 if context ==# 'local'
145 let file = secondFile
149 " If the path refers to a depot file, check if the local file is currently
150 " open in Vim and if so has the same version number as the depot file.
151 if context ==# 'local' && perforce#PFCall('s:IsDepotPath', file)
152 let localFile = perforce#PFCall('s:ConvertToLocalPath', file)
153 let bufNr = bufnr(localFile) + 0
155 let haveRev = getbufvar(bufNr, 'p4HaveRev')
156 let depotRev = s:GetFileRevision(file)
157 if haveRev == depotRev
160 " else " We could also try to run 'fstat' command and open up the file.
163 if perforce#PFCall('s:IsDepotPath', file)
164 let refresh = perforce#PFGet('s:refreshWindowsAlways')
166 call perforce#PFSet('s:refreshWindowsAlways', 0)
167 call perforce#PFIF(1, a:preview, 'print', file)
169 call perforce#PFSet('s:refreshWindowsAlways', refresh)
171 let offset = offset + 1 " For print header.
173 call perforce#PFCall('s:OpenFile', 1, a:preview, genutils#CleanupFileName(file))
175 if perforce#PFEval('s:errCode') == 0
180 exec (stLine + offset)
182 " Also works as a work-around for the buffer not getting scrolled.
188 call perforce#PFCall('s:EchoMessage', v:exception, 'Error')
193 function! perforceutils#SetupDiffLink()
194 command! -buffer -nargs=0 PDiffLink :PFDiffLink
195 command! -buffer -nargs=0 PDiffPLink :PFDiffPLink
196 nnoremap <buffer> <silent> O :PDiffLink<CR>
197 nnoremap <buffer> <silent> <CR> :PDiffPLink<CR>
200 function! s:GetFileRevision(depotPath)
201 let rev = matchstr(a:depotPath, '#\zs\d\+$')
202 return (rev !~# s:EMPTY_STR) ? rev + 0 : ''
208 function! perforceutils#ShowConflicts()
209 let _splitright = &splitright
212 let curFile = expand('%:p')
213 "exec 'split' curFile.'.Original'
214 exec 'edit' curFile.'.Original'
215 silent! exec 'read' curFile
217 call genutils#SilentSubstitute('^==== THEIRS \_.\{-}\%(^<<<<$\)\@=', '%s///e')
218 call genutils#SilentDelete('\%(^>>>> ORIGINAL \|^==== THEIRS\|^==== YOURS \|^<<<<$\)')
219 call genutils#SetupScratchBuffer()
220 setlocal nomodifiable
223 exec 'vsplit' curFile.'.Theirs'
224 silent! exec 'read' curFile
226 call genutils#SilentSubstitute('^>>>> ORIGINAL \_.\{-}\%(^==== THEIRS \)\@=', '%s///e')
227 call genutils#SilentSubstitute('^==== YOURS \_.\{-}\%(^<<<<$\)\@=', '%s///e')
228 call genutils#SilentDelete('\%(^>>>> ORIGINAL \|^==== THEIRS\|^==== YOURS \|^<<<<$\)')
229 call genutils#SetupScratchBuffer()
230 setlocal nomodifiable
233 exec 'vsplit' curFile.'.Yours'
234 silent! exec 'read' curFile
236 call genutils#SilentSubstitute('^>>>> ORIGINAL \_.\{-}\%(^==== YOURS \)\@=', '%s///e')
237 call genutils#SilentDelete('\%(^>>>> ORIGINAL \|^==== THEIRS\|^==== YOURS \|^<<<<$\)')
238 call genutils#SetupScratchBuffer()
241 exec "au Perforce BufWriteCmd <buffer> :call <SID>SaveYours('".curFile."')"
244 let &splitright = _splitright
248 function! s:SaveYours(orgFile)
249 if confirm('Do you want to accept the changes in "'.expand("%:p:t").'"?',
250 \ "&Yes\n&No", 2, "Question") == 1
257 let &cpo = s:save_cpo
260 " vim6:fdm=marker et sw=2