Mercurial > hg > mercurial-crew-with-dirclash
comparison contrib/vim/hgcommand.vim @ 2591:61f2008cd6bf
Addition of CVScommand vim script as a base for HGcommand
author | "Mathieu Clabaut <mathieu.clabaut@gmail.com>" |
---|---|
date | Mon, 10 Jul 2006 23:39:08 +0200 |
parents | |
children | 457846f400e8 |
comparison
equal
deleted
inserted
replaced
2576:6a961a54f953 | 2591:61f2008cd6bf |
---|---|
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 |