diff options
author | René 'Necoro' Neumann <necoro@necoro.net> | 2009-11-05 18:12:46 +0100 |
---|---|---|
committer | René 'Necoro' Neumann <necoro@necoro.net> | 2009-11-05 18:12:46 +0100 |
commit | ab20e46dc4275b550e532dff7440c2ec63015ac4 (patch) | |
tree | 96be83c75e3ac9420f5577148939d0e91592ac98 /.vim/plugin | |
parent | cc33d52dd6479096db8f77130e470ae8c56e0a91 (diff) | |
download | dotfiles-ab20e46dc4275b550e532dff7440c2ec63015ac4.tar.gz dotfiles-ab20e46dc4275b550e532dff7440c2ec63015ac4.tar.bz2 dotfiles-ab20e46dc4275b550e532dff7440c2ec63015ac4.zip |
Added VCSCommand vim plugin.
Diffstat (limited to '')
-rw-r--r-- | .vim/plugin/vcsbzr.vim | 254 | ||||
-rw-r--r-- | .vim/plugin/vcscommand.vim | 1344 | ||||
-rw-r--r-- | .vim/plugin/vcscvs.vim | 453 | ||||
-rw-r--r-- | .vim/plugin/vcsgit.vim | 260 | ||||
-rwxr-xr-x | .vim/plugin/vcshg.vim | 275 | ||||
-rw-r--r-- | .vim/plugin/vcssvk.vim | 262 | ||||
-rw-r--r-- | .vim/plugin/vcssvn.vim | 292 |
7 files changed, 3140 insertions, 0 deletions
diff --git a/.vim/plugin/vcsbzr.vim b/.vim/plugin/vcsbzr.vim new file mode 100644 index 0000000..60dc455 --- /dev/null +++ b/.vim/plugin/vcsbzr.vim @@ -0,0 +1,254 @@ +" vim600: set foldmethod=marker: +" +" BZR extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" 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. +" +" Section: Documentation {{{1 +" +" Options documentation: {{{2 +" +" VCSCommandBZRExec +" This variable specifies the BZR executable. If not set, it defaults to +" 'bzr' executed from the user's executable path. + +" Section: Plugin header {{{1 + +if 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 + +runtime plugin/vcscommand.vim + +if !executable(VCSCommandGetOption('VCSCommandBZRExec', 'bzr')) + " BZR is not installed + finish +endif + +" Section: Variable initialization {{{1 + +let s:bzrFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:DoCommand(cmd, cmdName, statusText) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the BZR executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'BZR' + let fullCmd = VCSCommandGetOption('VCSCommandBZRExec', 'bzr') . ' ' . a:cmd + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'BZR VCSCommand plugin called on non-BZR item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:bzrFunctions.Identify(buffer) {{{2 +function! s:bzrFunctions.Identify(buffer) + let fileName = resolve(bufname(a:buffer)) + let statusText = system(VCSCommandGetOption('VCSCommandBZRExec', 'bzr') . ' info "' . fileName . '"') + if(v:shell_error) + return 0 + else + return 1 + endif +endfunction + +" Function: s:bzrFunctions.Add() {{{2 +function! s:bzrFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Annotate(argList) {{{2 +function! s:bzrFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'BZRAnnotate' + " Perform annotation of the version indicated by the current line. + let caption = matchstr(getline('.'),'\v^\s+\zs\d+') + let options = ' -r' . caption + else + let caption = '' + let options = '' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let caption = a:argList[0] + let options = ' -r' . caption + else + let caption = join(a:argList, ' ') + let options = ' ' . caption + endif + + let resultBuffer = s:DoCommand('blame' . options, 'annotate', caption, {}) + if resultBuffer > 0 + normal 1G2dd + set filetype=BZRAnnotate + endif + return resultBuffer +endfunction + +" Function: s:bzrFunctions.Commit(argList) {{{2 +function! s:bzrFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif +endfunction + +" Function: s:bzrFunctions.Delete() {{{2 +function! s:bzrFunctions.Delete(argList) + return s:DoCommand(join(['rm'] + a:argList, ' '), 'rm', join(a:argList, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Diff(argList) {{{2 +function! s:bzrFunctions.Diff(argList) + if len(a:argList) == 0 + let revOptions = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let revOptions = ['-r' . join(a:argList, '..')] + let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')' + else + " Pass-through + let caption = join(a:argList, ' ') + let revOptions = a:argList + endif + + let resultBuffer = s:DoCommand(join(['diff'] + revOptions), 'diff', caption, {'allowNonZeroExit': 1}) + if resultBuffer > 0 + set filetype=diff + else + echomsg 'No differences found' + endif + return resultBuffer +endfunction + +" Function: s:bzrFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. +" Returns: List of results: [revision, repository] + +function! s:bzrFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = resolve(bufname(originalBuffer)) + let statusText = system(VCSCommandGetOption('VCSCommandBZRExec', 'bzr') . ' status -S "' . fileName . '"') + let revision = system(VCSCommandGetOption('VCSCommandBZRExec', 'bzr') . ' revno "' . fileName . '"') + if(v:shell_error) + return [] + endif + + " File not under BZR control. + if statusText =~ '^?' + return ['Unknown'] + endif + + let [flags, repository] = matchlist(statusText, '^\(.\{3}\)\s\+\(\S\+\)')[1:2] + if revision == '' + " Error + return ['Unknown'] + elseif flags =~ '^A' + return ['New', 'New'] + else + return [revision, repository] + endif +endfunction + +" Function: s:bzrFunctions.Info(argList) {{{2 +function! s:bzrFunctions.Info(argList) + return s:DoCommand(join(['version-info'] + a:argList, ' '), 'version-info', join(a:argList, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Lock(argList) {{{2 +function! s:bzrFunctions.Lock(argList) + echomsg 'bzr lock is not necessary' +endfunction + +" Function: s:bzrFunctions.Log() {{{2 +function! s:bzrFunctions.Log(argList) + if len(a:argList) == 0 + let options = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let options = ['-r' . join(a:argList, ':')] + let caption = options[0] + else + " Pass-through + let options = a:argList + let caption = join(a:argList, ' ') + endif + + let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {}) + return resultBuffer +endfunction + +" Function: s:bzrFunctions.Revert(argList) {{{2 +function! s:bzrFunctions.Revert(argList) + return s:DoCommand('revert', 'revert', '', {}) +endfunction + +" Function: s:bzrFunctions.Review(argList) {{{2 +function! s:bzrFunctions.Review(argList) + if len(a:argList) == 0 + let versiontag = '(current)' + let versionOption = '' + else + let versiontag = a:argList[0] + let versionOption = ' -r ' . versiontag . ' ' + endif + + let resultBuffer = s:DoCommand('cat' . versionOption, 'review', versiontag, {}) + if resultBuffer > 0 + let &filetype=getbufvar(b:VCSCommandOriginalBuffer, '&filetype') + endif + return resultBuffer +endfunction + +" Function: s:bzrFunctions.Status(argList) {{{2 +function! s:bzrFunctions.Status(argList) + let options = ['-S'] + if len(a:argList) == 0 + let options = a:argList + endif + return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {}) +endfunction + +" Function: s:bzrFunctions.Unlock(argList) {{{2 +function! s:bzrFunctions.Unlock(argList) + echomsg 'bzr unlock is not necessary' +endfunction +" Function: s:bzrFunctions.Update(argList) {{{2 +function! s:bzrFunctions.Update(argList) + return s:DoCommand('update', 'update', '', {}) +endfunction + +" Section: Plugin Registration {{{1 +call VCSCommandRegisterModule('BZR', expand('<sfile>'), s:bzrFunctions, []) + +let &cpo = s:save_cpo diff --git a/.vim/plugin/vcscommand.vim b/.vim/plugin/vcscommand.vim new file mode 100644 index 0000000..2070e1a --- /dev/null +++ b/.vim/plugin/vcscommand.vim @@ -0,0 +1,1344 @@ +" 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. +" +" Version: 1.99.31 +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" 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. +" +" If '!' is used, the view of the annotated buffer is split +" so that the annotation is in a separate window from the +" content, and each is highlighted separately. +" +" VCSBlame Alias for 'VCSAnnotate'. +" +" VCSCommit[!] Commits changes to the current file to source control. +" +" 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 <Plug>CommandName, for instance: +" +" nmap ,ca <Plug>VCSAdd +" +" The default mappings are as follow: +" +" <Leader>ca VCSAdd +" <Leader>cn VCSAnnotate +" <Leader>cN VCSAnnotate! +" <Leader>cc VCSCommit +" <Leader>cD VCSDelete +" <Leader>cd VCSDiff +" <Leader>cg VCSGotoOriginal +" <Leader>cG VCSGotoOriginal! +" <Leader>ci VCSInfo +" <Leader>cl VCSLog +" <Leader>cL VCSLock +" <Leader>cr VCSReview +" <Leader>cs VCSStatus +" <Leader>cu VCSUpdate +" <Leader>cU VCSUnlock +" <Leader>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 ('<Leader>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 <unique> <buffer> q :bwipeout<cr> +" 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 '<Leader>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', '<Leader>c') . a:shortcut + if !hasmapto(a:expansion) + try + execute 'nmap <silent> <unique>' 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] . "\<CR>" +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') + + " 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 + + call s:SetupScratchBuffer(a:command, vcsType, a:originalBuffer, a:statusText) + + finally + let s:isEditFileRunning -= 1 + endtry +endfunction + +" Function: s:SetupScratchBuffer(command, vcsType, originalBuffer, statusText) {{{2 +" Creates convenience buffer variables and the name of a vcscommand result +" buffer. + +function! s:SetupScratchBuffer(command, vcsType, originalBuffer, statusText) + let nameExtension = VCSCommandGetOption('VCSCommandResultBufferNameExtension', '') + if nameExtension == '' + let nameFunction = VCSCommandGetOption('VCSCommandResultBufferNameFunction', 's:GenerateResultBufferName') + else + let nameFunction = VCSCommandGetOption('VCSCommandResultBufferNameFunction', 's:GenerateResultBufferNameWithExtension') + endif + + let name = call(nameFunction, [a:command, a:originalBuffer, a:vcsType, a:statusText]) + + let b:VCSCommandCommand = a:command + let b:VCSCommandOriginalBuffer = a:originalBuffer + let b:VCSCommandSourceFile = bufname(a:originalBuffer) + let b:VCSCommandVCSType = a:vcsType + if a:statusText != '' + let b:VCSCommandStatusText = a:statusText + endif + + setlocal buftype=nofile + setlocal noswapfile + let &filetype = a:vcsType . a:command + + if VCSCommandGetOption('VCSCommandDeleteOnHide', 0) + setlocal bufhidden=delete + endif + silent noautocmd file `=name` +endfunction + +" Function: s:SetupBuffer() {{{2 +" Attempts to set the b:VCSCommandBufferInfo variable + +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:VCSAnnotate(...) {{{2 +function! s:VCSAnnotate(bang, ...) + try + let annotateBuffer = s:ExecuteVCSCommand('Annotate', a:000) + if annotateBuffer == -1 + return -1 + endif + if a:bang == '!' && VCSCommandGetOption('VCSCommandDisableSplitAnnotate', 0) == 0 + let vcsType = VCSCommandGetVCSType(annotateBuffer) + let functionMap = s:plugins[vcsType][1] + let splitRegex = '' + if has_key(s:plugins[vcsType][1], 'AnnotateSplitRegex') + let splitRegex = s:plugins[vcsType][1]['AnnotateSplitRegex'] + endif + let splitRegex = VCSCommandGetOption('VCSCommand' . vcsType . 'AnnotateSplitRegex', splitRegex) + if splitRegex == '' + return annotateBuffer + endif + let originalBuffer = VCSCommandGetOriginalBuffer(annotateBuffer) + let originalFileType = getbufvar(originalBuffer, '&ft') + let annotateFileType = getbufvar(annotateBuffer, '&ft') + execute "normal 0zR\<c-v>G/" . splitRegex . "/e\<cr>d" + call setbufvar('%', '&filetype', getbufvar(originalBuffer, '&filetype')) + set scrollbind + leftabove vert new + normal 0P + execute "normal" . col('$') . "\<c-w>|" + call s:SetupScratchBuffer('annotate', vcsType, originalBuffer, 'header') + wincmd l + endif + return annotateBuffer + catch + call s:ReportError(v:exception) + return -1 + endtry +endfunction + +" 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 <silent> <buffer> <Plug>VCSCommit :call <SID>VCSFinishCommitWithBuffer()<CR> + + 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 <leader>cc (or your own <Plug>VCSCommit mapping)' + + if VCSCommandGetOption('VCSCommandCommitOnWrite', 1) == 1 + setlocal buftype=acwrite + au VCSCommandCommit BufWriteCmd <buffer> 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 <SID>ExecuteExtensionMapping('" . shortcut . "')<CR>" + 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 +" <VCSCOMMANDFILE>, 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, '<VCSCOMMANDFILE>') > 0 + let fullCmd = substitute(a:cmd, '<VCSCOMMANDFILE>', 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', [<f-args>])) +com! -nargs=* -bang VCSAnnotate call s:VCSAnnotate(<q-bang>, <f-args>) +com! -nargs=* -bang VCSBlame call s:VCSAnnotate(<q-bang>, <f-args>) +com! -nargs=? -bang VCSCommit call s:VCSCommit(<q-bang>, <q-args>) +com! -nargs=* VCSDelete call s:ExecuteVCSCommand('Delete', [<f-args>]) +com! -nargs=* VCSDiff call s:ExecuteVCSCommand('Diff', [<f-args>]) +com! -nargs=0 -bang VCSGotoOriginal call s:VCSGotoOriginal(<q-bang>) +com! -nargs=* VCSInfo call s:ExecuteVCSCommand('Info', [<f-args>]) +com! -nargs=* VCSLock call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Lock', [<f-args>])) +com! -nargs=* VCSLog call s:ExecuteVCSCommand('Log', [<f-args>]) +com! -nargs=* VCSRemove call s:ExecuteVCSCommand('Delete', [<f-args>]) +com! -nargs=0 VCSRevert call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Revert', [])) +com! -nargs=? VCSReview call s:ExecuteVCSCommand('Review', [<f-args>]) +com! -nargs=* VCSStatus call s:ExecuteVCSCommand('Status', [<f-args>]) +com! -nargs=* VCSUnlock call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Unlock', [<f-args>])) +com! -nargs=0 VCSUpdate call s:MarkOrigBufferForSetup(s:ExecuteVCSCommand('Update', [])) +com! -nargs=* VCSVimDiff call s:VCSVimDiff(<f-args>) + +" 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 <silent> <Plug>VCSAdd :VCSAdd<CR> +nnoremap <silent> <Plug>VCSAnnotate :VCSAnnotate<CR> +nnoremap <silent> <Plug>VCSCommit :VCSCommit<CR> +nnoremap <silent> <Plug>VCSDelete :VCSDelete<CR> +nnoremap <silent> <Plug>VCSDiff :VCSDiff<CR> +nnoremap <silent> <Plug>VCSGotoOriginal :VCSGotoOriginal<CR> +nnoremap <silent> <Plug>VCSClearAndGotoOriginal :VCSGotoOriginal!<CR> +nnoremap <silent> <Plug>VCSInfo :VCSInfo<CR> +nnoremap <silent> <Plug>VCSLock :VCSLock<CR> +nnoremap <silent> <Plug>VCSLog :VCSLog<CR> +nnoremap <silent> <Plug>VCSRevert :VCSRevert<CR> +nnoremap <silent> <Plug>VCSReview :VCSReview<CR> +nnoremap <silent> <Plug>VCSSplitAnnotate :VCSAnnotate!<CR> +nnoremap <silent> <Plug>VCSStatus :VCSStatus<CR> +nnoremap <silent> <Plug>VCSUnlock :VCSUnlock<CR> +nnoremap <silent> <Plug>VCSUpdate :VCSUpdate<CR> +nnoremap <silent> <Plug>VCSVimDiff :VCSVimDiff<CR> + +" 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', 'VCSSplitAnnotate'], + \['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, '<Plug>' . vcsFunction, '''' . vcsFunction . '''') + endfor +endif + +" Section: Menu items {{{1 +amenu <silent> &Plugin.VCS.&Add <Plug>VCSAdd +amenu <silent> &Plugin.VCS.A&nnotate <Plug>VCSAnnotate +amenu <silent> &Plugin.VCS.&Commit <Plug>VCSCommit +amenu <silent> &Plugin.VCS.Delete <Plug>VCSDelete +amenu <silent> &Plugin.VCS.&Diff <Plug>VCSDiff +amenu <silent> &Plugin.VCS.&Info <Plug>VCSInfo +amenu <silent> &Plugin.VCS.&Log <Plug>VCSLog +amenu <silent> &Plugin.VCS.Revert <Plug>VCSRevert +amenu <silent> &Plugin.VCS.&Review <Plug>VCSReview +amenu <silent> &Plugin.VCS.&Status <Plug>VCSStatus +amenu <silent> &Plugin.VCS.&Update <Plug>VCSUpdate +amenu <silent> &Plugin.VCS.&VimDiff <Plug>VCSVimDiff + +" Section: Autocommands to restore vimdiff state {{{1 +augroup VimDiffRestore + au! + au BufUnload * call s:VimDiffRestore(str2nr(expand('<abuf>'))) +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/vcscvs.vim b/.vim/plugin/vcscvs.vim new file mode 100644 index 0000000..a548276 --- /dev/null +++ b/.vim/plugin/vcscvs.vim @@ -0,0 +1,453 @@ +" vim600: set foldmethod=marker: +" +" CVS extension for VCSCommand. +" +" Version: VCS development +" 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. +" +" Section: Documentation {{{1 +" +" Command documentation {{{2 +" +" The following commands only apply to files under CVS source control. +" +" CVSEdit Performs "cvs edit" on the current file. +" +" CVSEditors Performs "cvs editors" on the current file. +" +" CVSUnedit Performs "cvs unedit" on the current file. +" +" CVSWatch Takes an argument which must be one of [on|off|add|remove]. +" Performs "cvs watch" with the given argument on the current +" file. +" +" CVSWatchers Performs "cvs watchers" on the current file. +" +" CVSWatchAdd Alias for "CVSWatch add" +" +" CVSWatchOn Alias for "CVSWatch on" +" +" CVSWatchOff Alias for "CVSWatch off" +" +" CVSWatchRemove Alias for "CVSWatch remove" +" +" Mapping documentation: {{{2 +" +" By default, a mapping is defined for each command. User-provided mappings +" can be used instead by mapping to <Plug>CommandName, for instance: +" +" nnoremap ,ce <Plug>CVSEdit +" +" The default mappings are as follow: +" +" <Leader>ce CVSEdit +" <Leader>cE CVSEditors +" <Leader>ct CVSUnedit +" <Leader>cwv CVSWatchers +" <Leader>cwa CVSWatchAdd +" <Leader>cwn CVSWatchOn +" <Leader>cwf CVSWatchOff +" <Leader>cwr CVSWatchRemove +" +" Options documentation: {{{2 +" +" VCSCommandCVSExec +" This variable specifies the CVS executable. If not set, it defaults to +" 'cvs' executed from the user's executable path. +" +" VCSCommandCVSDiffOpt +" This variable, if set, determines the options passed to the cvs diff +" command. If not set, it defaults to 'u'. + +" 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('VCSCommandCVSExec', 'cvs')) + " CVS is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:cvsFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the CVS executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'CVS' + let fullCmd = VCSCommandGetOption('VCSCommandCVSExec', 'cvs') . ' ' . a:cmd + let ret = VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + + if ret > 0 + if getline(line('$')) =~ '^cvs \w\+: closing down connection' + $d + 1 + endif + + endif + + return ret + else + throw 'CVS VCSCommand plugin called on non-CVS item.' + endif +endfunction + +" Function: GetRevision() {{{2 +" Function for retrieving the current buffer's revision number. +" Returns: Revision number or an empty string if an error occurs. + +function! GetRevision() + if !exists('b:VCSCommandBufferInfo') + let b:VCSCommandBufferInfo = s:cvsFunctions.GetBufferInfo() + endif + + if len(b:VCSCommandBufferInfo) > 0 + return b:VCSCommandBufferInfo[0] + else + return '' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:cvsFunctions.Identify(buffer) {{{2 +function! s:cvsFunctions.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 CVSRoot = directoryName . '/CVS/Root' + else + let CVSRoot = 'CVS/Root' + endif + if filereadable(CVSRoot) + return 1 + else + return 0 + endif +endfunction + +" Function: s:cvsFunctions.Add(argList) {{{2 +function! s:cvsFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:cvsFunctions.Annotate(argList) {{{2 +function! s:cvsFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'CVSAnnotate' + " This is a CVSAnnotate buffer. Perform annotation of the version + " indicated by the current line. + let caption = matchstr(getline('.'),'\v^[0-9.]+') + + if VCSCommandGetOption('VCSCommandCVSAnnotateParent', 0) != 0 + if caption != '1.1' + let revmaj = matchstr(caption,'\v[0-9.]+\ze\.[0-9]+') + let revmin = matchstr(caption,'\v[0-9.]+\.\zs[0-9]+') - 1 + if revmin == 0 + " Jump to ancestor branch + let caption = matchstr(revmaj,'\v[0-9.]+\ze\.[0-9]+') + else + let caption = revmaj . "." . revmin + endif + endif + endif + + let options = ['-r' . caption] + else + " CVS defaults to pulling HEAD, regardless of current branch. + " Therefore, always pass desired revision. + let caption = '' + let options = ['-r' . GetRevision()] + 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 = a:argList + endif + + let resultBuffer = s:DoCommand(join(['-q', 'annotate'] + options), 'annotate', caption, {}) + if resultBuffer > 0 + set filetype=CVSAnnotate + " Remove header lines from standard error + silent v/^\d\+\%(\.\d\+\)\+/d + endif + return resultBuffer +endfunction + +" Function: s:cvsFunctions.Commit(argList) {{{2 +function! s:cvsFunctions.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:cvsFunctions.Delete() {{{2 +" By default, use the -f option to remove the file first. If options are +" passed in, use those instead. +function! s:cvsFunctions.Delete(argList) + let options = ['-f'] + let caption = '' + if len(a:argList) > 0 + let options = a:argList + let caption = join(a:argList, ' ') + endif + return s:DoCommand(join(['remove'] + options, ' '), 'delete', caption, {}) +endfunction + +" Function: s:cvsFunctions.Diff(argList) {{{2 +function! s:cvsFunctions.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, ' -r')] + let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')' + else + " Pass-through + let caption = join(a:argList, ' ') + let revOptions = a:argList + endif + + let cvsDiffOpt = VCSCommandGetOption('VCSCommandCVSDiffOpt', 'u') + if cvsDiffOpt == '' + let diffOptions = [] + else + let diffOptions = ['-' . cvsDiffOpt] + endif + + let resultBuffer = s:DoCommand(join(['diff'] + diffOptions + revOptions), 'diff', caption, {'allowNonZeroExit': 1}) + if resultBuffer > 0 + set filetype=diff + else + echomsg 'No differences found' + endif + return resultBuffer +endfunction + +" Function: s:cvsFunctions.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:cvsFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = bufname(originalBuffer) + if isdirectory(fileName) + let tag = '' + if filereadable(fileName . '/CVS/Tag') + let tagFile = readfile(fileName . '/CVS/Tag') + if len(tagFile) == 1 + let tag = substitute(tagFile[0], '^T', '', '') + endif + endif + return [tag] + endif + let realFileName = fnamemodify(resolve(fileName), ':t') + if !filereadable(fileName) + return ['Unknown'] + endif + let oldCwd = VCSCommandChangeToCurrentFileDir(fileName) + try + let statusText=system(VCSCommandGetOption('VCSCommandCVSExec', 'cvs') . ' status "' . realFileName . '"') + if(v:shell_error) + return [] + endif + let revision=substitute(statusText, '^\_.*Working revision:\s*\(\d\+\%(\.\d\+\)\+\|New file!\)\_.*$', '\1', '') + + " We can still be in a CVS-controlled directory without this being a CVS + " file + if match(revision, '^New file!$') >= 0 + let revision='New' + elseif match(revision, '^\d\+\.\d\+\%(\.\d\+\.\d\+\)*$') <0 + return ['Unknown'] + endif + + let branch=substitute(statusText, '^\_.*Sticky Tag:\s\+\(\d\+\%(\.\d\+\)\+\|\a[A-Za-z0-9-_]*\|(none)\).*$', '\1', '') + let repository=substitute(statusText, '^\_.*Repository revision:\s*\(\d\+\%(\.\d\+\)\+\|New file!\|No revision control file\)\_.*$', '\1', '') + let repository=substitute(repository, '^New file!\|No revision control file$', 'New', '') + return [revision, repository, branch] + finally + call VCSCommandChdir(oldCwd) + endtry +endfunction + +" Function: s:cvsFunctions.Log() {{{2 +function! s:cvsFunctions.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'] + options), 'log', caption, {}) + if resultBuffer > 0 + set filetype=rcslog + endif + return resultBuffer +endfunction + +" Function: s:cvsFunctions.Revert(argList) {{{2 +function! s:cvsFunctions.Revert(argList) + return s:DoCommand('update -C', 'revert', '', {}) +endfunction + +" Function: s:cvsFunctions.Review(argList) {{{2 +function! s:cvsFunctions.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('-q update -p' . versionOption, 'review', versiontag, {}) + if resultBuffer > 0 + let &filetype=getbufvar(b:VCSCommandOriginalBuffer, '&filetype') + endif + return resultBuffer +endfunction + +" Function: s:cvsFunctions.Status(argList) {{{2 +function! s:cvsFunctions.Status(argList) + return s:DoCommand(join(['status'] + a:argList, ' '), 'status', join(a:argList, ' '), {}) +endfunction + +" Function: s:cvsFunctions.Update(argList) {{{2 +function! s:cvsFunctions.Update(argList) + return s:DoCommand('update', 'update', '', {}) +endfunction + +" Section: CVS-specific functions {{{1 + +" Function: s:CVSEdit() {{{2 +function! s:CVSEdit() + return s:DoCommand('edit', 'cvsedit', '', {}) +endfunction + +" Function: s:CVSEditors() {{{2 +function! s:CVSEditors() + return s:DoCommand('editors', 'cvseditors', '', {}) +endfunction + +" Function: s:CVSUnedit() {{{2 +function! s:CVSUnedit() + return s:DoCommand('unedit', 'cvsunedit', '', {}) +endfunction + +" Function: s:CVSWatch(onoff) {{{2 +function! s:CVSWatch(onoff) + if a:onoff !~ '^\c\%(on\|off\|add\|remove\)$' + echoerr 'Argument to CVSWatch must be one of [on|off|add|remove]' + return -1 + end + return s:DoCommand('watch ' . tolower(a:onoff), 'cvswatch', '', {}) +endfunction + +" Function: s:CVSWatchers() {{{2 +function! s:CVSWatchers() + return s:DoCommand('watchers', 'cvswatchers', '', {}) +endfunction + +" Annotate setting {{{2 +let s:cvsFunctions.AnnotateSplitRegex = '): ' + +" Section: Command definitions {{{1 +" Section: Primary commands {{{2 +com! CVSEdit call s:CVSEdit() +com! CVSEditors call s:CVSEditors() +com! CVSUnedit call s:CVSUnedit() +com! -nargs=1 CVSWatch call s:CVSWatch(<f-args>) +com! CVSWatchAdd call s:CVSWatch('add') +com! CVSWatchOn call s:CVSWatch('on') +com! CVSWatchOff call s:CVSWatch('off') +com! CVSWatchRemove call s:CVSWatch('remove') +com! CVSWatchers call s:CVSWatchers() + +" Section: Plugin command mappings {{{1 + +let s:cvsExtensionMappings = {} +let mappingInfo = [ + \['CVSEdit', 'CVSEdit', 'e'], + \['CVSEditors', 'CVSEditors', 'E'], + \['CVSUnedit', 'CVSUnedit', 't'], + \['CVSWatchers', 'CVSWatchers', 'wv'], + \['CVSWatchAdd', 'CVSWatch add', 'wa'], + \['CVSWatchOff', 'CVSWatch off', 'wf'], + \['CVSWatchOn', 'CVSWatch on', 'wn'], + \['CVSWatchRemove', 'CVSWatch remove', 'wr'] + \] + +for [pluginName, commandText, shortCut] in mappingInfo + execute 'nnoremap <silent> <Plug>' . pluginName . ' :' . commandText . '<CR>' + if !hasmapto('<Plug>' . pluginName) + let s:cvsExtensionMappings[shortCut] = commandText + endif +endfor + +" Section: Menu items {{{1 +amenu <silent> &Plugin.VCS.CVS.&Edit <Plug>CVSEdit +amenu <silent> &Plugin.VCS.CVS.Ed&itors <Plug>CVSEditors +amenu <silent> &Plugin.VCS.CVS.Unedi&t <Plug>CVSUnedit +amenu <silent> &Plugin.VCS.CVS.&Watchers <Plug>CVSWatchers +amenu <silent> &Plugin.VCS.CVS.WatchAdd <Plug>CVSWatchAdd +amenu <silent> &Plugin.VCS.CVS.WatchOn <Plug>CVSWatchOn +amenu <silent> &Plugin.VCS.CVS.WatchOff <Plug>CVSWatchOff +amenu <silent> &Plugin.VCS.CVS.WatchRemove <Plug>CVSWatchRemove + +" Section: Plugin Registration {{{1 +call VCSCommandRegisterModule('CVS', expand('<sfile>'), s:cvsFunctions, s:cvsExtensionMappings) + +let &cpo = s:save_cpo diff --git a/.vim/plugin/vcsgit.vim b/.vim/plugin/vcsgit.vim new file mode 100644 index 0000000..d2eb50f --- /dev/null +++ b/.vim/plugin/vcsgit.vim @@ -0,0 +1,260 @@ +" vim600: set foldmethod=marker: +" +" git extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" 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 . '<VCSCOMMANDFILE>"' + 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 + +" Annotate setting {{{2 +let s:gitFunctions.AnnotateSplitRegex = ') ' + +" Section: Plugin Registration {{{1 +call VCSCommandRegisterModule('git', expand('<sfile>'), s:gitFunctions, []) + +let &cpo = s:save_cpo diff --git a/.vim/plugin/vcshg.vim b/.vim/plugin/vcshg.vim new file mode 100755 index 0000000..deff5cd --- /dev/null +++ b/.vim/plugin/vcshg.vim @@ -0,0 +1,275 @@ +" vim600: set foldmethod=marker: +" +" Mercurial extension for VCSCommand. +" +" Version: VCS development +" Maintainer: Bob Hiestand <bob.hiestand@gmail.com> +" 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. +" +" Section: Documentation {{{1 +" +" Options documentation: {{{2 +" +" VCSCommandHGExec +" This variable specifies the mercurial executable. If not set, it defaults +" to 'hg' executed from the user's executable path. +" +" VCSCommandHGDiffExt +" This variable, if set, sets the external diff program used by Subversion. +" +" VCSCommandHGDiffOpt +" This variable, if set, determines the options passed to the hg diff +" command (such as 'u', 'w', or 'b'). + +" Section: Plugin header {{{1 + +if exists('VCSCommandDisableAll') + finish +endif + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +runtime plugin/vcscommand.vim + +if !executable(VCSCommandGetOption('VCSCommandHGExec', 'hg')) + " HG is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:hgFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the HG executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'HG' + let fullCmd = VCSCommandGetOption('VCSCommandHGExec', 'hg') . ' ' . a:cmd + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'HG VCSCommand plugin called on non-HG item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:hgFunctions.Identify(buffer) {{{2 +function! s:hgFunctions.Identify(buffer) + call system(VCSCommandGetOption('VCSCommandHGExec', 'hg') . ' root') + if(v:shell_error) + return 0 + else + return g:VCSCOMMAND_IDENTIFY_INEXACT + endif +endfunction + +" Function: s:hgFunctions.Add() {{{2 +function! s:hgFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:hgFunctions.Annotate(argList) {{{2 +function! s:hgFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'HGAnnotate' + " Perform annotation of the version indicated by the current line. + let caption = matchstr(getline('.'),'\v^\s+\zs\d+') + let options = ' -r' . caption + else + let caption = '' + let options = '' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let caption = a:argList[0] + let options = ' -r' . caption + else + let caption = join(a:argList, ' ') + let options = ' ' . caption + endif + + let resultBuffer = s:DoCommand('blame' . options, 'annotate', caption, {}) + if resultBuffer > 0 + set filetype=HGAnnotate + endif + return resultBuffer +endfunction + +" Function: s:hgFunctions.Commit(argList) {{{2 +function! s:hgFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit -l "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif +endfunction + +" Function: s:hgFunctions.Delete() {{{2 +function! s:hgFunctions.Delete(argList) + return s:DoCommand(join(['remove'] + a:argList, ' '), 'remove', join(a:argList, ' '), {}) +endfunction + +" Function: s:hgFunctions.Diff(argList) {{{2 +function! s:hgFunctions.Diff(argList) + if len(a:argList) == 0 + let revOptions = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let revOptions = ['-r' . join(a:argList, ':')] + let caption = '(' . a:argList[0] . ' : ' . get(a:argList, 1, 'current') . ')' + else + " Pass-through + let caption = join(a:argList, ' ') + let revOptions = a:argList + endif + + let hgDiffExt = VCSCommandGetOption('VCSCommandHGDiffExt', '') + if hgDiffExt == '' + let diffExt = [] + else + let diffExt = ['--diff-cmd ' . hgDiffExt] + endif + + let hgDiffOpt = VCSCommandGetOption('VCSCommandHGDiffOpt', '') + if hgDiffOpt == '' + let diffOptions = [] + else + let diffOptions = ['-x -' . hgDiffOpt] + endif + + let resultBuffer = s:DoCommand(join(['diff'] + diffExt + diffOptions + revOptions), 'diff', caption, {}) + if resultBuffer > 0 + set filetype=diff + else + if hgDiffExt == '' + echomsg 'No differences found' + endif + endif + return resultBuffer +endfunction + +" Function: s:hgFunctions.Info(argList) {{{2 +function! s:hgFunctions.Info(argList) + return s:DoCommand(join(['log --limit 1'] + a:argList, ' '), 'log', join(a:argList, ' '), {}) +endfunction + +" Function: s:hgFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. +" Returns: List of results: [revision, repository, branch] + +function! s:hgFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = bufname(originalBuffer) + let statusText = system(VCSCommandGetOption('VCSCommandHGExec', 'hg') . ' status "' . fileName . '"') + if(v:shell_error) + return [] + endif + + " File not under HG control. + if statusText =~ '^?' + return ['Unknown'] + endif + + let parentsText = system(VCSCommandGetOption('VCSCommandHGExec', 'hg') . ' parents "' . fileName . '"') + let [revision] = matchlist(parentsText, '^changeset:\s\+\(\S\+\)\n')[1] + + let logText = system(VCSCommandGetOption('VCSCommandHGExec', 'hg') . ' log "' . fileName . '"') + let [repository] = matchlist(logText, '^changeset:\s\+\(\S\+\)\n')[1] + + if revision == '' + " Error + return ['Unknown'] + elseif statusText =~ '^A' + return ['New', 'New'] + else + return [revision, repository] + endif +endfunction + +" Function: s:hgFunctions.Log(argList) {{{2 +function! s:hgFunctions.Log(argList) + if len(a:argList) == 0 + let options = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let options = ['-r' . join(a:argList, ':')] + let caption = options[0] + else + " Pass-through + let options = a:argList + let caption = join(a:argList, ' ') + endif + + let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {}) + return resultBuffer +endfunction + +" Function: s:hgFunctions.Revert(argList) {{{2 +function! s:hgFunctions.Revert(argList) + return s:DoCommand('revert', 'revert', '', {}) +endfunction + +" Function: s:hgFunctions.Review(argList) {{{2 +function! s:hgFunctions.Review(argList) + if len(a:argList) == 0 + let versiontag = '(current)' + let versionOption = '' + else + let versiontag = a:argList[0] + let versionOption = ' -r ' . versiontag . ' ' + endif + +" let resultBuffer = s:DoCommand('cat --non-interactive' . versionOption, 'review', versiontag, {}) + let resultBuffer = s:DoCommand('cat' . versionOption, 'review', versiontag, {}) + if resultBuffer > 0 + let &filetype = getbufvar(b:VCSCommandOriginalBuffer, '&filetype') + endif + return resultBuffer +endfunction + +" Function: s:hgFunctions.Status(argList) {{{2 +function! s:hgFunctions.Status(argList) + let options = ['-u', '-v'] + if len(a:argList) == 0 + let options = a:argList + endif + return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {}) +endfunction + +" Function: s:hgFunctions.Update(argList) {{{2 +function! s:hgFunctions.Update(argList) + return s:DoCommand('update', 'update', '', {}) +endfunction + +" Section: Plugin Registration {{{1 +call VCSCommandRegisterModule('HG', expand('<sfile>'), s:hgFunctions, []) + +let &cpo = s:save_cpo diff --git a/.vim/plugin/vcssvk.vim b/.vim/plugin/vcssvk.vim new file mode 100644 index 0000000..f79f578 --- /dev/null +++ b/.vim/plugin/vcssvk.vim @@ -0,0 +1,262 @@ +" vim600: set foldmethod=marker: +" +" SVK extension for VCSCommand. +" +" Version: VCS development +" 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. +" +" Section: Documentation {{{1 +" +" Options documentation: {{{2 +" +" VCSCommandSVKExec +" This variable specifies the SVK executable. If not set, it defaults to +" 'svk' executed from the user's executable path. + +" Section: Plugin header {{{1 + +if exists('VCSCommandDisableAll') + finish +endif + +if v:version < 700 + echohl WarningMsg|echomsg 'VCSCommand requires at least VIM 7.0'|echohl None + finish +endif + +runtime plugin/vcscommand.vim + +if !executable(VCSCommandGetOption('VCSCommandSVKExec', 'svk')) + " SVK is not installed + finish +endif + +let s:save_cpo=&cpo +set cpo&vim + +" Section: Variable initialization {{{1 + +let s:svkFunctions = {} + +" Section: Utility functions {{{1 + +" Function: s:DoCommand(cmd, cmdName, statusText, options) {{{2 +" Wrapper to VCSCommandDoCommand to add the name of the SVK executable to the +" command argument. +function! s:DoCommand(cmd, cmdName, statusText, options) + if VCSCommandGetVCSType(expand('%')) == 'SVK' + let fullCmd = VCSCommandGetOption('VCSCommandSVKExec', 'svk') . ' ' . a:cmd + return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options) + else + throw 'SVK VCSCommand plugin called on non-SVK item.' + endif +endfunction + +" Section: VCS function implementations {{{1 + +" Function: s:svkFunctions.Identify(buffer) {{{2 +function! s:svkFunctions.Identify(buffer) + let fileName = resolve(bufname(a:buffer)) + if isdirectory(fileName) + let directoryName = fileName + else + let directoryName = fnamemodify(fileName, ':p:h') + endif + let statusText = system(VCSCommandGetOption('VCSCommandSVKExec', 'svk') . ' info "' . directoryName . '"') + if(v:shell_error) + return 0 + else + return 1 + endif +endfunction + +" Function: s:svkFunctions.Add() {{{2 +function! s:svkFunctions.Add(argList) + return s:DoCommand(join(['add'] + a:argList, ' '), 'add', join(a:argList, ' '), {}) +endfunction + +" Function: s:svkFunctions.Annotate(argList) {{{2 +function! s:svkFunctions.Annotate(argList) + if len(a:argList) == 0 + if &filetype == 'SVKAnnotate' + " Perform annotation of the version indicated by the current line. + let caption = matchstr(getline('.'),'\v^\s+\zs\d+') + let options = ' -r' . caption + else + let caption = '' + let options = '' + endif + elseif len(a:argList) == 1 && a:argList[0] !~ '^-' + let caption = a:argList[0] + let options = ' -r' . caption + else + let caption = join(a:argList, ' ') + let options = ' ' . caption + endif + + let resultBuffer = s:DoCommand('blame' . options, 'annotate', caption, {}) + if resultBuffer > 0 + normal 1G2dd + set filetype=SVKAnnotate + endif + return resultBuffer +endfunction + +" Function: s:svkFunctions.Commit(argList) {{{2 +function! s:svkFunctions.Commit(argList) + let resultBuffer = s:DoCommand('commit -F "' . a:argList[0] . '"', 'commit', '', {}) + if resultBuffer == 0 + echomsg 'No commit needed.' + endif +endfunction + +" Function: s:svkFunctions.Delete() {{{2 +function! s:svkFunctions.Delete(argList) + return s:DoCommand(join(['delete'] + a:argList, ' '), 'delete', join(a:argList, ' '), {}) +endfunction + +" Function: s:svkFunctions.Diff(argList) {{{2 +function! s:svkFunctions.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 resultBuffer = s:DoCommand(join(['diff'] + revOptions), 'diff', caption, {}) + if resultBuffer > 0 + set filetype=diff + else + echomsg 'No differences found' + endif + return resultBuffer +endfunction + +" Function: s:svkFunctions.GetBufferInfo() {{{2 +" Provides version control details for the current file. Current version +" number and current repository version number are required to be returned by +" the vcscommand plugin. +" Returns: List of results: [revision, repository] + +function! s:svkFunctions.GetBufferInfo() + let originalBuffer = VCSCommandGetOriginalBuffer(bufnr('%')) + let fileName = resolve(bufname(originalBuffer)) + let statusText = system(VCSCommandGetOption('VCSCommandSVKExec', 'svk') . ' status -v "' . fileName . '"') + if(v:shell_error) + return [] + endif + + " File not under SVK control. + if statusText =~ '^?' + return ['Unknown'] + endif + + let [flags, revision, repository] = matchlist(statusText, '^\(.\{3}\)\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:svkFunctions.Info(argList) {{{2 +function! s:svkFunctions.Info(argList) + return s:DoCommand(join(['info'] + a:argList, ' '), 'info', join(a:argList, ' '), {}) +endfunction + +" Function: s:svkFunctions.Lock(argList) {{{2 +function! s:svkFunctions.Lock(argList) + return s:DoCommand(join(['lock'] + a:argList, ' '), 'lock', join(a:argList, ' '), {}) +endfunction + +" Function: s:svkFunctions.Log() {{{2 +function! s:svkFunctions.Log(argList) + if len(a:argList) == 0 + let options = [] + let caption = '' + elseif len(a:argList) <= 2 && match(a:argList, '^-') == -1 + let options = ['-r' . join(a:argList, ':')] + let caption = options[0] + else + " Pass-through + let options = a:argList + let caption = join(a:argList, ' ') + endif + + let resultBuffer = s:DoCommand(join(['log', '-v'] + options), 'log', caption, {}) + return resultBuffer +endfunction + +" Function: s:svkFunctions.Revert(argList) {{{2 +function! s:svkFunctions.Revert(argList) + return s:DoCommand('revert', 'revert', '', {}) +endfunction + +" Function: s:svkFunctions.Review(argList) {{{2 +function! s:svkFunctions.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' . versionOption, 'review', versiontag, {}) + if resultBuffer > 0 + let &filetype=getbufvar(b:VCSCommandOriginalBuffer, '&filetype') + endif + return resultBuffer +endfunction + +" Function: s:svkFunctions.Status(argList) {{{2 +function! s:svkFunctions.Status(argList) + let options = ['-v'] + if len(a:argList) == 0 + let options = a:argList + endif + return s:DoCommand(join(['status'] + options, ' '), 'status', join(options, ' '), {}) +endfunction + +" Function: s:svkFunctions.Unlock(argList) {{{2 +function! s:svkFunctions.Unlock(argList) + return s:DoCommand(join(['unlock'] + a:argList, ' '), 'unlock', join(a:argList, ' '), {}) +endfunction +" Function: s:svkFunctions.Update(argList) {{{2 +function! s:svkFunctions.Update(argList) + return s:DoCommand('update', 'update', '', {}) +endfunction + +" Section: Plugin Registration {{{1 +call VCSCommandRegisterModule('SVK', expand('<sfile>'), s:svkFunctions, []) + +let &cpo = s:save_cpo diff --git a/.vim/plugin/vcssvn.vim b/.vim/plugin/vcssvn.vim new file mode 100644 index 0000000..90d2158 --- /dev/null +++ b/.vim/plugin/vcssvn.vim @@ -0,0 +1,292 @@ +" vim600: set foldmethod=marker: +" +" SVN extension for VCSCommand. +" +" Version: VCS development +" 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. +" +" 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 + +" Annotate setting {{{2 +let s:svnFunctions.AnnotateSplitRegex = '\s\+\S\+\s\+\S\+ ' + +" Section: Plugin Registration {{{1 +call VCSCommandRegisterModule('SVN', expand('<sfile>'), s:svnFunctions, []) + +let &cpo = s:save_cpo |