From: Iain Patterson Date: Thu, 9 Jul 2009 10:42:35 +0000 (+0100) Subject: VCSCommand plugins. X-Git-Url: http://git.iain.cx/?p=profile.git;a=commitdiff_plain;h=5010bd4c510f58dbc1e85e4a230c44304964c42b VCSCommand plugins. --- diff --git a/.vim/doc/vcscommand.txt b/.vim/doc/vcscommand.txt new file mode 100644 index 0000000..eaee014 --- /dev/null +++ b/.vim/doc/vcscommand.txt @@ -0,0 +1,814 @@ +*vcscommand.txt* vcscommand +Copyright (c) 2007 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. + +For instructions on installing this file, type + :help add-local-help +inside Vim. + +Author: Bob Hiestand +Credits: Benji Fisher's excellent MatchIt documentation + +============================================================================== +1. Contents *vcscommand-contents* + + Installation : |vcscommand-install| + vcscommand Intro : |vcscommand| + vcscommand Manual : |vcscommand-manual| + Customization : |vcscommand-customize| + SSH "integration" : |vcscommand-ssh| + Changes from cvscommand : |cvscommand-changes| + Bugs : |vcscommand-bugs| + +============================================================================== + +2. vcscommand Installation *vcscommand-install* + +The vcscommand plugin comprises five files: vcscommand.vim, vcssvn.vim, +vcscvs.vim, vcssvk.vim and vcscommand.txt (this file). In order to install +the plugin, place the vcscommand.vim, vcssvn.vim, vcssvk.vim, and vcscvs.vim +files into a plugin directory in your runtime path (please see +|add-global-plugin| and |'runtimepath'|. + +This help file can be included in the VIM help system by copying it into a +'doc' directory in your runtime path and then executing the |:helptags| +command, specifying the full path of the 'doc' directory. Please see +|add-local-help| for more details. + +vcscommand may be customized by setting variables, creating maps, and +specifying event handlers. Please see |vcscommand-customize| for more +details. + +============================================================================== + +3. vcscommand Intro *vcscommand* + *vcscommand-intro* + +The vcscommand plugin provides global ex commands for manipulating +version-controlled source files, currently those controlled either by CVS or +Subversion. In general, each command operates on the current buffer and +accomplishes a separate source control function, such as update, commit, log, +and others (please see |vcscommand-commands| for a list of all available +commands). The results of each operation are displayed in a scratch buffer. +Several buffer variables are defined for those scratch buffers (please see +|vcscommand-buffer-variables|). + +The notion of "current file" means either the current buffer, or, in the case +of a directory buffer (such as Explorer or netrw buffers), the directory (and +all subdirectories) represented by the the buffer. + +For convenience, any vcscommand invoked on a vcscommand scratch buffer acts as +though it was invoked on the original file and splits the screen so that the +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 +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 +|vcscommand-mappings-override|. + +The vcscommand plugin may be configured in several ways. For more details, +please see |vcscommand-customize|. + +============================================================================== + +4. vcscommand Manual *vcscommand-manual* + +4.1 vcscommand commands *vcscommand-commands* + +vcscommand defines the following commands: + +|:VCSAdd| +|:VCSAnnotate| +|:VCSBlame| +|:VCSCommit| +|:VCSDelete| +|:VCSDiff| +|:VCSGotoOriginal| +|:VCSLog| +|:VCSRemove| +|:VCSRevert| +|:VCSReview| +|:VCSStatus| +|:VCSUpdate| +|:VCSVimDiff| + +The following commands are specific to CVS files: + +|:CVSEdit| +|:CVSEditors| +|:CVSUnedit| +|:CVSWatch| +|:CVSWatchAdd| +|:CVSWatchOn| +|:CVSWatchOff| +|:CVSWatchRemove| +|:CVSWatchers| + +:VCSAdd *:VCSAdd* + +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* + +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 +argument is used as a revision number to display. If not given an argument, +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. + +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. + +:VCSBlame *:VCSBlame* + +Alias for |:VCSAnnotate|. + +:VCSCommit[!] *:VCSCommit* + +This command commits changes to the current file to source control. + +If called with arguments, the arguments are the log message. + +If '!' is used, an empty log message is committed. + +If called with no arguments, this is a two-step command. The first step opens +a buffer to accept a log message. When that buffer is written, it is +automatically closed and the file is committed using the information from that +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. + +:VCSDelete *:VCSDelete* + +Deletes the current file and removes it from source control. All parameters +to the command are passed to the underlying VCS. + +:VCSDiff *:VCSDiff* + +With no arguments, this displays the differences between the current file and +its parent version under source control in a new scratch buffer. + +With one argument, the diff is performed on the current file against the +specified revision. + +With two arguments, the diff is performed between the specified revisions of +the current file. + +For CVS, this command uses the |VCSCommandCVSDiffOpt| variable to specify diff +options. If that variable does not exist, a plugin-specific default is used. +If you wish to have no options, then set it to the empty string. + +For SVN, this command uses the |VCSCommandSVNDiffOpt| variable to specify diff +options. If that variable does not exist, the SVN default is used. +Additionally, |VCSCommandSVNDiffExt| can be used to select an external diff +application. + +:VCSGotoOriginal *:VCSGotoOriginal* + +This command jumps to the source buffer if the current buffer is a VCS scratch +buffer. + +:VCSGotoOriginal! + +Like ":VCSGotoOriginal" but also executes :bufwipeout on all VCS scrach +buffers associated with the original file. + +:VCSInfo *:VCSInfo* + +This command displays extended information about the current file in a new +scratch buffer. + +:VCSLock *:VCSLock* + +This command locks the current file in order to prevent other users from +concurrently modifying it. The exact semantics of this command depend on the +underlying VCS. This does nothing in CVS. All parameters are passed to the +underlying VCS. + +:VCSLog *:VCSLog* + +Displays the version history of the current file in a new scratch buffer. If +there is one parameter supplied, it is taken as as a revision parameters to be +passed through to the underlying VCS. Otherwise, all parameters are passed to +the underlying VCS. + +:VCSRemove *:VCSRemove* + +Alias for |:VCSDelete|. + +:VCSRevert *:VCSRevert* + +This command replaces the current file with the most recent version from the +repository in order to wipe out any undesired changes. + +:VCSReview *:VCSReview* + +Displays a particular version of the current file in a new scratch buffer. If +no argument is given, the most recent version of the file on the current +branch is retrieved. + +:VCSStatus *:VCSStatus* + +Displays versioning information about the current file in a new scratch +buffer. All parameters are passed to the underlying VCS. + + +:VCSUnlock *:VCSUnlock* + +Unlocks the current file in order to allow other users from concurrently +modifying it. The exact semantics of this command depend on the underlying +VCS. All parameters are passed to the underlying VCS. + +:VCSUpdate *:VCSUpdate* + +Updates the current file with any relevant changes from the repository. This +intentionally does not automatically reload the current buffer, though vim +should prompt the user to do so if the underlying file is altered by this +command. + +:VCSVimDiff *:VCSVimDiff* + +Uses vimdiff to display differences between versions of the current file. + +If no revision is specified, the most recent version of the file on the +current branch is used. With one argument, that argument is used as the +revision as above. With two arguments, the differences between the two +revisions is displayed using vimdiff. + +With either zero or one argument, the original buffer is used to perform the +vimdiff. When the scratch buffer is closed, the original buffer will be +returned to normal mode. + +Once vimdiff mode is started using the above methods, additional vimdiff +buffers may be added by passing a single version argument to the command. +There may be up to 4 vimdiff buffers total. + +Using the 2-argument form of the command resets the vimdiff to only those 2 +versions. Additionally, invoking the command on a different file will close +the previous vimdiff buffers. + +:CVSEdit *:CVSEdit* + +This command performs "cvs edit" on the current file. Yes, the output buffer +in this case is almost completely useless. + +:CVSEditors *:CVSEditors* + +This command performs "cvs edit" on the current file. + +:CVSUnedit *:CVSUnedit* + +Performs "cvs unedit" on the current file. Again, yes, the output buffer here +is basically useless. + +:CVSWatch *:CVSWatch* + +This command takes an argument which must be one of [on|off|add|remove]. The +command performs "cvs watch" with the given argument on the current file. + +:CVSWatchAdd *:CVSWatchAdd* + +This command is an alias for ":CVSWatch add" + +:CVSWatchOn *:CVSWatchOn* + +This command is an alias for ":CVSWatch on" + +:CVSWatchOff *:CVSWatchOff* + +This command is an alias for ":CVSWatch off" + +:CVSWatchRemove *:CVSWatchRemove* + +This command is an alias for ":CVSWatch remove" + +:CVSWatchers *:CVSWatchers* + +This command performs "cvs watchers" on the current file. + +4.2 Mappings *vcscommand-mappings* + +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 + +Only for CVS buffers: + +ce CVSEdit +cE CVSEditors +ct CVSUnedit +cwv CVSWatchers +cwa CVSWatchAdd +cwn CVSWatchOn +cwf CVSWatchOff +cwf CVSWatchRemove + + *vcscommand-mappings-override* + +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). + +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 +may be useful for additional customization in callbacks defined in the event +handlers (please see |vcscommand-events|). + +The following variables are automatically defined: + +b:VCSCommandOriginalBuffer *b:VCSCommandOriginalBuffer* + +This variable is set to the buffer number of the source file. + +b:VCSCommandCommand *b:VCSCommandCommand* + +This variable is set to the name of the vcscommand that created the result +buffer. + +b:VCSCommandSourceFile *b:VCSCommandSourceFile* + +This variable is set to the name of the original file under source control. + +b:VCSCommandVCSType *b:VCSCommandVCSType* + +This variable is set to the type of the source control. This variable is also +set on the original file itself. +============================================================================== + +5. Configuration and customization *vcscommand-customize* + *vcscommand-config* + +The vcscommand plugin can be configured in several ways: by setting +configuration variables (see |vcscommand-options|) or by defining vcscommand +event handlers (see |vcscommand-events|). Additionally, the vcscommand plugin +supports a customized status line (see |vcscommand-statusline| and +|vcscommand-buffer-management|). + +5.1 vcscommand configuration variables *vcscommand-options* + +Several variables affect the plugin's behavior. These variables are checked +at time of execution, and may be defined at the window, buffer, or global +level and are checked in that order of precedence. + + +The following variables are available: + +|VCSCommandCommitOnWrite| +|VCSCommandCVSDiffOpt| +|VCSCommandCVSExec| +|VCSCommandDeleteOnHide| +|VCSCommandDiffSplit| +|VCSCommandDisableAll| +|VCSCommandDisableMappings| +|VCSCommandDisableExtensionMappings| +|VCSCommandEdit| +|VCSCommandEnableBufferSetup| +|VCSCommandMappings| +|VCSCommandMapPrefix| +|VCSCommandResultBufferNameExtension| +|VCSCommandResultBufferNameFunction| +|VCSCommandSplit| +|VCSCommandSVKExec| +|VCSCommandSVNDiffExt| +|VCSCommandSVNDiffOpt| +|VCSCommandSVNExec| +|VCSCommandVCSTypeOverride| + +VCSCommandCommitOnWrite *VCSCommandCommitOnWrite* + +This variable, if set to a non-zero value, causes the pending commit +to take place immediately as soon as the log message buffer is written. +If set to zero, only the VCSCommit mapping will cause the pending commit to +occur. If not set, it defaults to 1. + +VCSCommandCVSExec *VCSCommandCVSExec* + +This variable controls the executable used for all CVS commands If not set, +it defaults to "cvs". + +VCSCommandDeleteOnHide *VCSCommandDeleteOnHide* + +This variable, if set to a non-zero value, causes the temporary result buffers +to automatically delete themselves when hidden. + +VCSCommandCVSDiffOpt *VCSCommandCVSDiffOpt* + +This variable, if set, determines the options passed to the diff command of +CVS. If not set, it defaults to 'u'. + +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 +mappings from being set. This supercedes +|VCSCommandDisableExtensionMappings|. + +VCSCommandDisableExtensionMappings *VCSCommandDisableExtensionMappings* + +This variable, if set to a non-zero value, prevents the default command +mappings from being set for commands specific to an individual VCS. + +VCSCommandEdit *VCSCommandEdit* + +This variable controls whether the original buffer is replaced ('edit') or +split ('split'). If not set, it defaults to 'split'. + +VCSCommandEnableBufferSetup *VCSCommandEnableBufferSetup* + +This variable, if set to a non-zero value, activates VCS buffer management +mode see (|vcscommand-buffer-management|). This mode means that the +'VCSCommandBufferInfo' variable is filled with version information if the file +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. + +VCSCommandResultBufferNameExtension *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 help +avoid problems caused by autocommands dependent on file extension. + +VCSCommandResultBufferNameFunction *VCSCommandResultBufferNameFunction* + +This variable, if set, specifies a custom function for naming VCS command +output buffers. This function is expected to return the new buffer name, and +will be passed the following arguments: + + command - name of the VCS command being executed (such as 'Log' or + 'Diff'). + + originalBuffer - buffer number of the source file. + + vcsType - type of VCS controlling this file (such as 'CVS' or 'SVN'). + + statusText - extra text associated with the VCS action (such as version + numbers). + +VCSCommandSplit *VCSCommandSplit* + +This variable controls the orientation of the various window splits that +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 default to the user's 'diffopt' +setting, if set, otherwise 'vertical'. + +VCSCommandSVKExec *VCSCommandSVKExec* + +This variable controls the executable used for all SVK commands If not set, +it defaults to "svk". + +VCSCommandSVNDiffExt *VCSCommandSVNDiffExt* + +This variable, if set, is passed to SVN via the --diff-cmd command to select +an external application for performing the diff. + +VCSCommandSVNDiffOpt *VCSCommandSVNDiffOpt* + +This variable, if set, determines the options passed with the '-x' parameter +to the SVN diff command. If not set, no options are passed. + +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. + +5.2 VCSCommand events *vcscommand-events* + +For additional customization, vcscommand can trigger user-defined events. +Event handlers are provided by defining User event autocommands (see +|autocommand|, |User|) in the vcscommand group with patterns matching the +event name. + +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 +augroup END + +The following hooks are available: + +VCSBufferCreated This event is fired just after a vcscommand + result buffer is created and populated. It is + executed within the context of the vcscommand + buffer. The vcscommand buffer variables may + be useful for handlers of this event (please + see |vcscommand-buffer-variables|). + +VCSBufferSetup This event is fired just after vcscommand buffer + setup occurs, if enabled. + +VCSPluginInit This event is fired when the vcscommand plugin + first loads. + +VCSPluginFinish This event is fired just after the vcscommand + plugin loads. + +VCSVimDiffFinish This event is fired just after the VCSVimDiff + command executes to allow customization of, + for instance, window placement and focus. + +Additionally, there is another hook which is used internally to handle loading +the multiple scripts in order. This hook should probably not be used by an +end user without a good idea of how it works. Among other things, any events +associated with this hook are cleared after they are executed (during +vcscommand.vim script initialization). + +VCSLoadExtensions This event is fired just before the + VCSPluginFinish. It is used internally to + execute any commands from the VCS + implementation plugins that needs to be + deferred until the primary plugin is + initialized. + +5.3 vcscommand buffer naming *vcscommand-naming* + +vcscommand result buffers use the following naming convention: +[{VCS type} {VCS command} {Source file name}] + +If additional buffers are created that would otherwise conflict, a +distinguishing number is added: + +[{VCS type} {VCS command} {Source file name}] (1,2, etc) + +5.4 vcscommand status line support *vcscommand-statusline* + +It is intended that the user will customize the |'statusline'| option to +include vcscommand result buffer attributes. A sample function that may be +used in the |'statusline'| option is provided by the plugin, +VCSCommandGetStatusLine(). In order to use that function in the status line, do +something like the following: + +set statusline=%<%f\ %{VCSCommandGetStatusLine()}\ %h%m%r%=%l,%c%V\ %P + +of which %{VCSCommandGetStatusLine()} is the relevant portion. + +The sample VCSCommandGetStatusLine() function handles both vcscommand result +buffers and VCS-managed files if vcscommand buffer management is enabled +(please see |vcscommand-buffer-management|). + +5.5 vcscommand buffer management *vcscommand-buffer-management* + +The vcscommand plugin can operate in buffer management mode, which means that +it attempts to set a buffer variable ('VCSCommandBufferInfo') upon entry into +a buffer. This is rather slow because it means that the VCS will be invoked +at each entry into a buffer (during the |BufEnter| autocommand). + +This mode is disabled by default. In order to enable it, set the +|VCSCommandEnableBufferSetup| variable to a true (non-zero) value. Enabling +this mode simply provides the buffer variable mentioned above. The user must +explicitly include information from the variable in the |'statusline'| option +if they are to appear in the status line (but see |vcscommand-statusline| for +a simple way to do that). + +The 'VCSCommandBufferInfo' variable is a list which contains, in order, the +revision of the current file, the latest revision of the file in the +repository, and (for CVS) the name of the branch. If those values cannot be +determined, the list is a single element: 'Unknown'. + +============================================================================== + +6. SSH "integration" *vcscommand-ssh* + +The following instructions are intended for use in integrating the +vcscommand.vim plugin with an SSH-based CVS environment. + +Familiarity with SSH and CVS are assumed. + +These instructions assume that the intent is to have a message box pop up in +order to allow the user to enter a passphrase. If, instead, the user is +comfortable using certificate-based authentication, then only instructions +6.1.1 and 6.1.2 (and optionally 6.1.4) need to be followed; ssh should then +work transparently. + +6.1 Environment settings *vcscommand-ssh-env* + +6.1.1 CVSROOT should be set to something like: + + :ext:user@host:/path_to_repository + +6.1.2 CVS_RSH should be set to: + + ssh + + Together, those settings tell CVS to use ssh as the transport when + performing CVS calls. + +6.1.3 SSH_ASKPASS should be set to the password-dialog program. In my case, + running gnome, it's set to: + + /usr/libexec/openssh/gnome-ssh-askpass + + This tells SSH how to get passwords if no input is available. + +6.1.4 OPTIONAL. You may need to set SSH_SERVER to the location of the cvs + executable on the remote (server) machine. + +6.2 CVS wrapper program *vcscommand-ssh-wrapper* + +Now you need to convince SSH to use the password-dialog program. This means +you need to execute SSH (and therefore CVS) without standard input. The +following script is a simple perl wrapper that dissasociates the CVS command +from the current terminal. Specific steps to do this may vary from system to +system; the following example works for me on linux. + +#!/usr/bin/perl -w +use strict; +use POSIX qw(setsid); +open STDIN, '/dev/null'; +fork and do {wait; exit;}; +setsid; +exec('cvs', @ARGV); + +6.3 Configuring vcscommand.vim *vcscommand-ssh-config* + +At this point, you should be able to use your wrapper script to invoke CVS with +various commands, and get the password dialog. All that's left is to make CVS +use your newly-created wrapper script. + +6.3.1 Tell vcscommand.vim what CVS executable to use. The easiest way to do this + is globally, by putting the following in your .vimrc: + + let VCSCommandCVSExec=/path/to/cvs/wrapper/script + +6.4 Where to go from here *vcscommand-ssh-other* + +The script given above works even when non-SSH CVS connections are used, +except possibly when interactively entering the message for CVS commit log +(depending on the editor you use... VIM works fine). Since the vcscommand.vim +plugin handles that message without a terminal, the wrapper script can be used +all the time. + +This allows mixed-mode operation, where some work is done with SSH-based CVS +repositories, and others with pserver or local access. + +It is possible, though beyond the scope of the plugin, to dynamically set the +CVS executable based on the CVSROOT for the file being edited. The user +events provided (such as VCSBufferCreated and VCSBufferSetup) can be used to +set a buffer-local value (b:VCSCommandCVSExec) to override the CVS executable +on a file-by-file basis. Alternatively, much the same can be done (less +automatically) by the various project-oriented plugins out there. + +It is highly recommended for ease-of-use that certificates with no passphrase +or ssh-agent are employed so that the user is not given the password prompt +too often. + +============================================================================== + +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. + +2. Renamed commands to start with 'VCS' instead of 'CVS'. The exceptions are +the 'CVSEdit' and 'CVSWatch' family of commands, which are specific to CVS. + +3. Renamed options, events to start with 'VCSCommand'. + +4. Removed option to jump to the parent version of the current line in an +annotated buffer, as opposed to the version on the current line. This made +little sense in the branching scheme used by subversion, where jumping to a +parent branch required finding a different location in the repository. It +didn't work consistently in CVS anyway. + +5. Removed option to have nameless scratch buffers. + +6. Changed default behavior of scratch buffers to split the window instead of +displaying in the current window. This may still be overridden using the +'VCSCommandEdit' option. + +7. Split plugin into multiple plugins. + +8. Added 'VCSLock' and 'VCSUnlock' commands. These are implemented for +subversion but not for CVS. These were not kept specific to subversion as they +seemed more general in nature and more likely to be supported by any future VCS +supported by this plugin. + +9. Changed name of buffer variables set by commands. + +'b:cvsOrigBuffNR' became 'b:VCSCommandOriginalBuffer' +'b:cvscmd' became 'b:VCSCommandCommand' + +10. Added new automatic variables to command result buffers. + +'b:VCSCommandSourceFile' +'b:VCSCommandVCSType' + +============================================================================== + +8. Known bugs *vcscommand-bugs* + +Please let me know if you run across any. + +CVSUnedit may, if a file is changed from the repository, provide prompt text +to determine whether the changes should be thrown away. Currently, that text +shows up in the CVS result buffer as information; there is no way for the user +to actually respond to the prompt and the CVS unedit command does nothing. If +this really bothers anyone, please let me know. + +VCSVimDiff, when using the original (real) source buffer as one of the diff +buffers, uses some hacks to try to restore the state of the original buffer +when the scratch buffer containing the other version is destroyed. There may +still be bugs in here, depending on many configuration details. + +vim:tw=78:ts=8:ft=help diff --git a/.vim/plugin/vcscommand.vim b/.vim/plugin/vcscommand.vim new file mode 100644 index 0000000..189da47 --- /dev/null +++ b/.vim/plugin/vcscommand.vim @@ -0,0 +1,1292 @@ +" vim600: set foldmethod=marker: +" +" Vim plugin to assist in working with files under control of various Version +" Control Systems, such as CVS, SVN, SVK, and git. +" +" Maintainer: Bob Hiestand +" Version: Beta 29 +" License: +" Copyright (c) 2008 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 +" +" Provides functions to invoke various source control commands on the current +" file (either the current buffer, or, in the case of an directory buffer, the +" 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. +" +" Command documentation {{{2 +" +" VCSAdd Adds the current file to source control. +" +" 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 +" most recent version of the file on the current branch. +" Additionally, if the current buffer is a VCSAnnotate buffer +" already, the version number on the current line is used. +" +" VCSBlame Alias for 'VCSAnnotate'. +" +" VCSCommit[!] Commits changes to the current file to source control. +" +" If called with arguments, the arguments are the log message. +" +" If '!' is used, an empty log message is committed. +" +" If called with no arguments, this is a two-step command. +" The first step opens a buffer to accept a log message. +" When that buffer is written, it is automatically closed and +" the file is committed using the information from that log +" message. The commit can be abandoned if the log message +" buffer is deleted or wiped before being written. +" +" VCSDelete Deletes the current file and removes it from source control. +" +" VCSDiff With no arguments, this displays the differences between +" the current file and its parent version under source +" control in a new scratch buffer. +" +" With one argument, the diff is performed on the +" current file against the specified revision. +" +" With two arguments, the diff is performed between the +" specified revisions of the current file. +" +" This command uses the 'VCSCommand{VCSType}DiffOpt' variable +" to specify diff options. If that variable does not exist, +" a plugin-specific default is used. If you wish to have no +" options, then set it to the empty string. +" +" VCSGotoOriginal Jumps to the source buffer if the current buffer is a VCS +" scratch buffer. If VCSGotoOriginal[!] is used, remove all +" VCS scratch buffers associated with the original file. +" +" VCSInfo Displays extended information about the current file in a +" new scratch buffer. +" +" VCSLock Locks the current file in order to prevent other users from +" concurrently modifying it. The exact semantics of this +" command depend on the underlying VCS. +" +" VCSLog Displays the version history of the current file in a new +" scratch buffer. +" +" VCSRemove Alias for 'VCSDelete'. +" +" VCSRevert Replaces the modified version of the current file with the +" most recent version from the repository. +" +" VCSReview Displays a particular version of the current file in a new +" scratch buffer. If no argument is given, the most recent +" version of the file on the current branch is retrieved. +" +" VCSStatus Displays versioning information about the current file in a +" new scratch buffer. +" +" VCSUnlock Unlocks the current file in order to allow other users from +" concurrently modifying it. The exact semantics of this +" command depend on the underlying VCS. +" +" VCSUpdate Updates the current file with any relevant changes from the +" repository. +" +" VCSVimDiff Uses vimdiff to display differences between versions of the +" current file. +" +" If no revision is specified, the most recent version of the +" file on the current branch is used. With one argument, +" that argument is used as the revision as above. With two +" arguments, the differences between the two revisions is +" displayed using vimdiff. +" +" With either zero or one argument, the original buffer is +" used to perform the vimdiff. When the scratch buffer is +" closed, the original buffer will be returned to normal +" mode. +" +" Once vimdiff mode is started using the above methods, +" additional vimdiff buffers may be added by passing a single +" version argument to the command. There may be up to 4 +" vimdiff buffers total. +" +" Using the 2-argument form of the command resets the vimdiff +" to only those 2 versions. Additionally, invoking the +" command on a different file will close the previous vimdiff +" buffers. +" +" Mapping documentation: {{{2 +" +" By default, a mapping is defined for each command. User-provided mappings +" can be used instead by mapping to CommandName, for instance: +" +" nmap ,ca VCSAdd +" +" The default mappings are as follow: +" +" 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 +" +" Options documentation: {{{2 +" +" Several variables are checked by the script to determine behavior as follow: +" +" VCSCommandCommitOnWrite +" This variable, if set to a non-zero value, causes the pending commit to +" take place immediately as soon as the log message buffer is written. If +" set to zero, only the VCSCommit mapping will cause the pending commit to +" occur. If not set, it defaults to 1. +" +" VCSCommandDeleteOnHide +" This variable, if set to a non-zero value, causes the temporary VCS result +" buffers to automatically delete themselves when hidden. +" +" VCSCommand{VCSType}DiffOpt +" This variable, if set, determines the options passed to the diff command +" of the underlying VCS. Each VCS plugin defines a default value. +" +" VCSCommandDiffSplit +" 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. +" +" VCSCommandDisableExtensionMappings +" This variable, if set to a non-zero value, prevents the default command +" mappings from being set for commands specific to an individual VCS. +" +" 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'). +" If not set, it defaults to 'split'. +" +" VCSCommandEnableBufferSetup +" This variable, if set to a non-zero value, activates VCS buffer management +" mode. This mode means that the buffer variable 'VCSRevision' is set if +" the file is VCS-controlled. This is useful for displaying version +" 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. +" +" 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 +" help avoid problems caused by autocommands dependent on file extension. +" +" VCSCommandResultBufferNameFunction +" This variable, if set, specifies a custom function for naming VCS command +" output buffers. This function will be passed the following arguments: +" +" command - name of the VCS command being executed (such as 'Log' or +" 'Diff'). +" +" originalBuffer - buffer number of the source file. +" +" vcsType - type of VCS controlling this file (such as 'CVS' or 'SVN'). +" +" statusText - extra text associated with the VCS action (such as version +" numbers). +" +" VCSCommandSplit +" This variable controls the orientation of the various window splits that +" may occur (such as with VCSVimDiff, when using a VCS command on a VCS +" command buffer, or when the 'VCSCommandEdit' variable is set to 'split'. +" 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. +" +" 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. +" +" Event documentation {{{2 +" For additional customization, VCSCommand.vim uses User event autocommand +" hooks. Each event is in the VCSCommand group, and different patterns +" match the various hooks. +" +" For instance, the following could be added to the vimrc to provide a 'q' +" mapping to quit a VCS scratch buffer: +" +" augroup VCSCommand +" au VCSCommand User VCSBufferCreated silent! nmap q :bwipeout +" augroup END +" +" The following hooks are available: +" +" VCSBufferCreated This event is fired just after a VCS command +" output buffer is created. It is executed +" within the context of the new buffer. +" +" VCSBufferSetup This event is fired just after VCS buffer setup +" occurs, if enabled. +" +" VCSPluginInit This event is fired when the VCSCommand plugin +" first loads. +" +" VCSPluginFinish This event is fired just after the VCSCommand +" plugin loads. +" +" VCSVimDiffFinish This event is fired just after the VCSVimDiff +" command executes to allow customization of, +" for instance, window placement and focus. +" +" Section: Plugin header {{{1 + +" loaded_VCSCommand is set to 1 when the initialization begins, and 2 when it +" 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 +let loaded_VCSCommand = 1 + +if v:version < 700 + "echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Event group setup {{{1 + +augroup VCSCommand +augroup END + +augroup VCSCommandCommit +augroup END + +" Section: Plugin initialization {{{1 +silent do VCSCommand User VCSPluginInit + +" Section: Constants declaration {{{1 + +let g:VCSCOMMAND_IDENTIFY_EXACT = 1 +let g:VCSCOMMAND_IDENTIFY_INEXACT = -1 + +" Section: Script variable initialization {{{1 + +" plugin-specific information: {vcs -> [script, {command -> function}, {key -> mapping}]} +let s:plugins = {} + +" temporary values of overridden configuration variables +let s:optionOverrides = {} + +" 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 +" Displays the given error in a consistent faction. This is intended to be +" invoked from a catch statement. + +function! s:ReportError(error) + echohl WarningMsg|echomsg 'VCSCommand: ' . a:error|echohl None +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. + +function! s:ExecuteExtensionMapping(mapping) + let buffer = bufnr('%') + let vcsType = VCSCommandGetVCSType(buffer) + if !has_key(s:plugins, vcsType) + throw 'Unknown VCS type: ' . vcsType + endif + 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] . "\" +endfunction + +" Function: s:ExecuteVCSCommand(command, argList) {{{2 +" Calls the indicated plugin-specific VCS command on the current buffer. +" Returns: buffer number of resulting output scratch buffer, or -1 if an error +" occurs. + +function! s:ExecuteVCSCommand(command, argList) + try + let buffer = bufnr('%') + + let vcsType = VCSCommandGetVCSType(buffer) + if !has_key(s:plugins, vcsType) + throw 'Unknown VCS type: ' . vcsType + endif + + let originalBuffer = VCSCommandGetOriginalBuffer(buffer) + let bufferName = bufname(originalBuffer) + + " It is already known that the directory is under VCS control. No further + " checks are needed. Otherwise, perform some basic sanity checks to avoid + " VCS-specific error messages from confusing things. + if !isdirectory(bufferName) + if !filereadable(bufferName) + throw 'No such file ' . bufferName + endif + endif + + let functionMap = s:plugins[vcsType][1] + if !has_key(functionMap, a:command) + throw 'Command ''' . a:command . ''' not implemented for ' . vcsType + endif + return functionMap[a:command](a:argList) + catch + call s:ReportError(v:exception) + return -1 + endtry +endfunction + +" Function: s:GenerateResultBufferName(command, originalBuffer, vcsType, statusText) {{{2 +" Default method of generating the name for VCS result buffers. This can be +" overridden with the VCSResultBufferNameFunction variable. + +function! s:GenerateResultBufferName(command, originalBuffer, vcsType, statusText) + let fileName = bufname(a:originalBuffer) + let bufferName = a:vcsType . ' ' . a:command + if strlen(a:statusText) > 0 + let bufferName .= ' ' . a:statusText + endif + let bufferName .= ' ' . fileName + let counter = 0 + let versionedBufferName = bufferName + while buflisted(versionedBufferName) + let counter += 1 + let versionedBufferName = bufferName . ' (' . counter . ')' + endwhile + return versionedBufferName +endfunction + +" Function: s:GenerateResultBufferNameWithExtension(command, originalBuffer, vcsType, statusText) {{{2 +" Method of generating the name for VCS result buffers that uses the original +" file name with the VCS type and command appended as extensions. + +function! s:GenerateResultBufferNameWithExtension(command, originalBuffer, vcsType, statusText) + let fileName = bufname(a:originalBuffer) + let bufferName = a:vcsType . ' ' . a:command + if strlen(a:statusText) > 0 + let bufferName .= ' ' . a:statusText + endif + let bufferName .= ' ' . fileName . VCSCommandGetOption('VCSCommandResultBufferNameExtension', '.vcs') + let counter = 0 + let versionedBufferName = bufferName + while buflisted(versionedBufferName) + let counter += 1 + let versionedBufferName = '(' . counter . ') ' . bufferName + endwhile + return versionedBufferName +endfunction + +" Function: s:EditFile(command, originalBuffer, statusText) {{{2 +" Creates a new buffer of the given name and associates it with the given +" original buffer. + +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 + let editCommand = VCSCommandGetOption('VCSCommandEdit', 'split') + if editCommand == 'split' + if VCSCommandGetOption('VCSCommandSplit', 'horizontal') == 'horizontal' + rightbelow split + else + vert rightbelow split + endif + endif + + enew + + let b:VCSCommandCommand = a:command + let b:VCSCommandOriginalBuffer = a:originalBuffer + let b:VCSCommandSourceFile = bufname(a:originalBuffer) + let b:VCSCommandVCSType = vcsType + + 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:SetupBuffer() {{{2 +" Attempts to set the b:VCSCommandBufferInfo variable + +function! s:SetupBuffer() + if (exists('b:VCSCommandBufferSetup') && b:VCSCommandBufferSetup) + " This buffer is already set up. + return + endif + + if !isdirectory(@%) && (strlen(&buftype) > 0 || !filereadable(@%)) + " No special status for special buffers other than directory buffers. + return + endif + + if !VCSCommandGetOption('VCSCommandEnableBufferSetup', 0) || s:isEditFileRunning > 0 + unlet! b:VCSCommandBufferSetup + return + endif + + try + let vcsType = VCSCommandGetVCSType(bufnr('%')) + let b:VCSCommandBufferInfo = s:plugins[vcsType][1].GetBufferInfo() + silent do VCSCommand User VCSBufferSetup + catch /No suitable plugin/ + " This is not a VCS-controlled file. + let b:VCSCommandBufferInfo = [] + endtry + + let b:VCSCommandBufferSetup = 1 +endfunction + +" Function: s:MarkOrigBufferForSetup(buffer) {{{2 +" Resets the buffer setup state of the original buffer for a given VCS scratch +" buffer. +" Returns: The VCS buffer number in a passthrough mode. + +function! s:MarkOrigBufferForSetup(buffer) + checktime + if a:buffer > 0 + let origBuffer = VCSCommandGetOriginalBuffer(a:buffer) + " This should never not work, but I'm paranoid + if origBuffer != a:buffer + call setbufvar(origBuffer, 'VCSCommandBufferSetup', 0) + endif + endif + 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. + +function! s:WipeoutCommandBuffers(originalBuffer, VCSCommand) + let buffer = 1 + while buffer <= bufnr('$') + if getbufvar(buffer, 'VCSCommandOriginalBuffer') == a:originalBuffer + if getbufvar(buffer, 'VCSCommandCommand') == a:VCSCommand + execute 'bw' buffer + endif + endif + let buffer = buffer + 1 + endwhile +endfunction + +" Function: s:VimDiffRestore(vimDiffBuff) {{{2 +" Checks whether the given buffer is one whose deletion should trigger +" restoration of an original buffer after it was diffed. If so, it executes +" the appropriate setting command stored with that original buffer. + +function! s:VimDiffRestore(vimDiffBuff) + let s:isEditFileRunning += 1 + try + if exists('s:vimDiffSourceBuffer') + if a:vimDiffBuff == s:vimDiffSourceBuffer + " Original file is being removed. + unlet! s:vimDiffSourceBuffer + unlet! s:vimDiffRestoreCmd + unlet! s:vimDiffScratchList + else + let index = index(s:vimDiffScratchList, a:vimDiffBuff) + if index >= 0 + call remove(s:vimDiffScratchList, index) + if len(s:vimDiffScratchList) == 0 + if exists('s:vimDiffRestoreCmd') + " All scratch buffers are gone, reset the original. + " Only restore if the source buffer is still in Diff mode + + let sourceWinNR = bufwinnr(s:vimDiffSourceBuffer) + if sourceWinNR != -1 + " The buffer is visible in at least one window + let currentWinNR = winnr() + while winbufnr(sourceWinNR) != -1 + if winbufnr(sourceWinNR) == s:vimDiffSourceBuffer + execute sourceWinNR . 'wincmd w' + if getwinvar(0, '&diff') + execute s:vimDiffRestoreCmd + endif + endif + let sourceWinNR = sourceWinNR + 1 + endwhile + execute currentWinNR . 'wincmd w' + else + " The buffer is hidden. It must be visible in order to set the + " diff option. + let currentBufNR = bufnr('') + execute 'hide buffer' s:vimDiffSourceBuffer + if getwinvar(0, '&diff') + execute s:vimDiffRestoreCmd + endif + execute 'hide buffer' currentBufNR + endif + + unlet s:vimDiffRestoreCmd + endif + " All buffers are gone. + unlet s:vimDiffSourceBuffer + unlet s:vimDiffScratchList + endif + endif + endif + endif + finally + let s:isEditFileRunning -= 1 + endtry +endfunction + +" Section: Generic VCS command functions {{{1 + +" Function: s:VCSCommit() {{{2 +function! s:VCSCommit(bang, message) + try + let vcsType = VCSCommandGetVCSType(bufnr('%')) + if !has_key(s:plugins, vcsType) + throw 'Unknown VCS type: ' . vcsType + endif + + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + + " Handle the commit message being specified. If a message is supplied, it + " is used; if bang is supplied, an empty message is used; otherwise, the + " user is provided a buffer from which to edit the commit message. + + if strlen(a:message) > 0 || a:bang == '!' + return s:VCSFinishCommit([a:message], originalBuffer) + endif + + call s:EditFile('commitlog', originalBuffer, '') + setlocal ft=vcscommit + + " Create a commit mapping. + + nnoremap VCSCommit :call VCSFinishCommitWithBuffer() + + silent 0put ='VCS: ----------------------------------------------------------------------' + silent put ='VCS: Please enter log message. Lines beginning with ''VCS:'' are removed automatically.' + silent put ='VCS: To finish the commit, Type cc (or your own VCSCommit mapping)' + + if VCSCommandGetOption('VCSCommandCommitOnWrite', 1) == 1 + setlocal buftype=acwrite + au VCSCommandCommit BufWriteCmd call s:VCSFinishCommitWithBuffer() + silent put ='VCS: or write this buffer' + endif + + silent put ='VCS: ----------------------------------------------------------------------' + $ + setlocal nomodified + catch + call s:ReportError(v:exception) + return -1 + endtry +endfunction + +" Function: s:VCSFinishCommitWithBuffer() {{{2 +" Wrapper for s:VCSFinishCommit which is called only from a commit log buffer +" which removes all lines starting with 'VCS:'. + +function! s:VCSFinishCommitWithBuffer() + setlocal nomodified + let currentBuffer = bufnr('%') + let logMessageList = getbufline('%', 1, '$') + call filter(logMessageList, 'v:val !~ ''^\s*VCS:''') + let resultBuffer = s:VCSFinishCommit(logMessageList, b:VCSCommandOriginalBuffer) + if resultBuffer >= 0 + execute 'bw' currentBuffer + endif + return resultBuffer +endfunction + +" Function: s:VCSFinishCommit(logMessageList, originalBuffer) {{{2 +function! s:VCSFinishCommit(logMessageList, originalBuffer) + let shellSlashBak = &shellslash + 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 + finally + let &shellslash = shellSlashBak + endtry +endfunction + +" Function: s:VCSGotoOriginal(bang) {{{2 +function! s:VCSGotoOriginal(bang) + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + if originalBuffer > 0 + let origWinNR = bufwinnr(originalBuffer) + if origWinNR == -1 + execute 'buffer' originalBuffer + else + execute origWinNR . 'wincmd w' + endif + if a:bang == '!' + let buffnr = 1 + let buffmaxnr = bufnr('$') + while buffnr <= buffmaxnr + if getbufvar(buffnr, 'VCSCommandOriginalBuffer') == originalBuffer + execute 'bw' buffnr + endif + let buffnr = buffnr + 1 + endwhile + endif + endif +endfunction + +" Function: s:VCSVimDiff(...) {{{2 +function! s:VCSVimDiff(...) + try + let vcsType = VCSCommandGetVCSType(bufnr('%')) + if !has_key(s:plugins, vcsType) + throw 'Unknown VCS type: ' . vcsType + endif + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let s:isEditFileRunning = s:isEditFileRunning + 1 + try + " 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 + " Clear the existing vimdiff setup by removing the result buffers. + call s:WipeoutCommandBuffers(s:vimDiffSourceBuffer, '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') + endif + let resultBuffer = s:plugins[vcsType][1].Review([a:1]) + if resultBuffer < 0 + echomsg 'Can''t open revision ' . a:1 + return resultBuffer + endif + let b:VCSCommandCommand = 'vimdiff' + diffthis + let s:vimDiffScratchList = [resultBuffer] + " If no split method is defined, cheat, and set it to vertical. + try + call s:OverrideOption('VCSCommandSplit', orientation) + let resultBuffer = s:plugins[vcsType][1].Review([a:2]) + finally + call s:OverrideOption('VCSCommandSplit') + endtry + if resultBuffer < 0 + echomsg 'Can''t open revision ' . a:1 + return resultBuffer + endif + let b:VCSCommandCommand = 'vimdiff' + diffthis + let s:vimDiffScratchList += [resultBuffer] + else + " Add new buffer + call s:OverrideOption('VCSCommandEdit', 'split') + try + " Force splitting behavior, otherwise why use vimdiff? + call s:OverrideOption('VCSCommandSplit', orientation) + 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 + finally + call s:OverrideOption('VCSCommandEdit') + endtry + if resultBuffer < 0 + echomsg 'Can''t open current revision' + return resultBuffer + endif + let b:VCSCommandCommand = 'vimdiff' + diffthis + + if !exists('s:vimDiffSourceBuffer') + " New instance of vimdiff. + let s:vimDiffScratchList = [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 = + \ 'call setbufvar('.originalBuffer.', ''&diff'', '.getbufvar(originalBuffer, '&diff').')' + \ . '|call setbufvar('.originalBuffer.', ''&foldcolumn'', '.getbufvar(originalBuffer, '&foldcolumn').')' + \ . '|call setbufvar('.originalBuffer.', ''&foldenable'', '.getbufvar(originalBuffer, '&foldenable').')' + \ . '|call setbufvar('.originalBuffer.', ''&foldmethod'', '''.getbufvar(originalBuffer, '&foldmethod').''')' + \ . '|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' + diffthis + wincmd w + else + " Adding a window to an existing vimdiff + let s:vimDiffScratchList += [resultBuffer] + endif + endif + + let s:vimDiffSourceBuffer = originalBuffer + + " Avoid executing the modeline in the current buffer after the autocommand. + + let currentBuffer = bufnr('%') + let saveModeline = getbufvar(currentBuffer, '&modeline') + try + call setbufvar(currentBuffer, '&modeline', 0) + silent do VCSCommand User VCSVimDiffFinish + finally + call setbufvar(currentBuffer, '&modeline', saveModeline) + endtry + return resultBuffer + finally + let s:isEditFileRunning = s:isEditFileRunning - 1 + endtry + catch + call s:ReportError(v:exception) + return -1 + endtry +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 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. + +function! VCSCommandGetVCSType(buffer) + let vcsType = getbufvar(a:buffer, 'VCSCommandVCSType') + if strlen(vcsType) > 0 + return vcsType + endif + if exists("g:VCSCommandVCSTypeOverride") + let fullpath = fnamemodify(bufname(a:buffer), ':p') + for [path, vcsType] in g:VCSCommandVCSTypeOverride + if match(fullpath, path) > -1 + call setbufvar(a:buffer, 'VCSCommandVCSType', vcsType) + return vcsType + endif + endfor + 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 + 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 +endfunction + +" Function: VCSCommandChdir(directory) {{{2 +" Changes the current directory, respecting :lcd changes. + +function! VCSCommandChdir(directory) + let command = 'cd' + if exists("*haslocaldir") && haslocaldir() + let command = 'lcd' + endif + execute command escape(a:directory, ' ') +endfunction + +" Function: VCSCommandChangeToCurrentFileDir() {{{2 +" Go to the directory in which the given file is located. + +function! VCSCommandChangeToCurrentFileDir(fileName) + let oldCwd = getcwd() + let newCwd = fnamemodify(resolve(a:fileName), ':p:h') + if strlen(newCwd) > 0 + call VCSCommandChdir(newCwd) + endif + return oldCwd +endfunction + +" Function: VCSCommandGetOriginalBuffer(vcsBuffer) {{{2 +" Attempts to locate the original file to which VCS operations were applied +" for a given buffer. + +function! VCSCommandGetOriginalBuffer(vcsBuffer) + let origBuffer = getbufvar(a:vcsBuffer, 'VCSCommandOriginalBuffer') + if origBuffer + if bufexists(origBuffer) + return origBuffer + else + " Original buffer no longer exists. + throw 'Original buffer for this VCS buffer no longer exists.' + endif + else + " No original buffer + return a:vcsBuffer + endif +endfunction + +" Function: VCSCommandRegisterModule(name, file, commandMap) {{{2 +" Allows VCS modules to register themselves. + +function! VCSCommandRegisterModule(name, path, commandMap, mappingMap) + let s:plugins[a:name] = [a:path, a:commandMap, a:mappingMap] + if !empty(a:mappingMap) + \ && !VCSCommandGetOption('VCSCommandDisableMappings', 0) + \ && !VCSCommandGetOption('VCSCommandDisableExtensionMappings', 0) + for shortcut in keys(a:mappingMap) + let expansion = ":call ExecuteExtensionMapping('" . shortcut . "')" + call s:CreateMapping(shortcut, expansion, a:name . " extension mapping " . shortcut) + endfor + endif +endfunction + +" Function: VCSCommandDoCommand(cmd, cmdName, statusText, [options]) {{{2 +" General skeleton for VCS function execution. The given command is executed +" after appending the current buffer name (or substituting it for +" , if such a token is present). The output is captured in a +" new buffer. +" +" The optional 'options' Dictionary may contain the following options: +" allowNonZeroExit: if non-zero, if the underlying VCS command has a +" non-zero exit status, the command is still considered +" successfuly. This defaults to zero. +" Returns: name of the new command buffer containing the command results + +function! VCSCommandDoCommand(cmd, cmdName, statusText, options) + let allowNonZeroExit = 0 + if has_key(a:options, 'allowNonZeroExit') + let allowNonZeroExit = a:options.allowNonZeroExit + endif + + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + if originalBuffer == -1 + throw 'Original buffer no longer exists, aborting.' + endif + + let path = resolve(bufname(originalBuffer)) + + " Work with netrw or other systems where a directory listing is displayed in + " a buffer. + + if isdirectory(path) + let fileName = '.' + else + let fileName = fnamemodify(path, ':t') + endif + + if match(a:cmd, '') > 0 + let fullCmd = substitute(a:cmd, '', fileName, 'g') + else + let fullCmd = a:cmd . ' "' . fileName . '"' + endif + + " Change to the directory of the current buffer. This is done for CVS, but + " is left in for other systems as it does not affect them negatively. + + let oldCwd = VCSCommandChangeToCurrentFileDir(path) + try + let output = system(fullCmd) + finally + call VCSCommandChdir(oldCwd) + endtry + + " HACK: if line endings in the repository have been corrupted, the output + " of the command will be confused. + let output = substitute(output, "\r", '', 'g') + + if v:shell_error && !allowNonZeroExit + if strlen(output) == 0 + throw 'Version control command failed' + else + let output = substitute(output, '\n', ' ', 'g') + throw 'Version control command failed: ' . output + endif + endif + + if strlen(output) == 0 + " Handle case of no output. In this case, it is important to check the + " file status, especially since cvs edit/unedit may change the attributes + " of the file with no visible output. + + checktime + return 0 + endif + + call s:EditFile(a:cmdName, originalBuffer, a:statusText) + + silent 0put=output + + " The last command left a blank line at the end of the buffer. If the + " last line is folded (a side effect of the 'put') then the attempt to + " remove the blank line will kill the last fold. + " + " This could be fixed by explicitly detecting whether the last line is + " within a fold, but I prefer to simply unfold the result buffer altogether. + + if has('folding') + normal zR + endif + + $d + 1 + + " Define the environment and execute user-defined hooks. + + silent do VCSCommand User VCSBufferCreated + return bufnr('%') +endfunction + +" Function: VCSCommandGetOption(name, default) {{{2 +" Grab a user-specified option to override the default provided. Options are +" 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) + return w:{a:name} + elseif exists('b:' . a:name) + return b:{a:name} + elseif exists('g:' . a:name) + return g:{a:name} + else + return a:default + endif +endfunction + +" Function: VCSCommandDisableBufferSetup() {{{2 +" Global function for deactivating the buffer autovariables. + +function! VCSCommandDisableBufferSetup() + let g:VCSCommandEnableBufferSetup = 0 + silent! augroup! VCSCommandPlugin +endfunction + +" Function: VCSCommandEnableBufferSetup() {{{2 +" Global function for activating the buffer autovariables. + +function! VCSCommandEnableBufferSetup() + let g:VCSCommandEnableBufferSetup = 1 + augroup VCSCommandPlugin + au! + au BufEnter * call s:SetupBuffer() + augroup END + + " Only auto-load if the plugin is fully loaded. This gives other plugins a + " chance to run. + if g:loaded_VCSCommand == 2 + call s:SetupBuffer() + endif +endfunction + +" Function: VCSCommandGetStatusLine() {{{2 +" Default (sample) status line entry for VCS-controlled files. This is only +" useful if VCS-managed buffer mode is on (see the VCSCommandEnableBufferSetup +" variable for how to do this). + +function! VCSCommandGetStatusLine() + if exists('b:VCSCommandCommand') + " This is a result buffer. Return nothing because the buffer name + " contains information already. + return '' + endif + + if exists('b:VCSCommandVCSType') + \ && exists('g:VCSCommandEnableBufferSetup') + \ && g:VCSCommandEnableBufferSetup + \ && exists('b:VCSCommandBufferInfo') + return '[' . join(extend([b:VCSCommandVCSType], b:VCSCommandBufferInfo), ' ') . ']' + else + return '' + endif +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 VCSCommit call s:VCSCommit(, ) +com! -nargs=* VCSDelete call s:ExecuteVCSCommand('Delete', []) +com! -nargs=* VCSDiff call s:ExecuteVCSCommand('Diff', []) +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=* VCSStatus call s:ExecuteVCSCommand('Status', []) +com! -nargs=* VCSUnlock call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Unlock', [])) +com! -nargs=0 VCSUpdate call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Update', [])) +com! -nargs=* VCSVimDiff call s:VCSVimDiff() + +" Section: VCS buffer management commands {{{2 +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 + +" 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 + +" Section: Default mappings {{{1 + +let s:defaultMappings = [ + \['a', 'VCSAdd'], + \['c', 'VCSCommit'], + \['D', 'VCSDelete'], + \['d', 'VCSDiff'], + \['G', 'VCSClearAndGotoOriginal'], + \['g', 'VCSGotoOriginal'], + \['i', 'VCSInfo'], + \['L', 'VCSLock'], + \['l', 'VCSLog'], + \['n', 'VCSAnnotate'], + \['q', 'VCSRevert'], + \['r', 'VCSReview'], + \['s', 'VCSStatus'], + \['U', 'VCSUnlock'], + \['u', 'VCSUpdate'], + \['v', 'VCSVimDiff'], + \] + +if !VCSCommandGetOption('VCSCommandDisableMappings', 0) + for [shortcut, vcsFunction] in VCSCommandGetOption('VCSCommandMappings', s:defaultMappings) + call s:CreateMapping(shortcut, '' . vcsFunction, '''' . vcsFunction . '''') + endfor +endif + +" 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 + +" Section: Autocommands to restore vimdiff state {{{1 +augroup VimDiffRestore + au! + au BufUnload * call s:VimDiffRestore(str2nr(expand(''))) +augroup END + +" Section: Optional activation of buffer management {{{1 + +if VCSCommandGetOption('VCSCommandEnableBufferSetup', 0) + call VCSCommandEnableBufferSetup() +endif + +" Section: VIM shutdown hook {{{1 + +" Close all result buffers when VIM exits, to prevent them from being restored +" via viminfo. + +" Function: s:CloseAllResultBuffers() {{{2 +" Closes all vcscommand result buffers. +function! s:CloseAllResultBuffers() + " This avoids using bufdo as that may load buffers already loaded in another + " vim process, resulting in an error. + let buffnr = 1 + let buffmaxnr = bufnr('$') + while buffnr <= buffmaxnr + if getbufvar(buffnr, 'VCSCommandOriginalBuffer') != "" + execute 'bw' buffnr + endif + let buffnr = buffnr + 1 + endwhile +endfunction + +augroup VCSCommandVIMShutdown + au! + au VimLeavePre * call s:CloseAllResultBuffers() +augroup END + +" Section: Plugin completion {{{1 + +let loaded_VCSCommand = 2 + +silent do VCSCommand User VCSPluginFinish + +let &cpo = s:save_cpo diff --git a/.vim/plugin/vcsgit.vim b/.vim/plugin/vcsgit.vim new file mode 100644 index 0000000..9eb7483 --- /dev/null +++ b/.vim/plugin/vcsgit.vim @@ -0,0 +1,258 @@ +" vim600: set foldmethod=marker: +" +" git extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand +" License: +" Copyright (c) 2008 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 +" +" VCSCommandGitExec +" This variable specifies the git executable. If not set, it defaults to +" 'git' executed from the user's executable path. +" +" VCSCommandGitDiffOpt +" This variable, if set, determines the default options passed to the +" VCSDiff command. If any options (starting with '-') are passed to the +" command, this variable is not used. + +" 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 !executable(VCSCommandGetOption('VCSCommandGitExec', 'git')) + " git is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:gitFunctions = {} + +" Section: Utility functions {{{1 + +" 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 + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'git VCSCommand plugin called on non-git item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:gitFunctions.Identify(buffer) {{{2 +" This function only returns an inexact match due to the detection method used +" by git, which simply traverses the directory structure upward. +function! s:gitFunctions.Identify(buffer) + let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(a:buffer))) + try + call system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' rev-parse --is-inside-work-tree') + if(v:shell_error) + return 0 + else + return g:VCSCOMMAND_IDENTIFY_INEXACT + endif + finally + call VCSCommandChdir(oldCwd) + endtry +endfunction + +" Function: s:gitFunctions.Add(argList) {{{2 +function! s:gitFunctions.Add(argList) + return s:DoCommand(join(['add'] + ['-v'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:gitFunctions.Annotate(argList) {{{2 +function! s:gitFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'gitAnnotate' + " Perform annotation of the version indicated by the current line. + let options = matchstr(getline('.'),'^\x\+') + else + let options = '' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let options = a:argList[0] + else + 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 +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 + echomsg 'No commit needed.' + endif + return resultBuffer +endfunction + +" Function: s:gitFunctions.Delete() {{{2 +" All options are passed through. +function! s:gitFunctions.Delete(argList) + let options = a:argList + let caption = join(a:argList, ' ') + return s:DoCommand(join(['rm'] + options, ' '), 'delete', caption, {}) +endfunction + +" Function: s:gitFunctions.Diff(argList) {{{2 +" Pass-through call to git-diff. If no options (starting with '-') are found, +" then the options in the 'VCSCommandGitDiffOpt' variable are added. +function! s:gitFunctions.Diff(argList) + let gitDiffOpt = VCSCommandGetOption('VCSCommandGitDiffOpt', '') + if gitDiffOpt == '' + let diffOptions = [] + else + let diffOptions = [gitDiffOpt] + for arg in a:argList + if arg =~ '^-' + let diffOptions = [] + break + endif + 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 +endfunction + +" Function: s:gitFunctions.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. This CVS extension adds branch name to the return +" list as well. +" Returns: List of results: [revision, repository, branch] + +function! s:gitFunctions.GetBufferInfo() + let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname('%'))) + try + let branch = substitute(system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' symbolic-ref -q HEAD'), '\n$', '', '') + if v:shell_error + let branch = 'DETACHED' + else + let branch = substitute(branch, '^refs/heads/', '', '') + endif + + let info = [branch] + + for method in split(VCSCommandGetOption('VCSCommandGitDescribeArgList', (',tags,all,always')), ',', 1) + if method != '' + let method = ' --' . method + endif + let tag = substitute(system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' describe' . method), '\n$', '', '') + if !v:shell_error + call add(info, tag) + break + endif + endfor + + return info + finally + call VCSCommandChdir(oldCwd) + endtry +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 +endfunction + +" Function: s:gitFunctions.Revert(argList) {{{2 +function! s:gitFunctions.Revert(argList) + return s:DoCommand('checkout', 'revert', '', {}) +endfunction + +" Function: s:gitFunctions.Review(argList) {{{2 +function! s:gitFunctions.Review(argList) + if len(a:argList) == 0 + let revision = 'HEAD' + else + let revision = a:argList[0] + endif + + let oldCwd = VCSCommandChangeToCurrentFileDir(resolve(bufname(VCSCommandGetOriginalBuffer('%')))) + try + let prefix = system(VCSCommandGetOption('VCSCommandGitExec', 'git') . ' 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 +endfunction + +" Function: s:gitFunctions.Status(argList) {{{2 +function! s:gitFunctions.Status(argList) + return s:DoCommand(join(['status'] + a:argList), 'status', join(a:argList), {'allowNonZeroExit': 1}) +endfunction + +" Function: s:gitFunctions.Update(argList) {{{2 +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 + + +" Section: Plugin Registration {{{1 +call VCSCommandRegisterModule('git', expand(''), s:gitFunctions, []) + +let &cpo = s:save_cpo diff --git a/.vim/plugin/vcssvn.vim b/.vim/plugin/vcssvn.vim new file mode 100644 index 0000000..82793f4 --- /dev/null +++ b/.vim/plugin/vcssvn.vim @@ -0,0 +1,288 @@ +" vim600: set foldmethod=marker: +" +" SVN extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand +" License: +" Copyright (c) 2007 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 +" +" VCSCommandSVNExec +" This variable specifies the SVN executable. If not set, it defaults to +" 'svn' executed from the user's executable path. +" +" VCSCommandSVNDiffExt +" This variable, if set, sets the external diff program used by Subversion. +" +" VCSCommandSVNDiffOpt +" This variable, if set, determines the options passed to the svn 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 + +runtime plugin/vcscommand.vim + +if !executable(VCSCommandGetOption('VCSCommandSVNExec', 'svn')) + " SVN is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:svnFunctions = {} + +" Section: Utility functions {{{1 + +" 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 + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'SVN VCSCommand plugin called on non-SVN item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" 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 +endfunction + +" Function: s:svnFunctions.Add() {{{2 +function! s:svnFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:svnFunctions.Annotate(argList) {{{2 +function! s:svnFunctions.Annotate(argList) + if len(a:argList) == 0 + 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 + 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 --non-interactive' . options, 'annotate', caption, {}) + if resultBuffer > 0 + set filetype=SVNAnnotate + endif + return resultBuffer +endfunction + +" Function: s:svnFunctions.Commit(argList) {{{2 +function! s:svnFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit --non-interactive -F "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif +endfunction + +" Function: s:svnFunctions.Delete() {{{2 +function! s:svnFunctions.Delete(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 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 svnDiffExt = VCSCommandGetOption('VCSCommandSVNDiffExt', '') + if svnDiffExt == '' + let diffExt = [] + else + let diffExt = ['--diff-cmd ' . svnDiffExt] + endif + + let svnDiffOpt = VCSCommandGetOption('VCSCommandSVNDiffOpt', '') + if svnDiffOpt == '' + let diffOptions = [] + else + let diffOptions = ['-x -' . svnDiffOpt] + endif + + let resultBuffer = s:DoCommand(join(['diff --non-interactive'] + diffExt + diffOptions + revOptions), 'diff', caption, {}) + if resultBuffer > 0 + set filetype=diff + else + if svnDiffExt == '' + echomsg 'No differences found' + endif + endif + return resultBuffer +endfunction + +" Function: s:svnFunctions.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:svnFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = bufname(originalBuffer) + let statusText = system(VCSCommandGetOption('VCSCommandSVNExec', 'svn') . ' status --non-interactive -vu "' . fileName . '"') + if(v:shell_error) + return [] + endif + + " File not under SVN control. + if statusText =~ '^?' + return ['Unknown'] + endif + + let [flags, revision, repository] = matchlist(statusText, '^\(.\{8}\)\s\+\(\S\+\)\s\+\(\S\+\)\s\+\(\S\+\)\s')[1:3] + if revision == '' + " Error + return ['Unknown'] + elseif flags =~ '^A' + return ['New', 'New'] + else + return [revision, repository] + endif +endfunction + +" Function: s:svnFunctions.Info(argList) {{{2 +function! s:svnFunctions.Info(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 --non-interactive'] + a:argList, ' '), 'lock', join(a:argList, ' '), {}) +endfunction + +" Function: s:svnFunctions.Log(argList) {{{2 +function! s:svnFunctions.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 --non-interactive', '-v'] + options), 'log', caption, {}) + return resultBuffer +endfunction + +" Function: s:svnFunctions.Revert(argList) {{{2 +function! s:svnFunctions.Revert(argList) + return s:DoCommand('revert', 'revert', '', {}) +endfunction + +" Function: s:svnFunctions.Review(argList) {{{2 +function! s:svnFunctions.Review(argList) + if len(a:argList) == 0 + let versiontag = '(current)' + let versionOption = '' + else + let versiontag = a:argList[0] + let versionOption = ' -r ' . versiontag . ' ' + endif + + let resultBuffer = s:DoCommand('cat --non-interactive' . versionOption, 'review', versiontag, {}) + if resultBuffer > 0 + let &filetype = getbufvar(b:VCSCommandOriginalBuffer, '&filetype') + endif + return resultBuffer +endfunction + +" Function: s:svnFunctions.Status(argList) {{{2 +function! s:svnFunctions.Status(argList) + let options = ['-u', '-v'] + if len(a:argList) == 0 + let options = a:argList + endif + 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 --non-interactive'] + a:argList, ' '), 'unlock', join(a:argList, ' '), {}) +endfunction +" Function: s:svnFunctions.Update(argList) {{{2 +function! s:svnFunctions.Update(argList) + return s:DoCommand('update --non-interactive', 'update', '', {}) +endfunction + +" Section: Plugin Registration {{{1 +call VCSCommandRegisterModule('SVN', expand(''), s:svnFunctions, []) + +let &cpo = s:save_cpo diff --git a/.vim/syntax/SVNAnnotate.vim b/.vim/syntax/SVNAnnotate.vim new file mode 100644 index 0000000..d46f771 --- /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) 2007 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/gitAnnotate.vim b/.vim/syntax/gitAnnotate.vim new file mode 100644 index 0000000..fdc0bd1 --- /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) 2009 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/vcscommit.vim b/.vim/syntax/vcscommit.vim new file mode 100644 index 0000000..0cd4c5e --- /dev/null +++ b/.vim/syntax/vcscommit.vim @@ -0,0 +1,31 @@ +" Vim syntax file +" Language: VCS commit file +" Maintainer: Bob Hiestand (bob.hiestand@gmail.com) +" License: +" Copyright (c) 2007 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 + +syntax region vcsComment start="^VCS: " end="$" +highlight link vcsComment Comment +let b:current_syntax = "vcscommit"