diff --git a/.vim/doc/vcscommand.txt b/.vim/doc/vcscommand.txt index 0c16aac..f56e7ef 100644 --- a/.vim/doc/vcscommand.txt +++ b/.vim/doc/vcscommand.txt @@ -1,5 +1,5 @@ *vcscommand.txt* vcscommand -Copyright (c) 2007 Bob Hiestand +Copyright (c) Bob Hiestand Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -81,7 +81,7 @@ output appears in a new window. Many of the commands accept revisions as arguments. By default, most operate on the most recent revision on the current branch if no revision is specified. -Each vcscommand is mapped to a key sequence starting with the +Each vcscommand is mapped to a key sequence starting with the || keystroke. The default mappings may be overridden by supplying different mappings before the plugin is loaded, such as in the vimrc, in the standard fashion for plugin mappings. For examples, please see @@ -131,7 +131,7 @@ This command adds the current file to source control. Please note, this does not commit the newly-added file. All parameters to the command are passed to the underlying VCS. -:VCSAnnotate *:VCSAnnotate* +:VCSAnnotate[!] *:VCSAnnotate* This command displays the current file with each line annotated with the version in which it was most recently changed. If an argument is given, the @@ -140,16 +140,19 @@ it uses the most recent version of the file (on the current branch, if under CVS control). Additionally, if the current buffer is a VCSAnnotate buffer already, the version number on the current line is used. +If '!' is used, the view of the annotated buffer is split so that the +annotation is in a separate window from the content, and each is highlighted +separately. + For CVS buffers, the 'VCSCommandCVSAnnotateParent' option, if set to non-zero, will cause the above behavior to change. Instead of annotating the version on the current line, the parent revision is used instead, crossing branches if necessary. -The filetype of the vcscommand scratch buffer is set to one of 'CVSAnnotate', -'SVNAnnotate', or 'SVKAnnotate' as appropriate, to take advantage of the -bundled syntax files. +With no arguments the cursor will jump to the line in the annotated buffer +corresponding to the current line in the source buffer. -:VCSBlame *:VCSBlame* +:VCSBlame[!] *:VCSBlame* Alias for |:VCSAnnotate|. @@ -168,9 +171,10 @@ log message. The commit can be abandoned if the log message buffer is deleted or wiped before being written. Alternatively, the mapping that is used to invoke :VCSCommit (by default -cc) can be used in the log message buffer to immediately commit. This -is useful if the |VCSCommandCommitOnWrite| variable is set to 0 to disable the -normal commit-on-write behavior. +||cc, please see |vcscommand-mappings|) can be used in the log message +buffer in Normal mode to immediately commit. This is useful if the +|VCSCommandCommitOnWrite| variable is set to 0 to disable the normal +commit-on-write behavior. :VCSDelete *:VCSDelete* @@ -325,45 +329,56 @@ This command performs "cvs watchers" on the current file. By default, a mapping is defined for each command. These mappings execute the default (no-argument) form of each command. -ca VCSAdd -cn VCSAnnotate -cc VCSCommit -cD VCSDelete -cd VCSDiff -cg VCSGotoOriginal -cG VCSGotoOriginal! -ci VCSInfo -cl VCSLog -cL VCSLock -cr VCSReview -cs VCSStatus -cu VCSUpdate -cU VCSUnlock -cv VCSVimDiff +||ca VCSAdd +||cn VCSAnnotate +||cN VCSAnnotate! +||cc VCSCommit +||cD VCSDelete +||cd VCSDiff +||cg VCSGotoOriginal +||cG VCSGotoOriginal! +||ci VCSInfo +||cl VCSLog +||cL VCSLock +||cr VCSReview +||cs VCSStatus +||cu VCSUpdate +||cU VCSUnlock +||cv VCSVimDiff Only for CVS buffers: -ce CVSEdit -cE CVSEditors -ct CVSUnedit -cwv CVSWatchers -cwa CVSWatchAdd -cwn CVSWatchOn -cwf CVSWatchOff -cwf CVSWatchRemove +||ce CVSEdit +||cE CVSEditors +||ct CVSUnedit +||cwv CVSWatchers +||cwa CVSWatchAdd +||cwn CVSWatchOn +||cwf CVSWatchOff +||cwf CVSWatchRemove *vcscommand-mappings-override* -The default mappings can be overriden by user-provided instead by mapping to +The default mappings can be overridden by user-provided instead by mapping to CommandName. This is especially useful when these mappings collide with other existing mappings (vim will warn of this during plugin initialization, but will not clobber the existing mappings). -For instance, to override the default mapping for :VCSAdd to set it to '\add', -add the following to the vimrc: +There are three methods for controlling mapping: + +First, maps can be overriden for individual commands. For instance, to +override the default mapping for :VCSAdd to set it to '\add', add the +following to the vimrc: nmap \add VCSAdd +Second, the default map prefix ('c') can be overridden by defining the +|VCSCommandMapPrefix| variable. + +Third, the entire set of default maps can be overridden by defining the +|VCSCommandMappings| variable. + + 4.3 Automatic buffer variables *vcscommand-buffer-variables* Several buffer variables are defined in each vcscommand result buffer. These @@ -414,10 +429,16 @@ The following variables are available: |VCSCommandCVSExec| |VCSCommandDeleteOnHide| |VCSCommandDiffSplit| +|VCSCommandDisableAll| |VCSCommandDisableMappings| |VCSCommandDisableExtensionMappings| +|VCSCommandDisableMenu| |VCSCommandEdit| |VCSCommandEnableBufferSetup| +|VCSCommandMappings| +|VCSCommandMapPrefix| +|VCSCommandMenuPriority| +|VCSCommandMenuRoot| |VCSCommandResultBufferNameExtension| |VCSCommandResultBufferNameFunction| |VCSCommandSplit| @@ -425,6 +446,8 @@ The following variables are available: |VCSCommandSVNDiffExt| |VCSCommandSVNDiffOpt| |VCSCommandSVNExec| +|VCSCommandVCSTypeOverride| +|VCSCommandVCSTypePreference| VCSCommandCommitOnWrite *VCSCommandCommitOnWrite* @@ -453,6 +476,12 @@ VCSCommandDiffSplit *VCSCommandDiffSplit* This variable overrides the |VCSCommandSplit| variable, but only for buffers created with |:VCSVimDiff|. +VCSCommandDisableAll *VCSCommandDisableAll* + +This variable, if set, prevents the plugin or any extensions from loading at +all. This is useful when a single runtime distribution is used on multiple +systems with varying versions. + VCSCommandDisableMappings *VCSCommandDisableMappings* This variable, if set to a non-zero value, prevents the default command @@ -469,6 +498,11 @@ VCSCommandEdit *VCSCommandEdit* This variable controls whether the original buffer is replaced ('edit') or split ('split'). If not set, it defaults to 'split'. +VCSCommandDisableMenu *VCSCommandDisableMenu* + +This variable, if set to a non-zero value, prevents the default command menu +from being set. + VCSCommandEnableBufferSetup *VCSCommandEnableBufferSetup* This variable, if set to a non-zero value, activates VCS buffer management @@ -477,6 +511,27 @@ mode see (|vcscommand-buffer-management|). This mode means that the is VCS-controlled. This is useful for displaying version information in the status bar. +VCSCommandMappings *VCSCommandMappings* + +This variable, if set, overrides the default mappings used for shortcuts. It +should be a List of 2-element Lists, each containing a shortcut and function +name pair. The value of the '|VCSCommandMapPrefix|' variable will be added to +each shortcut. + +VCSCommandMapPrefix *VCSCommandMapPrefix* + +This variable, if set, overrides the default mapping prefix ('c'). +This allows customization of the mapping space used by the vcscommand +shortcuts. + +VCSCommandMenuPriority *VCSCommandMenuPriority* + +This variable, if set, overrides the default menu priority '' (empty) + +VCSCommandMenuRoot *VCSCommandMenuRoot* + +This variable, if set, overrides the default menu root 'Plugin.VCS' + VCSCommandResultBufferNameExtension *VCSCommandResultBufferNameExtension* This variable, if set to a non-blank value, is appended to the name of the VCS @@ -507,7 +562,8 @@ may occur. If set to 'horizontal', the resulting windows will be on stacked on top of one another. If set to 'vertical', the resulting windows will be side-by-side. If not set, it defaults to 'horizontal' for all but -VCSVimDiff windows. +VCSVimDiff windows. VCSVimDiff windows default to the user's 'diffopt' +setting, if set, otherwise 'vertical'. VCSCommandSVKExec *VCSCommandSVKExec* @@ -529,6 +585,22 @@ VCSCommandSVNExec *VCSCommandSVNExec* This variable controls the executable used for all SVN commands If not set, it defaults to "svn". +VCSCommandVCSTypeOverride *VCSCommandVCSTypeOverride* + +This variable allows the VCS type detection to be overridden on a path-by-path +basis. The value of this variable is expected to be a List of Lists. Each +item in the high-level List is a List containing two elements. The first +element is a regular expression that will be matched against the full file +name of a given buffer. If it matches, the second element will be used as the +VCS type. + +VCSCommandVCSTypePreference *VCSCommandVCSTypePreference* + +This variable allows the VCS type detection to be weighted towards a specific +VCS, in case more than one potential VCS is detected as useable. The format +of the variable is either a list or a space-separated string containing the +ordered-by-preference abbreviations of the preferred VCS types. + 5.2 VCSCommand events *vcscommand-events* For additional customization, vcscommand can trigger user-defined events. @@ -540,7 +612,7 @@ For instance, the following could be added to the vimrc to provide a 'q' mapping to quit a vcscommand scratch buffer: augroup VCSCommand - au User VCSBufferCreated silent! nmap q: bwipeout + au User VCSBufferCreated silent! nmap q :bwipeout augroup END The following hooks are available: @@ -712,7 +784,7 @@ too often. ============================================================================== -7. Changes from cvscommandi *cvscommand-changes* +7. Changes from cvscommand *cvscommand-changes* 1. Require Vim 7 in order to leverage several convenient features; also because I wanted to play with Vim 7. diff --git a/.vim/plugin/vcsbzr.vim b/.vim/plugin/vcsbzr.vim new file mode 100644 index 0000000..966f2ee --- /dev/null +++ b/.vim/plugin/vcsbzr.vim @@ -0,0 +1,264 @@ +" vim600: set foldmethod=marker: +" +" BZR extension for VCSCommand. +" +" Maintainer: Bob Hiestand +" License: +" Copyright (c) Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. +" +" Section: Documentation {{{1 +" +" Options documentation: {{{2 +" +" VCSCommandBZRExec +" This variable specifies the BZR executable. If not set, it defaults to +" 'bzr' executed from the user's executable path. + +" Section: Plugin header {{{1 + +if exists('VCSCommandDisableAll') + finish +endif + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +if !exists('g:loaded_VCSCommand') + runtime plugin/vcscommand.vim +endif + +if !executable(VCSCommandGetOption('VCSCommandBZRExec', 'bzr')) + " BZR is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:bzrFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:Executable() {{{2 +" Returns the executable used to invoke bzr suitable for use in a shell +" command. +function! s:Executable() + return VCSCommandGetOption('VCSCommandBZRExec', 'bzr') +endfunction + +" Function: s:DoCommand(cmd, cmdName, statusText) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the BZR executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'BZR' + let fullCmd = s:Executable() . ' ' . a:cmd + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'BZR VCSCommand plugin called on non-BZR item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:bzrFunctions.Identify(buffer) {{{2 +function! s:bzrFunctions.Identify(buffer) + let fileName = resolve(bufname(a:buffer)) + let l:save_bzr_log=$BZR_LOG + try + let $BZR_LOG=has("win32") || has("win95") || has("win64") || has("win16") ? "nul" : "/dev/null" + let statusText = s:VCSCommandUtility.system(s:Executable() . ' info -- "' . fileName . '"') + finally + let $BZR_LOG=l:save_bzr_log + endtry + if(v:shell_error) + return 0 + else + return 1 + endif +endfunction + +" Function: s:bzrFunctions.Add() {{{2 +function! s:bzrFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Annotate(argList) {{{2 +function! s:bzrFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype ==? 'bzrannotate' + " Perform annotation of the version indicated by the current line. + let caption = matchstr(getline('.'),'\v^\s+\zs\d+') + let options = ' -r' . caption + else + let caption = '' + let options = '' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let caption = a:argList[0] + let options = ' -r' . caption + else + let caption = join(a:argList, ' ') + let options = ' ' . caption + endif + + let resultBuffer = s:DoCommand('blame' . options, 'annotate', caption, {}) + if resultBuffer > 0 + normal! 1G2dd + endif + return resultBuffer +endfunction + +" Function: s:bzrFunctions.Commit(argList) {{{2 +function! s:bzrFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif +endfunction + +" Function: s:bzrFunctions.Delete() {{{2 +function! s:bzrFunctions.Delete(argList) + return s:DoCommand(join(['rm'] + a:argList, ' '), 'rm', join(a:argList, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Diff(argList) {{{2 +function! s:bzrFunctions.Diff(argList) + if len(a:argList) == 0 + let revOptions = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let revOptions = ['-r' . join(a:argList, '..')] + let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')' + else + " Pass-through + let caption = join(a:argList, ' ') + let revOptions = a:argList + endif + + return s:DoCommand(join(['diff'] + revOptions), 'diff', caption, {'allowNonZeroExit': 1}) +endfunction + +" Function: s:bzrFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. +" Returns: List of results: [revision, repository] + +function! s:bzrFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = resolve(bufname(originalBuffer)) + let statusText = s:VCSCommandUtility.system(s:Executable() . ' status -S -- "' . fileName . '"') + let revision = s:VCSCommandUtility.system(s:Executable() . ' revno -- "' . fileName . '"') + if(v:shell_error) + return [] + endif + + " File not under BZR control. + if statusText =~ '^?' + return ['Unknown'] + endif + + let [flags, repository] = matchlist(statusText, '^\(.\{3}\)\s\+\(\S\+\)')[1:2] + if revision == '' + " Error + return ['Unknown'] + elseif flags =~ '^A' + return ['New', 'New'] + else + return [revision, repository] + endif +endfunction + +" Function: s:bzrFunctions.Info(argList) {{{2 +function! s:bzrFunctions.Info(argList) + return s:DoCommand(join(['version-info'] + a:argList, ' '), 'version-info', join(a:argList, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Lock(argList) {{{2 +function! s:bzrFunctions.Lock(argList) + echomsg 'bzr lock is not necessary' +endfunction + +" Function: s:bzrFunctions.Log() {{{2 +function! s:bzrFunctions.Log(argList) + if len(a:argList) == 0 + let options = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let options = ['-r' . join(a:argList, ':')] + let caption = options[0] + else + " Pass-through + let options = a:argList + let caption = join(a:argList, ' ') + endif + + let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {}) + return resultBuffer +endfunction + +" Function: s:bzrFunctions.Revert(argList) {{{2 +function! s:bzrFunctions.Revert(argList) + return s:DoCommand('revert', 'revert', '', {}) +endfunction + +" Function: s:bzrFunctions.Review(argList) {{{2 +function! s:bzrFunctions.Review(argList) + if len(a:argList) == 0 + let versiontag = '(current)' + let versionOption = '' + else + let versiontag = a:argList[0] + let versionOption = ' -r ' . versiontag . ' ' + endif + + return s:DoCommand('cat' . versionOption, 'review', versiontag, {}) +endfunction + +" Function: s:bzrFunctions.Status(argList) {{{2 +function! s:bzrFunctions.Status(argList) + let options = ['-S'] + if len(a:argList) != 0 + let options = a:argList + endif + return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Unlock(argList) {{{2 +function! s:bzrFunctions.Unlock(argList) + echomsg 'bzr unlock is not necessary' +endfunction +" Function: s:bzrFunctions.Update(argList) {{{2 +function! s:bzrFunctions.Update(argList) + return s:DoCommand('update', 'update', '', {}) +endfunction + +" Annotate setting {{{2 +let s:bzrFunctions.AnnotateSplitRegex = '^[^|]\+ | ' + +" Section: Plugin Registration {{{1 +let s:VCSCommandUtility = VCSCommandRegisterModule('BZR', expand(''), s:bzrFunctions, []) + +let &cpo = s:save_cpo diff --git a/.vim/plugin/vcscommand.vim b/.vim/plugin/vcscommand.vim index bfe8520..2726436 100644 --- a/.vim/plugin/vcscommand.vim +++ b/.vim/plugin/vcscommand.vim @@ -1,11 +1,11 @@ " vim600: set foldmethod=marker: " -" Vim plugin to assist in working with files under control of CVS or SVN. +" Vim plugin to assist in working with files under control of various Version +" Control Systems, such as CVS, SVN, SVK, and git. " -" Version: Beta 26 " Maintainer: Bob Hiestand " License: -" Copyright (c) 2008 Bob Hiestand +" Copyright (c) Bob Hiestand " " Permission is hereby granted, free of charge, to any person obtaining a copy " of this software and associated documentation files (the "Software"), to @@ -32,18 +32,17 @@ " directory and all subdirectories associated with the current buffer). The " output of the commands is captured in a new scratch window. " -" This plugin needs additional extension plugins, each specific to a source -" control system, to function. Those plugins should be placed in a -" subdirectory of the standard plugin directory named 'vcscommand'. Several -" options include the name of the version control system in the option name. -" Such options use the placeholder text '{VCSType}', which would be replaced -" in actual usage with 'CVS' or 'SVN', for instance. +" This plugin needs additional extension plugins, each specific to a source +" control system, to function. Several options include the name of the +" version control system in the option name. Such options use the placeholder +" text '{VCSType}', which would be replaced in actual usage with 'CVS' or +" 'SVN', for instance. " " Command documentation {{{2 " " VCSAdd Adds the current file to source control. " -" VCSAnnotate Displays the current file with each line annotated with the +" VCSAnnotate[!] Displays the current file with each line annotated with the " version in which it was most recently changed. If an " argument is given, the argument is used as a revision " number to display. If not given an argument, it uses the @@ -51,6 +50,10 @@ " Additionally, if the current buffer is a VCSAnnotate buffer " already, the version number on the current line is used. " +" If '!' is used, the view of the annotated buffer is split +" so that the annotation is in a separate window from the +" content, and each is highlighted separately. +" " VCSBlame Alias for 'VCSAnnotate'. " " VCSCommit[!] Commits changes to the current file to source control. @@ -88,7 +91,7 @@ " VCS scratch buffers associated with the original file. " " VCSInfo Displays extended information about the current file in a -" new scratch buffer. +" new scratch buffer. " " VCSLock Locks the current file in order to prevent other users from " concurrently modifying it. The exact semantics of this @@ -151,6 +154,7 @@ " " ca VCSAdd " cn VCSAnnotate +" cN VCSAnnotate! " cc VCSCommit " cD VCSDelete " cd VCSDiff @@ -187,6 +191,11 @@ " This variable overrides the VCSCommandSplit variable, but only for buffers " created with VCSVimDiff. " +" VCSCommandDisableAll +" This variable, if set, prevents the plugin or any extensions from loading +" at all. This is useful when a single runtime distribution is used on +" multiple systems with varying versions. +" " VCSCommandDisableMappings " This variable, if set to a non-zero value, prevents the default command " mappings from being set. @@ -195,6 +204,10 @@ " This variable, if set to a non-zero value, prevents the default command " mappings from being set for commands specific to an individual VCS. " +" VCSCommandDisableMenu +" This variable, if set to a non-zero value, prevents the default command +" menu from being set. +" " VCSCommandEdit " This variable controls whether to split the current window to display a " scratch buffer ('split'), or to display it in the current buffer ('edit'). @@ -207,6 +220,22 @@ " information in the status bar. Additional options may be set by " individual VCS plugins. " +" VCSCommandMappings +" This variable, if set, overrides the default mappings used for shortcuts. +" It should be a List of 2-element Lists, each containing a shortcut and +" function name pair. +" +" VCSCommandMapPrefix +" This variable, if set, overrides the default mapping prefix ('c'). +" This allows customization of the mapping space used by the vcscommand +" shortcuts. +" +" VCSCommandMenuPriority +" This variable, if set, overrides the default menu priority '' (empty) +" +" VCSCommandMenuRoot +" This variable, if set, overrides the default menu root 'Plugin.VCS' +" " VCSCommandResultBufferNameExtension " This variable, if set to a non-blank value, is appended to the name of the " VCS command output buffers. For example, '.vcs'. Using this option may @@ -235,6 +264,21 @@ " side-by-side. If not set, it defaults to 'horizontal' for all but " VCSVimDiff windows. " +" VCSCommandVCSTypeOverride +" This variable allows the VCS type detection to be overridden on a +" path-by-path basis. The value of this variable is expected to be a List +" of Lists. Each high-level List item is a List containing two elements. +" The first element is a regular expression that will be matched against the +" full file name of a given buffer. If it matches, the second element will +" be used as the VCS type. +" +" VCSCommandVCSTypePreference +" This variable allows the VCS type detection to be weighted towards a +" specific VCS, in case more than one potential VCS is detected as useable. +" The format of the variable is either a list or a space-separated string +" containing the ordered-by-preference abbreviations of the preferred VCS +" types. +" " Event documentation {{{2 " For additional customization, VCSCommand.vim uses User event autocommand " hooks. Each event is in the VCSCommand group, and different patterns @@ -244,7 +288,7 @@ " mapping to quit a VCS scratch buffer: " " augroup VCSCommand -" au VCSCommand User VCSBufferCreated silent! nmap q :bwipeout +" au VCSCommand User VCSBufferCreated silent! nmap q :bwipeout " augroup END " " The following hooks are available: @@ -272,6 +316,10 @@ " completes. This allows various actions to only be taken by functions after " system initialization. +if exists('VCSCommandDisableAll') + finish +endif + if exists('loaded_VCSCommand') finish endif @@ -303,24 +351,18 @@ let g:VCSCOMMAND_IDENTIFY_INEXACT = -1 " Section: Script variable initialization {{{1 +" Hidden functions for use by extensions +let s:VCSCommandUtility = {} + " plugin-specific information: {vcs -> [script, {command -> function}, {key -> mapping}]} let s:plugins = {} -" temporary values of overridden configuration variables -let s:optionOverrides = {} +" Stack of dictionaries representing nested options +let s:executionContext = [] " state flag used to vary behavior of certain automated actions let s:isEditFileRunning = 0 -" commands needed to restore diff buffers to their original state -unlet! s:vimDiffRestoreCmd - -" original buffer currently reflected in vimdiff windows -unlet! s:vimDiffSourceBuffer - -" -unlet! s:vimDiffScratchList - " Section: Utility functions {{{1 " Function: s:ReportError(mapping) {{{2 @@ -331,6 +373,90 @@ function! s:ReportError(error) echohl WarningMsg|echomsg 'VCSCommand: ' . a:error|echohl None endfunction +" Function: s:VCSCommandUtility.system(...) {{{2 +" Replacement for system() function. This version protects the quoting in the +" command line on Windows systems. + +function! s:VCSCommandUtility.system(...) + if (has("win32") || has("win64")) && &sxq !~ '"' + let save_sxq = &sxq + set sxq=\" + endif + try + let output = call('system', a:000) + if exists('*iconv') && has('multi_byte') + if(strlen(&tenc) && &tenc != &enc) + let output = iconv(output, &tenc, &enc) + else + let originalBuffer = VCSCommandGetOriginalBuffer(VCSCommandGetOption('VCSCommandEncodeAsFile', 0)) + if originalBuffer + let fenc = getbufvar(originalBuffer, '&fenc') + if fenc != &enc + let output = iconv(output, fenc, &enc) + endif + endif + endif + + endif + finally + if exists("save_sxq") + let &sxq = save_sxq + endif + endtry + return output +endfunction + +" Function: s:VCSCommandUtility.addMenuItem(shortcut, command) {{{2 +" Adds the given menu item. + +function! s:VCSCommandUtility.addMenuItem(shortcut, command) + if s:menuEnabled + exe 'amenu '.s:menuPriority.' '.s:menuRoot.'.'.a:shortcut.' '.a:command + endif +endfunction + +" Function: s:VCSCommandUtility.pushContext(context) {{{2 +" Adds a dictionary containing current options to the stack. + +function! s:VCSCommandUtility.pushContext(context) + call insert(s:executionContext, a:context) +endfunction + +" Function: s:VCSCommandUtility.popContext() {{{2 +" Removes a dictionary containing current options from the stack. + +function! s:VCSCommandUtility.popContext() + call remove(s:executionContext, 0) +endfunction + +" Function: s:ClearMenu() {{{2 +" Removes all VCSCommand menu items +function! s:ClearMenu() + if s:menuEnabled + execute 'aunmenu' s:menuRoot + endif +endfunction + +" Function: s:CreateMapping(shortcut, expansion, display) {{{2 +" Creates the given mapping by prepending the contents of +" 'VCSCommandMapPrefix' (by default 'c') to the given shortcut and +" mapping it to the given plugin function. If a mapping exists for the +" specified shortcut + prefix, emit an error but continue. If a mapping +" exists for the specified function, do nothing. + +function! s:CreateMapping(shortcut, expansion, display) + let lhs = VCSCommandGetOption('VCSCommandMapPrefix', 'c') . a:shortcut + if !hasmapto(a:expansion) + try + execute 'nmap ' lhs a:expansion + catch /^Vim(.*):E227:/ + if(&verbose != 0) + echohl WarningMsg|echomsg 'VCSCommand: mapping ''' . lhs . ''' already exists, refusing to overwrite. The mapping for ' . a:display . ' will not be available.'|echohl None + endif + endtry + endif +endfunction + " Function: s:ExecuteExtensionMapping(mapping) {{{2 " Invokes the appropriate extension mapping depending on the type of the " current buffer. @@ -344,7 +470,7 @@ function! s:ExecuteExtensionMapping(mapping) if !has_key(s:plugins[vcsType][2], a:mapping) throw 'This extended mapping is not defined for ' . vcsType endif - silent execute 'normal' ':' . s:plugins[vcsType][2][a:mapping] . "\" + silent execute 'normal!' ':' . s:plugins[vcsType][2][a:mapping] . "\" endfunction " Function: s:ExecuteVCSCommand(command, argList) {{{2 @@ -397,7 +523,7 @@ function! s:GenerateResultBufferName(command, originalBuffer, vcsType, statusTex let bufferName .= ' ' . fileName let counter = 0 let versionedBufferName = bufferName - while buflisted(versionedBufferName) + while bufexists(versionedBufferName) let counter += 1 let versionedBufferName = bufferName . ' (' . counter . ')' endwhile @@ -417,7 +543,7 @@ function! s:GenerateResultBufferNameWithExtension(command, originalBuffer, vcsTy let bufferName .= ' ' . fileName . VCSCommandGetOption('VCSCommandResultBufferNameExtension', '.vcs') let counter = 0 let versionedBufferName = bufferName - while buflisted(versionedBufferName) + while bufexists(versionedBufferName) let counter += 1 let versionedBufferName = '(' . counter . ') ' . bufferName endwhile @@ -431,15 +557,6 @@ endfunction function! s:EditFile(command, originalBuffer, statusText) let vcsType = getbufvar(a:originalBuffer, 'VCSCommandVCSType') - let nameExtension = VCSCommandGetOption('VCSCommandResultBufferNameExtension', '') - if nameExtension == '' - let nameFunction = VCSCommandGetOption('VCSCommandResultBufferNameFunction', 's:GenerateResultBufferName') - else - let nameFunction = VCSCommandGetOption('VCSCommandResultBufferNameFunction', 's:GenerateResultBufferNameWithExtension') - endif - - let resultBufferName = call(nameFunction, [a:command, a:originalBuffer, vcsType, a:statusText]) - " Protect against useless buffer set-up let s:isEditFileRunning += 1 try @@ -454,28 +571,103 @@ function! s:EditFile(command, originalBuffer, statusText) enew - let b:VCSCommandCommand = a:command - let b:VCSCommandOriginalBuffer = a:originalBuffer - let b:VCSCommandSourceFile = bufname(a:originalBuffer) - let b:VCSCommandVCSType = vcsType + call s:SetupScratchBuffer(a:command, vcsType, a:originalBuffer, a:statusText) - setlocal buftype=nofile - setlocal noswapfile - let &filetype = vcsType . a:command - - if a:statusText != '' - let b:VCSCommandStatusText = a:statusText - endif - - if VCSCommandGetOption('VCSCommandDeleteOnHide', 0) - setlocal bufhidden=delete - endif - silent noautocmd file `=resultBufferName` finally let s:isEditFileRunning -= 1 endtry endfunction +" Function: s:IdentifyVCSType() {{{2 +" This function implements the non-cached identification strategy for +" VcsCommandGetVCSType(). +" +" Returns: VCS type name identified for the given buffer; an exception is +" thrown in case no type can be identified. + +function! s:IdentifyVCSType(buffer) + if exists("g:VCSCommandVCSTypeOverride") + let fullpath = fnamemodify(bufname(a:buffer), ':p') + for [path, vcsType] in g:VCSCommandVCSTypeOverride + if match(fullpath, path) > -1 + return vcsType + endif + endfor + endif + let matches = [] + let exactMatch = '' + let exactMatchCount = 0 + for vcsType in keys(s:plugins) + let identified = s:plugins[vcsType][1].Identify(a:buffer) + if identified + if identified == g:VCSCOMMAND_IDENTIFY_EXACT + let exactMatch = vcsType + let exactMatchCount += 1 + endif + call add(matches, [vcsType, identified]) + endif + endfor + if len(matches) == 1 + return matches[0][0] + elseif len(matches) == 0 + throw 'No suitable plugin' + else + let preferences = VCSCommandGetOption("VCSCommandVCSTypePreference", []) + if len(preferences) > 0 + if type(preferences) == 1 + let listPreferences = split(preferences, '\W\+') + unlet preferences + let preferences = listPreferences + endif + for preferred in preferences + for [vcsType, identified] in matches + if vcsType ==? preferred + return vcsType + endif + endfor + endfor + endif + + if exactMatchCount == 1 + return exactMatch + endif + + throw 'can''t identify VCS type for current buffer due to too many matching VCS: ' . join(map(matches, 'v:val[0]')) + endif +endfunction + +" Function: s:SetupScratchBuffer(command, vcsType, originalBuffer, statusText) {{{2 +" Creates convenience buffer variables and the name of a vcscommand result +" buffer. + +function! s:SetupScratchBuffer(command, vcsType, originalBuffer, statusText) + let nameExtension = VCSCommandGetOption('VCSCommandResultBufferNameExtension', '') + if nameExtension == '' + let nameFunction = VCSCommandGetOption('VCSCommandResultBufferNameFunction', 's:GenerateResultBufferName') + else + let nameFunction = VCSCommandGetOption('VCSCommandResultBufferNameFunction', 's:GenerateResultBufferNameWithExtension') + endif + + let name = call(nameFunction, [a:command, a:originalBuffer, a:vcsType, a:statusText]) + + let b:VCSCommandCommand = a:command + let b:VCSCommandOriginalBuffer = a:originalBuffer + let b:VCSCommandSourceFile = bufname(a:originalBuffer) + let b:VCSCommandVCSType = a:vcsType + if a:statusText != '' + let b:VCSCommandStatusText = a:statusText + endif + + setlocal buftype=nofile + setlocal noswapfile + let &filetype = tolower(a:vcsType . a:command) + + if VCSCommandGetOption('VCSCommandDeleteOnHide', 0) + setlocal bufhidden=delete + endif + silent noautocmd file `=name` +endfunction + " Function: s:SetupBuffer() {{{2 " Attempts to set the b:VCSCommandBufferInfo variable @@ -514,7 +706,7 @@ endfunction function! s:MarkOrigBufferForSetup(buffer) checktime - if a:buffer > 0 + if a:buffer > 0 let origBuffer = VCSCommandGetOriginalBuffer(a:buffer) " This should never not work, but I'm paranoid if origBuffer != a:buffer @@ -524,21 +716,6 @@ function! s:MarkOrigBufferForSetup(buffer) return a:buffer endfunction -" Function: s:OverrideOption(option, [value]) {{{2 -" Provides a temporary override for the given VCS option. If no value is -" passed, the override is disabled. - -function! s:OverrideOption(option, ...) - if a:0 == 0 - call remove(s:optionOverrides[a:option], -1) - else - if !has_key(s:optionOverrides, a:option) - let s:optionOverrides[a:option] = [] - endif - call add(s:optionOverrides[a:option], a:1) - endif -endfunction - " Function: s:WipeoutCommandBuffers() {{{2 " Clears all current VCS output buffers of the specified type for a given source. @@ -562,30 +739,30 @@ endfunction function! s:VimDiffRestore(vimDiffBuff) let s:isEditFileRunning += 1 try - if exists('s:vimDiffSourceBuffer') - if a:vimDiffBuff == s:vimDiffSourceBuffer + if exists('t:vcsCommandVimDiffSourceBuffer') + if a:vimDiffBuff == t:vcsCommandVimDiffSourceBuffer " Original file is being removed. - unlet! s:vimDiffSourceBuffer - unlet! s:vimDiffRestoreCmd - unlet! s:vimDiffScratchList + unlet! t:vcsCommandVimDiffSourceBuffer + unlet! t:vcsCommandVimDiffRestoreCmd + unlet! t:vcsCommandVimDiffScratchList else - let index = index(s:vimDiffScratchList, a:vimDiffBuff) + let index = index(t:vcsCommandVimDiffScratchList, a:vimDiffBuff) if index >= 0 - call remove(s:vimDiffScratchList, index) - if len(s:vimDiffScratchList) == 0 - if exists('s:vimDiffRestoreCmd') + call remove(t:vcsCommandVimDiffScratchList, index) + if len(t:vcsCommandVimDiffScratchList) == 0 + if exists('t:vcsCommandVimDiffRestoreCmd') " All scratch buffers are gone, reset the original. " Only restore if the source buffer is still in Diff mode - let sourceWinNR = bufwinnr(s:vimDiffSourceBuffer) + let sourceWinNR = bufwinnr(t:vcsCommandVimDiffSourceBuffer) if sourceWinNR != -1 " The buffer is visible in at least one window let currentWinNR = winnr() while winbufnr(sourceWinNR) != -1 - if winbufnr(sourceWinNR) == s:vimDiffSourceBuffer + if winbufnr(sourceWinNR) == t:vcsCommandVimDiffSourceBuffer execute sourceWinNR . 'wincmd w' if getwinvar(0, '&diff') - execute s:vimDiffRestoreCmd + execute t:vcsCommandVimDiffRestoreCmd endif endif let sourceWinNR = sourceWinNR + 1 @@ -595,18 +772,18 @@ function! s:VimDiffRestore(vimDiffBuff) " The buffer is hidden. It must be visible in order to set the " diff option. let currentBufNR = bufnr('') - execute 'hide buffer' s:vimDiffSourceBuffer + execute 'hide buffer' t:vcsCommandVimDiffSourceBuffer if getwinvar(0, '&diff') - execute s:vimDiffRestoreCmd + execute t:vcsCommandVimDiffRestoreCmd endif execute 'hide buffer' currentBufNR endif - unlet s:vimDiffRestoreCmd - endif + unlet t:vcsCommandVimDiffRestoreCmd + endif " All buffers are gone. - unlet s:vimDiffSourceBuffer - unlet s:vimDiffScratchList + unlet t:vcsCommandVimDiffSourceBuffer + unlet t:vcsCommandVimDiffScratchList endif endif endif @@ -618,6 +795,76 @@ endfunction " Section: Generic VCS command functions {{{1 +" Function: s:VCSAnnotate(...) {{{2 +function! s:VCSAnnotate(bang, ...) + call s:VCSCommandUtility.pushContext({'VCSCommandEncodeAsFile': bufnr('%')}) + try + let line = line('.') + let currentBuffer = bufnr('%') + let originalBuffer = VCSCommandGetOriginalBuffer(currentBuffer) + + let annotateBuffer = s:ExecuteVCSCommand('Annotate', a:000) + if annotateBuffer == -1 + return -1 + endif + if a:bang == '!' && VCSCommandGetOption('VCSCommandDisableSplitAnnotate', 0) == 0 + let vcsType = VCSCommandGetVCSType(annotateBuffer) + let functionMap = s:plugins[vcsType][1] + let splitRegex = '' + if has_key(s:plugins[vcsType][1], 'AnnotateSplitRegex') + let splitRegex = s:plugins[vcsType][1]['AnnotateSplitRegex'] + endif + let splitRegex = VCSCommandGetOption('VCSCommand' . vcsType . 'AnnotateSplitRegex', splitRegex) + if splitRegex == '' + return annotateBuffer + endif + wincmd J + let originalFileType = getbufvar(originalBuffer, '&ft') + let annotateFileType = getbufvar(annotateBuffer, '&ft') + + let saveselection = &selection + set selection=inclusive + try + execute "normal! 0zR\G/" . splitRegex . "/e\d" + finally + let &selection = saveselection + endtry + + call setbufvar('%', '&filetype', getbufvar(originalBuffer, '&filetype')) + set scrollbind + leftabove vert new + normal! 0P + execute "normal!" . (col('$') + (&number ? &numberwidth : 0)). "\|" + call s:SetupScratchBuffer('annotate', vcsType, originalBuffer, 'header') + wincmd l + endif + + if currentBuffer == originalBuffer + " Starting from the original source buffer, so the + " current line is relevant. + if a:0 == 0 + " No argument list means that we're annotating + " the current version, so jumping to the same + " line is the expected action. + execute "normal!" line . 'G' + if has('folding') + " The execution of the buffer created autocommand + " re-folds the buffer. Display the current line + " unfolded. + normal! zv + endif + endif + endif + + return annotateBuffer + catch + call s:ReportError(v:exception) + return -1 + finally + call s:VCSCommandUtility.popContext() + endtry +endfunction + " Function: s:VCSCommit() {{{2 function! s:VCSCommit(bang, message) try @@ -656,6 +903,7 @@ function! s:VCSCommit(bang, message) silent put ='VCS: ----------------------------------------------------------------------' $ setlocal nomodified + silent do VCSCommand User VCSBufferCreated catch call s:ReportError(v:exception) return -1 @@ -668,7 +916,7 @@ endfunction function! s:VCSFinishCommitWithBuffer() setlocal nomodified - let currentBuffer = bufnr('%') + let currentBuffer = bufnr('%') let logMessageList = getbufline('%', 1, '$') call filter(logMessageList, 'v:val !~ ''^\s*VCS:''') let resultBuffer = s:VCSFinishCommit(logMessageList, b:VCSCommandOriginalBuffer) @@ -680,22 +928,21 @@ endfunction " Function: s:VCSFinishCommit(logMessageList, originalBuffer) {{{2 function! s:VCSFinishCommit(logMessageList, originalBuffer) - let shellSlashBak = &shellslash + let messageFileName = tempname() + if exists('*iconv') && has('multi_byte') + if(strlen(&tenc) && &tenc != &enc) + call map(a:logMessageList, 'iconv(v:val, &enc, &tenc)') + endif + endif + call writefile(a:logMessageList, messageFileName) try - set shellslash - let messageFileName = tempname() - call writefile(a:logMessageList, messageFileName) - try - let resultBuffer = s:ExecuteVCSCommand('Commit', [messageFileName]) - if resultBuffer < 0 - return resultBuffer - endif - return s:MarkOrigBufferForSetup(resultBuffer) - finally - call delete(messageFileName) - endtry + let resultBuffer = s:ExecuteVCSCommand('Commit', [messageFileName]) + if resultBuffer < 0 + return resultBuffer + endif + return s:MarkOrigBufferForSetup(resultBuffer) finally - let &shellslash = shellSlashBak + call delete(messageFileName) endtry endfunction @@ -722,6 +969,34 @@ function! s:VCSGotoOriginal(bang) endif endfunction +function! s:VCSDiff(...) "{{{2 + call s:VCSCommandUtility.pushContext({'VCSCommandEncodeAsFile': bufnr('%')}) + try + let resultBuffer = s:ExecuteVCSCommand('Diff', a:000) + if resultBuffer > 0 + let &filetype = 'diff' + elseif resultBuffer == 0 + echomsg 'No differences found' + endif + return resultBuffer + finally + call s:VCSCommandUtility.popContext() + endtry +endfunction + +function! s:VCSReview(...) "{{{2 + call s:VCSCommandUtility.pushContext({'VCSCommandEncodeAsFile': bufnr('%')}) + try + let resultBuffer = s:ExecuteVCSCommand('Review', a:000) + if resultBuffer > 0 + let &filetype = getbufvar(b:VCSCommandOriginalBuffer, '&filetype') + endif + return resultBuffer + finally + call s:VCSCommandUtility.popContext() + endtry +endfunction + " Function: s:VCSVimDiff(...) {{{2 function! s:VCSVimDiff(...) try @@ -735,31 +1010,35 @@ function! s:VCSVimDiff(...) " If there's already a VimDiff'ed window, restore it. " There may only be one VCSVimDiff original window at a time. - if exists('s:vimDiffSourceBuffer') && s:vimDiffSourceBuffer != originalBuffer + if exists('t:vcsCommandVimDiffSourceBuffer') && t:vcsCommandVimDiffSourceBuffer != originalBuffer " Clear the existing vimdiff setup by removing the result buffers. - call s:WipeoutCommandBuffers(s:vimDiffSourceBuffer, 'vimdiff') + call s:WipeoutCommandBuffers(t:vcsCommandVimDiffSourceBuffer, 'vimdiff') endif + let orientation = &diffopt =~ 'horizontal' ? 'horizontal' : 'vertical' + let orientation = VCSCommandGetOption('VCSCommandSplit', orientation) + let orientation = VCSCommandGetOption('VCSCommandDiffSplit', orientation) + " Split and diff if(a:0 == 2) " Reset the vimdiff system, as 2 explicit versions were provided. - if exists('s:vimDiffSourceBuffer') - call s:WipeoutCommandBuffers(s:vimDiffSourceBuffer, 'vimdiff') + if exists('t:vcsCommandVimDiffSourceBuffer') + call s:WipeoutCommandBuffers(t:vcsCommandVimDiffSourceBuffer, 'vimdiff') endif - let resultBuffer = s:plugins[vcsType][1].Review([a:1]) + let resultBuffer = s:VCSReview(a:1) if resultBuffer < 0 echomsg 'Can''t open revision ' . a:1 return resultBuffer endif let b:VCSCommandCommand = 'vimdiff' diffthis - let s:vimDiffScratchList = [resultBuffer] + let t:vcsCommandVimDiffScratchList = [resultBuffer] " If no split method is defined, cheat, and set it to vertical. + call s:VCSCommandUtility.pushContext({'VCSCommandSplit': orientation}) try - call s:OverrideOption('VCSCommandSplit', VCSCommandGetOption('VCSCommandDiffSplit', VCSCommandGetOption('VCSCommandSplit', 'vertical'))) - let resultBuffer = s:plugins[vcsType][1].Review([a:2]) + let resultBuffer = s:VCSReview(a:2) finally - call s:OverrideOption('VCSCommandSplit') + call s:VCSCommandUtility.popContext() endtry if resultBuffer < 0 echomsg 'Can''t open revision ' . a:1 @@ -767,24 +1046,18 @@ function! s:VCSVimDiff(...) endif let b:VCSCommandCommand = 'vimdiff' diffthis - let s:vimDiffScratchList += [resultBuffer] + let t:vcsCommandVimDiffScratchList += [resultBuffer] else - " Add new buffer - call s:OverrideOption('VCSCommandEdit', 'split') + " Add new buffer. Force splitting behavior, otherwise why use vimdiff? + call s:VCSCommandUtility.pushContext({'VCSCommandEdit': 'split', 'VCSCommandSplit': orientation}) try - " Force splitting behavior, otherwise why use vimdiff? - call s:OverrideOption('VCSCommandSplit', VCSCommandGetOption('VCSCommandDiffSplit', VCSCommandGetOption('VCSCommandSplit', 'vertical'))) - try - if(a:0 == 0) - let resultBuffer = s:plugins[vcsType][1].Review([]) - else - let resultBuffer = s:plugins[vcsType][1].Review([a:1]) - endif - finally - call s:OverrideOption('VCSCommandSplit') - endtry + if(a:0 == 0) + let resultBuffer = s:VCSReview() + else + let resultBuffer = s:VCSReview(a:1) + endif finally - call s:OverrideOption('VCSCommandEdit') + call s:VCSCommandUtility.popContext() endtry if resultBuffer < 0 echomsg 'Can''t open current revision' @@ -793,16 +1066,16 @@ function! s:VCSVimDiff(...) let b:VCSCommandCommand = 'vimdiff' diffthis - if !exists('s:vimDiffSourceBuffer') + if !exists('t:vcsCommandVimDiffSourceBuffer') " New instance of vimdiff. - let s:vimDiffScratchList = [resultBuffer] + let t:vcsCommandVimDiffScratchList = [resultBuffer] " This could have been invoked on a VCS result buffer, not the " original buffer. wincmd W execute 'buffer' originalBuffer " Store info for later original buffer restore - let s:vimDiffRestoreCmd = + let t:vcsCommandVimDiffRestoreCmd = \ 'call setbufvar('.originalBuffer.', ''&diff'', '.getbufvar(originalBuffer, '&diff').')' \ . '|call setbufvar('.originalBuffer.', ''&foldcolumn'', '.getbufvar(originalBuffer, '&foldcolumn').')' \ . '|call setbufvar('.originalBuffer.', ''&foldenable'', '.getbufvar(originalBuffer, '&foldenable').')' @@ -810,16 +1083,19 @@ function! s:VCSVimDiff(...) \ . '|call setbufvar('.originalBuffer.', ''&foldlevel'', '''.getbufvar(originalBuffer, '&foldlevel').''')' \ . '|call setbufvar('.originalBuffer.', ''&scrollbind'', '.getbufvar(originalBuffer, '&scrollbind').')' \ . '|call setbufvar('.originalBuffer.', ''&wrap'', '.getbufvar(originalBuffer, '&wrap').')' - \ . '|if &foldmethod==''manual''|execute ''normal zE''|endif' + if has('cursorbind') + let t:vcsCommandVimDiffRestoreCmd .= '|call setbufvar('.originalBuffer.', ''&cursorbind'', '.getbufvar(originalBuffer, '&cursorbind').')' + endif + let t:vcsCommandVimDiffRestoreCmd .= '|if &foldmethod==''manual''|execute ''normal! zE''|endif' diffthis wincmd w else " Adding a window to an existing vimdiff - let s:vimDiffScratchList += [resultBuffer] + let t:vcsCommandVimDiffScratchList += [resultBuffer] endif endif - let s:vimDiffSourceBuffer = originalBuffer + let t:vcsCommandVimDiffSourceBuffer = originalBuffer " Avoid executing the modeline in the current buffer after the autocommand. @@ -844,40 +1120,31 @@ endfunction " Section: Public functions {{{1 " Function: VCSCommandGetVCSType() {{{2 -" Sets the b:VCSCommandVCSType variable in the given buffer to the -" appropriate source control system name. +" This function sets the b:VCSCommandVCSType variable in the given buffer to the +" appropriate source control system name and returns the same name. " -" This uses the Identify extension function to test the buffer. If the -" Identify function returns VCSCOMMAND_IDENTIFY_EXACT, the match is considered -" exact. If the Identify function returns VCSCOMMAND_IDENTIFY_INEXACT, the -" match is considered inexact, and is only applied if no exact match is found. -" Multiple inexact matches is currently considered an error. +" Returns: VCS type name identified for the given buffer. An exception is +" thrown if no type can be identified. +" +" Rules for determining type: +" 1. use previously-cached value +" 2. use value from 'VCSCommandVCSTypeOverride' +" 3. use single match +" 4. use first matching value from 'VCSCommandTypePreference' +" 5. use single exact match +" 6. error if multiple matching types +" 7. error if no matching types function! VCSCommandGetVCSType(buffer) - let vcsType = getbufvar(a:buffer, 'VCSCommandVCSType') - if strlen(vcsType) > 0 - return vcsType - endif - let matches = [] - for vcsType in keys(s:plugins) - let identified = s:plugins[vcsType][1].Identify(a:buffer) - if identified - if identified == g:VCSCOMMAND_IDENTIFY_EXACT - let matches = [vcsType] - break - else - let matches += [vcsType] - endif + let vcsType = VCSCommandGetOption('VCSCommandVCSTypeExplicitOverride', '') + if len(vcsType) == 0 + let vcsType = getbufvar(a:buffer, 'VCSCommandVCSType') + if strlen(vcsType) == 0 + let vcsType = s:IdentifyVCSType(a:buffer) + call setbufvar(a:buffer, 'VCSCommandVCSType', vcsType) endif - endfor - if len(matches) == 1 - call setbufvar(a:buffer, 'VCSCommandVCSType', matches[0]) - return matches[0] - elseif len(matches) == 0 - throw 'No suitable plugin' - else - throw 'Too many matching VCS: ' . join(matches) endif + return vcsType endfunction " Function: VCSCommandChdir(directory) {{{2 @@ -888,7 +1155,11 @@ function! VCSCommandChdir(directory) if exists("*haslocaldir") && haslocaldir() let command = 'lcd' endif - execute command escape(a:directory, ' ') + if exists("*fnameescape") + execute command fnameescape(a:directory) + else + execute command escape(a:directory, ' ') + endif endfunction " Function: VCSCommandChangeToCurrentFileDir() {{{2 @@ -928,12 +1199,15 @@ endfunction function! VCSCommandRegisterModule(name, path, commandMap, mappingMap) let s:plugins[a:name] = [a:path, a:commandMap, a:mappingMap] if !empty(a:mappingMap) + \ && !exists("g:no_plugin_maps") \ && !VCSCommandGetOption('VCSCommandDisableMappings', 0) \ && !VCSCommandGetOption('VCSCommandDisableExtensionMappings', 0) - for mapname in keys(a:mappingMap) - execute 'noremap ' . mapname ':call ExecuteExtensionMapping(''' . mapname . ''')' + for shortcut in keys(a:mappingMap) + let expansion = ":call ExecuteExtensionMapping('" . shortcut . "')" + call s:CreateMapping(shortcut, expansion, a:name . " extension mapping " . shortcut) endfor endif + return s:VCSCommandUtility endfunction " Function: VCSCommandDoCommand(cmd, cmdName, statusText, [options]) {{{2 @@ -955,7 +1229,7 @@ function! VCSCommandDoCommand(cmd, cmdName, statusText, options) endif let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) - if originalBuffer == -1 + if originalBuffer == -1 throw 'Original buffer no longer exists, aborting.' endif @@ -973,7 +1247,7 @@ function! VCSCommandDoCommand(cmd, cmdName, statusText, options) if match(a:cmd, '') > 0 let fullCmd = substitute(a:cmd, '', fileName, 'g') else - let fullCmd = a:cmd . ' "' . fileName . '"' + let fullCmd = a:cmd . ' -- ' . shellescape(fileName) endif " Change to the directory of the current buffer. This is done for CVS, but @@ -981,7 +1255,7 @@ function! VCSCommandDoCommand(cmd, cmdName, statusText, options) let oldCwd = VCSCommandChangeToCurrentFileDir(path) try - let output = system(fullCmd) + let output = s:VCSCommandUtility.system(fullCmd) finally call VCSCommandChdir(oldCwd) endtry @@ -1020,7 +1294,7 @@ function! VCSCommandDoCommand(cmd, cmdName, statusText, options) " within a fold, but I prefer to simply unfold the result buffer altogether. if has('folding') - normal zR + normal! zR endif $d @@ -1037,9 +1311,12 @@ endfunction " searched in the window, buffer, then global spaces. function! VCSCommandGetOption(name, default) - if has_key(s:optionOverrides, a:name) && len(s:optionOverrides[a:name]) > 0 - return s:optionOverrides[a:name][-1] - elseif exists('w:' . a:name) + for context in s:executionContext + if has_key(context, a:name) + return context[a:name] + endif + endfor + if exists('w:' . a:name) return w:{a:name} elseif exists('b:' . a:name) return b:{a:name} @@ -1097,21 +1374,29 @@ function! VCSCommandGetStatusLine() endif endfunction +function! VCSCommandSetVCSType(type) + if exists('b:VCSCommandBufferSetup') + unlet b:VCSCommandBufferSetup + endif + let b:VCSCommandVCSType = a:type + call s:SetupBuffer() +endfunction + " Section: Command definitions {{{1 " Section: Primary commands {{{2 com! -nargs=* VCSAdd call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Add', [])) -com! -nargs=* VCSAnnotate call s:ExecuteVCSCommand('Annotate', []) -com! -nargs=* VCSBlame call s:ExecuteVCSCommand('Annotate', []) +com! -nargs=* -bang VCSAnnotate call s:VCSAnnotate(, ) +com! -nargs=* -bang VCSBlame call s:VCSAnnotate(, ) com! -nargs=? -bang VCSCommit call s:VCSCommit(, ) com! -nargs=* VCSDelete call s:ExecuteVCSCommand('Delete', []) -com! -nargs=* VCSDiff call s:ExecuteVCSCommand('Diff', []) +com! -nargs=* VCSDiff call s:VCSDiff() com! -nargs=0 -bang VCSGotoOriginal call s:VCSGotoOriginal() com! -nargs=* VCSInfo call s:ExecuteVCSCommand('Info', []) com! -nargs=* VCSLock call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Lock', [])) com! -nargs=* VCSLog call s:ExecuteVCSCommand('Log', []) com! -nargs=* VCSRemove call s:ExecuteVCSCommand('Delete', []) com! -nargs=0 VCSRevert call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Revert', [])) -com! -nargs=? VCSReview call s:ExecuteVCSCommand('Review', []) +com! -nargs=? VCSReview call s:VCSReview() com! -nargs=* VCSStatus call s:ExecuteVCSCommand('Status', []) com! -nargs=* VCSUnlock call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Unlock', [])) com! -nargs=0 VCSUpdate call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Update', [])) @@ -1122,92 +1407,82 @@ com! VCSCommandDisableBufferSetup call VCSCommandDisableBufferSetup() com! VCSCommandEnableBufferSetup call VCSCommandEnableBufferSetup() " Allow reloading VCSCommand.vim -com! VCSReload let savedPlugins = s:plugins|let s:plugins = {}|aunmenu Plugin.VCS|unlet! g:loaded_VCSCommand|runtime plugin/vcscommand.vim|for plugin in values(savedPlugins)|execute 'source' plugin[0]|endfor|unlet savedPlugins +com! VCSReload let savedPlugins = s:plugins|let s:plugins = {}|call s:ClearMenu()|unlet! g:loaded_VCSCommand|runtime plugin/vcscommand.vim|for plugin in values(savedPlugins)|execute 'source' plugin[0]|endfor|unlet savedPlugins " Section: Plugin command mappings {{{1 -nnoremap VCSAdd :VCSAdd -nnoremap VCSAnnotate :VCSAnnotate -nnoremap VCSCommit :VCSCommit -nnoremap VCSDelete :VCSDelete -nnoremap VCSDiff :VCSDiff -nnoremap VCSGotoOriginal :VCSGotoOriginal -nnoremap VCSClearAndGotoOriginal :VCSGotoOriginal! -nnoremap VCSInfo :VCSInfo -nnoremap VCSLock :VCSLock -nnoremap VCSLog :VCSLog -nnoremap VCSRevert :VCSRevert -nnoremap VCSReview :VCSReview -nnoremap VCSStatus :VCSStatus -nnoremap VCSUnlock :VCSUnlock -nnoremap VCSUpdate :VCSUpdate -nnoremap VCSVimDiff :VCSVimDiff +if !exists("no_plugin_maps") + nnoremap VCSAdd :VCSAdd + nnoremap VCSAnnotate :VCSAnnotate + nnoremap VCSCommit :VCSCommit + nnoremap VCSDelete :VCSDelete + nnoremap VCSDiff :VCSDiff + nnoremap VCSGotoOriginal :VCSGotoOriginal + nnoremap VCSClearAndGotoOriginal :VCSGotoOriginal! + nnoremap VCSInfo :VCSInfo + nnoremap VCSLock :VCSLock + nnoremap VCSLog :VCSLog + nnoremap VCSRevert :VCSRevert + nnoremap VCSReview :VCSReview + nnoremap VCSSplitAnnotate :VCSAnnotate! + nnoremap VCSStatus :VCSStatus + nnoremap VCSUnlock :VCSUnlock + nnoremap VCSUpdate :VCSUpdate + nnoremap VCSVimDiff :VCSVimDiff +endif " Section: Default mappings {{{1 -if !VCSCommandGetOption('VCSCommandDisableMappings', 0) - if !hasmapto('VCSAdd') - nmap ca VCSAdd - endif - if !hasmapto('VCSAnnotate') - nmap cn VCSAnnotate - endif - if !hasmapto('VCSClearAndGotoOriginal') - nmap cG VCSClearAndGotoOriginal - endif - if !hasmapto('VCSCommit') - nmap cc VCSCommit - endif - if !hasmapto('VCSDelete') - nmap cD VCSDelete - endif - if !hasmapto('VCSDiff') - nmap cd VCSDiff - endif - if !hasmapto('VCSGotoOriginal') - nmap cg VCSGotoOriginal - endif - if !hasmapto('VCSInfo') - nmap ci VCSInfo - endif - if !hasmapto('VCSLock') - nmap cL VCSLock - endif - if !hasmapto('VCSLog') - nmap cl VCSLog - endif - if !hasmapto('VCSRevert') - nmap cq VCSRevert - endif - if !hasmapto('VCSReview') - nmap cr VCSReview - endif - if !hasmapto('VCSStatus') - nmap cs VCSStatus - endif - if !hasmapto('VCSUnlock') - nmap cU VCSUnlock - endif - if !hasmapto('VCSUpdate') - nmap cu VCSUpdate - endif - if !hasmapto('VCSVimDiff') - nmap cv VCSVimDiff - endif +let s:defaultMappings = [ + \['a', 'VCSAdd'], + \['c', 'VCSCommit'], + \['D', 'VCSDelete'], + \['d', 'VCSDiff'], + \['G', 'VCSClearAndGotoOriginal'], + \['g', 'VCSGotoOriginal'], + \['i', 'VCSInfo'], + \['L', 'VCSLock'], + \['l', 'VCSLog'], + \['N', 'VCSSplitAnnotate'], + \['n', 'VCSAnnotate'], + \['q', 'VCSRevert'], + \['r', 'VCSReview'], + \['s', 'VCSStatus'], + \['U', 'VCSUnlock'], + \['u', 'VCSUpdate'], + \['v', 'VCSVimDiff'], + \] + +if !exists("g:no_plugin_maps") && !VCSCommandGetOption('VCSCommandDisableMappings', 0) + for [s:shortcut, s:vcsFunction] in VCSCommandGetOption('VCSCommandMappings', s:defaultMappings) + call s:CreateMapping(s:shortcut, '' . s:vcsFunction, '''' . s:vcsFunction . '''') + endfor + unlet s:shortcut s:vcsFunction endif +unlet s:defaultMappings " Section: Menu items {{{1 -amenu &Plugin.VCS.&Add VCSAdd -amenu &Plugin.VCS.A&nnotate VCSAnnotate -amenu &Plugin.VCS.&Commit VCSCommit -amenu &Plugin.VCS.Delete VCSDelete -amenu &Plugin.VCS.&Diff VCSDiff -amenu &Plugin.VCS.&Info VCSInfo -amenu &Plugin.VCS.&Log VCSLog -amenu &Plugin.VCS.Revert VCSRevert -amenu &Plugin.VCS.&Review VCSReview -amenu &Plugin.VCS.&Status VCSStatus -amenu &Plugin.VCS.&Update VCSUpdate -amenu &Plugin.VCS.&VimDiff VCSVimDiff + +let s:menuEnabled = !VCSCommandGetOption('VCSCommandDisableMenu', 0) +let s:menuRoot = VCSCommandGetOption('VCSCommandMenuRoot', '&Plugin.VCS') +let s:menuPriority = VCSCommandGetOption('VCSCommandMenuPriority', '') + +for [s:shortcut, s:command] in [ + \['&Add', 'VCSAdd'], + \['A&nnotate', 'VCSAnnotate'], + \['&Commit', 'VCSCommit'], + \['Delete', 'VCSDelete'], + \['&Diff', 'VCSDiff'], + \['&Info', 'VCSInfo'], + \['&Log', 'VCSLog'], + \['Revert', 'VCSRevert'], + \['&Review', 'VCSReview'], + \['&Status', 'VCSStatus'], + \['&Update', 'VCSUpdate'], + \['&VimDiff', 'VCSVimDiff'] + \] + call s:VCSCommandUtility.addMenuItem(s:shortcut, s:command) +endfor +unlet s:shortcut s:command " Section: Autocommands to restore vimdiff state {{{1 augroup VimDiffRestore @@ -1234,7 +1509,7 @@ function! s:CloseAllResultBuffers() let buffnr = 1 let buffmaxnr = bufnr('$') while buffnr <= buffmaxnr - if getbufvar(buffnr, 'VCSCommandOriginalBuffer') != "" + if getbufvar(buffnr, 'VCSCommandOriginalBuffer') != "" execute 'bw' buffnr endif let buffnr = buffnr + 1 diff --git a/.vim/plugin/vcscvs.vim b/.vim/plugin/vcscvs.vim index e2930e5..11c7433 100644 --- a/.vim/plugin/vcscvs.vim +++ b/.vim/plugin/vcscvs.vim @@ -2,10 +2,9 @@ " " CVS extension for VCSCommand. " -" Version: VCS development " Maintainer: Bob Hiestand " License: -" Copyright (c) 2007 Bob Hiestand +" Copyright (c) Bob Hiestand " " Permission is hereby granted, free of charge, to any person obtaining a copy " of this software and associated documentation files (the "Software"), to @@ -32,23 +31,23 @@ " The following commands only apply to files under CVS source control. " " CVSEdit Performs "cvs edit" on the current file. -" +" " CVSEditors Performs "cvs editors" on the current file. -" +" " CVSUnedit Performs "cvs unedit" on the current file. -" +" " CVSWatch Takes an argument which must be one of [on|off|add|remove]. " Performs "cvs watch" with the given argument on the current " file. -" +" " CVSWatchers Performs "cvs watchers" on the current file. -" +" " CVSWatchAdd Alias for "CVSWatch add" -" +" " CVSWatchOn Alias for "CVSWatch on" -" +" " CVSWatchOff Alias for "CVSWatch off" -" +" " CVSWatchRemove Alias for "CVSWatch remove" " " Mapping documentation: {{{2 @@ -81,12 +80,18 @@ " Section: Plugin header {{{1 +if exists('VCSCommandDisableAll') + finish +endif + if v:version < 700 echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None finish endif -runtime plugin/vcscommand.vim +if !exists('g:loaded_VCSCommand') + runtime plugin/vcscommand.vim +endif if !executable(VCSCommandGetOption('VCSCommandCVSExec', 'cvs')) " CVS is not installed @@ -102,23 +107,40 @@ let s:cvsFunctions = {} " Section: Utility functions {{{1 +" Function: s:Executable() {{{2 +" Returns the executable used to invoke cvs suitable for use in a shell +" command. +function! s:Executable() + return VCSCommandGetOption('VCSCommandCVSExec', 'cvs') +endfunction + " Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 " Wrapper to VCSCommandDoCommand to add the name of the CVS executable to the " command argument. function! s:DoCommand(cmd, cmdName, statusText, options) if VCSCommandGetVCSType(expand('%')) == 'CVS' - let fullCmd = VCSCommandGetOption('VCSCommandCVSExec', 'cvs') . ' ' . a:cmd - return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + let fullCmd = s:Executable() . ' ' . a:cmd + let ret = VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + + if ret > 0 + if getline(line('$')) =~ '^cvs \w\+: closing down connection' + $d + 1 + endif + + endif + + return ret else throw 'CVS VCSCommand plugin called on non-CVS item.' endif endfunction -" Function: GetRevision() {{{2 +" Function: s:GetRevision() {{{2 " Function for retrieving the current buffer's revision number. " Returns: Revision number or an empty string if an error occurs. -function! GetRevision() +function! s:GetRevision() if !exists('b:VCSCommandBufferInfo') let b:VCSCommandBufferInfo = s:cvsFunctions.GetBufferInfo() endif @@ -160,7 +182,7 @@ endfunction " Function: s:cvsFunctions.Annotate(argList) {{{2 function! s:cvsFunctions.Annotate(argList) if len(a:argList) == 0 - if &filetype == 'CVSAnnotate' + if &filetype ==? 'cvsannotate' " This is a CVSAnnotate buffer. Perform annotation of the version " indicated by the current line. let caption = matchstr(getline('.'),'\v^[0-9.]+') @@ -183,7 +205,7 @@ function! s:cvsFunctions.Annotate(argList) " CVS defaults to pulling HEAD, regardless of current branch. " Therefore, always pass desired revision. let caption = '' - let options = ['-r' . GetRevision()] + let options = ['-r' . s:GetRevision()] endif elseif len(a:argList) == 1 && a:argList[0] !~ '^-' let caption = a:argList[0] @@ -195,7 +217,6 @@ function! s:cvsFunctions.Annotate(argList) let resultBuffer = s:DoCommand(join(['-q', 'annotate'] + options), 'annotate', caption, {}) if resultBuffer > 0 - set filetype=CVSAnnotate " Remove header lines from standard error silent v/^\d\+\%(\.\d\+\)\+/d endif @@ -245,13 +266,7 @@ function! s:cvsFunctions.Diff(argList) let diffOptions = ['-' . cvsDiffOpt] endif - let resultBuffer = s:DoCommand(join(['diff'] + diffOptions + revOptions), 'diff', caption, {'allowNonZeroExit': 1}) - if resultBuffer > 0 - set filetype=diff - else - echomsg 'No differences found' - endif - return resultBuffer + return s:DoCommand(join(['diff'] + diffOptions + revOptions), 'diff', caption, {'allowNonZeroExit': 1}) endfunction " Function: s:cvsFunctions.GetBufferInfo() {{{2 @@ -280,7 +295,7 @@ function! s:cvsFunctions.GetBufferInfo() endif let oldCwd = VCSCommandChangeToCurrentFileDir(fileName) try - let statusText=system(VCSCommandGetOption('VCSCommandCVSExec', 'cvs') . ' status "' . realFileName . '"') + let statusText=s:VCSCommandUtility.system(s:Executable() . ' status -- "' . realFileName . '"') if(v:shell_error) return [] endif @@ -288,7 +303,7 @@ function! s:cvsFunctions.GetBufferInfo() " We can still be in a CVS-controlled directory without this being a CVS " file - if match(revision, '^New file!$') >= 0 + if match(revision, '^New file!$') >= 0 let revision='New' elseif match(revision, '^\d\+\.\d\+\%(\.\d\+\.\d\+\)*$') <0 return ['Unknown'] @@ -317,11 +332,7 @@ function! s:cvsFunctions.Log(argList) let caption = join(a:argList, ' ') endif - let resultBuffer=s:DoCommand(join(['log'] + options), 'log', caption, {}) - if resultBuffer > 0 - set filetype=rcslog - endif - return resultBuffer + return s:DoCommand(join(['log'] + options), 'log', caption, {}) endfunction " Function: s:cvsFunctions.Revert(argList) {{{2 @@ -339,11 +350,7 @@ function! s:cvsFunctions.Review(argList) let versionOption = ' -r ' . versiontag . ' ' endif - let resultBuffer = s:DoCommand('-q update -p' . versionOption, 'review', versiontag, {}) - if resultBuffer > 0 - let &filetype=getbufvar(b:VCSCommandOriginalBuffer, '&filetype') - endif - return resultBuffer + return s:DoCommand('-q update -p' . versionOption, 'review', versiontag, {}) endfunction " Function: s:cvsFunctions.Status(argList) {{{2 @@ -387,6 +394,9 @@ function! s:CVSWatchers() return s:DoCommand('watchers', 'cvswatchers', '', {}) endfunction +" Annotate setting {{{2 +let s:cvsFunctions.AnnotateSplitRegex = '): ' + " Section: Command definitions {{{1 " Section: Primary commands {{{2 com! CVSEdit call s:CVSEdit() @@ -402,36 +412,42 @@ com! CVSWatchers call s:CVSWatchers() " Section: Plugin command mappings {{{1 let s:cvsExtensionMappings = {} -let mappingInfo = [ - \['CVSEdit', 'CVSEdit', 'ce'], - \['CVSEditors', 'CVSEditors', 'cE'], - \['CVSUnedit', 'CVSUnedit', 'ct'], - \['CVSWatchers', 'CVSWatchers', 'cwv'], - \['CVSWatchAdd', 'CVSWatch add', 'cwa'], - \['CVSWatchOff', 'CVSWatch off', 'cwf'], - \['CVSWatchOn', 'CVSWatch on', 'cwn'], - \['CVSWatchRemove', 'CVSWatch remove', 'cwr'] - \] +if !exists("no_plugin_maps") + let mappingInfo = [ + \['CVSEdit', 'CVSEdit', 'e'], + \['CVSEditors', 'CVSEditors', 'E'], + \['CVSUnedit', 'CVSUnedit', 't'], + \['CVSWatchers', 'CVSWatchers', 'wv'], + \['CVSWatchAdd', 'CVSWatch add', 'wa'], + \['CVSWatchOff', 'CVSWatch off', 'wf'], + \['CVSWatchOn', 'CVSWatch on', 'wn'], + \['CVSWatchRemove', 'CVSWatch remove', 'wr'] + \] -for [pluginName, commandText, shortCut] in mappingInfo - execute 'nnoremap ' . pluginName . ' :' . commandText . '' - if !hasmapto('' . pluginName) - let s:cvsExtensionMappings[shortCut] = commandText - endif -endfor - -" Section: Menu items {{{1 -silent! aunmenu Plugin.VCS.CVS -amenu &Plugin.VCS.CVS.&Edit CVSEdit -amenu &Plugin.VCS.CVS.Ed&itors CVSEditors -amenu &Plugin.VCS.CVS.Unedi&t CVSUnedit -amenu &Plugin.VCS.CVS.&Watchers CVSWatchers -amenu &Plugin.VCS.CVS.WatchAdd CVSWatchAdd -amenu &Plugin.VCS.CVS.WatchOn CVSWatchOn -amenu &Plugin.VCS.CVS.WatchOff CVSWatchOff -amenu &Plugin.VCS.CVS.WatchRemove CVSWatchRemove + for [pluginName, commandText, shortCut] in mappingInfo + execute 'nnoremap ' . pluginName . ' :' . commandText . '' + if !hasmapto('' . pluginName) + let s:cvsExtensionMappings[shortCut] = commandText + endif + endfor +endif " Section: Plugin Registration {{{1 -call VCSCommandRegisterModule('CVS', expand(''), s:cvsFunctions, s:cvsExtensionMappings) +let s:VCSCommandUtility = VCSCommandRegisterModule('CVS', expand(''), s:cvsFunctions, s:cvsExtensionMappings) + +" Section: Menu items {{{1 +for [s:shortcut, s:command] in [ + \['CVS.&Edit', 'CVSEdit'], + \['CVS.Ed&itors', 'CVSEditors'], + \['CVS.Unedi&t', 'CVSUnedit'], + \['CVS.&Watchers', 'CVSWatchers'], + \['CVS.WatchAdd', 'CVSWatchAdd'], + \['CVS.WatchOn', 'CVSWatchOn'], + \['CVS.WatchOff', 'CVSWatchOff'], + \['CVS.WatchRemove', 'CVSWatchRemove'] + \] + call s:VCSCommandUtility.addMenuItem(s:shortcut, s:command) +endfor +unlet s:shortcut s:command let &cpo = s:save_cpo diff --git a/.vim/plugin/vcsgit.vim b/.vim/plugin/vcsgit.vim index 6508806..2667982 100755 --- a/.vim/plugin/vcsgit.vim +++ b/.vim/plugin/vcsgit.vim @@ -2,10 +2,9 @@ " " git extension for VCSCommand. " -" Version: VCS development " Maintainer: Bob Hiestand " License: -" Copyright (c) 2008 Bob Hiestand +" Copyright (c) Bob Hiestand " " Permission is hereby granted, free of charge, to any person obtaining a copy " of this software and associated documentation files (the "Software"), to @@ -40,12 +39,18 @@ " Section: Plugin header {{{1 +if exists('VCSCommandDisableAll') + finish +endif + if v:version < 700 echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None finish endif -runtime plugin/vcscommand.vim +if !exists('g:loaded_VCSCommand') + runtime plugin/vcscommand.vim +endif if !executable(VCSCommandGetOption('VCSCommandGitExec', 'git')) " git is not installed @@ -61,12 +66,19 @@ let s:gitFunctions = {} " Section: Utility functions {{{1 +" Function: s:Executable() {{{2 +" Returns the executable used to invoke git suitable for use in a shell +" command. +function! s:Executable() + return VCSCommandGetOption('VCSCommandGitExec', 'git') +endfunction + " Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 " Wrapper to VCSCommandDoCommand to add the name of the git executable to the " command argument. function! s:DoCommand(cmd, cmdName, statusText, options) if VCSCommandGetVCSType(expand('%')) == 'git' - let fullCmd = VCSCommandGetOption('VCSCommandGitExec', 'git',) . ' ' . a:cmd + let fullCmd = s:Executable() . ' ' . a:cmd return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) else throw 'git VCSCommand plugin called on non-git item.' @@ -81,7 +93,7 @@ endfunction function! s:gitFunctions.Identify(buffer) let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(a:buffer))) try - call system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' rev-parse --is-inside-work-tree') + call s:VCSCommandUtility.system(s:Executable() . ' rev-parse --is-inside-work-tree') if(v:shell_error) return 0 else @@ -100,7 +112,7 @@ endfunction " Function: s:gitFunctions.Annotate(argList) {{{2 function! s:gitFunctions.Annotate(argList) if len(a:argList) == 0 - if &filetype == 'gitAnnotate' + if &filetype == 'gitannotate' " Perform annotation of the version indicated by the current line. let options = matchstr(getline('.'),'^\x\+') else @@ -112,21 +124,16 @@ function! s:gitFunctions.Annotate(argList) let options = join(a:argList, ' ') endif - let resultBuffer = s:DoCommand('blame ' . options . ' -- ', 'annotate', options, {}) - if resultBuffer > 0 - normal 1G - set filetype=gitAnnotate - endif - return resultBuffer + return s:DoCommand('blame ' . options, 'annotate', options, {}) endfunction " Function: s:gitFunctions.Commit(argList) {{{2 function! s:gitFunctions.Commit(argList) - let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {}) - if resultBuffer == 0 + try + return s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {}) + catch /\m^Version control command failed.*nothing\%( added\)\? to commit/ echomsg 'No commit needed.' - endif - return resultBuffer + endtry endfunction " Function: s:gitFunctions.Delete() {{{2 @@ -154,13 +161,7 @@ function! s:gitFunctions.Diff(argList) endfor endif - let resultBuffer = s:DoCommand(join(['diff'] + diffOptions + a:argList), 'diff', join(a:argList), {}) - if resultBuffer > 0 - set filetype=diff - else - echomsg 'No differences found' - endif - return resultBuffer + return s:DoCommand(join(['diff'] + diffOptions + a:argList), 'diff', join(a:argList), {}) endfunction " Function: s:gitFunctions.GetBufferInfo() {{{2 @@ -173,7 +174,7 @@ endfunction function! s:gitFunctions.GetBufferInfo() let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname('%'))) try - let branch = substitute(system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' symbolic-ref -q HEAD'), '\n$', '', '') + let branch = substitute(s:VCSCommandUtility.system(s:Executable() . ' symbolic-ref -q HEAD'), '\n$', '', '') if v:shell_error let branch = 'DETACHED' else @@ -186,7 +187,7 @@ function! s:gitFunctions.GetBufferInfo() if method != '' let method = ' --' . method endif - let tag = substitute(system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' describe' . method), '\n$', '', '') + let tag = substitute(s:VCSCommandUtility.system(s:Executable() . ' describe' . method), '\n$', '', '') if !v:shell_error call add(info, tag) break @@ -201,11 +202,7 @@ endfunction " Function: s:gitFunctions.Log() {{{2 function! s:gitFunctions.Log(argList) - let resultBuffer=s:DoCommand(join(['log'] + a:argList), 'log', join(a:argList, ' '), {}) - if resultBuffer > 0 - set filetype=gitlog - endif - return resultBuffer + return s:DoCommand(join(['log'] + a:argList), 'log', join(a:argList, ' '), {}) endfunction " Function: s:gitFunctions.Revert(argList) {{{2 @@ -223,18 +220,14 @@ function! s:gitFunctions.Review(argList) let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(VCSCommandGetOriginalBuffer('%')))) try - let prefix = system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' rev-parse --show-prefix') + let prefix = s:VCSCommandUtility.system(s:Executable() . ' rev-parse --show-prefix') finally call VCSCommandChdir(oldCwd) endtry let prefix = substitute(prefix, '\n$', '', '') let blob = '"' . revision . ':' . prefix . '"' - let resultBuffer = s:DoCommand('show ' . blob, 'review', revision, {}) - if resultBuffer > 0 - let &filetype=getbufvar(b:VCSCommandOriginalBuffer, '&filetype') - endif - return resultBuffer + return s:DoCommand('show ' . blob, 'review', revision, {}) endfunction " Function: s:gitFunctions.Status(argList) {{{2 @@ -247,8 +240,10 @@ function! s:gitFunctions.Update(argList) throw "This command is not implemented for git because file-by-file update doesn't make much sense in that context. If you have an idea for what it should do, please let me know." endfunction +" Annotate setting {{{2 +let s:gitFunctions.AnnotateSplitRegex = ') ' " Section: Plugin Registration {{{1 -call VCSCommandRegisterModule('git', expand(''), s:gitFunctions, []) +let s:VCSCommandUtility = VCSCommandRegisterModule('git', expand(''), s:gitFunctions, []) let &cpo = s:save_cpo diff --git a/.vim/plugin/vcshg.vim b/.vim/plugin/vcshg.vim new file mode 100644 index 0000000..775ede0 --- /dev/null +++ b/.vim/plugin/vcshg.vim @@ -0,0 +1,275 @@ +" vim600: set foldmethod=marker: +" +" Mercurial extension for VCSCommand. +" +" Maintainer: Bob Hiestand +" License: +" Copyright (c) Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. +" +" Section: Documentation {{{1 +" +" Options documentation: {{{2 +" +" VCSCommandHGExec +" This variable specifies the mercurial executable. If not set, it defaults +" to 'hg' executed from the user's executable path. +" +" VCSCommandHGDiffExt +" This variable, if set, sets the external diff program used by Subversion. +" +" VCSCommandHGDiffOpt +" This variable, if set, determines the options passed to the hg diff +" command (such as 'u', 'w', or 'b'). + +" Section: Plugin header {{{1 + +if exists('VCSCommandDisableAll') + finish +endif + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +if !exists('g:loaded_VCSCommand') + runtime plugin/vcscommand.vim +endif + +if !executable(VCSCommandGetOption('VCSCommandHGExec', 'hg')) + " HG is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:hgFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:Executable() {{{2 +" Returns the executable used to invoke hg suitable for use in a shell +" command. +function! s:Executable() + return VCSCommandGetOption('VCSCommandHGExec', 'hg') +endfunction + +" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the HG executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'HG' + let fullCmd = s:Executable() . ' ' . a:cmd + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'HG VCSCommand plugin called on non-HG item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:hgFunctions.Identify(buffer) {{{2 +function! s:hgFunctions.Identify(buffer) + let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(a:buffer))) + try + call s:VCSCommandUtility.system(s:Executable() . ' root') + if(v:shell_error) + return 0 + else + return g:VCSCOMMAND_IDENTIFY_INEXACT + endif + finally + call VCSCommandChdir(oldCwd) + endtry +endfunction + +" Function: s:hgFunctions.Add() {{{2 +function! s:hgFunctions.Add(argList) + return s:DoCommand(join(['add -v'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:hgFunctions.Annotate(argList) {{{2 +function! s:hgFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype ==? 'hgannotate' + " Perform annotation of the version indicated by the current line. + let caption = matchstr(getline('.'),'\v^\s*\w+\s+\zs\d+') + let options = ' -un -r' . caption + else + let caption = '' + let options = ' -un' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let caption = a:argList[0] + let options = ' -un -r' . caption + else + let caption = join(a:argList, ' ') + let options = ' ' . caption + endif + + return s:DoCommand('blame' . options, 'annotate', caption, {}) +endfunction + +" Function: s:hgFunctions.Commit(argList) {{{2 +function! s:hgFunctions.Commit(argList) + try + return s:DoCommand('commit -v -l "' . a:argList[0] . '"', 'commit', '', {}) + catch /Version control command failed.*nothing changed/ + echomsg 'No commit needed.' + endtry +endfunction + +" Function: s:hgFunctions.Delete() {{{2 +function! s:hgFunctions.Delete(argList) + return s:DoCommand(join(['remove'] + a:argList, ' '), 'remove', join(a:argList, ' '), {}) +endfunction + +" Function: s:hgFunctions.Diff(argList) {{{2 +function! s:hgFunctions.Diff(argList) + if len(a:argList) == 0 + let revOptions = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let revOptions = ['-r' . join(a:argList, ':')] + let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')' + else + " Pass-through + let caption = join(a:argList, ' ') + let revOptions = a:argList + endif + + let hgDiffExt = VCSCommandGetOption('VCSCommandHGDiffExt', '') + if hgDiffExt == '' + let diffExt = [] + else + let diffExt = ['--diff-cmd ' . hgDiffExt] + endif + + let hgDiffOpt = VCSCommandGetOption('VCSCommandHGDiffOpt', '') + if hgDiffOpt == '' + let diffOptions = [] + else + let diffOptions = ['-x -' . hgDiffOpt] + endif + + return s:DoCommand(join(['diff'] + diffExt + diffOptions + revOptions), 'diff', caption, {}) +endfunction + +" Function: s:hgFunctions.Info(argList) {{{2 +function! s:hgFunctions.Info(argList) + return s:DoCommand(join(['log --limit 1'] + a:argList, ' '), 'log', join(a:argList, ' '), {}) +endfunction + +" Function: s:hgFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. +" Returns: List of results: [revision, repository, branch] + +function! s:hgFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = bufname(originalBuffer) + let statusText = s:VCSCommandUtility.system(s:Executable() . ' status -- "' . fileName . '"') + if(v:shell_error) + return [] + endif + + " File not under HG control. + if statusText =~ '^?' + return ['Unknown'] + endif + + let parentsText = s:VCSCommandUtility.system(s:Executable() . ' parents -- "' . fileName . '"') + let revision = matchlist(parentsText, '^changeset:\s\+\(\S\+\)\n')[1] + + let logText = s:VCSCommandUtility.system(s:Executable() . ' log -- "' . fileName . '"') + let repository = matchlist(logText, '^changeset:\s\+\(\S\+\)\n')[1] + + if revision == '' + " Error + return ['Unknown'] + elseif statusText =~ '^A' + return ['New', 'New'] + else + return [revision, repository] + endif +endfunction + +" Function: s:hgFunctions.Log(argList) {{{2 +function! s:hgFunctions.Log(argList) + if len(a:argList) == 0 + let options = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let options = ['-r' . join(a:argList, ':')] + let caption = options[0] + else + " Pass-through + let options = a:argList + let caption = join(a:argList, ' ') + endif + + let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {}) + return resultBuffer +endfunction + +" Function: s:hgFunctions.Revert(argList) {{{2 +function! s:hgFunctions.Revert(argList) + return s:DoCommand('revert', 'revert', '', {}) +endfunction + +" Function: s:hgFunctions.Review(argList) {{{2 +function! s:hgFunctions.Review(argList) + if len(a:argList) == 0 + let versiontag = '(current)' + let versionOption = '' + else + let versiontag = a:argList[0] + let versionOption = ' -r ' . versiontag . ' ' + endif + + return s:DoCommand('cat' . versionOption, 'review', versiontag, {}) +endfunction + +" Function: s:hgFunctions.Status(argList) {{{2 +function! s:hgFunctions.Status(argList) + let options = ['-A', '-v'] + if len(a:argList) != 0 + let options = a:argList + endif + return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {}) +endfunction + +" Function: s:hgFunctions.Update(argList) {{{2 +function! s:hgFunctions.Update(argList) + return s:DoCommand('update', 'update', '', {}) +endfunction + +" Annotate setting {{{2 +let s:hgFunctions.AnnotateSplitRegex = '\d\+: ' + +" Section: Plugin Registration {{{1 +let s:VCSCommandUtility = VCSCommandRegisterModule('HG', expand(''), s:hgFunctions, []) + +let &cpo = s:save_cpo diff --git a/.vim/plugin/vcssvk.vim b/.vim/plugin/vcssvk.vim index 116f953..bee84c3 100644 --- a/.vim/plugin/vcssvk.vim +++ b/.vim/plugin/vcssvk.vim @@ -2,10 +2,9 @@ " " SVK extension for VCSCommand. " -" Version: VCS development " Maintainer: Bob Hiestand " License: -" Copyright (c) 2007 Bob Hiestand +" Copyright (c) Bob Hiestand " " Permission is hereby granted, free of charge, to any person obtaining a copy " of this software and associated documentation files (the "Software"), to @@ -35,12 +34,18 @@ " Section: Plugin header {{{1 +if exists('VCSCommandDisableAll') + finish +endif + if v:version < 700 echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None finish endif -runtime plugin/vcscommand.vim +if !exists('g:loaded_VCSCommand') + runtime plugin/vcscommand.vim +endif if !executable(VCSCommandGetOption('VCSCommandSVKExec', 'svk')) " SVK is not installed @@ -56,12 +61,19 @@ let s:svkFunctions = {} " Section: Utility functions {{{1 +" Function: s:Executable() {{{2 +" Returns the executable used to invoke SVK suitable for use in a shell +" command. +function! s:Executable() + return VCSCommandGetOption('VCSCommandSVKExec', 'svk') +endfunction + " Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 " Wrapper to VCSCommandDoCommand to add the name of the SVK executable to the " command argument. function! s:DoCommand(cmd, cmdName, statusText, options) if VCSCommandGetVCSType(expand('%')) == 'SVK' - let fullCmd = VCSCommandGetOption('VCSCommandSVKExec', 'svk') . ' ' . a:cmd + let fullCmd = s:Executable() . ' ' . a:cmd return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) else throw 'SVK VCSCommand plugin called on non-SVK item.' @@ -78,7 +90,7 @@ function! s:svkFunctions.Identify(buffer) else let directoryName = fnamemodify(fileName, ':p:h') endif - let statusText = system(VCSCommandGetOption('VCSCommandSVKExec', 'svk') . ' info "' . directoryName . '"') + let statusText = s:VCSCommandUtility.system(s:Executable() . ' info -- "' . directoryName . '"', "no") if(v:shell_error) return 0 else @@ -94,7 +106,7 @@ endfunction " Function: s:svkFunctions.Annotate(argList) {{{2 function! s:svkFunctions.Annotate(argList) if len(a:argList) == 0 - if &filetype == 'SVKAnnotate' + if &filetype ==? 'svkannotate' " Perform annotation of the version indicated by the current line. let caption = matchstr(getline('.'),'\v^\s+\zs\d+') let options = ' -r' . caption @@ -112,8 +124,7 @@ function! s:svkFunctions.Annotate(argList) let resultBuffer = s:DoCommand('blame' . options, 'annotate', caption, {}) if resultBuffer > 0 - normal 1G2dd - set filetype=SVKAnnotate + normal! 1G2dd endif return resultBuffer endfunction @@ -134,7 +145,7 @@ endfunction " Function: s:svkFunctions.Diff(argList) {{{2 function! s:svkFunctions.Diff(argList) if len(a:argList) == 0 - let revOptions = [] + let revOptions = [] let caption = '' elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 let revOptions = ['-r' . join(a:argList, ':')] @@ -145,13 +156,7 @@ function! s:svkFunctions.Diff(argList) let revOptions = a:argList endif - let resultBuffer = s:DoCommand(join(['diff'] + revOptions), 'diff', caption, {}) - if resultBuffer > 0 - set filetype=diff - else - echomsg 'No differences found' - endif - return resultBuffer + return s:DoCommand(join(['diff'] + revOptions), 'diff', caption, {}) endfunction " Function: s:svkFunctions.GetBufferInfo() {{{2 @@ -163,7 +168,7 @@ endfunction function! s:svkFunctions.GetBufferInfo() let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) let fileName = resolve(bufname(originalBuffer)) - let statusText = system(VCSCommandGetOption('VCSCommandSVKExec', 'svk') . ' status -v "' . fileName . '"') + let statusText = s:VCSCommandUtility.system(s:Executable() . ' status -v -- "' . fileName . '"') if(v:shell_error) return [] endif @@ -227,17 +232,13 @@ function! s:svkFunctions.Review(argList) let versionOption = ' -r ' . versiontag . ' ' endif - let resultBuffer = s:DoCommand('cat' . versionOption, 'review', versiontag, {}) - if resultBuffer > 0 - let &filetype=getbufvar(b:VCSCommandOriginalBuffer, '&filetype') - endif - return resultBuffer + return s:DoCommand('cat' . versionOption, 'review', versiontag, {}) endfunction " Function: s:svkFunctions.Status(argList) {{{2 function! s:svkFunctions.Status(argList) let options = ['-v'] - if len(a:argList) == 0 + if len(a:argList) != 0 let options = a:argList endif return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {}) @@ -253,6 +254,6 @@ function! s:svkFunctions.Update(argList) endfunction " Section: Plugin Registration {{{1 -call VCSCommandRegisterModule('SVK', expand(''), s:svkFunctions, []) +let s:VCSCommandUtility = VCSCommandRegisterModule('SVK', expand(''), s:svkFunctions, []) let &cpo = s:save_cpo diff --git a/.vim/plugin/vcssvn.vim b/.vim/plugin/vcssvn.vim index 97bcbd5..8ad6388 100644 --- a/.vim/plugin/vcssvn.vim +++ b/.vim/plugin/vcssvn.vim @@ -2,10 +2,9 @@ " " SVN extension for VCSCommand. " -" Version: VCS development " Maintainer: Bob Hiestand " License: -" Copyright (c) 2007 Bob Hiestand +" Copyright (c) Bob Hiestand " " Permission is hereby granted, free of charge, to any person obtaining a copy " of this software and associated documentation files (the "Software"), to @@ -42,12 +41,18 @@ " Section: Plugin header {{{1 +if exists('VCSCommandDisableAll') + finish +endif + if v:version < 700 echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None finish endif -runtime plugin/vcscommand.vim +if !exists('g:loaded_VCSCommand') + runtime plugin/vcscommand.vim +endif if !executable(VCSCommandGetOption('VCSCommandSVNExec', 'svn')) " SVN is not installed @@ -63,12 +68,19 @@ let s:svnFunctions = {} " Section: Utility functions {{{1 +" Function: s:Executable() {{{2 +" Returns the executable used to invoke git suitable for use in a shell +" command. +function! s:Executable() + return VCSCommandGetOption('VCSCommandSVNExec', 'svn') +endfunction + " Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 " Wrapper to VCSCommandDoCommand to add the name of the SVN executable to the " command argument. function! s:DoCommand(cmd, cmdName, statusText, options) if VCSCommandGetVCSType(expand('%')) == 'SVN' - let fullCmd = VCSCommandGetOption('VCSCommandSVNExec', 'svn') . ' ' . a:cmd + let fullCmd = s:Executable() . ' ' . a:cmd return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) else throw 'SVN VCSCommand plugin called on non-SVN item.' @@ -79,22 +91,17 @@ endfunction " Function: s:svnFunctions.Identify(buffer) {{{2 function! s:svnFunctions.Identify(buffer) - let fileName = resolve(bufname(a:buffer)) - if isdirectory(fileName) - let directoryName = fileName - else - let directoryName = fnamemodify(fileName, ':h') - endif - if strlen(directoryName) > 0 - let svnDir = directoryName . '/.svn' - else - let svnDir = '.svn' - endif - if isdirectory(svnDir) - return 1 - else - return 0 - endif + let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(a:buffer))) + try + call s:VCSCommandUtility.system(s:Executable() . ' info .') + if(v:shell_error) + return 0 + else + return g:VCSCOMMAND_IDENTIFY_EXACT + endif + finally + call VCSCommandChdir(oldCwd) + endtry endfunction " Function: s:svnFunctions.Add() {{{2 @@ -105,7 +112,7 @@ endfunction " Function: s:svnFunctions.Annotate(argList) {{{2 function! s:svnFunctions.Annotate(argList) if len(a:argList) == 0 - if &filetype == 'SVNAnnotate' + if &filetype ==? 'svnannotate' " Perform annotation of the version indicated by the current line. let caption = matchstr(getline('.'),'\v^\s+\zs\d+') let options = ' -r' . caption @@ -121,16 +128,12 @@ function! s:svnFunctions.Annotate(argList) let options = ' ' . caption endif - let resultBuffer = s:DoCommand('blame' . options, 'annotate', caption, {}) - if resultBuffer > 0 - set filetype=SVNAnnotate - endif - return resultBuffer + return s:DoCommand('blame --non-interactive' . options, 'annotate', caption, {}) endfunction " Function: s:svnFunctions.Commit(argList) {{{2 function! s:svnFunctions.Commit(argList) - let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {}) + let resultBuffer = s:DoCommand('commit --non-interactive -F "' . a:argList[0] . '"', 'commit', '', {}) if resultBuffer == 0 echomsg 'No commit needed.' endif @@ -138,13 +141,13 @@ endfunction " Function: s:svnFunctions.Delete() {{{2 function! s:svnFunctions.Delete(argList) - return s:DoCommand(join(['delete'] + a:argList, ' '), 'delete', join(a:argList, ' '), {}) + return s:DoCommand(join(['delete --non-interactive'] + a:argList, ' '), 'delete', join(a:argList, ' '), {}) endfunction " Function: s:svnFunctions.Diff(argList) {{{2 function! s:svnFunctions.Diff(argList) if len(a:argList) == 0 - let revOptions = [] + let revOptions = [] let caption = '' elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 let revOptions = ['-r' . join(a:argList, ':')] @@ -169,15 +172,7 @@ function! s:svnFunctions.Diff(argList) let diffOptions = ['-x -' . svnDiffOpt] endif - let resultBuffer = s:DoCommand(join(['diff'] + diffExt + diffOptions + revOptions), 'diff', caption, {}) - if resultBuffer > 0 - set filetype=diff - else - if svnDiffExt == '' - echomsg 'No differences found' - endif - endif - return resultBuffer + return s:DoCommand(join(['diff --non-interactive'] + diffExt + diffOptions + revOptions), 'diff', caption, {}) endfunction " Function: s:svnFunctions.GetBufferInfo() {{{2 @@ -189,7 +184,7 @@ endfunction function! s:svnFunctions.GetBufferInfo() let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) let fileName = bufname(originalBuffer) - let statusText = system(VCSCommandGetOption('VCSCommandSVNExec', 'svn') . ' status -vu "' . fileName . '"') + let statusText = s:VCSCommandUtility.system(s:Executable() . ' status --non-interactive -v -- "' . fileName . '"') if(v:shell_error) return [] endif @@ -199,12 +194,14 @@ function! s:svnFunctions.GetBufferInfo() return ['Unknown'] endif - let [flags, revision, repository] = matchlist(statusText, '^\(.\{8}\)\s\+\(\S\+\)\s\+\(\S\+\)\s\+\(\S\+\)\s')[1:3] + let [flags, revision, repository] = matchlist(statusText, '^\(.\{9}\)\s*\(\d\+\)\s\+\(\d\+\)')[1:3] if revision == '' " Error return ['Unknown'] elseif flags =~ '^A' return ['New', 'New'] + elseif flags =~ '*' + return [revision, repository, '*'] else return [revision, repository] endif @@ -212,12 +209,12 @@ endfunction " Function: s:svnFunctions.Info(argList) {{{2 function! s:svnFunctions.Info(argList) - return s:DoCommand(join(['info'] + a:argList, ' '), 'info', join(a:argList, ' '), {}) + return s:DoCommand(join(['info --non-interactive'] + a:argList, ' '), 'info', join(a:argList, ' '), {}) endfunction " Function: s:svnFunctions.Lock(argList) {{{2 function! s:svnFunctions.Lock(argList) - return s:DoCommand(join(['lock'] + a:argList, ' '), 'lock', join(a:argList, ' '), {}) + return s:DoCommand(join(['lock --non-interactive'] + a:argList, ' '), 'lock', join(a:argList, ' '), {}) endfunction " Function: s:svnFunctions.Log(argList) {{{2 @@ -234,7 +231,7 @@ function! s:svnFunctions.Log(argList) let caption = join(a:argList, ' ') endif - let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {}) + let resultBuffer = s:DoCommand(join(['log --non-interactive', '-v'] + options), 'log', caption, {}) return resultBuffer endfunction @@ -253,32 +250,32 @@ function! s:svnFunctions.Review(argList) let versionOption = ' -r ' . versiontag . ' ' endif - let resultBuffer = s:DoCommand('cat' . versionOption, 'review', versiontag, {}) - if resultBuffer > 0 - let &filetype = getbufvar(b:VCSCommandOriginalBuffer, '&filetype') - endif - return resultBuffer + return s:DoCommand('cat --non-interactive' . versionOption, 'review', versiontag, {}) endfunction " Function: s:svnFunctions.Status(argList) {{{2 function! s:svnFunctions.Status(argList) let options = ['-u', '-v'] - if len(a:argList) == 0 + if len(a:argList) != 0 let options = a:argList endif - return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {}) + return s:DoCommand(join(['status --non-interactive'] + options, ' '), 'status', join(options, ' '), {}) endfunction " Function: s:svnFunctions.Unlock(argList) {{{2 function! s:svnFunctions.Unlock(argList) - return s:DoCommand(join(['unlock'] + a:argList, ' '), 'unlock', join(a:argList, ' '), {}) + return s:DoCommand(join(['unlock --non-interactive'] + a:argList, ' '), 'unlock', join(a:argList, ' '), {}) endfunction + " Function: s:svnFunctions.Update(argList) {{{2 function! s:svnFunctions.Update(argList) - return s:DoCommand('update', 'update', '', {}) + return s:DoCommand('update --non-interactive', 'update', '', {}) endfunction +" Annotate setting {{{2 +let s:svnFunctions.AnnotateSplitRegex = '\s\+\S\+\s\+\S\+ ' + " Section: Plugin Registration {{{1 -call VCSCommandRegisterModule('SVN', expand(''), s:svnFunctions, []) +let s:VCSCommandUtility = VCSCommandRegisterModule('SVN', expand(''), s:svnFunctions, []) let &cpo = s:save_cpo diff --git a/.vim/syntax/cvsannotate.vim b/.vim/syntax/cvsannotate.vim new file mode 100644 index 0000000..f35ed96 --- /dev/null +++ b/.vim/syntax/cvsannotate.vim @@ -0,0 +1,45 @@ +" Vim syntax file +" Language: CVS annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the cvscommand plugin. Originally written by Mathieu +" Clabaut +" License: +" Copyright (c) Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if version < 600 + syntax clear +elseif exists("b:current_syntax") + finish +endif + +syn match cvsDate /\d\d-...-\d\d/ contained +syn match cvsName /(\S* /hs=s+1,he=e-1 contained nextgroup=cvsDate +syn match cvsVer /^\d\+\(\.\d\+\)\+/ contained nextgroup=cvsName +syn region cvsHead start="^\d\+\.\d\+" end="):" contains=cvsVer,cvsName,cvsDate + +if !exists("did_cvsannotate_syntax_inits") + let did_cvsannotate_syntax_inits = 1 + hi link cvsDate Comment + hi link cvsName Type + hi link cvsVer Statement +endif + +let b:current_syntax="CVSAnnotate" diff --git a/.vim/syntax/gitannotate.vim b/.vim/syntax/gitannotate.vim new file mode 100644 index 0000000..77ad14e --- /dev/null +++ b/.vim/syntax/gitannotate.vim @@ -0,0 +1,44 @@ +" Vim syntax file +" Language: git annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the vcscommand plugin. +" License: +" Copyright (c) Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if exists("b:current_syntax") + finish +endif + +syn region gitName start="(\@<=" end="\( \d\d\d\d-\)\@=" contained +syn match gitCommit /^\^\?\x\+/ contained +syn match gitDate /\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d/ contained +syn match gitLineNumber /\d\+)\@=/ contained +syn region gitAnnotation start="^" end=") " oneline keepend contains=gitCommit,gitLineNumber,gitDate,gitName + +if !exists("did_gitannotate_syntax_inits") + let did_gitannotate_syntax_inits = 1 + hi link gitName Type + hi link gitCommit Statement + hi link gitDate Comment + hi link gitLineNumber Label +endif + +let b:current_syntax="gitAnnotate" diff --git a/.vim/syntax/hgannotate.vim b/.vim/syntax/hgannotate.vim new file mode 100644 index 0000000..4e1d627 --- /dev/null +++ b/.vim/syntax/hgannotate.vim @@ -0,0 +1,40 @@ +" Vim syntax file +" Language: HG annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the vcscommand plugin. +" License: +" Copyright (c) Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if exists("b:current_syntax") + finish +endif + +syn match hgVer /\d\+/ contained +syn match hgName /^\s*\S\+/ contained +syn match hgHead /^\s*\S\+\s\+\d\+:/ contains=hgVer,hgName + +if !exists("did_hgannotate_syntax_inits") + let did_hgannotate_syntax_inits = 1 + hi link hgName Type + hi link hgVer Statement +endif + +let b:current_syntax="hgAnnotate" diff --git a/.vim/syntax/svkannotate.vim b/.vim/syntax/svkannotate.vim new file mode 100644 index 0000000..d93e9dd --- /dev/null +++ b/.vim/syntax/svkannotate.vim @@ -0,0 +1,42 @@ +" Vim syntax file +" Language: SVK annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the vcscommand plugin. +" License: +" Copyright (c) Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if exists("b:current_syntax") + finish +endif + +syn match svkDate /\d\{4}-\d\{1,2}-\d\{1,2}/ skipwhite contained +syn match svkName /(\s*\zs\S\+/ contained nextgroup=svkDate skipwhite +syn match svkVer /^\s*\d\+/ contained nextgroup=svkName skipwhite +syn region svkHead start=/^/ end="):" contains=svkVer,svkName,svkDate oneline + +if !exists("did_svkannotate_syntax_inits") + let did_svkannotate_syntax_inits = 1 + hi link svkName Type + hi link svkDate Comment + hi link svkVer Statement +endif + +let b:current_syntax="svkAnnotate" diff --git a/.vim/syntax/svnannotate.vim b/.vim/syntax/svnannotate.vim new file mode 100644 index 0000000..87a63ab --- /dev/null +++ b/.vim/syntax/svnannotate.vim @@ -0,0 +1,40 @@ +" Vim syntax file +" Language: SVN annotate output +" Maintainer: Bob Hiestand +" Remark: Used by the vcscommand plugin. +" License: +" Copyright (c) Bob Hiestand +" +" Permission is hereby granted, free of charge, to any person obtaining a copy +" of this software and associated documentation files (the "Software"), to +" deal in the Software without restriction, including without limitation the +" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +" sell copies of the Software, and to permit persons to whom the Software is +" furnished to do so, subject to the following conditions: +" +" The above copyright notice and this permission notice shall be included in +" all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +" IN THE SOFTWARE. + +if exists("b:current_syntax") + finish +endif + +syn match svnName /\S\+/ contained +syn match svnVer /^\s*\zs\d\+/ contained nextgroup=svnName skipwhite +syn match svnHead /^\s*\d\+\s\+\S\+/ contains=svnVer,svnName + +if !exists("did_svnannotate_syntax_inits") + let did_svnannotate_syntax_inits = 1 + hi link svnName Type + hi link svnVer Statement +endif + +let b:current_syntax="svnAnnotate" diff --git a/.vim/syntax/vcscommit.vim b/.vim/syntax/vcscommit.vim index 0cd4c5e..80b4c6e 100644 --- a/.vim/syntax/vcscommit.vim +++ b/.vim/syntax/vcscommit.vim @@ -2,7 +2,7 @@ " Language: VCS commit file " Maintainer: Bob Hiestand (bob.hiestand@gmail.com) " License: -" Copyright (c) 2007 Bob Hiestand +" Copyright (c) Bob Hiestand " " Permission is hereby granted, free of charge, to any person obtaining a copy " of this software and associated documentation files (the "Software"), to