|
1 " vim600: set foldmethod=marker: |
|
2 " |
|
3 " Vim plugin to assist in working with CVS-controlled files. |
|
4 " |
|
5 " Last Change: 2006/02/22 |
|
6 " Version: 1.76 |
|
7 " Maintainer: Bob Hiestand <bob.hiestand@gmail.com> |
|
8 " License: This file is placed in the public domain. |
|
9 " Credits: {{{1 |
|
10 " Mathieu Clabaut for many suggestions and improvements. |
|
11 " |
|
12 " Suresh Govindachar and Jeeva Chelladhurai for finding waaaay |
|
13 " too many bugs. |
|
14 " |
|
15 " Suresh Govindachar (again!) for finding the |
|
16 " fully-folded-last-line-delete bug. |
|
17 " |
|
18 " Albrecht Gass for the Delete-on-Hide behavior suggestion. |
|
19 " |
|
20 " Joe MacDonald for finding the CVS log message header bug and |
|
21 " pointing out that buffer refreshes are needed after CVS |
|
22 " \%(un\)\?edit. |
|
23 " |
|
24 " Srinath Avadhanula for the suggestion and original patch for |
|
25 " the CVSCommitOnWrite option and mapping hot key. |
|
26 " |
|
27 " John Sivak for helping to debug Windows issues and suggesting |
|
28 " the CVSEditors and CVSWatchers commands. |
|
29 " |
|
30 " Igor Levko for the patch to recognize numerical sticky tags. |
|
31 " |
|
32 " Domink Strasser for the patch to correct the status line for |
|
33 " CVSAdd'd files. |
|
34 " |
|
35 " Weerapong Sirikanya for finding a bug with CVSCommit and |
|
36 " autochdir. |
|
37 " |
|
38 " David Gotz for finding a bug with CVSVimDiff buffer splitting |
|
39 " and original buffer restoration. |
|
40 " |
|
41 " CJ van den Berg for the patch to not change working directory |
|
42 " when editing a non-CVS file. |
|
43 " |
|
44 " Luca Gerli for noticing bad behavior for keywords in files |
|
45 " after commit if split windows are used. |
|
46 |
|
47 " Section: Documentation {{{1 |
|
48 " |
|
49 " Provides functions to invoke various CVS commands on the current file |
|
50 " (either the current buffer, or, in the case of an directory buffer, the file |
|
51 " on the current line). The output of the commands is captured in a new |
|
52 " scratch window. For convenience, if the functions are invoked on a CVS |
|
53 " output window, the original file is used for the cvs operation instead after |
|
54 " the window is split. This is primarily useful when running CVSCommit and |
|
55 " you need to see the changes made, so that CVSDiff is usable and shows up in |
|
56 " another window. |
|
57 " |
|
58 " Command documentation {{{2 |
|
59 " |
|
60 " CVSAdd Performs "cvs add" on the current file. |
|
61 " |
|
62 " CVSAnnotate Performs "cvs annotate" on the current file. If an |
|
63 " argument is given, the argument is used as a revision |
|
64 " number to display. If not given an argument, it uses the |
|
65 " most recent version of the file on the current branch. |
|
66 " Additionally, if the current buffer is a CVSAnnotate buffer |
|
67 " already, the version number on the current line is used. |
|
68 " |
|
69 " If the 'CVSCommandAnnotateParent' variable is set to a |
|
70 " non-zero value, the version previous to the one on the |
|
71 " current line is used instead. This allows one to navigate |
|
72 " back to examine the previous version of a line. |
|
73 " |
|
74 " CVSCommit[!] If called with arguments, this performs "cvs commit" using |
|
75 " the arguments as the log message. |
|
76 " |
|
77 " If '!' is used, an empty log message is committed. |
|
78 " |
|
79 " If called with no arguments, this is a two-step command. |
|
80 " The first step opens a buffer to accept a log message. |
|
81 " When that buffer is written, it is automatically closed and |
|
82 " the file is committed using the information from that log |
|
83 " message. The commit can be abandoned if the log message |
|
84 " buffer is deleted or wiped before being written. |
|
85 " |
|
86 " CVSDiff With no arguments, this performs "cvs diff" on the current |
|
87 " file. With one argument, "cvs diff" is performed on the |
|
88 " current file against the specified revision. With two |
|
89 " arguments, cvs diff is performed between the specified |
|
90 " revisions of the current file. This command uses the |
|
91 " 'CVSCommandDiffOpt' variable to specify diff options. If |
|
92 " that variable does not exist, then 'wbBc' is assumed. If |
|
93 " you wish to have no options, then set it to the empty |
|
94 " string. |
|
95 " |
|
96 " CVSEdit Performs "cvs edit" on the current file. |
|
97 " |
|
98 " CVSEditors Performs "cvs editors" on the current file. |
|
99 " |
|
100 " CVSGotoOriginal Returns the current window to the source buffer if the |
|
101 " current buffer is a CVS output buffer. |
|
102 " |
|
103 " CVSLog Performs "cvs log" on the current file. |
|
104 " |
|
105 " CVSRevert Replaces the modified version of the current file with the |
|
106 " most recent version from the repository. |
|
107 " |
|
108 " CVSReview Retrieves a particular version of the current file. If no |
|
109 " argument is given, the most recent version of the file on |
|
110 " the current branch is retrieved. The specified revision is |
|
111 " retrieved into a new buffer. |
|
112 " |
|
113 " CVSStatus Performs "cvs status" on the current file. |
|
114 " |
|
115 " CVSUnedit Performs "cvs unedit" on the current file. |
|
116 " |
|
117 " CVSUpdate Performs "cvs update" on the current file. |
|
118 " |
|
119 " CVSVimDiff With no arguments, this prompts the user for a revision and |
|
120 " then uses vimdiff to display the differences between the |
|
121 " current file and the specified revision. If no revision is |
|
122 " specified, the most recent version of the file on the |
|
123 " current branch is used. With one argument, that argument |
|
124 " is used as the revision as above. With two arguments, the |
|
125 " differences between the two revisions is displayed using |
|
126 " vimdiff. |
|
127 " |
|
128 " With either zero or one argument, the original buffer is used |
|
129 " to perform the vimdiff. When the other buffer is closed, the |
|
130 " original buffer will be returned to normal mode. |
|
131 " |
|
132 " Once vimdiff mode is started using the above methods, |
|
133 " additional vimdiff buffers may be added by passing a single |
|
134 " version argument to the command. There may be up to 4 |
|
135 " vimdiff buffers total. |
|
136 " |
|
137 " Using the 2-argument form of the command resets the vimdiff |
|
138 " to only those 2 versions. Additionally, invoking the |
|
139 " command on a different file will close the previous vimdiff |
|
140 " buffers. |
|
141 " |
|
142 " CVSWatch Takes an argument which must be one of [on|off|add|remove]. |
|
143 " Performs "cvs watch" with the given argument on the current |
|
144 " file. |
|
145 " |
|
146 " CVSWatchers Performs "cvs watchers" on the current file. |
|
147 " |
|
148 " CVSWatchAdd Alias for "CVSWatch add" |
|
149 " |
|
150 " CVSWatchOn Alias for "CVSWatch on" |
|
151 " |
|
152 " CVSWatchOff Alias for "CVSWatch off" |
|
153 " |
|
154 " CVSWatchRemove Alias for "CVSWatch remove" |
|
155 " |
|
156 " Mapping documentation: {{{2 |
|
157 " |
|
158 " By default, a mapping is defined for each command. User-provided mappings |
|
159 " can be used instead by mapping to <Plug>CommandName, for instance: |
|
160 " |
|
161 " nnoremap ,ca <Plug>CVSAdd |
|
162 " |
|
163 " The default mappings are as follow: |
|
164 " |
|
165 " <Leader>ca CVSAdd |
|
166 " <Leader>cn CVSAnnotate |
|
167 " <Leader>cc CVSCommit |
|
168 " <Leader>cd CVSDiff |
|
169 " <Leader>ce CVSEdit |
|
170 " <Leader>ci CVSEditors |
|
171 " <Leader>cg CVSGotoOriginal |
|
172 " <Leader>cG CVSGotoOriginal! |
|
173 " <Leader>cl CVSLog |
|
174 " <Leader>cr CVSReview |
|
175 " <Leader>cs CVSStatus |
|
176 " <Leader>ct CVSUnedit |
|
177 " <Leader>cu CVSUpdate |
|
178 " <Leader>cv CVSVimDiff |
|
179 " <Leader>cwv CVSWatchers |
|
180 " <Leader>cwa CVSWatchAdd |
|
181 " <Leader>cwn CVSWatchOn |
|
182 " <Leader>cwa CVSWatchOff |
|
183 " <Leader>cwr CVSWatchRemove |
|
184 " |
|
185 " Options documentation: {{{2 |
|
186 " |
|
187 " Several variables are checked by the script to determine behavior as follow: |
|
188 " |
|
189 " CVSCommandAnnotateParent |
|
190 " This variable, if set to a non-zero value, causes the zero-argument form |
|
191 " of CVSAnnotate when invoked on a CVSAnnotate buffer to go to the version |
|
192 " previous to that displayed on the current line. If not set, it defaults |
|
193 " to 0. |
|
194 " |
|
195 " CVSCommandCommitOnWrite |
|
196 " This variable, if set to a non-zero value, causes the pending cvs commit |
|
197 " to take place immediately as soon as the log message buffer is written. |
|
198 " If set to zero, only the CVSCommit mapping will cause the pending commit |
|
199 " to occur. If not set, it defaults to 1. |
|
200 " |
|
201 " CVSCommandDeleteOnHide |
|
202 " This variable, if set to a non-zero value, causes the temporary CVS result |
|
203 " buffers to automatically delete themselves when hidden. |
|
204 " |
|
205 " CVSCommandDiffOpt |
|
206 " This variable, if set, determines the options passed to the diff command |
|
207 " of CVS. If not set, it defaults to 'wbBc'. |
|
208 " |
|
209 " CVSCommandDiffSplit |
|
210 " This variable overrides the CVSCommandSplit variable, but only for buffers |
|
211 " created with CVSVimDiff. |
|
212 " |
|
213 " CVSCommandEdit |
|
214 " This variable controls whether the original buffer is replaced ('edit') or |
|
215 " split ('split'). If not set, it defaults to 'edit'. |
|
216 " |
|
217 " CVSCommandEnableBufferSetup |
|
218 " This variable, if set to a non-zero value, activates CVS buffer management |
|
219 " mode. This mode means that two buffer variables, 'CVSRevision' and |
|
220 " 'CVSBranch', are set if the file is CVS-controlled. This is useful for |
|
221 " displaying version information in the status bar. |
|
222 " |
|
223 " CVSCommandInteractive |
|
224 " This variable, if set to a non-zero value, causes appropriate functions (for |
|
225 " the moment, only CVSReview) to query the user for a revision to use |
|
226 " instead of the current revision if none is specified. |
|
227 " |
|
228 " CVSCommandNameMarker |
|
229 " This variable, if set, configures the special attention-getting characters |
|
230 " that appear on either side of the cvs buffer type in the buffer name. |
|
231 " This has no effect unless 'CVSCommandNameResultBuffers' is set to a true |
|
232 " value. If not set, it defaults to '_'. |
|
233 " |
|
234 " CVSCommandNameResultBuffers |
|
235 " This variable, if set to a true value, causes the cvs result buffers to be |
|
236 " named in the old way ('<source file name> _<cvs command>_'). If not set |
|
237 " or set to a false value, the result buffer is nameless. |
|
238 " |
|
239 " CVSCommandSplit |
|
240 " This variable controls the orientation of the various window splits that |
|
241 " may occur (such as with CVSVimDiff, when using a CVS command on a CVS |
|
242 " command buffer, or when the 'CVSCommandEdit' variable is set to 'split'. |
|
243 " If set to 'horizontal', the resulting windows will be on stacked on top of |
|
244 " one another. If set to 'vertical', the resulting windows will be |
|
245 " side-by-side. If not set, it defaults to 'horizontal' for all but |
|
246 " CVSVimDiff windows. |
|
247 " |
|
248 " Event documentation {{{2 |
|
249 " For additional customization, cvscommand.vim uses User event autocommand |
|
250 " hooks. Each event is in the CVSCommand group, and different patterns |
|
251 " match the various hooks. |
|
252 " |
|
253 " For instance, the following could be added to the vimrc to provide a 'q' |
|
254 " mapping to quit a CVS buffer: |
|
255 " |
|
256 " augroup CVSCommand |
|
257 " au CVSCommand User CVSBufferCreated silent! nmap <unique> <buffer> q :bwipeout<cr> |
|
258 " augroup END |
|
259 " |
|
260 " The following hooks are available: |
|
261 " |
|
262 " CVSBufferCreated This event is fired just after a cvs command |
|
263 " result buffer is created and filled with the |
|
264 " result of a cvs command. It is executed within |
|
265 " the context of the new buffer. |
|
266 " |
|
267 " CVSBufferSetup This event is fired just after CVS buffer setup |
|
268 " occurs, if enabled. |
|
269 " |
|
270 " CVSPluginInit This event is fired when the CVSCommand plugin |
|
271 " first loads. |
|
272 " |
|
273 " CVSPluginFinish This event is fired just after the CVSCommand |
|
274 " plugin loads. |
|
275 " |
|
276 " CVSVimDiffFinish This event is fired just after the CVSVimDiff |
|
277 " command executes to allow customization of, |
|
278 " for instance, window placement and focus. |
|
279 " |
|
280 " Section: Plugin header {{{1 |
|
281 |
|
282 " loaded_cvscommand is set to 1 when the initialization begins, and 2 when it |
|
283 " completes. This allows various actions to only be taken by functions after |
|
284 " system initialization. |
|
285 |
|
286 if exists("loaded_cvscommand") |
|
287 finish |
|
288 endif |
|
289 let loaded_cvscommand = 1 |
|
290 |
|
291 if v:version < 602 |
|
292 echohl WarningMsg|echomsg "CVSCommand 1.69 or later requires VIM 6.2 or later"|echohl None |
|
293 finish |
|
294 endif |
|
295 |
|
296 " Section: Event group setup {{{1 |
|
297 |
|
298 augroup CVSCommand |
|
299 augroup END |
|
300 |
|
301 " Section: Plugin initialization {{{1 |
|
302 silent do CVSCommand User CVSPluginInit |
|
303 |
|
304 " Section: Script variable initialization {{{1 |
|
305 |
|
306 let s:CVSCommandEditFileRunning = 0 |
|
307 unlet! s:vimDiffRestoreCmd |
|
308 unlet! s:vimDiffSourceBuffer |
|
309 unlet! s:vimDiffBufferCount |
|
310 unlet! s:vimDiffScratchList |
|
311 |
|
312 " Section: Utility functions {{{1 |
|
313 |
|
314 " Function: s:CVSResolveLink() {{{2 |
|
315 " Fully resolve the given file name to remove shortcuts or symbolic links. |
|
316 |
|
317 function! s:CVSResolveLink(fileName) |
|
318 let resolved = resolve(a:fileName) |
|
319 if resolved != a:fileName |
|
320 let resolved = s:CVSResolveLink(resolved) |
|
321 endif |
|
322 return resolved |
|
323 endfunction |
|
324 |
|
325 " Function: s:CVSChangeToCurrentFileDir() {{{2 |
|
326 " Go to the directory in which the current CVS-controlled file is located. |
|
327 " If this is a CVS command buffer, first switch to the original file. |
|
328 |
|
329 function! s:CVSChangeToCurrentFileDir(fileName) |
|
330 let oldCwd=getcwd() |
|
331 let fileName=s:CVSResolveLink(a:fileName) |
|
332 let newCwd=fnamemodify(fileName, ':h') |
|
333 if strlen(newCwd) > 0 |
|
334 execute 'cd' escape(newCwd, ' ') |
|
335 endif |
|
336 return oldCwd |
|
337 endfunction |
|
338 |
|
339 " Function: s:CVSGetOption(name, default) {{{2 |
|
340 " Grab a user-specified option to override the default provided. Options are |
|
341 " searched in the window, buffer, then global spaces. |
|
342 |
|
343 function! s:CVSGetOption(name, default) |
|
344 if exists("s:" . a:name . "Override") |
|
345 execute "return s:".a:name."Override" |
|
346 elseif exists("w:" . a:name) |
|
347 execute "return w:".a:name |
|
348 elseif exists("b:" . a:name) |
|
349 execute "return b:".a:name |
|
350 elseif exists("g:" . a:name) |
|
351 execute "return g:".a:name |
|
352 else |
|
353 return a:default |
|
354 endif |
|
355 endfunction |
|
356 |
|
357 " Function: s:CVSEditFile(name, origBuffNR) {{{2 |
|
358 " Wrapper around the 'edit' command to provide some helpful error text if the |
|
359 " current buffer can't be abandoned. If name is provided, it is used; |
|
360 " otherwise, a nameless scratch buffer is used. |
|
361 " Returns: 0 if successful, -1 if an error occurs. |
|
362 |
|
363 function! s:CVSEditFile(name, origBuffNR) |
|
364 "Name parameter will be pasted into expression. |
|
365 let name = escape(a:name, ' *?\') |
|
366 |
|
367 let editCommand = s:CVSGetOption('CVSCommandEdit', 'edit') |
|
368 if editCommand != 'edit' |
|
369 if s:CVSGetOption('CVSCommandSplit', 'horizontal') == 'horizontal' |
|
370 if name == "" |
|
371 let editCommand = 'rightbelow new' |
|
372 else |
|
373 let editCommand = 'rightbelow split ' . name |
|
374 endif |
|
375 else |
|
376 if name == "" |
|
377 let editCommand = 'vert rightbelow new' |
|
378 else |
|
379 let editCommand = 'vert rightbelow split ' . name |
|
380 endif |
|
381 endif |
|
382 else |
|
383 if name == "" |
|
384 let editCommand = 'enew' |
|
385 else |
|
386 let editCommand = 'edit ' . name |
|
387 endif |
|
388 endif |
|
389 |
|
390 " Protect against useless buffer set-up |
|
391 let s:CVSCommandEditFileRunning = s:CVSCommandEditFileRunning + 1 |
|
392 try |
|
393 execute editCommand |
|
394 finally |
|
395 let s:CVSCommandEditFileRunning = s:CVSCommandEditFileRunning - 1 |
|
396 endtry |
|
397 |
|
398 let b:CVSOrigBuffNR=a:origBuffNR |
|
399 let b:CVSCommandEdit='split' |
|
400 endfunction |
|
401 |
|
402 " Function: s:CVSCreateCommandBuffer(cmd, cmdName, statusText, filename) {{{2 |
|
403 " Creates a new scratch buffer and captures the output from execution of the |
|
404 " given command. The name of the scratch buffer is returned. |
|
405 |
|
406 function! s:CVSCreateCommandBuffer(cmd, cmdName, statusText, origBuffNR) |
|
407 let fileName=bufname(a:origBuffNR) |
|
408 |
|
409 let resultBufferName='' |
|
410 |
|
411 if s:CVSGetOption("CVSCommandNameResultBuffers", 0) |
|
412 let nameMarker = s:CVSGetOption("CVSCommandNameMarker", '_') |
|
413 if strlen(a:statusText) > 0 |
|
414 let bufName=a:cmdName . ' -- ' . a:statusText |
|
415 else |
|
416 let bufName=a:cmdName |
|
417 endif |
|
418 let bufName=fileName . ' ' . nameMarker . bufName . nameMarker |
|
419 let counter=0 |
|
420 let resultBufferName = bufName |
|
421 while buflisted(resultBufferName) |
|
422 let counter=counter + 1 |
|
423 let resultBufferName=bufName . ' (' . counter . ')' |
|
424 endwhile |
|
425 endif |
|
426 |
|
427 let cvsCommand = s:CVSGetOption("CVSCommandCVSExec", "cvs") . " " . a:cmd |
|
428 let cvsOut = system(cvsCommand) |
|
429 " HACK: diff command does not return proper error codes |
|
430 if v:shell_error && a:cmdName != 'cvsdiff' |
|
431 if strlen(cvsOut) == 0 |
|
432 echoerr "CVS command failed" |
|
433 else |
|
434 echoerr "CVS command failed: " . cvsOut |
|
435 endif |
|
436 return -1 |
|
437 endif |
|
438 if strlen(cvsOut) == 0 |
|
439 " Handle case of no output. In this case, it is important to check the |
|
440 " file status, especially since cvs edit/unedit may change the attributes |
|
441 " of the file with no visible output. |
|
442 |
|
443 echomsg "No output from CVS command" |
|
444 checktime |
|
445 return -1 |
|
446 endif |
|
447 |
|
448 if s:CVSEditFile(resultBufferName, a:origBuffNR) == -1 |
|
449 return -1 |
|
450 endif |
|
451 |
|
452 set buftype=nofile |
|
453 set noswapfile |
|
454 set filetype= |
|
455 |
|
456 if s:CVSGetOption("CVSCommandDeleteOnHide", 0) |
|
457 set bufhidden=delete |
|
458 endif |
|
459 |
|
460 silent 0put=cvsOut |
|
461 |
|
462 " The last command left a blank line at the end of the buffer. If the |
|
463 " last line is folded (a side effect of the 'put') then the attempt to |
|
464 " remove the blank line will kill the last fold. |
|
465 " |
|
466 " This could be fixed by explicitly detecting whether the last line is |
|
467 " within a fold, but I prefer to simply unfold the result buffer altogether. |
|
468 |
|
469 if has('folding') |
|
470 normal zR |
|
471 endif |
|
472 |
|
473 $d |
|
474 1 |
|
475 |
|
476 " Define the environment and execute user-defined hooks. |
|
477 |
|
478 let b:CVSSourceFile=fileName |
|
479 let b:CVSCommand=a:cmdName |
|
480 if a:statusText != "" |
|
481 let b:CVSStatusText=a:statusText |
|
482 endif |
|
483 |
|
484 silent do CVSCommand User CVSBufferCreated |
|
485 return bufnr("%") |
|
486 endfunction |
|
487 |
|
488 " Function: s:CVSBufferCheck(cvsBuffer) {{{2 |
|
489 " Attempts to locate the original file to which CVS operations were applied |
|
490 " for a given buffer. |
|
491 |
|
492 function! s:CVSBufferCheck(cvsBuffer) |
|
493 let origBuffer = getbufvar(a:cvsBuffer, "CVSOrigBuffNR") |
|
494 if origBuffer |
|
495 if bufexists(origBuffer) |
|
496 return origBuffer |
|
497 else |
|
498 " Original buffer no longer exists. |
|
499 return -1 |
|
500 endif |
|
501 else |
|
502 " No original buffer |
|
503 return a:cvsBuffer |
|
504 endif |
|
505 endfunction |
|
506 |
|
507 " Function: s:CVSCurrentBufferCheck() {{{2 |
|
508 " Attempts to locate the original file to which CVS operations were applied |
|
509 " for the current buffer. |
|
510 |
|
511 function! s:CVSCurrentBufferCheck() |
|
512 return s:CVSBufferCheck(bufnr("%")) |
|
513 endfunction |
|
514 |
|
515 " Function: s:CVSToggleDeleteOnHide() {{{2 |
|
516 " Toggles on and off the delete-on-hide behavior of CVS buffers |
|
517 |
|
518 function! s:CVSToggleDeleteOnHide() |
|
519 if exists("g:CVSCommandDeleteOnHide") |
|
520 unlet g:CVSCommandDeleteOnHide |
|
521 else |
|
522 let g:CVSCommandDeleteOnHide=1 |
|
523 endif |
|
524 endfunction |
|
525 |
|
526 " Function: s:CVSDoCommand(cvscmd, cmdName, statusText) {{{2 |
|
527 " General skeleton for CVS function execution. |
|
528 " Returns: name of the new command buffer containing the command results |
|
529 |
|
530 function! s:CVSDoCommand(cmd, cmdName, statusText) |
|
531 let cvsBufferCheck=s:CVSCurrentBufferCheck() |
|
532 if cvsBufferCheck == -1 |
|
533 echo "Original buffer no longer exists, aborting." |
|
534 return -1 |
|
535 endif |
|
536 |
|
537 let fileName=bufname(cvsBufferCheck) |
|
538 if isdirectory(fileName) |
|
539 let fileName=fileName . "/" . getline(".") |
|
540 endif |
|
541 let realFileName = fnamemodify(s:CVSResolveLink(fileName), ':t') |
|
542 let oldCwd=s:CVSChangeToCurrentFileDir(fileName) |
|
543 try |
|
544 if !filereadable('CVS/Root') |
|
545 throw fileName . ' is not a CVS-controlled file.' |
|
546 endif |
|
547 let fullCmd = a:cmd . ' "' . realFileName . '"' |
|
548 let resultBuffer=s:CVSCreateCommandBuffer(fullCmd, a:cmdName, a:statusText, cvsBufferCheck) |
|
549 return resultBuffer |
|
550 catch |
|
551 echoerr v:exception |
|
552 return -1 |
|
553 finally |
|
554 execute 'cd' escape(oldCwd, ' ') |
|
555 endtry |
|
556 endfunction |
|
557 |
|
558 |
|
559 " Function: s:CVSGetStatusVars(revision, branch, repository) {{{2 |
|
560 " |
|
561 " Obtains a CVS revision number and branch name. The 'revisionVar', |
|
562 " 'branchVar'and 'repositoryVar' arguments, if non-empty, contain the names of variables to hold |
|
563 " the corresponding results. |
|
564 " |
|
565 " Returns: string to be exec'd that sets the multiple return values. |
|
566 |
|
567 function! s:CVSGetStatusVars(revisionVar, branchVar, repositoryVar) |
|
568 let cvsBufferCheck=s:CVSCurrentBufferCheck() |
|
569 if cvsBufferCheck == -1 |
|
570 return "" |
|
571 endif |
|
572 let fileName=bufname(cvsBufferCheck) |
|
573 let realFileName = fnamemodify(s:CVSResolveLink(fileName), ':t') |
|
574 let oldCwd=s:CVSChangeToCurrentFileDir(fileName) |
|
575 try |
|
576 if !filereadable('CVS/Root') |
|
577 return "" |
|
578 endif |
|
579 let cvsCommand = s:CVSGetOption("CVSCommandCVSExec", "cvs") . " status " . escape(realFileName, ' *?\') |
|
580 let statustext=system(cvsCommand) |
|
581 if(v:shell_error) |
|
582 return "" |
|
583 endif |
|
584 let revision=substitute(statustext, '^\_.*Working revision:\s*\(\d\+\%(\.\d\+\)\+\|New file!\)\_.*$', '\1', "") |
|
585 |
|
586 " We can still be in a CVS-controlled directory without this being a CVS |
|
587 " file |
|
588 if match(revision, '^New file!$') >= 0 |
|
589 let revision="NEW" |
|
590 elseif match(revision, '^\d\+\.\d\+\%(\.\d\+\.\d\+\)*$') >=0 |
|
591 else |
|
592 return "" |
|
593 endif |
|
594 |
|
595 let returnExpression = "let " . a:revisionVar . "='" . revision . "'" |
|
596 |
|
597 if a:branchVar != "" |
|
598 let branch=substitute(statustext, '^\_.*Sticky Tag:\s\+\(\d\+\%(\.\d\+\)\+\|\a[A-Za-z0-9-_]*\|(none)\).*$', '\1', "") |
|
599 let returnExpression=returnExpression . " | let " . a:branchVar . "='" . branch . "'" |
|
600 endif |
|
601 |
|
602 if a:repositoryVar != "" |
|
603 let repository=substitute(statustext, '^\_.*Repository revision:\s*\(\d\+\%(\.\d\+\)\+\|New file!\|No revision control file\)\_.*$', '\1', "") |
|
604 let repository=substitute(repository, '^New file!\|No revision control file$', 'NEW', "") |
|
605 let returnExpression=returnExpression . " | let " . a:repositoryVar . "='" . repository . "'" |
|
606 endif |
|
607 |
|
608 return returnExpression |
|
609 finally |
|
610 execute 'cd' escape(oldCwd, ' ') |
|
611 endtry |
|
612 endfunction |
|
613 |
|
614 " Function: s:CVSSetupBuffer() {{{2 |
|
615 " Attempts to set the b:CVSBranch, b:CVSRevision and b:CVSRepository variables. |
|
616 |
|
617 function! s:CVSSetupBuffer() |
|
618 if (exists("b:CVSBufferSetup") && b:CVSBufferSetup) |
|
619 " This buffer is already set up. |
|
620 return |
|
621 endif |
|
622 |
|
623 if !s:CVSGetOption("CVSCommandEnableBufferSetup", 0) |
|
624 \ || @% == "" |
|
625 \ || s:CVSCommandEditFileRunning > 0 |
|
626 \ || exists("b:CVSOrigBuffNR") |
|
627 unlet! b:CVSRevision |
|
628 unlet! b:CVSBranch |
|
629 unlet! b:CVSRepository |
|
630 return |
|
631 endif |
|
632 |
|
633 if !filereadable(expand("%")) |
|
634 return -1 |
|
635 endif |
|
636 |
|
637 let revision="" |
|
638 let branch="" |
|
639 let repository="" |
|
640 |
|
641 exec s:CVSGetStatusVars('revision', 'branch', 'repository') |
|
642 if revision != "" |
|
643 let b:CVSRevision=revision |
|
644 else |
|
645 unlet! b:CVSRevision |
|
646 endif |
|
647 if branch != "" |
|
648 let b:CVSBranch=branch |
|
649 else |
|
650 unlet! b:CVSBranch |
|
651 endif |
|
652 if repository != "" |
|
653 let b:CVSRepository=repository |
|
654 else |
|
655 unlet! b:CVSRepository |
|
656 endif |
|
657 silent do CVSCommand User CVSBufferSetup |
|
658 let b:CVSBufferSetup=1 |
|
659 endfunction |
|
660 |
|
661 " Function: s:CVSMarkOrigBufferForSetup(cvsbuffer) {{{2 |
|
662 " Resets the buffer setup state of the original buffer for a given CVS buffer. |
|
663 " Returns: The CVS buffer number in a passthrough mode. |
|
664 |
|
665 function! s:CVSMarkOrigBufferForSetup(cvsBuffer) |
|
666 checktime |
|
667 if a:cvsBuffer != -1 |
|
668 let origBuffer = s:CVSBufferCheck(a:cvsBuffer) |
|
669 "This should never not work, but I'm paranoid |
|
670 if origBuffer != a:cvsBuffer |
|
671 call setbufvar(origBuffer, "CVSBufferSetup", 0) |
|
672 endif |
|
673 endif |
|
674 return a:cvsBuffer |
|
675 endfunction |
|
676 |
|
677 " Function: s:CVSOverrideOption(option, [value]) {{{2 |
|
678 " Provides a temporary override for the given CVS option. If no value is |
|
679 " passed, the override is disabled. |
|
680 |
|
681 function! s:CVSOverrideOption(option, ...) |
|
682 if a:0 == 0 |
|
683 unlet! s:{a:option}Override |
|
684 else |
|
685 let s:{a:option}Override = a:1 |
|
686 endif |
|
687 endfunction |
|
688 |
|
689 " Function: s:CVSWipeoutCommandBuffers() {{{2 |
|
690 " Clears all current CVS buffers of the specified type for a given source. |
|
691 |
|
692 function! s:CVSWipeoutCommandBuffers(originalBuffer, cvsCommand) |
|
693 let buffer = 1 |
|
694 while buffer <= bufnr('$') |
|
695 if getbufvar(buffer, 'CVSOrigBuffNR') == a:originalBuffer |
|
696 if getbufvar(buffer, 'CVSCommand') == a:cvsCommand |
|
697 execute 'bw' buffer |
|
698 endif |
|
699 endif |
|
700 let buffer = buffer + 1 |
|
701 endwhile |
|
702 endfunction |
|
703 |
|
704 " Section: Public functions {{{1 |
|
705 |
|
706 " Function: CVSGetRevision() {{{2 |
|
707 " Global function for retrieving the current buffer's CVS revision number. |
|
708 " Returns: Revision number or an empty string if an error occurs. |
|
709 |
|
710 function! CVSGetRevision() |
|
711 let revision="" |
|
712 exec s:CVSGetStatusVars('revision', '', '') |
|
713 return revision |
|
714 endfunction |
|
715 |
|
716 " Function: CVSDisableBufferSetup() {{{2 |
|
717 " Global function for deactivating the buffer autovariables. |
|
718 |
|
719 function! CVSDisableBufferSetup() |
|
720 let g:CVSCommandEnableBufferSetup=0 |
|
721 silent! augroup! CVSCommandPlugin |
|
722 endfunction |
|
723 |
|
724 " Function: CVSEnableBufferSetup() {{{2 |
|
725 " Global function for activating the buffer autovariables. |
|
726 |
|
727 function! CVSEnableBufferSetup() |
|
728 let g:CVSCommandEnableBufferSetup=1 |
|
729 augroup CVSCommandPlugin |
|
730 au! |
|
731 au BufEnter * call s:CVSSetupBuffer() |
|
732 augroup END |
|
733 |
|
734 " Only auto-load if the plugin is fully loaded. This gives other plugins a |
|
735 " chance to run. |
|
736 if g:loaded_cvscommand == 2 |
|
737 call s:CVSSetupBuffer() |
|
738 endif |
|
739 endfunction |
|
740 |
|
741 " Function: CVSGetStatusLine() {{{2 |
|
742 " Default (sample) status line entry for CVS files. This is only useful if |
|
743 " CVS-managed buffer mode is on (see the CVSCommandEnableBufferSetup variable |
|
744 " for how to do this). |
|
745 |
|
746 function! CVSGetStatusLine() |
|
747 if exists('b:CVSSourceFile') |
|
748 " This is a result buffer |
|
749 let value='[' . b:CVSCommand . ' ' . b:CVSSourceFile |
|
750 if exists('b:CVSStatusText') |
|
751 let value=value . ' ' . b:CVSStatusText |
|
752 endif |
|
753 let value = value . ']' |
|
754 return value |
|
755 endif |
|
756 |
|
757 if exists('b:CVSRevision') |
|
758 \ && b:CVSRevision != '' |
|
759 \ && exists('b:CVSBranch') |
|
760 \ && b:CVSBranch != '' |
|
761 \ && exists('b:CVSRepository') |
|
762 \ && b:CVSRepository != '' |
|
763 \ && exists('g:CVSCommandEnableBufferSetup') |
|
764 \ && g:CVSCommandEnableBufferSetup |
|
765 if b:CVSRevision == b:CVSRepository |
|
766 return '[CVS ' . b:CVSBranch . '/' . b:CVSRevision . ']' |
|
767 else |
|
768 return '[CVS ' . b:CVSBranch . '/' . b:CVSRevision . '/' . b:CVSRepository . ']' |
|
769 endif |
|
770 else |
|
771 return '' |
|
772 endif |
|
773 endfunction |
|
774 |
|
775 " Section: CVS command functions {{{1 |
|
776 |
|
777 " Function: s:CVSAdd() {{{2 |
|
778 function! s:CVSAdd() |
|
779 return s:CVSMarkOrigBufferForSetup(s:CVSDoCommand('add', 'cvsadd', '')) |
|
780 endfunction |
|
781 |
|
782 " Function: s:CVSAnnotate(...) {{{2 |
|
783 function! s:CVSAnnotate(...) |
|
784 if a:0 == 0 |
|
785 if &filetype == "CVSAnnotate" |
|
786 " This is a CVSAnnotate buffer. Perform annotation of the version |
|
787 " indicated by the current line. |
|
788 let revision = substitute(getline("."),'\(^[0-9.]*\).*','\1','') |
|
789 let revmin = substitute(revision,'^[0-9.]*\.\([0-9]\+\)','\1','') |
|
790 let revmaj = substitute(revision,'^\([0-9.]*\)\.[0-9]\+','\1','') |
|
791 if s:CVSGetOption('CVSCommandAnnotateParent', 0) != 0 |
|
792 let revmin = revmin - 1 |
|
793 endif |
|
794 if revmin == 0 |
|
795 " Jump to ancestor branch |
|
796 let revision = substitute(revmaj,'^\([0-9.]*\)\.[0-9]\+','\1','') |
|
797 else |
|
798 let revision=revmaj . "." . revmin |
|
799 endif |
|
800 else |
|
801 let revision=CVSGetRevision() |
|
802 if revision == "" |
|
803 echoerr "Unable to obtain CVS version information." |
|
804 return -1 |
|
805 endif |
|
806 endif |
|
807 else |
|
808 let revision=a:1 |
|
809 endif |
|
810 |
|
811 if revision == "NEW" |
|
812 echo "No annotatation available for new file." |
|
813 return -1 |
|
814 endif |
|
815 |
|
816 let resultBuffer=s:CVSDoCommand('-q annotate -r ' . revision, 'cvsannotate', revision) |
|
817 if resultBuffer != -1 |
|
818 set filetype=CVSAnnotate |
|
819 " Remove header lines from standard error |
|
820 silent v/^\d\+\%(\.\d\+\)\+/d |
|
821 endif |
|
822 |
|
823 return resultBuffer |
|
824 endfunction |
|
825 |
|
826 " Function: s:CVSCommit() {{{2 |
|
827 function! s:CVSCommit(...) |
|
828 " Handle the commit message being specified. If a message is supplied, it |
|
829 " is used; if bang is supplied, an empty message is used; otherwise, the |
|
830 " user is provided a buffer from which to edit the commit message. |
|
831 if a:2 != "" || a:1 == "!" |
|
832 return s:CVSMarkOrigBufferForSetup(s:CVSDoCommand('commit -m "' . a:2 . '"', 'cvscommit', '')) |
|
833 endif |
|
834 |
|
835 let cvsBufferCheck=s:CVSCurrentBufferCheck() |
|
836 if cvsBufferCheck == -1 |
|
837 echo "Original buffer no longer exists, aborting." |
|
838 return -1 |
|
839 endif |
|
840 |
|
841 " Protect against windows' backslashes in paths. They confuse exec'd |
|
842 " commands. |
|
843 |
|
844 let shellSlashBak = &shellslash |
|
845 try |
|
846 set shellslash |
|
847 |
|
848 let messageFileName = tempname() |
|
849 |
|
850 let fileName=bufname(cvsBufferCheck) |
|
851 let realFilePath=s:CVSResolveLink(fileName) |
|
852 let newCwd=fnamemodify(realFilePath, ':h') |
|
853 if strlen(newCwd) == 0 |
|
854 " Account for autochdir being in effect, which will make this blank, but |
|
855 " we know we'll be in the current directory for the original file. |
|
856 let newCwd = getcwd() |
|
857 endif |
|
858 |
|
859 let realFileName=fnamemodify(realFilePath, ':t') |
|
860 |
|
861 if s:CVSEditFile(messageFileName, cvsBufferCheck) == -1 |
|
862 return |
|
863 endif |
|
864 |
|
865 " Protect against case and backslash issues in Windows. |
|
866 let autoPattern = '\c' . messageFileName |
|
867 |
|
868 " Ensure existance of group |
|
869 augroup CVSCommit |
|
870 augroup END |
|
871 |
|
872 execute 'au CVSCommit BufDelete' autoPattern 'call delete("' . messageFileName . '")' |
|
873 execute 'au CVSCommit BufDelete' autoPattern 'au! CVSCommit * ' autoPattern |
|
874 |
|
875 " Create a commit mapping. The mapping must clear all autocommands in case |
|
876 " it is invoked when CVSCommandCommitOnWrite is active, as well as to not |
|
877 " invoke the buffer deletion autocommand. |
|
878 |
|
879 execute 'nnoremap <silent> <buffer> <Plug>CVSCommit '. |
|
880 \ ':au! CVSCommit * ' . autoPattern . '<CR>'. |
|
881 \ ':g/^CVS:/d<CR>'. |
|
882 \ ':update<CR>'. |
|
883 \ ':call <SID>CVSFinishCommit("' . messageFileName . '",' . |
|
884 \ '"' . newCwd . '",' . |
|
885 \ '"' . realFileName . '",' . |
|
886 \ cvsBufferCheck . ')<CR>' |
|
887 |
|
888 silent 0put ='CVS: ----------------------------------------------------------------------' |
|
889 silent put =\"CVS: Enter Log. Lines beginning with `CVS:' are removed automatically\" |
|
890 silent put ='CVS: Type <leader>cc (or your own <Plug>CVSCommit mapping)' |
|
891 |
|
892 if s:CVSGetOption('CVSCommandCommitOnWrite', 1) == 1 |
|
893 execute 'au CVSCommit BufWritePre' autoPattern 'g/^CVS:/d' |
|
894 execute 'au CVSCommit BufWritePost' autoPattern 'call s:CVSFinishCommit("' . messageFileName . '", "' . newCwd . '", "' . realFileName . '", ' . cvsBufferCheck . ') | au! * ' autoPattern |
|
895 silent put ='CVS: or write this buffer' |
|
896 endif |
|
897 |
|
898 silent put ='CVS: to finish this commit operation' |
|
899 silent put ='CVS: ----------------------------------------------------------------------' |
|
900 $ |
|
901 let b:CVSSourceFile=fileName |
|
902 let b:CVSCommand='CVSCommit' |
|
903 set filetype=cvs |
|
904 finally |
|
905 let &shellslash = shellSlashBak |
|
906 endtry |
|
907 |
|
908 endfunction |
|
909 |
|
910 " Function: s:CVSDiff(...) {{{2 |
|
911 function! s:CVSDiff(...) |
|
912 if a:0 == 1 |
|
913 let revOptions = '-r' . a:1 |
|
914 let caption = a:1 . ' -> current' |
|
915 elseif a:0 == 2 |
|
916 let revOptions = '-r' . a:1 . ' -r' . a:2 |
|
917 let caption = a:1 . ' -> ' . a:2 |
|
918 else |
|
919 let revOptions = '' |
|
920 let caption = '' |
|
921 endif |
|
922 |
|
923 let cvsdiffopt=s:CVSGetOption('CVSCommandDiffOpt', 'wbBc') |
|
924 |
|
925 if cvsdiffopt == "" |
|
926 let diffoptionstring="" |
|
927 else |
|
928 let diffoptionstring=" -" . cvsdiffopt . " " |
|
929 endif |
|
930 |
|
931 let resultBuffer = s:CVSDoCommand('diff ' . diffoptionstring . revOptions , 'cvsdiff', caption) |
|
932 if resultBuffer != -1 |
|
933 set filetype=diff |
|
934 endif |
|
935 return resultBuffer |
|
936 endfunction |
|
937 |
|
938 " Function: s:CVSEdit() {{{2 |
|
939 function! s:CVSEdit() |
|
940 return s:CVSDoCommand('edit', 'cvsedit', '') |
|
941 endfunction |
|
942 |
|
943 " Function: s:CVSEditors() {{{2 |
|
944 function! s:CVSEditors() |
|
945 return s:CVSDoCommand('editors', 'cvseditors', '') |
|
946 endfunction |
|
947 |
|
948 " Function: s:CVSGotoOriginal(["!]) {{{2 |
|
949 function! s:CVSGotoOriginal(...) |
|
950 let origBuffNR = s:CVSCurrentBufferCheck() |
|
951 if origBuffNR > 0 |
|
952 let origWinNR = bufwinnr(origBuffNR) |
|
953 if origWinNR == -1 |
|
954 execute 'buffer' origBuffNR |
|
955 else |
|
956 execute origWinNR . 'wincmd w' |
|
957 endif |
|
958 if a:0 == 1 |
|
959 if a:1 == "!" |
|
960 let buffnr = 1 |
|
961 let buffmaxnr = bufnr("$") |
|
962 while buffnr <= buffmaxnr |
|
963 if getbufvar(buffnr, "CVSOrigBuffNR") == origBuffNR |
|
964 execute "bw" buffnr |
|
965 endif |
|
966 let buffnr = buffnr + 1 |
|
967 endwhile |
|
968 endif |
|
969 endif |
|
970 endif |
|
971 endfunction |
|
972 |
|
973 " Function: s:CVSFinishCommit(messageFile, targetDir, targetFile) {{{2 |
|
974 function! s:CVSFinishCommit(messageFile, targetDir, targetFile, origBuffNR) |
|
975 if filereadable(a:messageFile) |
|
976 let oldCwd=getcwd() |
|
977 if strlen(a:targetDir) > 0 |
|
978 execute 'cd' escape(a:targetDir, ' ') |
|
979 endif |
|
980 let resultBuffer=s:CVSCreateCommandBuffer('commit -F "' . a:messageFile . '" "'. a:targetFile . '"', 'cvscommit', '', a:origBuffNR) |
|
981 execute 'cd' escape(oldCwd, ' ') |
|
982 execute 'bw' escape(a:messageFile, ' *?\') |
|
983 silent execute 'call delete("' . a:messageFile . '")' |
|
984 return s:CVSMarkOrigBufferForSetup(resultBuffer) |
|
985 else |
|
986 echoerr "Can't read message file; no commit is possible." |
|
987 return -1 |
|
988 endif |
|
989 endfunction |
|
990 |
|
991 " Function: s:CVSLog() {{{2 |
|
992 function! s:CVSLog(...) |
|
993 if a:0 == 0 |
|
994 let versionOption = "" |
|
995 let caption = '' |
|
996 else |
|
997 let versionOption=" -r" . a:1 |
|
998 let caption = a:1 |
|
999 endif |
|
1000 |
|
1001 let resultBuffer=s:CVSDoCommand('log' . versionOption, 'cvslog', caption) |
|
1002 if resultBuffer != "" |
|
1003 set filetype=rcslog |
|
1004 endif |
|
1005 return resultBuffer |
|
1006 endfunction |
|
1007 |
|
1008 " Function: s:CVSRevert() {{{2 |
|
1009 function! s:CVSRevert() |
|
1010 return s:CVSMarkOrigBufferForSetup(s:CVSDoCommand('update -C', 'cvsrevert', '')) |
|
1011 endfunction |
|
1012 |
|
1013 " Function: s:CVSReview(...) {{{2 |
|
1014 function! s:CVSReview(...) |
|
1015 if a:0 == 0 |
|
1016 let versiontag="" |
|
1017 if s:CVSGetOption('CVSCommandInteractive', 0) |
|
1018 let versiontag=input('Revision: ') |
|
1019 endif |
|
1020 if versiontag == "" |
|
1021 let versiontag="(current)" |
|
1022 let versionOption="" |
|
1023 else |
|
1024 let versionOption=" -r " . versiontag . " " |
|
1025 endif |
|
1026 else |
|
1027 let versiontag=a:1 |
|
1028 let versionOption=" -r " . versiontag . " " |
|
1029 endif |
|
1030 |
|
1031 let resultBuffer = s:CVSDoCommand('-q update -p' . versionOption, 'cvsreview', versiontag) |
|
1032 if resultBuffer > 0 |
|
1033 let &filetype=getbufvar(b:CVSOrigBuffNR, '&filetype') |
|
1034 endif |
|
1035 |
|
1036 return resultBuffer |
|
1037 endfunction |
|
1038 |
|
1039 " Function: s:CVSStatus() {{{2 |
|
1040 function! s:CVSStatus() |
|
1041 return s:CVSDoCommand('status', 'cvsstatus', '') |
|
1042 endfunction |
|
1043 |
|
1044 " Function: s:CVSUnedit() {{{2 |
|
1045 function! s:CVSUnedit() |
|
1046 return s:CVSDoCommand('unedit', 'cvsunedit', '') |
|
1047 endfunction |
|
1048 |
|
1049 " Function: s:CVSUpdate() {{{2 |
|
1050 function! s:CVSUpdate() |
|
1051 return s:CVSMarkOrigBufferForSetup(s:CVSDoCommand('update', 'update', '')) |
|
1052 endfunction |
|
1053 |
|
1054 " Function: s:CVSVimDiff(...) {{{2 |
|
1055 function! s:CVSVimDiff(...) |
|
1056 let originalBuffer = s:CVSCurrentBufferCheck() |
|
1057 let s:CVSCommandEditFileRunning = s:CVSCommandEditFileRunning + 1 |
|
1058 try |
|
1059 " If there's already a VimDiff'ed window, restore it. |
|
1060 " There may only be one CVSVimDiff original window at a time. |
|
1061 |
|
1062 if exists("s:vimDiffSourceBuffer") && s:vimDiffSourceBuffer != originalBuffer |
|
1063 " Clear the existing vimdiff setup by removing the result buffers. |
|
1064 call s:CVSWipeoutCommandBuffers(s:vimDiffSourceBuffer, 'vimdiff') |
|
1065 endif |
|
1066 |
|
1067 " Split and diff |
|
1068 if(a:0 == 2) |
|
1069 " Reset the vimdiff system, as 2 explicit versions were provided. |
|
1070 if exists('s:vimDiffSourceBuffer') |
|
1071 call s:CVSWipeoutCommandBuffers(s:vimDiffSourceBuffer, 'vimdiff') |
|
1072 endif |
|
1073 let resultBuffer = s:CVSReview(a:1) |
|
1074 if resultBuffer < 0 |
|
1075 echomsg "Can't open CVS revision " . a:1 |
|
1076 return resultBuffer |
|
1077 endif |
|
1078 let b:CVSCommand = 'vimdiff' |
|
1079 diffthis |
|
1080 let s:vimDiffBufferCount = 1 |
|
1081 let s:vimDiffScratchList = '{'. resultBuffer . '}' |
|
1082 " If no split method is defined, cheat, and set it to vertical. |
|
1083 try |
|
1084 call s:CVSOverrideOption('CVSCommandSplit', s:CVSGetOption('CVSCommandDiffSplit', s:CVSGetOption('CVSCommandSplit', 'vertical'))) |
|
1085 let resultBuffer=s:CVSReview(a:2) |
|
1086 finally |
|
1087 call s:CVSOverrideOption('CVSCommandSplit') |
|
1088 endtry |
|
1089 if resultBuffer < 0 |
|
1090 echomsg "Can't open CVS revision " . a:1 |
|
1091 return resultBuffer |
|
1092 endif |
|
1093 let b:CVSCommand = 'vimdiff' |
|
1094 diffthis |
|
1095 let s:vimDiffBufferCount = 2 |
|
1096 let s:vimDiffScratchList = s:vimDiffScratchList . '{'. resultBuffer . '}' |
|
1097 else |
|
1098 " Add new buffer |
|
1099 try |
|
1100 " Force splitting behavior, otherwise why use vimdiff? |
|
1101 call s:CVSOverrideOption("CVSCommandEdit", "split") |
|
1102 call s:CVSOverrideOption("CVSCommandSplit", s:CVSGetOption('CVSCommandDiffSplit', s:CVSGetOption('CVSCommandSplit', 'vertical'))) |
|
1103 if(a:0 == 0) |
|
1104 let resultBuffer=s:CVSReview() |
|
1105 else |
|
1106 let resultBuffer=s:CVSReview(a:1) |
|
1107 endif |
|
1108 finally |
|
1109 call s:CVSOverrideOption("CVSCommandEdit") |
|
1110 call s:CVSOverrideOption("CVSCommandSplit") |
|
1111 endtry |
|
1112 if resultBuffer < 0 |
|
1113 echomsg "Can't open current CVS revision" |
|
1114 return resultBuffer |
|
1115 endif |
|
1116 let b:CVSCommand = 'vimdiff' |
|
1117 diffthis |
|
1118 |
|
1119 if !exists('s:vimDiffBufferCount') |
|
1120 " New instance of vimdiff. |
|
1121 let s:vimDiffBufferCount = 2 |
|
1122 let s:vimDiffScratchList = '{' . resultBuffer . '}' |
|
1123 |
|
1124 " This could have been invoked on a CVS result buffer, not the |
|
1125 " original buffer. |
|
1126 wincmd W |
|
1127 execute 'buffer' originalBuffer |
|
1128 " Store info for later original buffer restore |
|
1129 let s:vimDiffRestoreCmd = |
|
1130 \ "call setbufvar(".originalBuffer.", \"&diff\", ".getbufvar(originalBuffer, '&diff').")" |
|
1131 \ . "|call setbufvar(".originalBuffer.", \"&foldcolumn\", ".getbufvar(originalBuffer, '&foldcolumn').")" |
|
1132 \ . "|call setbufvar(".originalBuffer.", \"&foldenable\", ".getbufvar(originalBuffer, '&foldenable').")" |
|
1133 \ . "|call setbufvar(".originalBuffer.", \"&foldmethod\", '".getbufvar(originalBuffer, '&foldmethod')."')" |
|
1134 \ . "|call setbufvar(".originalBuffer.", \"&scrollbind\", ".getbufvar(originalBuffer, '&scrollbind').")" |
|
1135 \ . "|call setbufvar(".originalBuffer.", \"&wrap\", ".getbufvar(originalBuffer, '&wrap').")" |
|
1136 \ . "|if &foldmethod=='manual'|execute 'normal zE'|endif" |
|
1137 diffthis |
|
1138 wincmd w |
|
1139 else |
|
1140 " Adding a window to an existing vimdiff |
|
1141 let s:vimDiffBufferCount = s:vimDiffBufferCount + 1 |
|
1142 let s:vimDiffScratchList = s:vimDiffScratchList . '{' . resultBuffer . '}' |
|
1143 endif |
|
1144 endif |
|
1145 |
|
1146 let s:vimDiffSourceBuffer = originalBuffer |
|
1147 |
|
1148 " Avoid executing the modeline in the current buffer after the autocommand. |
|
1149 |
|
1150 let currentBuffer = bufnr('%') |
|
1151 let saveModeline = getbufvar(currentBuffer, '&modeline') |
|
1152 try |
|
1153 call setbufvar(currentBuffer, '&modeline', 0) |
|
1154 silent do CVSCommand User CVSVimDiffFinish |
|
1155 finally |
|
1156 call setbufvar(currentBuffer, '&modeline', saveModeline) |
|
1157 endtry |
|
1158 return resultBuffer |
|
1159 finally |
|
1160 let s:CVSCommandEditFileRunning = s:CVSCommandEditFileRunning - 1 |
|
1161 endtry |
|
1162 endfunction |
|
1163 |
|
1164 " Function: s:CVSWatch(onoff) {{{2 |
|
1165 function! s:CVSWatch(onoff) |
|
1166 if a:onoff !~ '^\c\%(on\|off\|add\|remove\)$' |
|
1167 echoerr "Argument to CVSWatch must be one of [on|off|add|remove]" |
|
1168 return -1 |
|
1169 end |
|
1170 return s:CVSDoCommand('watch ' . tolower(a:onoff), 'cvswatch', '') |
|
1171 endfunction |
|
1172 |
|
1173 " Function: s:CVSWatchers() {{{2 |
|
1174 function! s:CVSWatchers() |
|
1175 return s:CVSDoCommand('watchers', 'cvswatchers', '') |
|
1176 endfunction |
|
1177 |
|
1178 " Section: Command definitions {{{1 |
|
1179 " Section: Primary commands {{{2 |
|
1180 com! CVSAdd call s:CVSAdd() |
|
1181 com! -nargs=? CVSAnnotate call s:CVSAnnotate(<f-args>) |
|
1182 com! -bang -nargs=? CVSCommit call s:CVSCommit(<q-bang>, <q-args>) |
|
1183 com! -nargs=* CVSDiff call s:CVSDiff(<f-args>) |
|
1184 com! CVSEdit call s:CVSEdit() |
|
1185 com! CVSEditors call s:CVSEditors() |
|
1186 com! -bang CVSGotoOriginal call s:CVSGotoOriginal(<q-bang>) |
|
1187 com! -nargs=? CVSLog call s:CVSLog(<f-args>) |
|
1188 com! CVSRevert call s:CVSRevert() |
|
1189 com! -nargs=? CVSReview call s:CVSReview(<f-args>) |
|
1190 com! CVSStatus call s:CVSStatus() |
|
1191 com! CVSUnedit call s:CVSUnedit() |
|
1192 com! CVSUpdate call s:CVSUpdate() |
|
1193 com! -nargs=* CVSVimDiff call s:CVSVimDiff(<f-args>) |
|
1194 com! -nargs=1 CVSWatch call s:CVSWatch(<f-args>) |
|
1195 com! CVSWatchAdd call s:CVSWatch('add') |
|
1196 com! CVSWatchOn call s:CVSWatch('on') |
|
1197 com! CVSWatchOff call s:CVSWatch('off') |
|
1198 com! CVSWatchRemove call s:CVSWatch('remove') |
|
1199 com! CVSWatchers call s:CVSWatchers() |
|
1200 |
|
1201 " Section: CVS buffer management commands {{{2 |
|
1202 com! CVSDisableBufferSetup call CVSDisableBufferSetup() |
|
1203 com! CVSEnableBufferSetup call CVSEnableBufferSetup() |
|
1204 |
|
1205 " Allow reloading cvscommand.vim |
|
1206 com! CVSReload unlet! loaded_cvscommand | runtime plugin/cvscommand.vim |
|
1207 |
|
1208 " Section: Plugin command mappings {{{1 |
|
1209 nnoremap <silent> <Plug>CVSAdd :CVSAdd<CR> |
|
1210 nnoremap <silent> <Plug>CVSAnnotate :CVSAnnotate<CR> |
|
1211 nnoremap <silent> <Plug>CVSCommit :CVSCommit<CR> |
|
1212 nnoremap <silent> <Plug>CVSDiff :CVSDiff<CR> |
|
1213 nnoremap <silent> <Plug>CVSEdit :CVSEdit<CR> |
|
1214 nnoremap <silent> <Plug>CVSEditors :CVSEditors<CR> |
|
1215 nnoremap <silent> <Plug>CVSGotoOriginal :CVSGotoOriginal<CR> |
|
1216 nnoremap <silent> <Plug>CVSClearAndGotoOriginal :CVSGotoOriginal!<CR> |
|
1217 nnoremap <silent> <Plug>CVSLog :CVSLog<CR> |
|
1218 nnoremap <silent> <Plug>CVSRevert :CVSRevert<CR> |
|
1219 nnoremap <silent> <Plug>CVSReview :CVSReview<CR> |
|
1220 nnoremap <silent> <Plug>CVSStatus :CVSStatus<CR> |
|
1221 nnoremap <silent> <Plug>CVSUnedit :CVSUnedit<CR> |
|
1222 nnoremap <silent> <Plug>CVSUpdate :CVSUpdate<CR> |
|
1223 nnoremap <silent> <Plug>CVSVimDiff :CVSVimDiff<CR> |
|
1224 nnoremap <silent> <Plug>CVSWatchers :CVSWatchers<CR> |
|
1225 nnoremap <silent> <Plug>CVSWatchAdd :CVSWatchAdd<CR> |
|
1226 nnoremap <silent> <Plug>CVSWatchOn :CVSWatchOn<CR> |
|
1227 nnoremap <silent> <Plug>CVSWatchOff :CVSWatchOff<CR> |
|
1228 nnoremap <silent> <Plug>CVSWatchRemove :CVSWatchRemove<CR> |
|
1229 |
|
1230 " Section: Default mappings {{{1 |
|
1231 if !hasmapto('<Plug>CVSAdd') |
|
1232 nmap <unique> <Leader>ca <Plug>CVSAdd |
|
1233 endif |
|
1234 if !hasmapto('<Plug>CVSAnnotate') |
|
1235 nmap <unique> <Leader>cn <Plug>CVSAnnotate |
|
1236 endif |
|
1237 if !hasmapto('<Plug>CVSClearAndGotoOriginal') |
|
1238 nmap <unique> <Leader>cG <Plug>CVSClearAndGotoOriginal |
|
1239 endif |
|
1240 if !hasmapto('<Plug>CVSCommit') |
|
1241 nmap <unique> <Leader>cc <Plug>CVSCommit |
|
1242 endif |
|
1243 if !hasmapto('<Plug>CVSDiff') |
|
1244 nmap <unique> <Leader>cd <Plug>CVSDiff |
|
1245 endif |
|
1246 if !hasmapto('<Plug>CVSEdit') |
|
1247 nmap <unique> <Leader>ce <Plug>CVSEdit |
|
1248 endif |
|
1249 if !hasmapto('<Plug>CVSEditors') |
|
1250 nmap <unique> <Leader>ci <Plug>CVSEditors |
|
1251 endif |
|
1252 if !hasmapto('<Plug>CVSGotoOriginal') |
|
1253 nmap <unique> <Leader>cg <Plug>CVSGotoOriginal |
|
1254 endif |
|
1255 if !hasmapto('<Plug>CVSLog') |
|
1256 nmap <unique> <Leader>cl <Plug>CVSLog |
|
1257 endif |
|
1258 if !hasmapto('<Plug>CVSRevert') |
|
1259 nmap <unique> <Leader>cq <Plug>CVSRevert |
|
1260 endif |
|
1261 if !hasmapto('<Plug>CVSReview') |
|
1262 nmap <unique> <Leader>cr <Plug>CVSReview |
|
1263 endif |
|
1264 if !hasmapto('<Plug>CVSStatus') |
|
1265 nmap <unique> <Leader>cs <Plug>CVSStatus |
|
1266 endif |
|
1267 if !hasmapto('<Plug>CVSUnedit') |
|
1268 nmap <unique> <Leader>ct <Plug>CVSUnedit |
|
1269 endif |
|
1270 if !hasmapto('<Plug>CVSUpdate') |
|
1271 nmap <unique> <Leader>cu <Plug>CVSUpdate |
|
1272 endif |
|
1273 if !hasmapto('<Plug>CVSVimDiff') |
|
1274 nmap <unique> <Leader>cv <Plug>CVSVimDiff |
|
1275 endif |
|
1276 if !hasmapto('<Plug>CVSWatchers') |
|
1277 nmap <unique> <Leader>cwv <Plug>CVSWatchers |
|
1278 endif |
|
1279 if !hasmapto('<Plug>CVSWatchAdd') |
|
1280 nmap <unique> <Leader>cwa <Plug>CVSWatchAdd |
|
1281 endif |
|
1282 if !hasmapto('<Plug>CVSWatchOn') |
|
1283 nmap <unique> <Leader>cwn <Plug>CVSWatchOn |
|
1284 endif |
|
1285 if !hasmapto('<Plug>CVSWatchOff') |
|
1286 nmap <unique> <Leader>cwf <Plug>CVSWatchOff |
|
1287 endif |
|
1288 if !hasmapto('<Plug>CVSWatchRemove') |
|
1289 nmap <unique> <Leader>cwr <Plug>CVSWatchRemove |
|
1290 endif |
|
1291 |
|
1292 " Section: Menu items {{{1 |
|
1293 silent! aunmenu Plugin.CVS |
|
1294 amenu <silent> &Plugin.CVS.&Add <Plug>CVSAdd |
|
1295 amenu <silent> &Plugin.CVS.A&nnotate <Plug>CVSAnnotate |
|
1296 amenu <silent> &Plugin.CVS.&Commit <Plug>CVSCommit |
|
1297 amenu <silent> &Plugin.CVS.&Diff <Plug>CVSDiff |
|
1298 amenu <silent> &Plugin.CVS.&Edit <Plug>CVSEdit |
|
1299 amenu <silent> &Plugin.CVS.Ed&itors <Plug>CVSEditors |
|
1300 amenu <silent> &Plugin.CVS.&Log <Plug>CVSLog |
|
1301 amenu <silent> &Plugin.CVS.Revert <Plug>CVSRevert |
|
1302 amenu <silent> &Plugin.CVS.&Review <Plug>CVSReview |
|
1303 amenu <silent> &Plugin.CVS.&Status <Plug>CVSStatus |
|
1304 amenu <silent> &Plugin.CVS.Unedi&t <Plug>CVSUnedit |
|
1305 amenu <silent> &Plugin.CVS.&Update <Plug>CVSUpdate |
|
1306 amenu <silent> &Plugin.CVS.&VimDiff <Plug>CVSVimDiff |
|
1307 amenu <silent> &Plugin.CVS.&Watchers <Plug>CVSWatchers |
|
1308 amenu <silent> &Plugin.CVS.WatchAdd <Plug>CVSWatchAdd |
|
1309 amenu <silent> &Plugin.CVS.WatchOn <Plug>CVSWatchOn |
|
1310 amenu <silent> &Plugin.CVS.WatchOff <Plug>CVSWatchOff |
|
1311 amenu <silent> &Plugin.CVS.WatchRemove <Plug>CVSWatchRemove |
|
1312 |
|
1313 " Section: Autocommands to restore vimdiff state {{{1 |
|
1314 function! s:CVSVimDiffRestore(vimDiffBuff) |
|
1315 let s:CVSCommandEditFileRunning = s:CVSCommandEditFileRunning + 1 |
|
1316 try |
|
1317 if exists("s:vimDiffSourceBuffer") |
|
1318 if a:vimDiffBuff == s:vimDiffSourceBuffer |
|
1319 " Original file is being removed. |
|
1320 unlet! s:vimDiffSourceBuffer |
|
1321 unlet! s:vimDiffBufferCount |
|
1322 unlet! s:vimDiffRestoreCmd |
|
1323 unlet! s:vimDiffScratchList |
|
1324 elseif match(s:vimDiffScratchList, '{' . a:vimDiffBuff . '}') >= 0 |
|
1325 let s:vimDiffScratchList = substitute(s:vimDiffScratchList, '{' . a:vimDiffBuff . '}', '', '') |
|
1326 let s:vimDiffBufferCount = s:vimDiffBufferCount - 1 |
|
1327 if s:vimDiffBufferCount == 1 && exists('s:vimDiffRestoreCmd') |
|
1328 " All scratch buffers are gone, reset the original. |
|
1329 " Only restore if the source buffer is still in Diff mode |
|
1330 |
|
1331 let sourceWinNR=bufwinnr(s:vimDiffSourceBuffer) |
|
1332 if sourceWinNR != -1 |
|
1333 " The buffer is visible in at least one window |
|
1334 let currentWinNR = winnr() |
|
1335 while winbufnr(sourceWinNR) != -1 |
|
1336 if winbufnr(sourceWinNR) == s:vimDiffSourceBuffer |
|
1337 execute sourceWinNR . 'wincmd w' |
|
1338 if getwinvar('', "&diff") |
|
1339 execute s:vimDiffRestoreCmd |
|
1340 endif |
|
1341 endif |
|
1342 let sourceWinNR = sourceWinNR + 1 |
|
1343 endwhile |
|
1344 execute currentWinNR . 'wincmd w' |
|
1345 else |
|
1346 " The buffer is hidden. It must be visible in order to set the |
|
1347 " diff option. |
|
1348 let currentBufNR = bufnr('') |
|
1349 execute "hide buffer" s:vimDiffSourceBuffer |
|
1350 if getwinvar('', "&diff") |
|
1351 execute s:vimDiffRestoreCmd |
|
1352 endif |
|
1353 execute "hide buffer" currentBufNR |
|
1354 endif |
|
1355 |
|
1356 unlet s:vimDiffRestoreCmd |
|
1357 unlet s:vimDiffSourceBuffer |
|
1358 unlet s:vimDiffBufferCount |
|
1359 unlet s:vimDiffScratchList |
|
1360 elseif s:vimDiffBufferCount == 0 |
|
1361 " All buffers are gone. |
|
1362 unlet s:vimDiffSourceBuffer |
|
1363 unlet s:vimDiffBufferCount |
|
1364 unlet s:vimDiffScratchList |
|
1365 endif |
|
1366 endif |
|
1367 endif |
|
1368 finally |
|
1369 let s:CVSCommandEditFileRunning = s:CVSCommandEditFileRunning - 1 |
|
1370 endtry |
|
1371 endfunction |
|
1372 |
|
1373 augroup CVSVimDiffRestore |
|
1374 au! |
|
1375 au BufUnload * call s:CVSVimDiffRestore(expand("<abuf>")) |
|
1376 augroup END |
|
1377 |
|
1378 " Section: Optional activation of buffer management {{{1 |
|
1379 |
|
1380 if s:CVSGetOption('CVSCommandEnableBufferSetup', 0) |
|
1381 call CVSEnableBufferSetup() |
|
1382 endif |
|
1383 |
|
1384 " Section: Plugin completion {{{1 |
|
1385 |
|
1386 let loaded_cvscommand=2 |
|
1387 silent do CVSCommand User CVSPluginFinish |