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