Add vim plugins

This commit is contained in:
Mathieu 2009-11-01 19:04:42 +01:00
parent 1f6117d004
commit 256b0cc80f
32 changed files with 15438 additions and 0 deletions

View File

@ -0,0 +1,2 @@
" OmniCppComplete initialization
call omni#cpp#complete#Init()

View File

@ -0,0 +1,2 @@
" OmniCppComplete initialization
call omni#cpp#complete#Init()

View File

@ -0,0 +1,32 @@
" Description: Omni completion debug functions
" Maintainer: Vissale NEANG
" Last Change: 26 sept. 2007
let s:CACHE_DEBUG_TRACE = []
" Start debug, clear the debug file
function! omni#common#debug#Start()
let s:CACHE_DEBUG_TRACE = []
call extend(s:CACHE_DEBUG_TRACE, ['============ Debug Start ============'])
call writefile(s:CACHE_DEBUG_TRACE, "Omni.dbg")
endfunc
" End debug, write to debug file
function! omni#common#debug#End()
call extend(s:CACHE_DEBUG_TRACE, ["============= Debug End ============="])
call extend(s:CACHE_DEBUG_TRACE, [""])
call writefile(s:CACHE_DEBUG_TRACE, "Omni.dbg")
endfunc
" Debug trace function
function! omni#common#debug#Trace(szFuncName, ...)
let szTrace = a:szFuncName
let paramNum = a:0
if paramNum>0
let szTrace .= ':'
endif
for i in range(paramNum)
let szTrace = szTrace .' ('. string(eval('a:'.string(i+1))).')'
endfor
call extend(s:CACHE_DEBUG_TRACE, [szTrace])
endfunc

View File

@ -0,0 +1,67 @@
" Description: Omni completion utils
" Maintainer: Vissale NEANG
" Last Change: 26 sept. 2007
" For sort numbers in list
function! omni#common#utils#CompareNumber(i1, i2)
let num1 = eval(a:i1)
let num2 = eval(a:i2)
return num1 == num2 ? 0 : num1 > num2 ? 1 : -1
endfunc
" TagList function calling the vim taglist() with try catch
" The only throwed exception is 'TagList:UserInterrupt'
" We also force the noignorecase option to avoid linear search when calling
" taglist()
function! omni#common#utils#TagList(szTagQuery)
let result = []
let bUserIgnoreCase = &ignorecase
" Forcing noignorecase search => binary search can be used in taglist()
" if tags in the tag file are sorted
if bUserIgnoreCase
set noignorecase
endif
try
let result = taglist(a:szTagQuery)
catch /^Vim:Interrupt$/
" Restoring user's setting
if bUserIgnoreCase
set ignorecase
endif
throw 'TagList:UserInterrupt'
catch
"Note: it seems that ctags can generate corrupted files, in this case
"taglist() will fail to read the tagfile and an exception from
"has_add() is thrown
endtry
" Restoring user's setting
if bUserIgnoreCase
set ignorecase
endif
return result
endfunc
" Same as TagList but don't throw exception
function! omni#common#utils#TagListNoThrow(szTagQuery)
let result = []
try
let result = omni#common#utils#TagList(a:szTagQuery)
catch
endtry
return result
endfunc
" Get the word under the cursor
function! omni#common#utils#GetWordUnderCursor()
let szLine = getline('.')
let startPos = getpos('.')[2]-1
let startPos = (startPos < 0)? 0 : startPos
if szLine[startPos] =~ '\w'
let startPos = searchpos('\<\w\+', 'cbn', line('.'))[1] - 1
endif
let startPos = (startPos < 0)? 0 : startPos
let szResult = matchstr(szLine, '\w\+', startPos)
return szResult
endfunc

View File

@ -0,0 +1,569 @@
" Description: Omni completion script for cpp files
" Maintainer: Vissale NEANG
" Last Change: 27 sept. 2007
if v:version < 700
echohl WarningMsg
echomsg "omni#cpp#complete.vim: Please install vim 7.0 or higher for omni-completion"
echohl None
finish
endif
call omni#cpp#settings#Init()
let s:OmniCpp_ShowScopeInAbbr = g:OmniCpp_ShowScopeInAbbr
let s:OmniCpp_ShowPrototypeInAbbr = g:OmniCpp_ShowPrototypeInAbbr
let s:OmniCpp_ShowAccess = g:OmniCpp_ShowAccess
let s:szCurrentWorkingDir = getcwd()
" Cache data
let s:CACHE_TAG_POPUP_ITEMS = {}
let s:CACHE_TAG_FILES = {}
let s:CACHE_TAG_ENV = ''
let s:CACHE_OVERLOADED_FUNCTIONS = {}
" Has preview window?
let s:hasPreviewWindow = match(&completeopt, 'preview')>=0
let s:hasPreviewWindowOld = s:hasPreviewWindow
" Popup item list
let s:popupItemResultList = []
" May complete indicator
let s:bMayComplete = 0
" Init mappings
function! omni#cpp#complete#Init()
call omni#cpp#settings#Init()
set omnifunc=omni#cpp#complete#Main
inoremap <expr> <C-X><C-O> omni#cpp#maycomplete#Complete()
inoremap <expr> . omni#cpp#maycomplete#Dot()
inoremap <expr> > omni#cpp#maycomplete#Arrow()
inoremap <expr> : omni#cpp#maycomplete#Scope()
endfunc
" Find the start position of the completion
function! s:FindStartPositionOfCompletion()
" Locate the start of the item, including ".", "->" and "[...]".
let line = getline('.')
let start = col('.') - 1
let lastword = -1
while start > 0
if line[start - 1] =~ '\w'
let start -= 1
elseif line[start - 1] =~ '\.'
" Searching for dot '.'
if lastword == -1
let lastword = start
endif
let start -= 1
elseif start > 1 && line[start - 2] == '-' && line[start - 1] == '>'
" Searching for '->'
if lastword == -1
let lastword = start
endif
let start -= 2
elseif start > 1 && line[start - 2] == ':' && line[start - 1] == ':'
" Searching for '::' for namespaces and class
if lastword == -1
let lastword = start
endif
let start -= 2
elseif line[start - 1] == ']'
" Skip over [...].
let n = 0
let start -= 1
while start > 0
let start -= 1
if line[start] == '['
if n == 0
break
endif
let n -= 1
elseif line[start] == ']' " nested []
let n += 1
endif
endwhile
else
break
endif
endwhile
if lastword==-1
" For completion on the current scope
let lastword = start
endif
return lastword
endfunc
" Returns if szKey1.szKey2 is in the cache
" @return
" - 0 = key not found
" - 1 = szKey1.szKey2 found
" - 2 = szKey1.[part of szKey2] found
function! s:IsCached(cache, szKey1, szKey2)
" Searching key in the result cache
let szResultKey = a:szKey1 . a:szKey2
let result = [0, szResultKey]
if a:szKey2 != ''
let szKey = a:szKey2
while len(szKey)>0
if has_key(a:cache, a:szKey1 . szKey)
let result[1] = a:szKey1 . szKey
if szKey != a:szKey2
let result[0] = 2
else
let result[0] = 1
endif
break
endif
let szKey = szKey[:-2]
endwhile
else
if has_key(a:cache, szResultKey)
let result[0] = 1
endif
endif
return result
endfunc
" Extend a tag item to a popup item
function! s:ExtendTagItemToPopupItem(tagItem, szTypeName)
let tagItem = a:tagItem
" Add the access
let szItemMenu = ''
let accessChar = {'public': '+','protected': '#','private': '-'}
if g:OmniCpp_ShowAccess
if has_key(tagItem, 'access') && has_key(accessChar, tagItem.access)
let szItemMenu = szItemMenu.accessChar[tagItem.access]
else
let szItemMenu = szItemMenu." "
endif
endif
" Formating optional menu string we extract the scope information
let szName = substitute(tagItem.name, '.*::', '', 'g')
let szItemWord = szName
let szAbbr = szName
if !g:OmniCpp_ShowScopeInAbbr
let szScopeOfTag = omni#cpp#utils#ExtractScope(tagItem)
let szItemMenu = szItemMenu.' '.szScopeOfTag[2:]
let szItemMenu = substitute(szItemMenu, '\s\+$', '', 'g')
else
let szAbbr = tagItem.name
endif
if g:OmniCpp_ShowAccess
let szItemMenu = substitute(szItemMenu, '^\s\+$', '', 'g')
else
let szItemMenu = substitute(szItemMenu, '\(^\s\+\)\|\(\s\+$\)', '', 'g')
endif
" Formating information for the preview window
if index(['f', 'p'], tagItem.kind[0])>=0
let szItemWord .= '('
if g:OmniCpp_ShowPrototypeInAbbr && has_key(tagItem, 'signature')
let szAbbr .= tagItem.signature
else
let szAbbr .= '('
endif
endif
let szItemInfo = ''
if s:hasPreviewWindow
let szItemInfo = omni#cpp#utils#GetPreviewWindowStringFromTagItem(tagItem)
endif
" If a function is a ctor we add a new key in the tagItem
if index(['f', 'p'], tagItem.kind[0])>=0
if match(szName, '^\~') < 0 && a:szTypeName =~ '\C\<'.szName.'$'
" It's a ctor
let tagItem['ctor'] = 1
elseif has_key(tagItem, 'access') && tagItem.access == 'friend'
" Friend function
let tagItem['friendfunc'] = 1
endif
endif
" Extending the tag item to a popup item
let tagItem['word'] = szItemWord
let tagItem['abbr'] = szAbbr
let tagItem['menu'] = szItemMenu
let tagItem['info'] = szItemInfo
let tagItem['dup'] = (s:hasPreviewWindow && index(['f', 'p', 'm'], tagItem.kind[0])>=0)
return tagItem
endfunc
" Get tag popup item list
function! s:TagPopupList(szTypeName, szBase)
let result = []
" Searching key in the result cache
let cacheResult = s:IsCached(s:CACHE_TAG_POPUP_ITEMS, a:szTypeName, a:szBase)
" Building the tag query, we don't forget dtors when a:szBase==''
if a:szTypeName!=''
" Scope search
let szTagQuery = '^' . a:szTypeName . '::' . a:szBase . '\~\?\w\+$'
else
" Global search
let szTagQuery = '^' . a:szBase . '\w\+$'
endif
" If the result is already in the cache we return it
if cacheResult[0]
let result = s:CACHE_TAG_POPUP_ITEMS[ cacheResult[1] ]
if cacheResult[0] == 2
let result = filter(copy(result), 'v:val.name =~ szTagQuery' )
endif
return result
endif
try
" Getting tags
let result = omni#common#utils#TagList(szTagQuery)
" We extend tag items to popup items
call map(result, 's:ExtendTagItemToPopupItem(v:val, a:szTypeName)')
" We store the result in a cache
if cacheResult[1] != ''
let s:CACHE_TAG_POPUP_ITEMS[ cacheResult[1] ] = result
endif
catch /^TagList:UserInterrupt$/
endtry
return result
endfunc
" Find complete matches for a completion on the global scope
function! s:SearchGlobalMembers(szBase)
if a:szBase != ''
let tagPopupList = s:TagPopupList('', a:szBase)
let tagPopupList = filter(copy(tagPopupList), g:omni#cpp#utils#szFilterGlobalScope)
call extend(s:popupItemResultList, tagPopupList)
endif
endfunc
" Search class, struct, union members
" @param resolvedTagItem: a resolved tag item
" @param szBase: string base
" @return list of tag items extended to popup items
function! s:SearchMembers(resolvedTagItem, szBase)
let result = []
if a:resolvedTagItem == {}
return result
endif
" Get type info without the starting '::'
let szTagName = omni#cpp#utils#ExtractTypeInfoFromTag(a:resolvedTagItem)[2:]
" Unnamed type case. A tag item representing an unnamed type is a variable
" ('v') a member ('m') or a typedef ('t')
if index(['v', 't', 'm'], a:resolvedTagItem.kind[0])>=0 && has_key(a:resolvedTagItem, 'typeref')
" We remove the 'struct:' or 'class:' etc...
let szTagName = substitute(a:resolvedTagItem.typeref, '^\w\+:', '', 'g')
endif
return copy(s:TagPopupList(szTagName, a:szBase))
endfunc
" Return if the tag env has changed
function! s:HasTagEnvChanged()
if s:CACHE_TAG_ENV == &tags
return 0
else
let s:CACHE_TAG_ENV = &tags
return 1
endif
endfunc
" Return if a tag file has changed in tagfiles()
function! s:HasATagFileOrTagEnvChanged()
if s:HasTagEnvChanged()
let s:CACHE_TAG_FILES = {}
return 1
endif
let result = 0
for tagFile in tagfiles()
if tagFile == ""
continue
endif
if has_key(s:CACHE_TAG_FILES, tagFile)
let currentFiletime = getftime(tagFile)
if currentFiletime > s:CACHE_TAG_FILES[tagFile]
" The file has changed, updating the cache
let s:CACHE_TAG_FILES[tagFile] = currentFiletime
let result = 1
endif
else
" We store the time of the file
let s:CACHE_TAG_FILES[tagFile] = getftime(tagFile)
let result = 1
endif
endfor
return result
endfunc
" Initialization
call s:HasATagFileOrTagEnvChanged()
" Filter same function signatures of base classes
function! s:FilterOverloadedFunctions(tagPopupList)
let result = []
for tagPopupItem in a:tagPopupList
if has_key(tagPopupItem, 'kind') && index(['f', 'p'], tagPopupItem.kind[0])>=0 && has_key(tagPopupItem, 'signature')
if !has_key(s:CACHE_OVERLOADED_FUNCTIONS, tagPopupItem.word . tagPopupItem.signature)
let s:CACHE_OVERLOADED_FUNCTIONS[tagPopupItem.word . tagPopupItem.signature] = 1
call extend(result, [tagPopupItem])
endif
else
call extend(result, [tagPopupItem])
endif
endfor
return result
endfunc
" Access filter
function! s:GetAccessFilter(szFilter, szAccessFilter)
let szFilter = a:szFilter
if g:OmniCpp_DisplayMode == 0
if a:szAccessFilter == 'public'
" We only get public members
let szFilter .= "&& v:val.access == 'public'"
elseif a:szAccessFilter == 'protected'
" We get public and protected members
let szFilter .= "&& v:val.access != 'private'"
endif
endif
return szFilter
endfunc
" Filter class members in the popup menu after a completion with -> or .
function! s:FilterClassMembers(tagPopupList, szAccessFilter)
let szFilter = "(!has_key(v:val, 'friendfunc') && !has_key(v:val, 'ctor') && has_key(v:val, 'kind') && index(['m', 'p', 'f'], v:val.kind[0])>=0 && has_key(v:val, 'access'))"
call filter(a:tagPopupList, s:GetAccessFilter(szFilter, a:szAccessFilter))
call extend(s:popupItemResultList, s:FilterOverloadedFunctions(a:tagPopupList))
endfunc
" Filter class scope members in the popup menu after a completion with ::
" We only display attribute and functions members that
" have an access information. We also display nested
" class, struct, union, and enums, typedefs
function! s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
let szFilter = "!has_key(v:val, 'friendfunc') && has_key(v:val, 'kind') && (index(['m', 'p', 'f'], v:val.kind[0])>=0 && has_key(v:val, 'access'))"
let szFilter = s:GetAccessFilter(szFilter, a:szAccessFilter)
let szFilter .= "|| index(['c','e','g','s','t','u'], v:val.kind[0])>=0"
call filter(a:tagPopupList, szFilter)
call extend(s:popupItemResultList, s:FilterOverloadedFunctions(a:tagPopupList))
endfunc
" Filter static class members in the popup menu
function! s:FilterStaticClassMembers(tagPopupList, szAccessFilter)
let szFilter = "!has_key(v:val, 'friendfunc') && has_key(v:val, 'kind') && (index(['m', 'p', 'f'], v:val.kind[0])>=0 && has_key(v:val, 'access') && match(v:val.cmd, '\\Cstatic')!=-1)"
let szFilter = s:GetAccessFilter(szFilter, a:szAccessFilter)
let szFilter = szFilter . "|| index(['c','e','g','n','s','t','u','v'], v:val.kind[0])>=0"
call filter(a:tagPopupList, szFilter)
call extend(s:popupItemResultList, s:FilterOverloadedFunctions(a:tagPopupList))
endfunc
" Filter scope members in the popup menu
function! s:FilterNamespaceScopeMembers(tagPopupList)
call extend(s:popupItemResultList, a:tagPopupList)
endfunc
" Init data at the start of completion
function! s:InitComplete()
" Reset the popup item list
let s:popupItemResultList = []
let s:CACHE_OVERLOADED_FUNCTIONS = {}
" Reset includes cache when the current working directory has changed
let szCurrentWorkingDir = getcwd()
if s:szCurrentWorkingDir != szCurrentWorkingDir
let s:szCurrentWorkingDir = szCurrentWorkingDir
let g:omni#cpp#includes#CACHE_INCLUDES = {}
let g:omni#cpp#includes#CACHE_FILE_TIME = {}
endif
" Has preview window ?
let s:hasPreviewWindow = match(&completeopt, 'preview')>=0
let bResetCache = 0
" Reset tag env or tag files dependent caches
if s:HasATagFileOrTagEnvChanged()
let bResetCache = 1
endif
if (s:OmniCpp_ShowScopeInAbbr != g:OmniCpp_ShowScopeInAbbr)
\|| (s:OmniCpp_ShowPrototypeInAbbr != g:OmniCpp_ShowPrototypeInAbbr)
\|| (s:OmniCpp_ShowAccess != g:OmniCpp_ShowAccess)
let s:OmniCpp_ShowScopeInAbbr = g:OmniCpp_ShowScopeInAbbr
let s:OmniCpp_ShowPrototypeInAbbr = g:OmniCpp_ShowPrototypeInAbbr
let s:OmniCpp_ShowAccess = g:OmniCpp_ShowAccess
let bResetCache = 1
endif
if s:hasPreviewWindow != s:hasPreviewWindowOld
let s:hasPreviewWindowOld = s:hasPreviewWindow
let bResetCache = 1
endif
if bResetCache
let g:omni#cpp#namespaces#CacheResolve = {}
let s:CACHE_TAG_POPUP_ITEMS = {}
let g:omni#cpp#utils#CACHE_TAG_INHERITS = {}
call garbagecollect()
endif
" Check for updates
for szIncludeName in keys(g:omni#cpp#includes#CACHE_INCLUDES)
let fTime = getftime(szIncludeName)
let bNeedUpdate = 0
if has_key(g:omni#cpp#includes#CACHE_FILE_TIME, szIncludeName)
if fTime != g:omni#cpp#includes#CACHE_FILE_TIME[szIncludeName]
let bNeedUpdate = 1
endif
else
let g:omni#cpp#includes#CACHE_FILE_TIME[szIncludeName] = fTime
let bNeedUpdate = 1
endif
if bNeedUpdate
" We have to update include list and namespace map of this file
call omni#cpp#includes#GetList(szIncludeName, 1)
call omni#cpp#namespaces#GetMapFromBuffer(szIncludeName, 1)
endif
endfor
let s:bDoNotComplete = 0
endfunc
" This function is used for the 'omnifunc' option.
function! omni#cpp#complete#Main(findstart, base)
if a:findstart
"call omni#common#debug#Start()
call s:InitComplete()
" Note: if s:bMayComplete==1 g:omni#cpp#items#data is build by MayComplete functions
if !s:bMayComplete
" If the cursor is in a comment we go out
if omni#cpp#utils#IsCursorInCommentOrString()
" Returning -1 is not enough we have to set a variable to let
" the second call of omni#cpp#complete knows that the
" cursor was in a comment
" Why is there a second call when the first call returns -1 ?
let s:bDoNotComplete = 1
return -1
endif
" We get items here (whend a:findstart==1) because GetItemsToComplete()
" depends on the cursor position.
" When a:findstart==0 the cursor position is modified
let g:omni#cpp#items#data = omni#cpp#items#Get(omni#cpp#utils#TokenizeCurrentInstruction())
endif
" Get contexts stack
let s:contextStack = omni#cpp#namespaces#GetContexts()
" Reinit of may complete indicator
let s:bMayComplete = 0
return s:FindStartPositionOfCompletion()
endif
" If the cursor is in a comment we return an empty result
if s:bDoNotComplete
let s:bDoNotComplete = 0
return []
endif
if len(g:omni#cpp#items#data)==0
" A) CURRENT_SCOPE_COMPLETION_MODE
" 1) Displaying data of each context
let szAccessFilter = 'all'
for szCurrentContext in s:contextStack
if szCurrentContext == '::'
continue
endif
let resolvedTagItem = omni#cpp#utils#GetResolvedTagItem(s:contextStack, omni#cpp#utils#CreateTypeInfo(szCurrentContext))
if resolvedTagItem != {}
" We don't search base classes because bases classes are
" already in the context stack
let tagPopupList = s:SearchMembers(resolvedTagItem, a:base)
if index(['c','s'], resolvedTagItem.kind[0])>=0
" It's a class or struct
call s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
let szAccessFilter = 'protected'
else
" It's a namespace or union, we display all members
call s:FilterNamespaceScopeMembers(tagPopupList)
endif
endif
endfor
" 2) Displaying global scope members
if g:OmniCpp_GlobalScopeSearch
call s:SearchGlobalMembers(a:base)
endif
else
let typeInfo = omni#cpp#items#ResolveItemsTypeInfo(s:contextStack, g:omni#cpp#items#data)
if typeInfo != {}
if g:omni#cpp#items#data[-1].kind == 'itemScope'
" B) SCOPE_COMPLETION_MODE
if omni#cpp#utils#GetTypeInfoString(typeInfo)==''
call s:SearchGlobalMembers(a:base)
else
for resolvedTagItem in omni#cpp#utils#GetResolvedTags(s:contextStack, typeInfo)
let tagPopupList = s:SearchMembers(resolvedTagItem, a:base)
if index(['c','s'], resolvedTagItem.kind[0])>=0
let szTypeInfo = omni#cpp#utils#ExtractTypeInfoFromTag(resolvedTagItem)
if g:OmniCpp_DisplayMode==0
" We want to complete a class or struct
" If this class is a base class so we display all class members
if index(s:contextStack, szTypeInfo)<0
let szAccessFilter = 'public'
call s:FilterStaticClassMembers(tagPopupList, szAccessFilter)
else
let szAccessFilter = (s:contextStack[0] == szTypeInfo)? 'all' : 'protected'
call s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
endif
else
if index(s:contextStack, szTypeInfo)<0
let szAccessFilter = 'public'
else
let szAccessFilter = (s:contextStack[0] == szTypeInfo)? 'all' : 'protected'
endif
call s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
endif
else
" We want to complete a namespace
call s:FilterNamespaceScopeMembers(tagPopupList)
endif
endfor
endif
else
" C) CLASS_MEMBERS_COMPLETION_MODE
for resolvedTagItem in omni#cpp#utils#GetResolvedTags(s:contextStack, typeInfo)
let szTypeInfo = omni#cpp#utils#ExtractTypeInfoFromTag(resolvedTagItem)
if index(s:contextStack, szTypeInfo)<0
let szAccessFilter = 'public'
else
let szAccessFilter = (s:contextStack[0] == szTypeInfo)? 'all' : 'protected'
endif
call s:FilterClassMembers(s:SearchMembers(resolvedTagItem, a:base), szAccessFilter)
endfor
endif
endif
endif
"call omni#common#debug#End()
return s:popupItemResultList
endfunc

View File

@ -0,0 +1,126 @@
" Description: Omni completion script for cpp files
" Maintainer: Vissale NEANG
" Last Change: 26 sept. 2007
let g:omni#cpp#includes#CACHE_INCLUDES = {}
let g:omni#cpp#includes#CACHE_FILE_TIME = {}
let s:rePreprocIncludePart = '\C#\s*include\s*'
let s:reIncludeFilePart = '\(<\|"\)\(\f\|\s\)\+\(>\|"\)'
let s:rePreprocIncludeFile = s:rePreprocIncludePart . s:reIncludeFilePart
" Get the include list of a file
function! omni#cpp#includes#GetList(...)
if a:0 > 0
return s:GetIncludeListFromFile(a:1, (a:0 > 1)? a:2 : 0 )
else
return s:GetIncludeListFromCurrentBuffer()
endif
endfunc
" Get the include list from the current buffer
function! s:GetIncludeListFromCurrentBuffer()
let listIncludes = []
let originalPos = getpos('.')
call setpos('.', [0, 1, 1, 0])
let curPos = [1,1]
let alreadyInclude = {}
while curPos != [0,0]
let curPos = searchpos('\C\(^'.s:rePreprocIncludeFile.'\)', 'W')
if curPos != [0,0]
let szLine = getline('.')
let startPos = curPos[1]
let endPos = matchend(szLine, s:reIncludeFilePart, startPos-1)
if endPos!=-1
let szInclusion = szLine[startPos-1:endPos-1]
let szIncludeFile = substitute(szInclusion, '\('.s:rePreprocIncludePart.'\)\|[<>""]', '', 'g')
let szResolvedInclude = omni#cpp#utils#ResolveFilePath(szIncludeFile)
" Protection over self inclusion
if szResolvedInclude != '' && szResolvedInclude != omni#cpp#utils#ResolveFilePath(getreg('%'))
let includePos = curPos
if !has_key(alreadyInclude, szResolvedInclude)
call extend(listIncludes, [{'pos' : includePos, 'include' : szResolvedInclude}])
let alreadyInclude[szResolvedInclude] = 1
endif
endif
endif
endif
endwhile
call setpos('.', originalPos)
return listIncludes
endfunc
" Get the include list from a file
function! s:GetIncludeListFromFile(szFilePath, bUpdate)
let listIncludes = []
if a:szFilePath == ''
return listIncludes
endif
if !a:bUpdate && has_key(g:omni#cpp#includes#CACHE_INCLUDES, a:szFilePath)
return copy(g:omni#cpp#includes#CACHE_INCLUDES[a:szFilePath])
endif
let g:omni#cpp#includes#CACHE_FILE_TIME[a:szFilePath] = getftime(a:szFilePath)
let szFixedPath = escape(a:szFilePath, g:omni#cpp#utils#szEscapedCharacters)
execute 'silent! lvimgrep /\C\(^'.s:rePreprocIncludeFile.'\)/gj '.szFixedPath
let listQuickFix = getloclist(0)
let alreadyInclude = {}
for qf in listQuickFix
let szLine = qf.text
let startPos = qf.col
let endPos = matchend(szLine, s:reIncludeFilePart, startPos-1)
if endPos!=-1
let szInclusion = szLine[startPos-1:endPos-1]
let szIncludeFile = substitute(szInclusion, '\('.s:rePreprocIncludePart.'\)\|[<>""]', '', 'g')
let szResolvedInclude = omni#cpp#utils#ResolveFilePath(szIncludeFile)
" Protection over self inclusion
if szResolvedInclude != '' && szResolvedInclude != a:szFilePath
let includePos = [qf.lnum, qf.col]
if !has_key(alreadyInclude, szResolvedInclude)
call extend(listIncludes, [{'pos' : includePos, 'include' : szResolvedInclude}])
let alreadyInclude[szResolvedInclude] = 1
endif
endif
endif
endfor
let g:omni#cpp#includes#CACHE_INCLUDES[a:szFilePath] = listIncludes
return copy(listIncludes)
endfunc
" For debug purpose
function! omni#cpp#includes#Display()
let szPathBuffer = omni#cpp#utils#ResolveFilePath(getreg('%'))
call s:DisplayIncludeTree(szPathBuffer, 0)
endfunc
" For debug purpose
function! s:DisplayIncludeTree(szFilePath, indent, ...)
let includeGuard = {}
if a:0 >0
let includeGuard = a:1
endif
let szFilePath = omni#cpp#utils#ResolveFilePath(a:szFilePath)
if has_key(includeGuard, szFilePath)
return
else
let includeGuard[szFilePath] = 1
endif
let szIndent = repeat(' ', a:indent)
echo szIndent . a:szFilePath
let incList = omni#cpp#includes#GetList(a:szFilePath)
for inc in incList
call s:DisplayIncludeTree(inc.include, a:indent+1, includeGuard)
endfor
endfunc

View File

@ -0,0 +1,660 @@
" Description: Omni completion script for cpp files
" Maintainer: Vissale NEANG
" Last Change: 26 sept. 2007
" Build the item list of an instruction
" An item is an instruction between a -> or . or ->* or .*
" We can sort an item in different kinds:
" eg: ((MyClass1*)(pObject))->_memberOfClass1.get() ->show()
" | cast | | member | | method | | method |
" @return a list of item
" an item is a dictionnary where keys are:
" tokens = list of token
" kind = itemVariable|itemCast|itemCppCast|itemTemplate|itemFunction|itemUnknown|itemThis|itemScope
function! omni#cpp#items#Get(tokens, ...)
let bGetWordUnderCursor = (a:0>0)? a:1 : 0
let result = []
let itemsDelimiters = ['->', '.', '->*', '.*']
let tokens = reverse(omni#cpp#utils#BuildParenthesisGroups(a:tokens))
" fsm states:
" 0 = initial state
" TODO: add description of fsm states
let state=(bGetWordUnderCursor)? 1 : 0
let item = {'tokens' : [], 'kind' : 'itemUnknown'}
let parenGroup=-1
for token in tokens
if state==0
if index(itemsDelimiters, token.value)>=0
let item = {'tokens' : [], 'kind' : 'itemUnknown'}
let state = 1
elseif token.value=='::'
let state = 9
let item.kind = 'itemScope'
" Maybe end of tokens
elseif token.kind =='cppOperatorPunctuator'
" If it's a cppOperatorPunctuator and the current token is not
" a itemsDelimiters or '::' we can exit
let state=-1
break
endif
elseif state==1
call insert(item.tokens, token)
if token.kind=='cppWord'
" It's an attribute member or a variable
let item.kind = 'itemVariable'
let state = 2
" Maybe end of tokens
elseif token.value=='this'
let item.kind = 'itemThis'
let state = 2
" Maybe end of tokens
elseif token.value==')'
let parenGroup = token.group
let state = 3
elseif token.value==']'
let parenGroup = token.group
let state = 4
elseif token.kind == 'cppDigit'
let state = -1
break
endif
elseif state==2
if index(itemsDelimiters, token.value)>=0
call insert(result, item)
let item = {'tokens' : [], 'kind' : 'itemUnknown'}
let state = 1
elseif token.value == '::'
call insert(item.tokens, token)
" We have to get namespace or classscope
let state = 8
" Maybe end of tokens
else
call insert(result, item)
let state=-1
break
endif
elseif state==3
call insert(item.tokens, token)
if token.value=='(' && token.group == parenGroup
let state = 5
" Maybe end of tokens
endif
elseif state==4
call insert(item.tokens, token)
if token.value=='[' && token.group == parenGroup
let state = 1
endif
elseif state==5
if token.kind=='cppWord'
" It's a function or method
let item.kind = 'itemFunction'
call insert(item.tokens, token)
let state = 2
" Maybe end of tokens
elseif token.value == '>'
" Maybe a cpp cast or template
let item.kind = 'itemTemplate'
call insert(item.tokens, token)
let parenGroup = token.group
let state = 6
else
" Perhaps it's a C cast eg: ((void*)(pData)) or a variable eg:(*pData)
let item.kind = omni#cpp#utils#GetCastType(item.tokens)
let state=-1
call insert(result, item)
break
endif
elseif state==6
call insert(item.tokens, token)
if token.value == '<' && token.group == parenGroup
" Maybe a cpp cast or template
let state = 7
endif
elseif state==7
call insert(item.tokens, token)
if token.kind=='cppKeyword'
" It's a cpp cast
let item.kind = omni#cpp#utils#GetCastType(item.tokens)
let state=-1
call insert(result, item)
break
else
" Template ?
let state=-1
call insert(result, item)
break
endif
elseif state==8
if token.kind=='cppWord'
call insert(item.tokens, token)
let state = 2
" Maybe end of tokens
else
let state=-1
call insert(result, item)
break
endif
elseif state==9
if token.kind == 'cppWord'
call insert(item.tokens, token)
let state = 10
" Maybe end of tokens
else
let state=-1
call insert(result, item)
break
endif
elseif state==10
if token.value == '::'
call insert(item.tokens, token)
let state = 9
" Maybe end of tokens
else
let state=-1
call insert(result, item)
break
endif
endif
endfor
if index([2, 5, 8, 9, 10], state)>=0
if state==5
let item.kind = omni#cpp#utils#GetCastType(item.tokens)
endif
call insert(result, item)
endif
return result
endfunc
" Resolve type information of items
" @param namespaces: list of namespaces used in the file
" @param szCurrentClassScope: the current class scope, only used for the first
" item to detect if this item is a class member (attribute, method)
" @param items: list of item, can be an empty list @see GetItemsToComplete
function! omni#cpp#items#ResolveItemsTypeInfo(contextStack, items)
" Note: kind = itemVariable|cCast|cppCast|template|function|itemUnknown|this
" For the first item, if it's a variable we try to detect the type of the
" variable with the function searchdecl. If it fails, thanks to the
" current class scope, we try to detect if the variable is an attribute
" member.
" If the kind of the item is a function, we have to first check if the
" function is a method of the class, if it fails we try to get a match in
" the global namespace. After that we get the returned type of the
" function.
" It the kind is a C cast or C++ cast, there is no problem, it's the
" easiest case. We just extract the type of the cast.
let szCurrentContext = ''
let typeInfo = {}
" Note: We search the decl only for the first item
let bSearchDecl = 1
for item in a:items
let curItem = item
if index(['itemVariable', 'itemFunction'], curItem.kind)>=0
" Note: a variable can be : MyNs::MyClass::_var or _var or (*pVar)
" or _var[0][0]
let szSymbol = s:GetSymbol(curItem.tokens)
" If we have MyNamespace::myVar
" We add MyNamespace in the context stack set szSymbol to myVar
if match(szSymbol, '::\w\+$') >= 0
let szCurrentContext = substitute(szSymbol, '::\w\+$', '', 'g')
let szSymbol = matchstr(szSymbol, '\w\+$')
endif
let tmpContextStack = a:contextStack
if szCurrentContext != ''
let tmpContextStack = [szCurrentContext] + a:contextStack
endif
if curItem.kind == 'itemVariable'
let typeInfo = s:GetTypeInfoOfVariable(tmpContextStack, szSymbol, bSearchDecl)
else
let typeInfo = s:GetTypeInfoOfReturnedType(tmpContextStack, szSymbol)
endif
elseif curItem.kind == 'itemThis'
if len(a:contextStack)
let typeInfo = omni#cpp#utils#CreateTypeInfo(substitute(a:contextStack[0], '^::', '', 'g'))
endif
elseif curItem.kind == 'itemCast'
let typeInfo = omni#cpp#utils#CreateTypeInfo(s:ResolveCCast(curItem.tokens))
elseif curItem.kind == 'itemCppCast'
let typeInfo = omni#cpp#utils#CreateTypeInfo(s:ResolveCppCast(curItem.tokens))
elseif curItem.kind == 'itemScope'
let typeInfo = omni#cpp#utils#CreateTypeInfo(substitute(s:TokensToString(curItem.tokens), '\s', '', 'g'))
endif
if omni#cpp#utils#IsTypeInfoValid(typeInfo)
let szCurrentContext = omni#cpp#utils#GetTypeInfoString(typeInfo)
endif
let bSearchDecl = 0
endfor
return typeInfo
endfunc
" Get symbol name
function! s:GetSymbol(tokens)
let szSymbol = ''
let state = 0
for token in a:tokens
if state == 0
if token.value == '::'
let szSymbol .= token.value
let state = 1
elseif token.kind == 'cppWord'
let szSymbol .= token.value
let state = 2
" Maybe end of token
endif
elseif state == 1
if token.kind == 'cppWord'
let szSymbol .= token.value
let state = 2
" Maybe end of token
else
" Error
break
endif
elseif state == 2
if token.value == '::'
let szSymbol .= token.value
let state = 1
else
break
endif
endif
endfor
return szSymbol
endfunc
" Search a declaration.
" eg: std::map
" can be empty
" Note: The returned type info can be a typedef
" The typedef resolution is done later
" @return
" - a dictionnary where keys are
" - type: the type of value same as type()
" - value: the value
function! s:GetTypeInfoOfVariable(contextStack, szVariable, bSearchDecl)
let result = {}
if a:bSearchDecl
" Search type of declaration
"let result = s:SearchTypeInfoOfDecl(a:szVariable)
let result = s:SearchDecl(a:szVariable)
endif
if result=={}
let szFilter = "index(['m', 'v'], v:val.kind[0])>=0"
let tagItem = s:ResolveSymbol(a:contextStack, a:szVariable, szFilter)
if tagItem=={}
return result
endif
let szCmdWithoutVariable = substitute(omni#cpp#utils#ExtractCmdFromTagItem(tagItem), '\C\<'.a:szVariable.'\>.*', '', 'g')
let tokens = omni#cpp#tokenizer#Tokenize(omni#cpp#utils#GetCodeFromLine(szCmdWithoutVariable))
let result = omni#cpp#utils#CreateTypeInfo(omni#cpp#utils#ExtractTypeInfoFromTokens(tokens))
" TODO: Namespace resolution for result
if result != {} && result.value==''
" result.value==''
" eg:
" struct
" {
" }gVariable;
if has_key(tagItem, 'typeref')
" Maybe the variable is a global var of an
" unnamed class, struct or union.
" eg:
" 1)
" struct
" {
" }gVariable;
" In this case we need the tags (the patched version)
" Note: We can have a named type like this:
" 2)
" class A
" {
" }gVariable;
if s:IsUnnamedType(tagItem)
" It's an unnamed type we are in the case 1)
let result = omni#cpp#utils#CreateTypeInfo(tagItem)
else
" It's not an unnamed type we are in the case 2)
" eg: tagItem.typeref = 'struct:MY_STRUCT::MY_SUBSTRUCT'
let szTypeRef = substitute(tagItem.typeref, '^\w\+:', '', '')
" eg: szTypeRef = 'MY_STRUCT::MY_SUBSTRUCT'
let result = omni#cpp#utils#CreateTypeInfo(szTypeRef)
endif
endif
endif
endif
return result
endfunc
" Get the type info string from the returned type of function
function! s:GetTypeInfoOfReturnedType(contextStack, szFunctionName)
let result = {}
let szFilter = "index(['f', 'p'], v:val.kind[0])>=0"
let tagItem = s:ResolveSymbol(a:contextStack, a:szFunctionName, szFilter)
if tagItem != {}
let szCmdWithoutVariable = substitute(omni#cpp#utils#ExtractCmdFromTagItem(tagItem), '\C\<'.a:szFunctionName.'\>.*', '', 'g')
let tokens = omni#cpp#tokenizer#Tokenize(omni#cpp#utils#GetCodeFromLine(szCmdWithoutVariable))
let result = omni#cpp#utils#CreateTypeInfo(omni#cpp#utils#ExtractTypeInfoFromTokens(tokens))
" TODO: Namespace resolution for result
return result
endif
return result
endfunc
" Resolve a symbol, return a tagItem
" Gets the first symbol found in the context stack
function! s:ResolveSymbol(contextStack, szSymbol, szTagFilter)
let tagItem = {}
for szCurrentContext in a:contextStack
if szCurrentContext != '::'
let szTagQuery = substitute(szCurrentContext, '^::', '', 'g').'::'.a:szSymbol
else
let szTagQuery = a:szSymbol
endif
let tagList = omni#common#utils#TagListNoThrow('^'.szTagQuery.'$')
call filter(tagList, a:szTagFilter)
if len(tagList)
let tagItem = tagList[0]
break
endif
endfor
return tagItem
endfunc
" Return if the tag item represent an unnamed type
function! s:IsUnnamedType(tagItem)
let bResult = 0
if has_key(a:tagItem, 'typeref')
" Note: Thanks for __anon !
let bResult = match(a:tagItem.typeref, '\C\<__anon') >= 0
endif
return bResult
endfunc
" Search the declaration of a variable and return the type info
function! s:SearchTypeInfoOfDecl(szVariable)
let szReVariable = '\C\<'.a:szVariable.'\>'
let originalPos = getpos('.')
let origPos = originalPos[1:2]
let curPos = origPos
let stopPos = origPos
while curPos !=[0,0]
" We go to the start of the current scope
let curPos = searchpairpos('{', '', '}', 'bW', g:omni#cpp#utils#expIgnoreComments)
if curPos != [0,0]
let matchPos = curPos
" Now want to search our variable but we don't want to go in child
" scope
while matchPos != [0,0]
let matchPos = searchpos('{\|'.szReVariable, 'W', stopPos[0])
if matchPos != [0,0]
" We ignore matches under comment
if omni#cpp#utils#IsCursorInCommentOrString()
continue
endif
" Getting the current line
let szLine = getline('.')
if match(szLine, szReVariable)>=0
" We found our variable
" Check if the current instruction is a decl instruction
let tokens = omni#cpp#utils#TokenizeCurrentInstruction()
let szTypeInfo = s:ExtractTypeInfoFromDecl(tokens)
if szTypeInfo != ''
call setpos('.', originalPos)
return omni#cpp#utils#CreateTypeInfo(szTypeInfo)
endif
else
" We found a child scope, we don't want to go in, thus
" we search for the end } of this child scope
let bracketEnd = searchpairpos('{', '', '}', 'nW', g:omni#cpp#utils#expIgnoreComments)
if bracketEnd == [0,0]
break
endif
if bracketEnd[0] >= stopPos[0]
" The end of the scope is after our cursor we stop
" the search
break
else
" We move the cursor and continue to search our
" variable
call setpos('.', [0, bracketEnd[0], bracketEnd[1], 0])
endif
endif
endif
endwhile
" Backing to the start of the scope
call setpos('.', [0,curPos[0], curPos[1], 0])
let stopPos = curPos
endif
endwhile
let result = {}
if s:LocalSearchDecl(a:szVariable)==0 && !omni#cpp#utils#IsCursorInCommentOrString()
let tokens = omni#cpp#utils#TokenizeCurrentInstruction()
let szTypeInfo = s:ExtractTypeInfoFromDecl(tokens)
if szTypeInfo != ''
let result = omni#cpp#utils#CreateTypeInfo(szTypeInfo)
endif
endif
call setpos('.', originalPos)
return result
endfunc
" Search a declaration
" @return
" - tokens of the current instruction if success
" - empty list if failure
function! s:SearchDecl(szVariable)
let result = {}
let originalPos = getpos('.')
let searchResult = s:LocalSearchDecl(a:szVariable)
if searchResult==0
" searchdecl() may detect a decl if the variable is in a conditional
" instruction (if, elseif, while etc...)
" We have to check if the detected decl is really a decl instruction
let tokens = omni#cpp#utils#TokenizeCurrentInstruction()
for token in tokens
" Simple test
if index(['if', 'elseif', 'while', 'for', 'switch'], token.value)>=0
" Invalid declaration instruction
call setpos('.', originalPos)
return result
endif
endfor
let szTypeInfo = s:ExtractTypeInfoFromDecl(tokens)
if szTypeInfo != ''
let result = omni#cpp#utils#CreateTypeInfo(szTypeInfo)
endif
endif
call setpos('.', originalPos)
return result
endfunc
" Extract the type info string from an instruction.
" We use a small parser to extract the type
" We parse the code according to a C++ BNF from: http://www.nongnu.org/hcb/#basic.link
" @param tokens: token list of the current instruction
function! s:ExtractTypeInfoFromDecl(tokens)
return omni#cpp#utils#ExtractTypeInfoFromTokens(a:tokens)
endfunc
" Convert tokens to string
function! s:TokensToString(tokens)
let result = ''
for token in a:tokens
let result = result . token.value . ' '
endfor
return result[:-2]
endfunc
" Resolve a cast.
" Resolve a C++ cast
" @param list of token. tokens must be a list that represents
" a cast expression (C++ cast) the function does not control
" if it's a cast or not
" eg: static_cast<MyClass*>(something)
" @return type info string
function! s:ResolveCppCast(tokens)
return omni#cpp#utils#ExtractTypeInfoFromTokens(s:ResolveCast(a:tokens, '<', '>'))
endfunc
" Resolve a cast.
" Resolve a C cast
" @param list of token. tokens must be a list that represents
" a cast expression (C cast) the function does not control
" if it's a cast or not
" eg: (MyClass*)something
" @return type info string
function! s:ResolveCCast(tokens)
return omni#cpp#utils#ExtractTypeInfoFromTokens(s:ResolveCast(a:tokens, '(', ')'))
endfunc
" Resolve a cast.
" Resolve a C cast
" @param list of token. tokens must be a list that represents
" a cast expression (C cast) the function does not control
" if it's a cast or not
" eg: (MyClass*)something
" @return type tokens
function! s:ResolveCast(tokens, startChar, endChar)
let tokens = omni#cpp#utils#BuildParenthesisGroups(a:tokens)
" We remove useless parenthesis eg: (((MyClass)))
let tokens = omni#cpp#utils#SimplifyParenthesis(tokens)
let countItem=0
let startIndex = -1
let endIndex = -1
let i = 0
for token in tokens
if startIndex==-1
if token.value==a:startChar
let countItem += 1
let startIndex = i
endif
else
if token.value==a:startChar
let countItem += 1
elseif token.value==a:endChar
let countItem -= 1
endif
if countItem==0
let endIndex = i
break
endif
endif
let i+=1
endfor
return tokens[startIndex+1 : endIndex-1]
endfunc
" Replacement for build-in function 'searchdecl'
" It does not require that the upper-level bracket is in the first column.
" Otherwise it should be equal to 'searchdecl(name, 0, 1)'
" @param name: name of variable to find declaration for
function! s:LocalSearchDecl(name)
if g:OmniCpp_LocalSearchDecl == 0
let bUserIgnoreCase = &ignorecase
" Forcing the noignorecase option
" avoid bug when, for example, if we have a declaration like this : "A a;"
set noignorecase
let result = searchdecl(a:name, 0, 1)
" Restoring user's setting
let &ignorecase = bUserIgnoreCase
return result
endif
let lastpos = getpos('.')
let winview = winsaveview()
let lastfoldenable = &foldenable
let &foldenable = 0
" We add \C (noignorecase) to
" avoid bug when, for example, if we have a declaration like this : "A a;"
let varname = "\\C\\<" . a:name . "\\>"
" Go to first blank line before begin of highest scope
normal 99[{
let scopepos = getpos('.')
while (line('.') > 1) && (len(split(getline('.'))) > 0)
call cursor(line('.')-1, 0)
endwhile
let declpos = [ 0, 0, 0, 0 ]
while search(varname, '', scopepos[1]) > 0
" Check if we are a string or a comment
if omni#cpp#utils#IsCursorInCommentOrString()
continue
endif
" Remember match
let declpos = getpos('.')
endwhile
if declpos[1] != 0
" We found a match
call winrestview(winview)
call setpos('.', declpos)
let &foldenable = lastfoldenable
return 0
endif
while search(varname, '', lastpos[1]) > 0
" Check if current scope is ending before variable
let old_cur = getpos('.')
normal ]}
let new_cur = getpos('.')
call setpos('.', old_cur)
if (new_cur[1] < lastpos[1]) || ((new_cur[1] == lastpos[1]) && (new_cur[2] < lastpos[2]))
continue
endif
" Check if we are a string or a comment
if omni#cpp#utils#IsCursorInCommentOrString()
continue
endif
" We found match
call winrestview(winview)
call setpos('.', old_cur)
let &foldenable = lastfoldenable
return 0
endwhile
" No match found.
call winrestview(winview)
let &foldenable = lastfoldenable
return 1
endfunc

View File

@ -0,0 +1,82 @@
" Description: Omni completion script for cpp files
" Maintainer: Vissale NEANG
" Last Change: 26 sept. 2007
" Check if we can use omni completion in the current buffer
function! s:CanUseOmnicompletion()
" For C and C++ files and only if the omnifunc is omni#cpp#complete#Main
return (index(['c', 'cpp'], &filetype)>=0 && &omnifunc == 'omni#cpp#complete#Main' && !omni#cpp#utils#IsCursorInCommentOrString())
endfunc
" Return the mapping of omni completion
function! omni#cpp#maycomplete#Complete()
let szOmniMapping = "\<C-X>\<C-O>"
" 0 = don't select first item
" 1 = select first item (inserting it to the text, default vim behaviour)
" 2 = select first item (without inserting it to the text)
if g:OmniCpp_SelectFirstItem == 0
" We have to force the menuone option to avoid confusion when there is
" only one popup item
set completeopt-=menu
set completeopt+=menuone
let szOmniMapping .= "\<C-P>"
elseif g:OmniCpp_SelectFirstItem == 2
" We have to force the menuone option to avoid confusion when there is
" only one popup item
set completeopt-=menu
set completeopt+=menuone
let szOmniMapping .= "\<C-P>"
let szOmniMapping .= "\<C-R>=pumvisible() ? \"\\<down>\" : \"\"\<cr>"
endif
return szOmniMapping
endfunc
" May complete function for dot
function! omni#cpp#maycomplete#Dot()
if s:CanUseOmnicompletion() && g:OmniCpp_MayCompleteDot
let g:omni#cpp#items#data = omni#cpp#items#Get(omni#cpp#utils#TokenizeCurrentInstruction('.'))
if len(g:omni#cpp#items#data)
let s:bMayComplete = 1
return '.' . omni#cpp#maycomplete#Complete()
endif
endif
return '.'
endfunc
" May complete function for arrow
function! omni#cpp#maycomplete#Arrow()
if s:CanUseOmnicompletion() && g:OmniCpp_MayCompleteArrow
let index = col('.') - 2
if index >= 0
let char = getline('.')[index]
if char == '-'
let g:omni#cpp#items#data = omni#cpp#items#Get(omni#cpp#utils#TokenizeCurrentInstruction('>'))
if len(g:omni#cpp#items#data)
let s:bMayComplete = 1
return '>' . omni#cpp#maycomplete#Complete()
endif
endif
endif
endif
return '>'
endfunc
" May complete function for double points
function! omni#cpp#maycomplete#Scope()
if s:CanUseOmnicompletion() && g:OmniCpp_MayCompleteScope
let index = col('.') - 2
if index >= 0
let char = getline('.')[index]
if char == ':'
let g:omni#cpp#items#data = omni#cpp#items#Get(omni#cpp#utils#TokenizeCurrentInstruction(':'))
if len(g:omni#cpp#items#data)
if len(g:omni#cpp#items#data[-1].tokens) && g:omni#cpp#items#data[-1].tokens[-1].value != '::'
let s:bMayComplete = 1
return ':' . omni#cpp#maycomplete#Complete()
endif
endif
endif
endif
endif
return ':'
endfunc

View File

@ -0,0 +1,838 @@
" Description: Omni completion script for cpp files
" Maintainer: Vissale NEANG
" Last Change: 26 sept. 2007
let g:omni#cpp#namespaces#CacheResolve = {}
let g:omni#cpp#namespaces#CacheUsing = {}
" TODO: For the next release
"let g:omni#cpp#namespaces#CacheAlias = {}
" Get the using namespace list from a line
function! s:GetNamespaceAliasListFromLine(szLine)
let result = {}
let tokens = omni#cpp#tokenizer#Tokenize(a:szLine)
let szAlias = ''
let szNamespace = ''
let state = 0
for token in tokens
if state==0
let szAlias = ''
let szNamespace = ''
if token.value == '/*'
let state = 1
elseif token.value == '//'
" It's a comment
let state = -1
break
elseif token.value == 'namespace'
let state = 2
endif
elseif state==1
if token.value == '*/'
let state=0
endif
elseif state==2
if token.kind == 'cppWord'
let szAlias .= token.value
let state = 3
else
let state = -1
break
endif
elseif state == 3
if token.value == '='
let state = 4
else
let state = -1
break
endif
elseif state == 4
if token.value == '::'
let szNamespace .= token.value
let state = 5
elseif token.kind == 'cppWord'
let szNamespace .= token.value
let state = 6
" Maybe end of tokens
endif
elseif state==5
if token.kind == 'cppWord'
let szNamespace .= token.value
let state = 6
" Maybe end of tokens
else
" Error, we can't have 'namespace ALIAS = Something::'
let state = -1
break
endif
elseif state==6
if token.value == '::'
let szNamespace .= token.value
let state = 5
else
call extend(result, {szAlias : szNamespace})
let state = 0
endif
endif
endfor
if state == 6
call extend(result, {szAlias : szNamespace})
endif
return result
endfunc
" Get the using namespace list from a line
function! s:GetNamespaceListFromLine(szLine)
let result = []
let tokens = omni#cpp#tokenizer#Tokenize(a:szLine)
let szNamespace = ''
let state = 0
for token in tokens
if state==0
let szNamespace = ''
if token.value == '/*'
let state = 1
elseif token.value == '//'
" It's a comment
let state = -1
break
elseif token.value == 'using'
let state = 2
endif
elseif state==1
if token.value == '*/'
let state=0
endif
elseif state==2
if token.value == 'namespace'
let state = 3
else
" Error, 'using' must be followed by 'namespace'
let state = -1
break
endif
elseif state==3
if token.value == '::'
let szNamespace .= token.value
let state = 4
elseif token.kind == 'cppWord'
let szNamespace .= token.value
let state = 5
" Maybe end of tokens
endif
elseif state==4
if token.kind == 'cppWord'
let szNamespace .= token.value
let state = 5
" Maybe end of tokens
else
" Error, we can't have 'using namespace Something::'
let state = -1
break
endif
elseif state==5
if token.value == '::'
let szNamespace .= token.value
let state = 4
else
call extend(result, [szNamespace])
let state = 0
endif
endif
endfor
if state == 5
call extend(result, [szNamespace])
endif
return result
endfunc
" Get the namespace list from a namespace map
function! s:GetUsingNamespaceListFromMap(namespaceMap, ...)
let stopLine = 0
if a:0>0
let stopLine = a:1
endif
let result = []
let keys = sort(keys(a:namespaceMap), 'omni#common#utils#CompareNumber')
for i in keys
if stopLine != 0 && i > stopLine
break
endif
call extend(result, a:namespaceMap[i])
endfor
return result
endfunc
" Get global using namespace list from the current buffer
function! omni#cpp#namespaces#GetListFromCurrentBuffer(...)
let namespaceMap = s:GetAllUsingNamespaceMapFromCurrentBuffer()
let result = []
if namespaceMap != {}
let result = s:GetUsingNamespaceListFromMap(namespaceMap, (a:0 > 0)? a:1 : line('.'))
endif
return result
endfunc
" Get global using namespace map from the current buffer and include files recursively
function! s:GetAllUsingNamespaceMapFromCurrentBuffer(...)
let includeGuard = (a:0>0)? a:1 : {}
let szBufferName = getreg("%")
let szFilePath = omni#cpp#utils#ResolveFilePath(szBufferName)
let szFilePath = (szFilePath=='')? szBufferName : szFilePath
let namespaceMap = {}
if has_key(includeGuard, szFilePath)
return namespaceMap
else
let includeGuard[szFilePath] = 1
endif
let namespaceMap = omni#cpp#namespaces#GetMapFromCurrentBuffer()
if g:OmniCpp_NamespaceSearch != 2
" We don't search included files if OmniCpp_NamespaceSearch != 2
return namespaceMap
endif
for inc in omni#cpp#includes#GetList()
let lnum = inc.pos[0]
let tmpMap = s:GetAllUsingNamespaceMapFromFile(inc.include, includeGuard)
if tmpMap != {}
if has_key(namespaceMap, lnum)
call extend(namespaceMap[lnum], s:GetUsingNamespaceListFromMap(tmpMap))
else
let namespaceMap[lnum] = s:GetUsingNamespaceListFromMap(tmpMap)
endif
endif
endfor
return namespaceMap
endfunc
" Get global using namespace map from a file and include files recursively
function! s:GetAllUsingNamespaceMapFromFile(szFilePath, ...)
let includeGuard = {}
if a:0 >0
let includeGuard = a:1
endif
let szFilePath = omni#cpp#utils#ResolveFilePath(a:szFilePath)
let szFilePath = (szFilePath=='')? a:szFilePath : szFilePath
let namespaceMap = {}
if has_key(includeGuard, szFilePath)
return namespaceMap
else
let includeGuard[szFilePath] = 1
endif
" If g:OmniCpp_NamespaceSearch == 1 (search namespaces only in the current
" buffer) we don't use cache for the current buffer
let namespaceMap = omni#cpp#namespaces#GetMapFromBuffer(szFilePath, g:OmniCpp_NamespaceSearch==1)
if g:OmniCpp_NamespaceSearch != 2
" We don't search included files if OmniCpp_NamespaceSearch != 2
return namespaceMap
endif
for inc in omni#cpp#includes#GetList(szFilePath)
let lnum = inc.pos[0]
let tmpMap = s:GetAllUsingNamespaceMapFromFile(inc.include, includeGuard)
if tmpMap != {}
if has_key(namespaceMap, lnum)
call extend(namespaceMap[lnum], s:GetUsingNamespaceListFromMap(tmpMap))
else
let namespaceMap[lnum] = s:GetUsingNamespaceListFromMap(tmpMap)
endif
endif
endfor
return namespaceMap
endfunc
" Get global using namespace map from a the current buffer
function! omni#cpp#namespaces#GetMapFromCurrentBuffer()
let namespaceMap = {}
let originalPos = getpos('.')
call setpos('.', [0, 1, 1, 0])
let curPos = [1,1]
while curPos != [0,0]
let curPos = searchpos('\C^using\s\+namespace', 'W')
if curPos != [0,0]
let szLine = getline('.')
let startPos = curPos[1]
let endPos = match(szLine, ';', startPos-1)
if endPos!=-1
" We get the namespace list from the line
let namespaceMap[curPos[0]] = s:GetNamespaceListFromLine(szLine)
endif
endif
endwhile
call setpos('.', originalPos)
return namespaceMap
endfunc
" Get global using namespace map from a file
function! omni#cpp#namespaces#GetMapFromBuffer(szFilePath, ...)
let bUpdate = 0
if a:0 > 0
let bUpdate = a:1
endif
let szFilePath = omni#cpp#utils#ResolveFilePath(a:szFilePath)
let szFilePath = (szFilePath=='')? a:szFilePath : szFilePath
if !bUpdate && has_key(g:omni#cpp#namespaces#CacheUsing, szFilePath)
return copy(g:omni#cpp#namespaces#CacheUsing[szFilePath])
endif
let namespaceMap = {}
" The file exists, we get the global namespaces in this file
let szFixedPath = escape(szFilePath, g:omni#cpp#utils#szEscapedCharacters)
execute 'silent! lvimgrep /\C^using\s\+namespace/gj '.szFixedPath
" key = line number
" value = list of namespaces
let listQuickFix = getloclist(0)
for qf in listQuickFix
let szLine = qf.text
let startPos = qf.col
let endPos = match(szLine, ';', startPos-1)
if endPos!=-1
" We get the namespace list from the line
let namespaceMap[qf.lnum] = s:GetNamespaceListFromLine(szLine)
endif
endfor
if szFixedPath != ''
let g:omni#cpp#namespaces#CacheUsing[szFixedPath] = namespaceMap
endif
return copy(namespaceMap)
endfunc
" Get the stop position when searching for local variables
function! s:GetStopPositionForLocalSearch()
" Stop position when searching a local variable
let originalPos = getpos('.')
let origPos = originalPos[1:2]
let stopPosition = origPos
let curPos = origPos
while curPos !=[0,0]
let stopPosition = curPos
let curPos = searchpairpos('{', '', '}', 'bW', g:omni#cpp#utils#expIgnoreComments)
endwhile
call setpos('.', originalPos)
return stopPosition
endfunc
" Get namespaces alias used at the cursor postion in a vim buffer
" Note: The result depends on the current cursor position
" @return
" - Map of namespace alias
function! s:GetNamespaceAliasMap()
" We store the cursor position because searchpairpos() moves the cursor
let result = {}
let originalPos = getpos('.')
let origPos = originalPos[1:2]
let stopPos = s:GetStopPositionForLocalSearch()
let stopLine = stopPos[0]
let curPos = origPos
let lastLine = 0
let nextStopLine = origPos[0]
let szReAlias = '\Cnamespace\s\+\w\+\s\+='
while curPos !=[0,0]
let curPos = searchpos('}\|\('. szReAlias .'\)', 'bW',stopLine)
if curPos!=[0,0] && curPos[0]!=lastLine
let lastLine = curPos[0]
let szLine = getline('.')
if origPos[0] == curPos[0]
" We get the line until cursor position
let szLine = szLine[:origPos[1]]
endif
let szLine = omni#cpp#utils#GetCodeFromLine(szLine)
if match(szLine, szReAlias)<0
" We found a '}'
let curPos = searchpairpos('{', '', '}', 'bW', g:omni#cpp#utils#expIgnoreComments)
else
" We get the namespace alias from the line
call extend(result, s:GetNamespaceAliasListFromLine(szLine))
let nextStopLine = curPos[0]
endif
endif
endwhile
" Setting the cursor to the original position
call setpos('.', originalPos)
call s:ResolveAliasKeys(result)
return result
endfunc
" Resolve an alias
" eg: namespace IAmAnAlias1 = Ns1
" eg: namespace IAmAnAlias2 = IAmAnAlias1::Ns2
" => IAmAnAlias2 = Ns1::Ns2
function! s:ResolveAliasKey(mapNamespaceAlias, szAlias)
let szResult = a:mapNamespaceAlias[a:szAlias]
" ::Ns1::Ns2::Ns3 => ['Ns1', 'Ns2', 'Ns3']
let listNamespace = split(szResult, '::')
if len(listNamespace)
" szBeginPart = 'Ns1'
let szBeginPart = remove(listNamespace, 0)
" Is 'Ns1' an alias ?
if has_key(a:mapNamespaceAlias, szBeginPart) && szBeginPart != a:szAlias
" Resolving alias 'Ns1'
" eg: Ns1 = NsResolved
let szResult = s:ResolveAliasKey(a:mapNamespaceAlias, szBeginPart)
" szEndPart = 'Ns2::Ns3'
let szEndPart = join(listNamespace, '::')
if szEndPart != ''
" Concatenation => szResult = 'NsResolved::Ns2::Ns3'
let szResult .= '::' . szEndPart
endif
endif
endif
return szResult
endfunc
" Resolve all keys in the namespace alias map
function! s:ResolveAliasKeys(mapNamespaceAlias)
let mapNamespaceAlias = a:mapNamespaceAlias
call map(mapNamespaceAlias, 's:ResolveAliasKey(mapNamespaceAlias, v:key)')
endfunc
" Resolve namespace alias
function! omni#cpp#namespaces#ResolveAlias(mapNamespaceAlias, szNamespace)
let szResult = a:szNamespace
" ::Ns1::Ns2::Ns3 => ['Ns1', 'Ns2', 'Ns3']
let listNamespace = split(a:szNamespace, '::')
if len(listNamespace)
" szBeginPart = 'Ns1'
let szBeginPart = remove(listNamespace, 0)
" Is 'Ns1' an alias ?
if has_key(a:mapNamespaceAlias, szBeginPart)
" Resolving alias 'Ns1'
" eg: Ns1 = NsResolved
let szResult = a:mapNamespaceAlias[szBeginPart]
" szEndPart = 'Ns2::Ns3'
let szEndPart = join(listNamespace, '::')
if szEndPart != ''
" Concatenation => szResult = 'NsResolved::Ns2::Ns3'
let szResult .= '::' . szEndPart
endif
" If a:szNamespace starts with '::' we add '::' to the beginning
" of the result
if match(a:szNamespace, '^::')>=0
let szResult = omni#cpp#utils#SimplifyScope('::' . szResult)
endif
endif
endif
return szResult
endfunc
" Resolve namespace alias
function! s:ResolveAliasInNamespaceList(mapNamespaceAlias, listNamespaces)
call map(a:listNamespaces, 'omni#cpp#namespaces#ResolveAlias(a:mapNamespaceAlias, v:val)')
endfunc
" Get namespaces used at the cursor postion in a vim buffer
" Note: The result depends on the current cursor position
" @return
" - List of namespace used in the reverse order
function! omni#cpp#namespaces#GetUsingNamespaces()
" We have to get local using namespace declarations
" We need the current cursor position and the position of the start of the
" current scope
" We store the cursor position because searchpairpos() moves the cursor
let result = []
let originalPos = getpos('.')
let origPos = originalPos[1:2]
let stopPos = s:GetStopPositionForLocalSearch()
let stopLine = stopPos[0]
let curPos = origPos
let lastLine = 0
let nextStopLine = origPos[0]
while curPos !=[0,0]
let curPos = searchpos('\C}\|\(using\s\+namespace\)', 'bW',stopLine)
if curPos!=[0,0] && curPos[0]!=lastLine
let lastLine = curPos[0]
let szLine = getline('.')
if origPos[0] == curPos[0]
" We get the line until cursor position
let szLine = szLine[:origPos[1]]
endif
let szLine = omni#cpp#utils#GetCodeFromLine(szLine)
if match(szLine, '\Cusing\s\+namespace')<0
" We found a '}'
let curPos = searchpairpos('{', '', '}', 'bW', g:omni#cpp#utils#expIgnoreComments)
else
" We get the namespace list from the line
let result = s:GetNamespaceListFromLine(szLine) + result
let nextStopLine = curPos[0]
endif
endif
endwhile
" Setting the cursor to the original position
call setpos('.', originalPos)
" 2) Now we can get all global using namespace declaration from the
" beginning of the file to nextStopLine
let result = omni#cpp#namespaces#GetListFromCurrentBuffer(nextStopLine) + result
" Resolving alias in the namespace list
" TODO: For the next release
"let g:omni#cpp#namespaces#CacheAlias= s:GetNamespaceAliasMap()
"call s:ResolveAliasInNamespaceList(g:omni#cpp#namespaces#CacheAlias, result)
return ['::'] + result
endfunc
" Resolve a using namespace regarding the current context
" For each namespace used:
" - We get all possible contexts where the namespace
" can be define
" - We do a comparison test of each parent contexts with the current
" context list
" - If one and only one parent context is present in the
" current context list we add the namespace in the current
" context
" - If there is more than one of parent contexts in the
" current context the namespace is ambiguous
" @return
" - result item
" - kind = 0|1
" - 0 = unresolved or error
" - 1 = resolved
" - value = resolved namespace
function! s:ResolveNamespace(namespace, mapCurrentContexts)
let result = {'kind':0, 'value': ''}
" If the namespace is already resolved we add it in the list of
" current contexts
if match(a:namespace, '^::')>=0
let result.kind = 1
let result.value = a:namespace
return result
elseif match(a:namespace, '\w\+::\w\+')>=0
let mapCurrentContextsTmp = copy(a:mapCurrentContexts)
let resolvedItem = {}
for nsTmp in split(a:namespace, '::')
let resolvedItem = s:ResolveNamespace(nsTmp, mapCurrentContextsTmp)
if resolvedItem.kind
" Note: We don't extend the map
let mapCurrentContextsTmp = {resolvedItem.value : 1}
else
break
endif
endfor
if resolvedItem!={} && resolvedItem.kind
let result.kind = 1
let result.value = resolvedItem.value
endif
return result
endif
" We get all possible parent contexts of this namespace
let listTagsOfNamespace = []
if has_key(g:omni#cpp#namespaces#CacheResolve, a:namespace)
let listTagsOfNamespace = g:omni#cpp#namespaces#CacheResolve[a:namespace]
else
let listTagsOfNamespace = omni#common#utils#TagList('^'.a:namespace.'$')
let g:omni#cpp#namespaces#CacheResolve[a:namespace] = listTagsOfNamespace
endif
if len(listTagsOfNamespace)==0
return result
endif
call filter(listTagsOfNamespace, 'v:val.kind[0]=="n"')
" We extract parent context from tags
" We use a map to avoid multiple entries
let mapContext = {}
for tagItem in listTagsOfNamespace
let szParentContext = omni#cpp#utils#ExtractScope(tagItem)
let mapContext[szParentContext] = 1
endfor
let listParentContext = keys(mapContext)
" Now for each parent context we test if the context is in the current
" contexts list
let listResolvedNamespace = []
for szParentContext in listParentContext
if has_key(a:mapCurrentContexts, szParentContext)
call extend(listResolvedNamespace, [omni#cpp#utils#SimplifyScope(szParentContext.'::'.a:namespace)])
endif
endfor
" Now we know if the namespace is ambiguous or not
let len = len(listResolvedNamespace)
if len==1
" Namespace resolved
let result.kind = 1
let result.value = listResolvedNamespace[0]
elseif len > 1
" Ambiguous namespace, possible matches are in listResolvedNamespace
else
" Other cases
endif
return result
endfunc
" Resolve namespaces
"@return
" - List of resolved namespaces
function! omni#cpp#namespaces#ResolveAll(namespacesUsed)
" We add the default context '::'
let contextOrder = 0
let mapCurrentContexts = {}
" For each namespace used:
" - We get all possible contexts where the namespace
" can be define
" - We do a comparison test of each parent contexts with the current
" context list
" - If one and only one parent context is present in the
" current context list we add the namespace in the current
" context
" - If there is more than one of parent contexts in the
" current context the namespace is ambiguous
for ns in a:namespacesUsed
let resolvedItem = s:ResolveNamespace(ns, mapCurrentContexts)
if resolvedItem.kind
let contextOrder+=1
let mapCurrentContexts[resolvedItem.value] = contextOrder
endif
endfor
" Build the list of current contexts from the map, we have to keep the
" order
let mapReorder = {}
for key in keys(mapCurrentContexts)
let mapReorder[ mapCurrentContexts[key] ] = key
endfor
let result = []
for key in sort(keys(mapReorder))
call extend(result, [mapReorder[key]])
endfor
return result
endfunc
" Build the context stack
function! s:BuildContextStack(namespaces, szCurrentScope)
let result = copy(a:namespaces)
if a:szCurrentScope != '::'
let tagItem = omni#cpp#utils#GetResolvedTagItem(a:namespaces, omni#cpp#utils#CreateTypeInfo(a:szCurrentScope))
if has_key(tagItem, 'inherits')
let listBaseClass = omni#cpp#utils#GetClassInheritanceList(a:namespaces, omni#cpp#utils#CreateTypeInfo(a:szCurrentScope))
let result = listBaseClass + result
elseif has_key(tagItem, 'kind') && index(['c', 's', 'u', 'n'], tagItem.kind[0])>=0
call insert(result, omni#cpp#utils#ExtractTypeInfoFromTag(tagItem))
endif
endif
return result
endfunc
" Returns the class scope at the current position of the cursor
" @return a string that represents the class scope
" eg: ::NameSpace1::Class1
" The returned string always starts with '::'
" Note: In term of performance it's the weak point of the script
function! s:GetClassScopeAtCursor()
" We store the cursor position because searchpairpos() moves the cursor
let originalPos = getpos('.')
let endPos = originalPos[1:2]
let listCode = []
let result = {'namespaces': [], 'scope': ''}
while endPos!=[0,0]
let endPos = searchpairpos('{', '', '}', 'bW', g:omni#cpp#utils#expIgnoreComments)
let szReStartPos = '[;{}]\|\%^'
let startPos = searchpairpos(szReStartPos, '', '{', 'bWn', g:omni#cpp#utils#expIgnoreComments)
" If the file starts with a comment so the startPos can be [0,0]
" we change it to [1,1]
if startPos==[0,0]
let startPos = [1,1]
endif
" Get lines backward from cursor position to last ; or { or }
" or when we are at the beginning of the file.
" We store lines in listCode
if endPos!=[0,0]
" We remove the last character which is a '{'
" We also remove starting { or } or ; if exits
let szCodeWithoutComments = substitute(omni#cpp#utils#GetCode(startPos, endPos)[:-2], '^[;{}]', '', 'g')
call insert(listCode, {'startLine' : startPos[0], 'code' : szCodeWithoutComments})
endif
endwhile
" Setting the cursor to the original position
call setpos('.', originalPos)
let listClassScope = []
let bResolved = 0
let startLine = 0
" Now we can check in the list of code if there is a function
for code in listCode
" We get the name of the namespace, class, struct or union
" and we store it in listClassScope
let tokens = omni#cpp#tokenizer#Tokenize(code.code)
let bContinue=0
let bAddNamespace = 0
let state=0
for token in tokens
if state==0
if index(['namespace', 'class', 'struct', 'union'], token.value)>=0
if token.value == 'namespace'
let bAddNamespace = 1
endif
let state= 1
" Maybe end of tokens
endif
elseif state==1
if token.kind == 'cppWord'
" eg: namespace MyNs { class MyCl {}; }
" => listClassScope = [MyNs, MyCl]
call extend( listClassScope , [token.value] )
" Add the namespace in result
if bAddNamespace
call extend(result.namespaces, [token.value])
let bAddNamespace = 0
endif
let bContinue=1
break
endif
endif
endfor
if bContinue==1
continue
endif
" Simple test to check if we have a chance to find a
" class method
let aPos = matchend(code.code, '::\s*\~*\s*\w\+\s*(')
if aPos ==-1
continue
endif
let startLine = code.startLine
let listTmp = []
" eg: 'void MyNamespace::MyClass::foo('
" => tokens = ['MyClass', '::', 'MyNamespace', 'void']
let tokens = reverse(omni#cpp#tokenizer#Tokenize(code.code[:aPos-1])[:-4])
let state = 0
" Reading tokens backward
for token in tokens
if state==0
if token.kind=='cppWord'
call insert(listTmp, token.value)
let state=1
endif
elseif state==1
if token.value=='::'
let state=2
else
break
endif
elseif state==2
if token.kind=='cppWord'
call insert(listTmp, token.value)
let state=1
else
break
endif
endif
endfor
if len(listTmp)
if len(listClassScope)
let bResolved = 1
" Merging class scopes
" eg: current class scope = 'MyNs::MyCl1'
" method class scope = 'MyCl1::MyCl2'
" If we add the method class scope to current class scope
" we'll have MyNs::MyCl1::MyCl1::MyCl2 => it's wrong
" we want MyNs::MyCl1::MyCl2
let index = 0
for methodClassScope in listTmp
if methodClassScope==listClassScope[-1]
let listTmp = listTmp[index+1:]
break
else
let index+=1
endif
endfor
endif
call extend(listClassScope, listTmp)
break
endif
endfor
let szClassScope = '::'
if len(listClassScope)
if bResolved
let szClassScope .= join(listClassScope, '::')
else
let szClassScope = join(listClassScope, '::')
" The class scope is not resolved, we have to check using
" namespace declarations and search the class scope in each
" namespace
if startLine != 0
let namespaces = ['::'] + omni#cpp#namespaces#GetListFromCurrentBuffer(startLine)
let namespaces = omni#cpp#namespaces#ResolveAll(namespaces)
let tagItem = omni#cpp#utils#GetResolvedTagItem(namespaces, omni#cpp#utils#CreateTypeInfo(szClassScope))
if tagItem != {}
let szClassScope = omni#cpp#utils#ExtractTypeInfoFromTag(tagItem)
endif
endif
endif
endif
let result.scope = szClassScope
return result
endfunc
" Get all contexts at the cursor position
function! omni#cpp#namespaces#GetContexts()
" Get the current class scope at the cursor, the result depends on the current cursor position
let scopeItem = s:GetClassScopeAtCursor()
let listUsingNamespace = copy(g:OmniCpp_DefaultNamespaces)
call extend(listUsingNamespace, scopeItem.namespaces)
if g:OmniCpp_NamespaceSearch && &filetype != 'c'
" Get namespaces used in the file until the cursor position
let listUsingNamespace = omni#cpp#namespaces#GetUsingNamespaces() + listUsingNamespace
" Resolving namespaces, removing ambiguous namespaces
let namespaces = omni#cpp#namespaces#ResolveAll(listUsingNamespace)
else
let namespaces = ['::'] + listUsingNamespace
endif
call reverse(namespaces)
" Building context stack from namespaces and the current class scope
return s:BuildContextStack(namespaces, scopeItem.scope)
endfunc

View File

@ -0,0 +1,96 @@
" Description: Omni completion script for cpp files
" Maintainer: Vissale NEANG
" Last Change: 26 sept. 2007
function! omni#cpp#settings#Init()
" Global scope search on/off
" 0 = disabled
" 1 = enabled
if !exists('g:OmniCpp_GlobalScopeSearch')
let g:OmniCpp_GlobalScopeSearch = 1
endif
" Sets the namespace search method
" 0 = disabled
" 1 = search namespaces in the current file
" 2 = search namespaces in the current file and included files
if !exists('g:OmniCpp_NamespaceSearch')
let g:OmniCpp_NamespaceSearch = 1
endif
" Set the class scope completion mode
" 0 = auto
" 1 = show all members (static, public, protected and private)
if !exists('g:OmniCpp_DisplayMode')
let g:OmniCpp_DisplayMode = 0
endif
" Set if the scope is displayed in the abbr column of the popup
" 0 = no
" 1 = yes
if !exists('g:OmniCpp_ShowScopeInAbbr')
let g:OmniCpp_ShowScopeInAbbr = 0
endif
" Set if the function prototype is displayed in the abbr column of the popup
" 0 = no
" 1 = yes
if !exists('g:OmniCpp_ShowPrototypeInAbbr')
let g:OmniCpp_ShowPrototypeInAbbr = 0
endif
" Set if the access (+,#,-) is displayed
" 0 = no
" 1 = yes
if !exists('g:OmniCpp_ShowAccess')
let g:OmniCpp_ShowAccess = 1
endif
" Set the list of default namespaces
" eg: ['std']
if !exists('g:OmniCpp_DefaultNamespaces')
let g:OmniCpp_DefaultNamespaces = []
endif
" Set MayComplete to '.'
" 0 = disabled
" 1 = enabled
" default = 1
if !exists('g:OmniCpp_MayCompleteDot')
let g:OmniCpp_MayCompleteDot = 1
endif
" Set MayComplete to '->'
" 0 = disabled
" 1 = enabled
" default = 1
if !exists('g:OmniCpp_MayCompleteArrow')
let g:OmniCpp_MayCompleteArrow = 1
endif
" Set MayComplete to dot
" 0 = disabled
" 1 = enabled
" default = 0
if !exists('g:OmniCpp_MayCompleteScope')
let g:OmniCpp_MayCompleteScope = 0
endif
" When completeopt does not contain longest option, this setting
" controls the behaviour of the popup menu selection when starting the completion
" 0 = don't select first item
" 1 = select first item (inserting it to the text)
" 2 = select first item (without inserting it to the text)
" default = 0
if !exists('g:OmniCpp_SelectFirstItem')
let g:OmniCpp_SelectFirstItem= 0
endif
" Use local search function for variable definitions
" 0 = use standard vim search function
" 1 = use local search function
" default = 0
if !exists('g:OmniCpp_LocalSearchDecl')
let g:OmniCpp_LocalSearchDecl= 0
endif
endfunc

View File

@ -0,0 +1,93 @@
" Description: Omni completion tokenizer
" Maintainer: Vissale NEANG
" Last Change: 26 sept. 2007
" TODO: Generic behaviour for Tokenize()
" From the C++ BNF
let s:cppKeyword = ['asm', 'auto', 'bool', 'break', 'case', 'catch', 'char', 'class', 'const', 'const_cast', 'continue', 'default', 'delete', 'do', 'double', 'dynamic_cast', 'else', 'enum', 'explicit', 'export', 'extern', 'false', 'float', 'for', 'friend', 'goto', 'if', 'inline', 'int', 'long', 'mutable', 'namespace', 'new', 'operator', 'private', 'protected', 'public', 'register', 'reinterpret_cast', 'return', 'short', 'signed', 'sizeof', 'static', 'static_cast', 'struct', 'switch', 'template', 'this', 'throw', 'true', 'try', 'typedef', 'typeid', 'typename', 'union', 'unsigned', 'using', 'virtual', 'void', 'volatile', 'wchar_t', 'while', 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not', 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq']
let s:reCppKeyword = '\C\<'.join(s:cppKeyword, '\>\|\<').'\>'
" The order of items in this list is very important because we use this list to build a regular
" expression (see below) for tokenization
let s:cppOperatorPunctuator = ['->*', '->', '--', '-=', '-', '!=', '!', '##', '#', '%:%:', '%=', '%>', '%:', '%', '&&', '&=', '&', '(', ')', '*=', '*', ',', '...', '.*', '.', '/=', '/', '::', ':>', ':', ';', '?', '[', ']', '^=', '^', '{', '||', '|=', '|', '}', '~', '++', '+=', '+', '<<=', '<%', '<:', '<<', '<=', '<', '==', '=', '>>=', '>>', '>=', '>']
" We build the regexp for the tokenizer
let s:reCComment = '\/\*\|\*\/'
let s:reCppComment = '\/\/'
let s:reComment = s:reCComment.'\|'.s:reCppComment
let s:reCppOperatorOrPunctuator = escape(join(s:cppOperatorPunctuator, '\|'), '*./^~[]')
" Tokenize a c++ code
" a token is dictionary where keys are:
" - kind = cppKeyword|cppWord|cppOperatorPunctuator|unknown|cComment|cppComment|cppDigit
" - value = 'something'
" Note: a cppWord is any word that is not a cpp keyword
function! omni#cpp#tokenizer#Tokenize(szCode)
let result = []
" The regexp to find a token, a token is a keyword, word or
" c++ operator or punctuator. To work properly we have to put
" spaces and tabs to our regexp.
let reTokenSearch = '\(\w\+\)\|\s\+\|'.s:reComment.'\|'.s:reCppOperatorOrPunctuator
" eg: 'using namespace std;'
" ^ ^
" start=0 end=5
let startPos = 0
let endPos = matchend(a:szCode, reTokenSearch)
let len = endPos-startPos
while endPos!=-1
" eg: 'using namespace std;'
" ^ ^
" start=0 end=5
" token = 'using'
" We also remove space and tabs
let token = substitute(strpart(a:szCode, startPos, len), '\s', '', 'g')
" eg: 'using namespace std;'
" ^ ^
" start=5 end=15
let startPos = endPos
let endPos = matchend(a:szCode, reTokenSearch, startPos)
let len = endPos-startPos
" It the token is empty we continue
if token==''
continue
endif
" Building the token
let resultToken = {'kind' : 'unknown', 'value' : token}
" Classify the token
if token =~ '^\d\+'
" It's a digit
let resultToken.kind = 'cppDigit'
elseif token=~'^\w\+$'
" It's a word
let resultToken.kind = 'cppWord'
" But maybe it's a c++ keyword
if match(token, s:reCppKeyword)>=0
let resultToken.kind = 'cppKeyword'
endif
else
if match(token, s:reComment)>=0
if index(['/*','*/'],token)>=0
let resultToken.kind = 'cComment'
else
let resultToken.kind = 'cppComment'
endif
else
" It's an operator
let resultToken.kind = 'cppOperatorPunctuator'
endif
endif
" We have our token, let's add it to the result list
call extend(result, [resultToken])
endwhile
return result
endfunc

View File

@ -0,0 +1,587 @@
" Description: Omni completion script for cpp files
" Maintainer: Vissale NEANG
" Last Change: 26 sept. 2007
let g:omni#cpp#utils#CACHE_TAG_INHERITS = {}
let g:omni#cpp#utils#szFilterGlobalScope = "(!has_key(v:val, 'class') && !has_key(v:val, 'struct') && !has_key(v:val, 'union') && !has_key(v:val, 'namespace')"
let g:omni#cpp#utils#szFilterGlobalScope .= "&& (!has_key(v:val, 'enum') || (has_key(v:val, 'enum') && v:val.enum =~ '^\\w\\+$')))"
" Expression used to ignore comments
" Note: this expression drop drastically the performance
"let omni#cpp#utils#expIgnoreComments = 'match(synIDattr(synID(line("."), col("."), 1), "name"), '\CcComment')!=-1'
" This one is faster but not really good for C comments
let omni#cpp#utils#reIgnoreComment = escape('\/\/\|\/\*\|\*\/', '*/\')
let omni#cpp#utils#expIgnoreComments = 'getline(".") =~ g:omni#cpp#utils#reIgnoreComment'
" Characters to escape in a filename for vimgrep
"TODO: Find more characters to escape
let omni#cpp#utils#szEscapedCharacters = ' %#'
" Resolve the path of the file
" TODO: absolute file path
function! omni#cpp#utils#ResolveFilePath(szFile)
let result = ''
let listPath = split(globpath(&path, a:szFile), "\n")
if len(listPath)
let result = listPath[0]
endif
return simplify(result)
endfunc
" Get code without comments and with empty strings
" szSingleLine must not have carriage return
function! omni#cpp#utils#GetCodeFromLine(szSingleLine)
" We set all strings to empty strings, it's safer for
" the next of the process
let szResult = substitute(a:szSingleLine, '".*"', '""', 'g')
" Removing c++ comments, we can use the pattern ".*" because
" we are modifying a line
let szResult = substitute(szResult, '\/\/.*', '', 'g')
" Now we have the entire code in one line and we can remove C comments
return s:RemoveCComments(szResult)
endfunc
" Remove C comments on a line
function! s:RemoveCComments(szLine)
let result = a:szLine
" We have to match the first '/*' and first '*/'
let startCmt = match(result, '\/\*')
let endCmt = match(result, '\*\/')
while startCmt!=-1 && endCmt!=-1 && startCmt<endCmt
if startCmt>0
let result = result[ : startCmt-1 ] . result[ endCmt+2 : ]
else
" Case where '/*' is at the start of the line
let result = result[ endCmt+2 : ]
endif
let startCmt = match(result, '\/\*')
let endCmt = match(result, '\*\/')
endwhile
return result
endfunc
" Get a c++ code from current buffer from [lineStart, colStart] to
" [lineEnd, colEnd] without c++ and c comments, without end of line
" and with empty strings if any
" @return a string
function! omni#cpp#utils#GetCode(posStart, posEnd)
let posStart = a:posStart
let posEnd = a:posEnd
if a:posStart[0]>a:posEnd[0]
let posStart = a:posEnd
let posEnd = a:posStart
elseif a:posStart[0]==a:posEnd[0] && a:posStart[1]>a:posEnd[1]
let posStart = a:posEnd
let posEnd = a:posStart
endif
" Getting the lines
let lines = getline(posStart[0], posEnd[0])
let lenLines = len(lines)
" Formatting the result
let result = ''
if lenLines==1
let sStart = posStart[1]-1
let sEnd = posEnd[1]-1
let line = lines[0]
let lenLastLine = strlen(line)
let sEnd = (sEnd>lenLastLine)?lenLastLine : sEnd
if sStart >= 0
let result = omni#cpp#utils#GetCodeFromLine(line[ sStart : sEnd ])
endif
elseif lenLines>1
let sStart = posStart[1]-1
let sEnd = posEnd[1]-1
let lenLastLine = strlen(lines[-1])
let sEnd = (sEnd>lenLastLine)?lenLastLine : sEnd
if sStart >= 0
let lines[0] = lines[0][ sStart : ]
let lines[-1] = lines[-1][ : sEnd ]
for aLine in lines
let result = result . omni#cpp#utils#GetCodeFromLine(aLine)." "
endfor
let result = result[:-2]
endif
endif
" Now we have the entire code in one line and we can remove C comments
return s:RemoveCComments(result)
endfunc
" Extract the scope (context) of a tag item
" eg: ::MyNamespace
" @return a string of the scope. a scope from tag always starts with '::'
function! omni#cpp#utils#ExtractScope(tagItem)
let listKindScope = ['class', 'struct', 'union', 'namespace', 'enum']
let szResult = '::'
for scope in listKindScope
if has_key(a:tagItem, scope)
let szResult = szResult . a:tagItem[scope]
break
endif
endfor
return szResult
endfunc
" Simplify scope string, remove consecutive '::' if any
function! omni#cpp#utils#SimplifyScope(szScope)
let szResult = substitute(a:szScope, '\(::\)\+', '::', 'g')
if szResult=='::'
return szResult
else
return substitute(szResult, '::$', '', 'g')
endif
endfunc
" Check if the cursor is in comment
function! omni#cpp#utils#IsCursorInCommentOrString()
return match(synIDattr(synID(line("."), col(".")-1, 1), "name"), '\C\<cComment\|\<cCppString\|\<cIncluded')>=0
endfunc
" Tokenize the current instruction until the cursor position.
" @return list of tokens
function! omni#cpp#utils#TokenizeCurrentInstruction(...)
let szAppendText = ''
if a:0>0
let szAppendText = a:1
endif
let startPos = searchpos('[;{}]\|\%^', 'bWn')
let curPos = getpos('.')[1:2]
" We don't want the character under the cursor
let column = curPos[1]-1
let curPos[1] = (column<1)?1:column
return omni#cpp#tokenizer#Tokenize(omni#cpp#utils#GetCode(startPos, curPos)[1:] . szAppendText)
endfunc
" Tokenize the current instruction until the word under the cursor.
" @return list of tokens
function! omni#cpp#utils#TokenizeCurrentInstructionUntilWord()
let startPos = searchpos('[;{}]\|\%^', 'bWn')
" Saving the current cursor pos
let originalPos = getpos('.')
" We go at the end of the word
execute 'normal gee'
let curPos = getpos('.')[1:2]
" Restoring the original cursor pos
call setpos('.', originalPos)
let szCode = omni#cpp#utils#GetCode(startPos, curPos)[1:]
return omni#cpp#tokenizer#Tokenize(szCode)
endfunc
" Build parenthesis groups
" add a new key 'group' in the token
" where value is the group number of the parenthesis
" eg: (void*)(MyClass*)
" group1 group0
" if a parenthesis is unresolved the group id is -1
" @return a copy of a:tokens with parenthesis group
function! omni#cpp#utils#BuildParenthesisGroups(tokens)
let tokens = copy(a:tokens)
let kinds = {'(': '()', ')' : '()', '[' : '[]', ']' : '[]', '<' : '<>', '>' : '<>', '{': '{}', '}': '{}'}
let unresolved = {'()' : [], '[]': [], '<>' : [], '{}' : []}
let groupId = 0
" Note: we build paren group in a backward way
" because we can often have parenthesis unbalanced
" instruction
" eg: doSomething(_member.get()->
for token in reverse(tokens)
if index([')', ']', '>', '}'], token.value)>=0
let token['group'] = groupId
call extend(unresolved[kinds[token.value]], [token])
let groupId+=1
elseif index(['(', '[', '<', '{'], token.value)>=0
if len(unresolved[kinds[token.value]])
let tokenResolved = remove(unresolved[kinds[token.value]], -1)
let token['group'] = tokenResolved.group
else
let token['group'] = -1
endif
endif
endfor
return reverse(tokens)
endfunc
" Determine if tokens represent a C cast
" @return
" - itemCast
" - itemCppCast
" - itemVariable
" - itemThis
function! omni#cpp#utils#GetCastType(tokens)
" Note: a:tokens is not modified
let tokens = omni#cpp#utils#SimplifyParenthesis(omni#cpp#utils#BuildParenthesisGroups(a:tokens))
if tokens[0].value == '('
return 'itemCast'
elseif index(['static_cast', 'dynamic_cast', 'reinterpret_cast', 'const_cast'], tokens[0].value)>=0
return 'itemCppCast'
else
for token in tokens
if token.value=='this'
return 'itemThis'
endif
endfor
return 'itemVariable'
endif
endfunc
" Remove useless parenthesis
function! omni#cpp#utils#SimplifyParenthesis(tokens)
"Note: a:tokens is not modified
let tokens = a:tokens
" We remove useless parenthesis eg: (((MyClass)))
if len(tokens)>2
while tokens[0].value=='(' && tokens[-1].value==')' && tokens[0].group==tokens[-1].group
let tokens = tokens[1:-2]
endwhile
endif
return tokens
endfunc
" Function create a type info
function! omni#cpp#utils#CreateTypeInfo(param)
let type = type(a:param)
return {'type': type, 'value':a:param}
endfunc
" Extract type info from a tag item
" eg: ::MyNamespace::MyClass
function! omni#cpp#utils#ExtractTypeInfoFromTag(tagItem)
let szTypeInfo = omni#cpp#utils#ExtractScope(a:tagItem) . '::' . substitute(a:tagItem.name, '.*::', '', 'g')
return omni#cpp#utils#SimplifyScope(szTypeInfo)
endfunc
" Build a class inheritance list
function! omni#cpp#utils#GetClassInheritanceList(namespaces, typeInfo)
let result = []
for tagItem in omni#cpp#utils#GetResolvedTags(a:namespaces, a:typeInfo)
call extend(result, [omni#cpp#utils#ExtractTypeInfoFromTag(tagItem)])
endfor
return result
endfunc
" Get class inheritance list where items in the list are tag items.
" TODO: Verify inheritance order
function! omni#cpp#utils#GetResolvedTags(namespaces, typeInfo)
let result = []
let tagItem = omni#cpp#utils#GetResolvedTagItem(a:namespaces, a:typeInfo)
if tagItem!={}
let szTypeInfo = omni#cpp#utils#ExtractTypeInfoFromTag(tagItem)
if has_key(g:omni#cpp#utils#CACHE_TAG_INHERITS, szTypeInfo)
let result = g:omni#cpp#utils#CACHE_TAG_INHERITS[szTypeInfo]
else
call extend(result, [tagItem])
if has_key(tagItem, 'inherits')
for baseClassTypeInfo in split(tagItem.inherits, ',')
let namespaces = [omni#cpp#utils#ExtractScope(tagItem), '::']
call extend(result, omni#cpp#utils#GetResolvedTags(namespaces, omni#cpp#utils#CreateTypeInfo(baseClassTypeInfo)))
endfor
endif
let g:omni#cpp#utils#CACHE_TAG_INHERITS[szTypeInfo] = result
endif
endif
return result
endfunc
" Get a tag item after a scope resolution and typedef resolution
function! omni#cpp#utils#GetResolvedTagItem(namespaces, typeInfo)
let typeInfo = {}
if type(a:typeInfo) == 1
let typeInfo = omni#cpp#utils#CreateTypeInfo(a:typeInfo)
else
let typeInfo = a:typeInfo
endif
let result = {}
if !omni#cpp#utils#IsTypeInfoValid(typeInfo)
return result
endif
" Unnamed type case eg: '1::2'
if typeInfo.type == 4
" Here there is no typedef or namespace to resolve, the tagInfo.value is a tag item
" representing a variable ('v') a member ('m') or a typedef ('t') and the typename is
" always in global scope
return typeInfo.value
endif
" Named type case eg: 'MyNamespace::MyClass'
let szTypeInfo = omni#cpp#utils#GetTypeInfoString(typeInfo)
" Resolving namespace alias
" TODO: For the next release
"let szTypeInfo = omni#cpp#namespaces#ResolveAlias(g:omni#cpp#namespaces#CacheAlias, szTypeInfo)
if szTypeInfo=='::'
return result
endif
" We can only get members of class, struct, union and namespace
let szTagFilter = "index(['c', 's', 'u', 'n', 't'], v:val.kind[0])>=0"
let szTagQuery = szTypeInfo
if s:IsTypeInfoResolved(szTypeInfo)
" The type info is already resolved, we remove the starting '::'
let szTagQuery = substitute(szTypeInfo, '^::', '', 'g')
if len(split(szTagQuery, '::'))==1
" eg: ::MyClass
" Here we have to get tags that have no parent scope
" That's why we change the szTagFilter
let szTagFilter .= '&& ' . g:omni#cpp#utils#szFilterGlobalScope
let tagList = omni#common#utils#TagListNoThrow('^'.szTagQuery.'$')
call filter(tagList, szTagFilter)
if len(tagList)
let result = tagList[0]
endif
else
" eg: ::MyNamespace::MyClass
let tagList = omni#common#utils#TagListNoThrow('^'.szTagQuery.'$')
call filter(tagList, szTagFilter)
if len(tagList)
let result = tagList[0]
endif
endif
else
" The type is not resolved
let tagList = omni#common#utils#TagListNoThrow('^'.szTagQuery.'$')
call filter(tagList, szTagFilter)
if len(tagList)
" Resolving scope (namespace, nested class etc...)
let szScopeOfTypeInfo = s:ExtractScopeFromTypeInfo(szTypeInfo)
if s:IsTypeInfoResolved(szTypeInfo)
let result = s:GetTagOfSameScope(tagList, szScopeOfTypeInfo)
else
" For each namespace of the namespace list we try to get a tag
" that can be in the same scope
if g:OmniCpp_NamespaceSearch && &filetype != 'c'
for scope in a:namespaces
let szTmpScope = omni#cpp#utils#SimplifyScope(scope.'::'.szScopeOfTypeInfo)
let result = s:GetTagOfSameScope(tagList, szTmpScope)
if result!={}
break
endif
endfor
else
let szTmpScope = omni#cpp#utils#SimplifyScope('::'.szScopeOfTypeInfo)
let result = s:GetTagOfSameScope(tagList, szTmpScope)
endif
endif
endif
endif
if result!={}
" We have our tagItem but maybe it's a typedef or an unnamed type
if result.kind[0]=='t'
" Here we can have a typedef to another typedef, a class, struct, union etc
" but we can also have a typedef to an unnamed type, in that
" case the result contains a 'typeref' key
let namespaces = [omni#cpp#utils#ExtractScope(result), '::']
if has_key(result, 'typeref')
let result = omni#cpp#utils#GetResolvedTagItem(namespaces, omni#cpp#utils#CreateTypeInfo(result))
else
let szCmd = omni#cpp#utils#ExtractCmdFromTagItem(result)
let szCode = substitute(omni#cpp#utils#GetCodeFromLine(szCmd), '\C\<'.result.name.'\>.*', '', 'g')
let szTypeInfo = omni#cpp#utils#ExtractTypeInfoFromTokens(omni#cpp#tokenizer#Tokenize(szCode))
let result = omni#cpp#utils#GetResolvedTagItem(namespaces, omni#cpp#utils#CreateTypeInfo(szTypeInfo))
" TODO: Namespace resolution for result
endif
endif
endif
return result
endfunc
" Returns if the type info is valid
" @return
" - 1 if valid
" - 0 otherwise
function! omni#cpp#utils#IsTypeInfoValid(typeInfo)
if a:typeInfo=={}
return 0
else
if a:typeInfo.type == 1 && a:typeInfo.value==''
" String case
return 0
elseif a:typeInfo.type == 4 && a:typeInfo.value=={}
" Dictionary case
return 0
endif
endif
return 1
endfunc
" Get the string of the type info
function! omni#cpp#utils#GetTypeInfoString(typeInfo)
if a:typeInfo.type == 1
return a:typeInfo.value
else
return substitute(a:typeInfo.value.typeref, '^\w\+:', '', 'g')
endif
endfunc
" A resolved type info starts with '::'
" @return
" - 1 if type info starts with '::'
" - 0 otherwise
function! s:IsTypeInfoResolved(szTypeInfo)
return match(a:szTypeInfo, '^::')!=-1
endfunc
" A returned type info's scope may not have the global namespace '::'
" eg: '::NameSpace1::NameSpace2::MyClass' => '::NameSpace1::NameSpace2'
" 'NameSpace1::NameSpace2::MyClass' => 'NameSpace1::NameSpace2'
function! s:ExtractScopeFromTypeInfo(szTypeInfo)
let szScope = substitute(a:szTypeInfo, '\w\+$', '', 'g')
if szScope =='::'
return szScope
else
return substitute(szScope, '::$', '', 'g')
endif
endfunc
" @return
" - the tag with the same scope
" - {} otherwise
function! s:GetTagOfSameScope(listTags, szScopeToMatch)
for tagItem in a:listTags
let szScopeOfTag = omni#cpp#utils#ExtractScope(tagItem)
if szScopeOfTag == a:szScopeToMatch
return tagItem
endif
endfor
return {}
endfunc
" Extract the cmd of a tag item without regexp
function! omni#cpp#utils#ExtractCmdFromTagItem(tagItem)
let line = a:tagItem.cmd
let re = '\(\/\^\)\|\(\$\/\)'
if match(line, re)!=-1
let line = substitute(line, re, '', 'g')
return line
else
" TODO: the cmd is a line number
return ''
endif
endfunc
" Extract type from tokens.
" eg: examples of tokens format
" 'const MyClass&'
" 'const map < int, int >&'
" 'MyNs::MyClass'
" '::MyClass**'
" 'MyClass a, *b = NULL, c[1] = {};
" 'hello(MyClass a, MyClass* b'
" @return the type info string eg: ::std::map
" can be empty
function! omni#cpp#utils#ExtractTypeInfoFromTokens(tokens)
let szResult = ''
let state = 0
let tokens = omni#cpp#utils#BuildParenthesisGroups(a:tokens)
" If there is an unbalanced parenthesis we are in a parameter list
let bParameterList = 0
for token in tokens
if token.value == '(' && token.group==-1
let bParameterList = 1
break
endif
endfor
if bParameterList
let tokens = reverse(tokens)
let state = 0
let parenGroup = -1
for token in tokens
if state==0
if token.value=='>'
let parenGroup = token.group
let state=1
elseif token.kind == 'cppWord'
let szResult = token.value.szResult
let state=2
elseif index(['*', '&'], token.value)<0
break
endif
elseif state==1
if token.value=='<' && token.group==parenGroup
let state=0
endif
elseif state==2
if token.value=='::'
let szResult = token.value.szResult
let state=3
else
break
endif
elseif state==3
if token.kind == 'cppWord'
let szResult = token.value.szResult
let state=2
else
break
endif
endif
endfor
return szResult
endif
for token in tokens
if state==0
if token.value == '::'
let szResult .= token.value
let state = 1
elseif token.kind == 'cppWord'
let szResult .= token.value
let state = 2
" Maybe end of token
endif
elseif state==1
if token.kind == 'cppWord'
let szResult .= token.value
let state = 2
" Maybe end of token
else
break
endif
elseif state==2
if token.value == '::'
let szResult .= token.value
let state = 1
else
break
endif
endif
endfor
return szResult
endfunc
" Get the preview window string
function! omni#cpp#utils#GetPreviewWindowStringFromTagItem(tagItem)
let szResult = ''
let szResult .= 'name: '.a:tagItem.name."\n"
for tagKey in keys(a:tagItem)
if index(['name', 'static'], tagKey)>=0
continue
endif
let szResult .= tagKey.': '.a:tagItem[tagKey]."\n"
endfor
return substitute(szResult, "\n$", '', 'g')
endfunc

980
.vim/doc/NERD_tree.txt Normal file
View File

@ -0,0 +1,980 @@
*NERD_tree.txt* A tree explorer plugin that owns your momma!
________ ________ _ ____________ ____ __________ ____________~
/_ __/ / / / ____/ / | / / ____/ __ \/ __ \ /_ __/ __ \/ ____/ ____/~
/ / / /_/ / __/ / |/ / __/ / /_/ / / / / / / / /_/ / __/ / __/ ~
/ / / __ / /___ / /| / /___/ _, _/ /_/ / / / / _, _/ /___/ /___ ~
/_/ /_/ /_/_____/ /_/ |_/_____/_/ |_/_____/ /_/ /_/ |_/_____/_____/ ~
Reference Manual~
==============================================================================
CONTENTS *NERDTree-contents*
1.Intro...................................|NERDTree|
2.Functionality provided..................|NERDTreeFunctionality|
2.1 Commands..........................|NERDTreeCommands|
2.2 NERD tree mappings................|NERDTreeMappings|
2.3 The filesystem menu...............|NERDTreeFilesysMenu|
3.Options.................................|NERDTreeOptions|
3.1 Option summary....................|NERDTreeOptionSummary|
3.2 Option details....................|NERDTreeOptionDetails|
4.Public functions........................|NERDTreePublicFunctions|
5.TODO list...............................|NERDTreeTodo|
6.The Author..............................|NERDTreeAuthor|
7.Changelog...............................|NERDTreeChangelog|
8.Credits.................................|NERDTreeCredits|
==============================================================================
1. Intro *NERDTree*
What is this "NERD tree"??
The NERD tree allows you to explore your filesystem and to open files and
directories. It presents the filesystem to you in the form of a tree which you
manipulate with the keyboard and/or mouse. It also allows you to perform
simple filesystem operations so you can alter the tree dynamically.
The following features and functionality are provided by the NERD tree:
* Files and directories are displayed in a hierarchical tree structure
* Different highlighting is provided for the following types of nodes:
* files
* directories
* sym-links
* windows .lnk files
* read-only files
* Many (customisable) mappings are provided to manipulate the tree:
* Mappings to open/close/explore directory nodes
* Mappings to open files in new/existing windows/tabs
* Mappings to change the current root of the tree
* Mappings to navigate around the tree
* ...
* Most NERD tree navigation can also be done with the mouse
* Dynamic customisation of tree content
* custom file filters to prevent e.g. vim backup files being displayed
* optional displaying of hidden files (. files)
* files can be "turned off" so that only directories are displayed
* A textual filesystem menu is provided which allows you to
create/delete/rename file and directory nodes
* The position and size of the NERD tree window can be customised
* The order in which the nodes in the tree are listed can be customised.
* A model of your filesystem is created/maintained as you explore it. This
has several advantages:
* All filesystem information is cached and is only re-read on demand
* If you revisit a part of the tree that you left earlier in your
session, the directory nodes will be opened/closed as you left them
* The script remembers the cursor position and window position in the NERD
tree so you can toggle it off (or just close the tree window) and then
reopen it (with NERDTreeToggle) the NERD tree window will appear EXACTLY
as you left it
* You can have a separate NERD tree for each tab
==============================================================================
2. Functionality provided *NERDTreeFunctionality*
------------------------------------------------------------------------------
2.1. Commands *NERDTreeCommands*
:NERDTree [start-directory] *:NERDTree*
Opens a fresh NERD tree in [start-directory] or the current
directory if [start-directory] isn't specified.
For example: >
:NERDTree /home/marty/vim7/src
< will open a NERD tree in /home/marty/vim7/src.
:NERDTreeToggle [start-directory] *:NERDTreeToggle*
If a NERD tree already exists for this tab, it is reopened and
rendered again. If no NERD tree exists for this tab then this
command acts the same as the |:NERDTree| command.
------------------------------------------------------------------------------
2.2. NERD tree Mappings *NERDTreeMappings*
Default Description~ help-tag~
Key~
o.......Open selected file, or expand selected dir...............|NERDTree-o|
go......Open selected file, but leave cursor in the NERDTree.....|NERDTree-go|
t.......Open selected node in a new tab..........................|NERDTree-t|
T.......Same as 't' but keep the focus on the current tab........|NERDTree-T|
<tab>...Open selected file in a split window.....................|NERDTree-tab|
g<tab>..Same as <tab>, but leave the cursor on the NERDTree......|NERDTree-gtab|
!.......Execute the current file.................................|NERDTree-!|
O.......Recursively open the selected directory..................|NERDTree-O|
x.......Close the current nodes parent...........................|NERDTree-x|
X.......Recursively close all children of the current node.......|NERDTree-X|
e.......Open a netrw for the current dir.........................|NERDTree-e|
double-click.......same as the |NERDTree-o| map.
middle-click.......same as |NERDTree-tab| for files, same as
|NERDTree-e| for dirs.
P.......Jump to the root node....................................|NERDTree-P|
p.......Jump to current nodes parent.............................|NERDTree-p|
K.......Jump up inside directories at the current tree depth.....|NERDTree-K|
J.......Jump down inside directories at the current tree depth...|NERDTree-J|
<C-j>...Jump down to the next sibling of the current directory...|NERDTree-c-j|
<C-k>...Jump up to the previous sibling of the current directory.|NERDTree-c-k|
C.......Change the tree root to the selected dir.................|NERDTree-C|
u.......Move the tree root up one directory......................|NERDTree-u|
U.......Same as 'u' except the old root node is left open........|NERDTree-U|
r.......Recursively refresh the current directory................|NERDTree-r|
R.......Recursively refresh the current root.....................|NERDTree-R|
m.......Display the filesystem menu..............................|NERDTree-m|
cd......Change the CWD to the dir of the selected node...........|NERDTree-cd|
H.......Toggle whether hidden files displayed....................|NERDTree-H|
f.......Toggle whether the file filters are used.................|NERDTree-f|
F.......Toggle whether files are displayed.......................|NERDTree-F|
q.......Close the NERDTree window................................|NERDTree-q|
?.......Toggle the display of the quick help.....................|NERDTree-?|
------------------------------------------------------------------------------
*NERDTree-o*
Default key: o
Map option: NERDTreeMapActivateNode
Applies to: files and directories.
If a file node is selected, it is opened in the previous window. If a
directory is selected it is opened or closed depending on its current state.
------------------------------------------------------------------------------
*NERDTree-go*
Default key: go
Map option: None
Applies to: files.
If a file node is selected, it is opened in the previous window, but the
cursor does not move.
The key combo for this mapping is always "g" + NERDTreeMapActivateNode (see
|NERDTree-o|).
------------------------------------------------------------------------------
*NERDTree-t*
Default key: t
Map option: NERDTreeMapOpenInTab
Applies to: files and directories.
Opens the selected file in a new tab. If a directory is selected, a netrw is
opened in a new tab.
------------------------------------------------------------------------------
*NERDTree-T*
Default key: T
Map option: NERDTreeMapOpenInTabSilent
Applies to: files and directories.
The same as |NERDTree-t| except that the focus is kept in the current tab.
------------------------------------------------------------------------------
*NERDTree-tab*
Default key: <tab>
Map option: NERDTreeMapOpenSplit
Applies to: files.
Opens the selected file in a new split window and puts the cursor in the new
window.
------------------------------------------------------------------------------
*NERDTree-gtab*
Default key: g<tab>
Map option: None
Applies to: files.
The same as |NERDTree-tab| except that the cursor is not moved.
The key combo for this mapping is always "g" + NERDTreeMapOpenSplit (see
|NERDTree-tab|).
------------------------------------------------------------------------------
*NERDTree-!*
Default key: !
Map option: NERDTreeMapExecute
Applies to: files.
Executes the selected file, prompting for arguments first.
------------------------------------------------------------------------------
*NERDTree-O*
Default key: O
Map option: NERDTreeMapOpenRecursively
Applies to: directories.
Recursively opens the selelected directory.
All files and directories are cached, but if a directory would not be
displayed due to file filters (see |NERDTreeIgnore| |NERDTree-f|) or the
hidden file filter (see |NERDTreeShowHidden|) then it is not opened. This is
handy, especially if you have .svn directories.
------------------------------------------------------------------------------
*NERDTree-x*
Default key: x
Map option: NERDTreeMapCloseDir
Applies to: files and directories.
Closes the parent of the selected node.
------------------------------------------------------------------------------
*NERDTree-X*
Default key: X
Map option: NERDTreeMapCloseChildren
Applies to: directories.
Recursively closes all children of the selected directory.
Tip: To quickly "reset" the tree, use |NERDTree-P| with this mapping.
------------------------------------------------------------------------------
*NERDTree-e*
Default key: e
Map option: NERDTreeMapOpenExpl
Applies to: files and directories.
Opens a netrw on the selected directory, or the selected file's directory.
------------------------------------------------------------------------------
*NERDTree-P*
Default key: P
Map option: NERDTreeMapJumpRoot
Applies to: no restrictions.
Jump to the tree root.
------------------------------------------------------------------------------
*NERDTree-p*
Default key: p
Map option: NERDTreeMapJumpParent
Applies to: files and directories.
Jump to the parent node of the selected node.
------------------------------------------------------------------------------
*NERDTree-K*
Default key: K
Map option: NERDTreeMapJumpFirstChild
Applies to: files and directories.
Jump to the first child of the current nodes parent.
If the cursor is already on the first node then do the following:
* loop back thru the siblings of the current nodes parent until we find an
open dir with children
* go to the first child of that node
------------------------------------------------------------------------------
*NERDTree-J*
Default key: J
Map option: NERDTreeMapJumpLastChild
Applies to: files and directories.
Jump to the last child of the current nodes parent.
If the cursor is already on the last node then do the following:
* loop forward thru the siblings of the current nodes parent until we find
an open dir with children
* go to the last child of that node
------------------------------------------------------------------------------
*NERDTree-c-j*
Default key: <C-j>
Map option: NERDTreeMapJumpNextSibling
Applies to: files and directories.
If a dir node is selected, jump to the next sibling of that node.
If a file node is selected, jump to the next sibling of that nodes parent.
------------------------------------------------------------------------------
*NERDTree-c-k*
Default key: <C-k>
Map option: NERDTreeMapJumpPrevSibling
Applies to: files and directories.
If a dir node is selected, jump to the previous sibling of that node.
If a file node is selected, jump to the previous sibling of that nodes parent.
------------------------------------------------------------------------------
*NERDTree-C*
Default key: C
Map option: NERDTreeMapChdir
Applies to: directories.
Made the selected directory node the new tree root.
------------------------------------------------------------------------------
*NERDTree-u*
Default key: u
Map option: NERDTreeMapUpdir
Applies to: no restrictions.
Move the tree root up a dir (like doing a "cd ..").
------------------------------------------------------------------------------
*NERDTree-U*
Default key: U
Map option: NERDTreeMapUpdirKeepOpen
Applies to: no restrictions.
Like |NERDTree-u| except that the old tree root is kept open.
------------------------------------------------------------------------------
*NERDTree-r*
Default key: r
Map option: NERDTreeMapRefresh
Applies to: files and directories.
If a dir is selected, recursively refresh that dir, i.e. scan the filesystem
for changes and represent them in the tree.
If a file node is selected then the above is done on it's parent.
------------------------------------------------------------------------------
*NERDTree-R*
Default key: R
Map option: NERDTreeMapRefreshRoot
Applies to: no restrictions.
Recursively refresh the tree root.
------------------------------------------------------------------------------
*NERDTree-m*
Default key: m
Map option: NERDTreeMapFilesystemMenu
Applies to: files and directories.
Display the filesystem menu. See |NERDTreeFilesysMenu| for details.
------------------------------------------------------------------------------
*NERDTree-H*
Default key: H
Map option: NERDTreeMapToggleHidden
Applies to: no restrictions.
Toggles whether hidden files are displayed. Hidden files are any
file/directory that starts with a "."
------------------------------------------------------------------------------
*NERDTree-f*
Default key: f
Map option: NERDTreeMapToggleFilters
Applies to: no restrictions.
Toggles whether file filters are used. See |NERDTreeIgnore| for details.
------------------------------------------------------------------------------
*NERDTree-F*
Default key: F
Map option: NERDTreeMapToggleFiles
Applies to: no restrictions.
Toggles whether file nodes are displayed.
------------------------------------------------------------------------------
*NERDTree-q*
Default key: q
Map option: NERDTreeMapQuit
Applies to: no restrictions.
Closes the NERDtree window.
------------------------------------------------------------------------------
*NERDTree-?*
Default key: ?
Map option: NERDTreeMapHelp
Applies to: no restrictions.
Toggles whether the quickhelp is displayed.
------------------------------------------------------------------------------
2.3. The filesystem menu *NERDTreeFilesysMenu*
The purpose of the filesystem menu is to allow you to perform basic filesystem
operations quickly from the NERD tree rather than the console.
The filesystem menu can be accessed with 'm' mapping and has four supported
operations: >
1. Adding nodes.
2. Move nodes.
3. Deleting nodes.
3. Copying nodes.
<
1. Adding nodes:
To add a node move the cursor onto (or anywhere inside) the directory you wish
to create the new node inside. Select the 'add node' option from the
filesystem menu and type a filename. If the filename you type ends with a '/'
character then a directory will be created. Once the operation is completed,
the cursor is placed on the new node.
2. Move nodes:
To move/rename a node, put the cursor on it and select the 'move' option from
the filesystem menu. Enter the new location for the node and it will be
moved. If the old file is open in a buffer, you will be asked if you wish to
delete that buffer. Once the operation is complete the cursor will be placed
on the renamed node.
3. Deleting nodes:
To delete a node put the cursor on it and select the 'delete' option from the
filesystem menu. After confirmation the node will be deleted. If a file is
deleted but still exists as a buffer you will be given the option to delete
that buffer.
4. Copying nodes:
To copy a node put the cursor on it and select the 'copy' option from the
filesystem menu. Enter the new location and you're done. Note: copying is
currently only supported for *nix operating systems. If someone knows a
one line copying command for windows that doesnt require user confirmation
then id be grateful if you'd email me.
==============================================================================
3. Customisation *NERDTreeOptions*
------------------------------------------------------------------------------
3.1. Customisation summary *NERDTreeOptionSummary*
The script provides the following options that can customise the behaviour the
NERD tree. These options should be set in your vimrc.
|loaded_nerd_tree| Turns off the script.
|NERDChristmasTree| Tells the NERD tree to make itself colourful
and pretty.
|NERDTreeAutoCenter| Controls whether the NERD tree window centers
when the cursor moves within a specified
distance to the top/bottom of the window.
|NERDTreeAutoCenterThreshold| Controls the sensitivity of autocentering.
|NERDTreeCaseSensitiveSort| Tells the NERD tree whether to be case
sensitive or not when sorting nodes.
|NERDTreeChDirMode| Tells the NERD tree if/when it should change
vim's current working directory.
|NERDTreeHighlightCursorline| Tell the NERD tree whether to highlight the
current cursor line.
|NERDTreeIgnore| Tells the NERD tree which files to ignore.
|NERDTreeMouseMode| Tells the NERD tree how to handle mouse
clicks.
|NERDTreeShowFiles| Tells the NERD tree whether to display files
in the tree on startup.
|NERDTreeShowHidden| Tells the NERD tree whether to display hidden
files on startup.
|NERDTreeSortOrder| Tell the NERD tree how to sort the nodes in
the tree.
|NERDTreeSplitVertical| Tells the script whether the NERD tree should
be created by splitting the window vertically
or horizontally.
|NERDTreeWinPos| Tells the script where to put the NERD tree
window.
|NERDTreeWinSize| Sets the window size when the NERD tree is
opened.
------------------------------------------------------------------------------
3.2. Customisation details *NERDTreeOptionDetails*
To enable any of the below options you should put the given line in your
~/.vimrc
*loaded_nerd_tree*
If this plugin is making you feel homicidal, it may be a good idea to turn it
off with this line in your vimrc: >
let loaded_nerd_tree=1
<
------------------------------------------------------------------------------
*NERDChristmasTree*
Values: 0 or 1.
Default: 1.
If this option is set to 1 then some extra syntax highlighting elements are
added to the nerd tree to make it more colourful.
Set it to 0 for a more vanilla looking tree.
------------------------------------------------------------------------------
*NERDTreeAutoCenter*
Values: 0 or 1.
Default: 1
If set to 1, the NERD tree window will center around the cursor if it moves to
within |NERDTreeAutoCenterThreshold| lines of the top/bottom of the window.
This is ONLY done in response to tree navigation mappings,
i.e. |NERDTree-J| |NERDTree-K| |NERDTree-C-J| |NERDTree-c-K| |NERDTree-p|
|NERDTree-P|
The centering is done with a |zz| operation.
------------------------------------------------------------------------------
*NERDTreeAutoCenterThreshold*
Values: Any natural number.
Default: 3
This option controls the "sensitivity" of the NERD tree auto centering. See
|NERDTreeAutoCenter| for details.
------------------------------------------------------------------------------
*NERDTreeCaseSensitiveSort*
Values: 0 or 1.
Default: 0.
By default the NERD tree does not sort nodes case sensitively, i.e. nodes
could appear like this: >
bar.c
Baz.c
blarg.c
boner.c
Foo.c
<
But, if you set this option to 1 then the case of the nodes will be taken into
account. The above nodes would then be sorted like this: >
Baz.c
Foo.c
bar.c
blarg.c
boner.c
<
------------------------------------------------------------------------------
*NERDTreeChDirMode*
Values: 0, 1 or 2.
Default: 1.
Use this option to tell the script when (if at all) to change the current
working directory (CWD) for vim.
If it is set to 0 then the CWD is never changed by the NERD tree.
If set to 1 then the CWD is changed when the NERD tree is first loaded to the
directory it is initialized in. For example, if you start the NERD tree with >
:NERDTree /home/marty/foobar
<
then the CWD will be changed to /home/marty/foobar and will not be changed
again unless you init another NERD tree with a similar command.
If the option is set to 2 then it behaves the same as if set to 1 except that
the CWD is changed whenever the tree root is changed. For example, if the CWD
is /home/marty/foobar and you make the node for /home/marty/foobar/baz the new
root then the CWD will become /home/marty/foobar/baz.
Note to windows users: it is highly recommended that you have this option set
to either 1 or 2 or else the script wont function properly if you attempt to
open a NERD tree on a different drive to the one vim is currently in.
Authors note: at work i have this option set to 1 because i have a giant ctags
file in the root dir of my project. This way i can initialise the NERD tree
with the root dir of my project and always have ctags available to me --- no
matter where i go with the NERD tree.
------------------------------------------------------------------------------
*NERDTreeHighlightCursorline*
Values: 0 or 1.
Default: 1.
If set to 1, the current cursor line in the NERD tree buffer will be
highlighted. This is done using the |cursorline| option.
------------------------------------------------------------------------------
*NERDTreeIgnore*
Values: a list of regular expressions.
Default: ['\~$'].
This option is used to specify which files the NERD tree should ignore. It
must be a list of regular expressions. When the NERD tree is rendered, any
files/dirs that match any of the regex's in NERDTreeIgnore wont be displayed.
For example if you put the following line in your vimrc: >
let NERDTreeIgnore=['\.vim$', '\~$']
<
then all files ending in .vim or ~ will be ignored.
Note: to tell the NERD tree not to ignore any files you must use the following
line: >
let NERDTreeIgnore=[]
<
The file filters can be turned on and off dynamically with the |NERDTree-f|
mapping.
------------------------------------------------------------------------------
*NERDTreeMouseMode*
Values: 1, 2 or 3.
Default: 1.
If set to 1 then a double click on a node is required to open it.
If set to 2 then a single click will open directory nodes, while a double
click will still be required for file nodes.
If set to 3 then a single click will open any node.
Note: a double click anywhere on a line that a tree node is on will
activate it, but all single-click activations must be done on name of the node
itself. For example, if you have the following node: >
| | |-application.rb
<
then (to single click activate it) you must click somewhere in
'application.rb'.
------------------------------------------------------------------------------
*NERDTreeShowFiles*
Values: 0 or 1.
Default: 1.
If this option is set to 1 then files are displayed in the NERD tree. If it is
set to 0 then only directories are displayed.
This option can be toggled dynamically with the |NERDTree-F| mapping and is
useful for drastically shrinking the tree when you are navigating to a
different part of the tree.
------------------------------------------------------------------------------
*NERDTreeShowHidden*
Values: 0 or 1.
Default: 0.
This option tells vim whether to display hidden files by default. This option
can be dynamically toggled with the |NERDTree-H| mapping.
Use one of the follow lines to set this option: >
let NERDTreeShowHidden=0
let NERDTreeShowHidden=1
<
------------------------------------------------------------------------------
*NERDTreeSortOrder*
Values: a list of regular expressions.
Default: ['\/$', '*', '\.swp$', '\.bak$', '\~$']
This option is set to a list of regular expressions which are used to
specify the order of nodes under their parent.
For example, if the option is set to: >
['\.vim$', '\.c$', '\.h$', '*', 'foobar']
<
then all .vim files will be placed at the top, followed by all .c files then
all .h files. All files containing the string 'foobar' will be placed at the
end. The star is a special flag: it tells the script that every node that
doesnt match any of the other regexps should be placed here.
If no star is present in NERDTreeSortOrder then one is automatically appended
to the array.
The regex '\/$' should be used to match directory nodes.
After this sorting is done, the files in each group are sorted alphabetically.
Other examples: >
(1) ['*', '\/$']
(2) []
(3) ['\/$', '\.rb$', '\.php$', '*', '\.swp$', '\.bak$', '\~$']
<
1. Directories will appear last, everything else will appear above.
2. Every will simply appear in alphabetical order.
3. Dirs will appear first, then ruby and php. Swap files, bak files and vim
backup files will appear last with everything else preceding them.
------------------------------------------------------------------------------
*NERDTreeSplitVertical*
Values: 0 or 1.
Default: 1.
This option, along with |NERDTreeWinPos|, is used to determine where the NERD
tree window appears.
If it is set to 1 then the NERD tree window will appear on either the left or
right side of the screen (depending on the |NERDTreeWinPos| option).
If it set to 0 then the NERD tree window will appear at the top of the screen.
------------------------------------------------------------------------------
*NERDTreeWinPos*
Values: 0 or 1.
Default: 1.
This option works in conjunction with the |NERDTreeSplitVertical| option to
determine where NERD tree window is placed on the screen.
If the option is set to 1 then the NERD tree will appear on the left or top of
the screen (depending on the value of |NERDTreeSplitVertical|). If set to 0,
the window will appear on the right or bottom of the screen.
This option is makes it possible to use two different explorer type
plugins simultaneously. For example, you could have the taglist plugin on the
left of the window and the NERD tree on the right.
------------------------------------------------------------------------------
*NERDTreeWinSize*
Values: a positive integer.
Default: 31.
This option is used to change the size of the NERD tree when it is loaded.
==============================================================================
*NERDTreePublicFunctions*
5. Public functions ~
The script provides 2 public functions for your hacking pleasure. Their
signatures are: >
function! NERDTreeGetCurrentNode()
function! NERDTreeGetCurrentPath()
<
The first returns the node object that the cursor is currently on, while the
second returns the corresponding path object.
This is probably a good time to mention that the script implements prototype
style OO. To see the functions that each class provides you can read look at
the code.
Use the node objects to manipulate the structure of the tree. Use the path
objects to access the data the tree represents and to make changes to the
filesystem.
==============================================================================
5. TODO list *NERDTreeTodo*
Window manager integration?
==============================================================================
6. The Author *NERDTreeAuthor*
The author of the NERD tree is a terrible terrible monster called Martyzilla
who gobbles up small children with milk and sugar for breakfast. He has an odd
love/hate relationship with computers (but monsters hate everything by nature
you know...) which can be awkward for him since he is a pro computer nerd for
a living.
He can be reached at martin_grenfell at msn.com. He would love to hear from
you, so feel free to send him suggestions and/or comments about this plugin.
Don't be shy --- the worst he can do is slaughter you and stuff you in the
fridge for later ;)
==============================================================================
7. Changelog *NERDTreeChangelog*
2.7.1
- Changed the keys for the filesystem menu to be mnemonic rather than
arbitrary integers
- Documented the copying functionality in the filesystem menu
2.7.0
- Bug fix: Now when you have the tree on the right and you open it with
multiple windows stacked, it will take up the full height of the vim
window.
- Now line numbers always turned off in the tree by default
- Implemented copying of nodes (via the filesystem menu) for *nix/macosx
- took the help doc out of the script and repackaged the whole thing as a
zip
2.6.2
- Now when you try to open a file node into a window that is modified, the
window is not split if the &hidden option is set. Thanks to Niels Aan
de Brugh for this suggestion.
2.6.1
- Fixed a major bug with the <tab> mapping. Thanks to Zhang Weiwu for
emailing me.
2.6.0
- Extended the behaviour of <c-j/k>. Now if the cursor is on a file node
and you use <c-j/k> the cursor will jump to its PARENTS next/previous
sibling. Go :help NERDTree-c-j and :help NERDTree-c-k for info.
- Extended the behaviour of the J/K mappings. Now if the cursor is on the
last child of a node and you push J/K it will jump down to the last child
of the next/prev of its parents siblings that is open and has children.
Go :help NERDTree-J and :help NERDTree-K for info.
- The goal of these changes is to make tree navigation faster.
- Reorganised the help page a bit.
- Removed the E mapping.
- bugfixes
2.5.0
- Added an option to enforce case sensitivity when sorting tree nodes.
Read :help NERDTreeCaseSensitiveSort for details. (thanks to Michael
Madsen for emailing me about this). Case sensitivity defaults to off.
- Made the script echo a "please wait" style message when opening large
directories. Thanks to AOYAMA Shotaro for this suggestion.
- Added 2 public functions that can be used to retrieve the treenode and
path that the cursor is on. Read :help NERDTreePublicFunctions for
details (thanks again to AOYAMA Shotaro for the idea :).
- added 2 new mappings for file nodes: "g<tab>" and "go". These are the
same as the "<tab>" and "o" maps except that the cursor stays in the
NERDTree. Note: these maps are slaved to the o and <tab> mappings, so if
eg you remap "<tab>" to "i" then the "g<tab>" map will also be changed
to "gi".
- Renamed many of the help tags to be simpler.
- Simplified the ascii "graphics" for the filesystem menu
- Fixed bugs.
- Probably created bugs.
- Refactoring.
2.4.0
- Added the P mapping to jump to the tree root.
- Added window centering functionality that can be triggered when doing
using any of the tree nav mappings. Essentially, if the cursor comes
within a certain distance of the top/bottom of the window then a zz is
done in the window. Two related options were added: NERDTreeAutoCenter
to turn this functionality on/off, and NERDTreeAutoCenterThreshold to
control how close the cursor has to be to the window edge to trigger the
centering.
2.3.0
- Tree navigation changes:
- Added J and K mappings to jump to last/first child of the current dir.
Options to customise these mappings have also been added.
- Remapped the jump to next/prev sibling commands to be <C-j> and <C-k> by
default.
These changes should hopefully make tree navigation mappings easier to
remember and use as the j and k keys are simply reused 3 times (twice
with modifier keys).
- Made it so that, when any of the tree filters are toggled, the cursor
stays with the selected node (or goes to its parent/grandparent/... if
that node is no longer visible)
- Fixed an error in the doc for the mouse mode option.
- Made the quickhelp correctly display the current single/double click
mappings for opening nodes as specified by the NERDTreeMouseMode option.
- Fixed a bug where the script was spazzing after prompting you to delete
a modified buffer when using the filesystem menu.
- Refactoring
2.2.3
- Refactored the :echo output from the script.
- Fixed some minor typos in the doc.
- Made some minor changes to the output of the 'Tree filtering mappings'
part of the quickhelp
2.2.2
- More bugfixes... doh.
2.2.1
- Bug fix that was causing an exception when closing the nerd tree. Thanks
to Tim carey-smith and Yu Jun for pointing this out.
2.2.0
- Now 'cursorline' is set in the NERD tree buffer by default. See :help
NERDTreeHighlightCursorline for how to disable it.
2.1.2
- Stopped the script from clobbering the 1,2,3 .. 9 registers.
- Made it "silent!"ly delete buffers when renaming/deleting file nodes.
- Minor correction to the doc
- Fixed a bug when refreshing that was occurring when the node you
refreshed had been deleted externally.
- Fixed a bug that was occurring when you open a file that is already open
and modified.
2.1.1
- Added a bit more info about the buffers you are prompted to delete when
renaming/deleting nodes from the filesystem menu that are already loaded
into buffers.
- Refactoring and bugfixes
2.1.0
- Finally removed the blank line that always appears at the top of the
NERDTree buffer
- Added NERDTreeMouseMode option. If set to 1, then a double click is
required to activate all nodes, if set to 2 then a single click will
activate directory nodes, if set to 3 then a single click will activate
all nodes.
- Now if you delete a file node and have it open in a buffer you are given
the option to delete that buffer as well. Similarly if you rename a file
you are given the option to delete any buffers containing the old file
(if any exist)
- When you rename or create a node, the cursor is now put on the new node,
this makes it easy immediately edit the new file.
- Fixed a bug with the ! mapping that was occurring on windows with paths
containing spaces.
- Made all the mappings customisable. See |NERD_tree-mappings| for
details. A side effect is that a lot of the "double mappings" have
disappeared. E.g 'o' is now the key that is used to activate a node,
<CR> is no longer mapped to the same.
- Made the script echo warnings in some places rather than standard echos
- Insane amounts of refactoring all over the place.
2.0.0
- Added two new NERDChristmasTree decorations. First person to spot them
and email me gets a free copy of the NERDTree.
- Made it so that when you jump around the tree (with the p, s and S
mappings) it is counted as a jump by vim. This means if you, eg, push
'p' one too many times then you can go `` or ctrl-o.
- Added a new option called NERDTreeSortOrder which takes an array of
regexs and is used to determine the order that the treenodes are listed
in. Go :help NERDTreeSortOrder for details.
- Removed the NERDTreeSortDirs option because it is consumed by
NERDTreeSortOrder
- Added the 'i' mapping which is the same as <tab> but requires less
effort to reach.
- Added the ! mapping which is used to execute file in the tree (after it
prompts you for arguments etc)
==============================================================================
8. Credits *NERDTreeCredits*
Thanks to Tim Carey-Smith for testing/using the NERD tree from the first
pre-beta version, for his many suggestions and for his constant stream of bug
complaints.
Thanks to Vigil for trying it out before the first release :) and suggesting
that mappings to open files in new tabs should be implemented.
Thanks to Nick Brettell for testing, fixing my spelling and suggesting i put a
.. (up a directory)
line in the gui.
Thanks to Thomas Scott Urban - the author of the vtreeexplorer plugin - whose
gui code i borrowed from.
Thanks to Terrance Cohen for pointing out a bug where the script was changing
vims CWD all over the show.
Thanks to Yegappan Lakshmanan (author of Taglist and other orgasmically
wonderful plugins) for telling me how to fix a bug that was causing vim to go
into visual mode everytime you double clicked a node :)
Thanks to Jason Mills for sending me a fix that allows windows paths to use
forward slashes as well as backward.
Thanks to Michael Geddes (frogonwheels on #vim at freenode) for giving me some
tips about syntax highlighting when i was doing highlighting for the
quickhelp.
Thanks to Yu Jun for emailing me about a bug that was occurring when closing
the tree.
Thanks to Michael Madsen for emailing me about making case sensitivity
optional when sorting nodes.
Thanks to AOYAMA Shotaro for suggesting that i echo a "please wait" message
when opening large directories.
Thanks to Michael Madsen for requesting the NERDTreeCaseSensitiveSort option.
Thanks to AOYAMA Shotaro for suggesting that a "please wait" style message be
echoed when opening large directories. Also, thanks for the suggestion of
having public functions in the script to access the internal data :D
Thanks to Zhang Weiwu for emailing me about a bug with the the <tab> mapping
in 2.6.0
Thanks to Niels Aan de Brugh for the suggestion that the script now split the
window if you try to open a file in a window containing a modified buffer when
the &hidden option is set.

1078
.vim/doc/omnicppcomplete.txt Normal file

File diff suppressed because it is too large Load Diff

710
.vim/doc/project.txt Normal file
View File

@ -0,0 +1,710 @@
*project.txt* Plugin for managing multiple projects with multiple sources
For Vim version 6.x and Vim version 7.x.
Last Change: Fri 13 Oct 2006 10:20:13 AM EDT
By Aric Blumer
aricvim email-at-sign charter.net
*project* *project-plugin*
Contents:
Commands...................|project-invoking|
Inheritance.............|project-inheritance|
Mappings...................|project-mappings|
Adding Mappings.....|project-adding-mappings|
Settings...................|project-settings|
Example File................|project-example|
Tips...........................|project-tips|
You can use this plugin's basic functionality to set up a list of
frequently-accessed files for easy navigation. The list of files will be
displayed in a window on the left side of the Vim window, and you can press
<Return> or double-click on filenames in the list to open the files. I find
this easier to use than having to navigate a directory hierarchy with the
|file-explorer|.
You can also instruct the Plugin to change to a directory and to run Vim
scripts when you select a file. These scripts can, for example, modify the
environment to include compilers in $PATH. This makes it very easy to use
quickfix with multiple projects that use different environments.
Other features include:
o Loading/Unloading all the files in a Project (\l, \L, \w, and \W)
o Grepping all the files in a Project (\g and \G)
o Running a user-specified script on a file (can be used to launch an
external program on the file) (\1 through \9)
o Running a user-specified script on all the files in a Project
(\f1-\f9 and \F1-\F9)
o High degree of user-configurability
o Also works with |netrw| using the XXXX://... notation where XXXX is
ftp, rcp, scp, or http.
All of this is specified within a simple text file and a few global variables
in your vimrc file.
You must set 'nocompatible' in your |vimrc| file to use this plugin. You can
stop the plugin from being loaded by setting the "loaded_project" variable: >
:let loaded_project = 1
==============================================================================
COMMANDS *project-invoking*
You can use the plugin by placing it in your plugin directory (e.g.,
~/.vim/plugin). See |add-global-plugin|. When you start vim the next time, you
then enter the command >
:Project
or >
:Project {file}
If you do not specify the filename, $HOME/.vimprojects is used.
To have Vim come up with the Project Window enabled automatically (say, from a
GUI launcher), run Vim like this: [g]vim +Project
Note that you can invoke :Project on only one file at a time. If you wish to
change the Project File, do a :bwipe in the Project Buffer, then re-invoke the
Plugin as described above.
Several Projects can be kept and displayed in the same file, each in a fold
delimited by { and } (see |fold.txt|). There can be any number of nested
folds to provide you with a Project hierarchy. Any line without a { or a } in
the file is considered to be a filename. Blank lines are ignored, and any
text after a # is ignored.
Because the plugin uses standard Vim folds, you can use any of the
|fold-commands|. You can double-click on the first line of a fold to open and
close it. You can select a file to open by putting the cursor on its name and
pressing <Return> or by double-clicking on it. The plugin will create a new
window to the right or use the |CTRL-W_p| equivalent if it exists.
*project-syntax*
Each Project Entry has this form:
project_entry ::=
<Description>={projpath} [{options}] {
[ filename ]
[ project_entry ]
}
{options} is one or more of the following (on the same line):
CD={path}
in={filename}
out={filename}
filter="{pat}"
flags={flag}
Note that a project_entry can reside within a project_entry. This allows you
to set up a hierarchy within your Project.
The <Description> will be displayed in the foldtext and cannot contain "=".
There can be no space character directly on either side of the =.
The {projpath} is the path in which the files listed in the Project's fold
will be found, and it may contain environment variables. If the path is a
relative path, then the plugin constructs the whole path from the Project's
parent, grandparent, etc., all the way up the hierarchy. An outermost
project_entry must have an absolute path. See the |project-inheritance|
example below. {projpath} may contain spaces, but they must be escaped like
normal Vim escapes. Here are two examples of the same directory:
>
Example=/my/directory/with\ spaces {
}
Example="/my/directory/with spaces" {
}
I recommend this for Windows®: >
Example="c:\My Documents" {
}
But Vim is smart enough to do this, too: >
Example=c:\My\ Documents {
}
CD= provides the directory that Vim will change to when you select a file in
that fold (using |:cd|). This allows you, for example, to enter |:make| to use
the local Makefile. A CD=. means that Vim will make {projpath} or its
inherited equivalent the current working directory. When CD is omitted, the
directory is not changed. There can be no space on either side of the =. The
value of CD can also be a relative path from a parent's CD. See the
|project-inheritance| example below. This directive is ignored for |netrw|
projects. Spaces are allowed in the path as for {projpath}.
in= and out= provide the means to run arbitrary Vim scripts whenever you enter
or leave a file's buffer (see the |BufEnter| and |BufLeave| autocommand
events). The idea is to have a Vim script that sets up or tears down the
environment for the Project like this:
in.vim: >
let $PROJECT_HOME='~/my_project'
" Put the compiler in $PATH
if $PATH !~ '/path/to/my/compiler'
let $PATH=$PATH.':/path/to/my/compiler'
endif
out.vim: >
" Remove compiler from $PATH
if $PATH =~ '/path/to/my/compiler'
let $PATH=substitute($PATH, ':/path/to/my/compiler', '', 'g')
endif
Then you can use :make with the proper environment depending on what file you
are currently editing. If the path to the script is relative, then it is
relative from {projpath}. These directives are inherited by Subprojects
unless the Subproject specifies its own. For use with |netrw| projects, the
paths specified for in= and out= must be absolute and local.
filter= specifies a |glob()| file pattern. It is used to regenerate the list
of files in a Project fold when using the \r (<LocalLeader>r) map in the
Project Window. The filter value must be in quotes because it can contain
multiple file patterns. If filter is omitted, then the * pattern is used.
There can be no space on either side of the =. A Subproject will inherit the
filter of its parent unless it specifies its own filter.
flags= provides the means to enable/disable features for a particular fold.
The general mnemonic scheme is for lower case to turn something off and upper
case to turn something on. {flag} can contain any of the following
characters:
flag Description ~
l Turn off recursion for this fold for \L. Subfolds are also
blocked from the recursion.
r Turn off refresh. When present, do not refresh this fold when
\r or \R is used. This does not affect subfold recursion.
S Turn on sorting for refresh and create.
s Turn off sorting for refresh and create.
T Turn on top gravity. Forces folds to the top of the current
fold when refreshing. It has the same affect as the 'T' flag
in g:proj_flags, but controls the feature on a per-fold basis.
t Turn off top gravity. Forces folds to the bottom of the
current fold when refreshing.
w Turn off recursion for this fold for \W. Subfolds are also
blocked from the recursion.
Flags are not inherited by Subprojects.
Any text outside a fold is ignored.
==============================================================================
INHERITANCE *project-inheritance*
It's best to show inheritance by comparing these two Project Files:
>
Parent=~/my_project CD=. filter="Make* *.mk" flags=r {
Child1=c_code {
}
Child2=include CD=. filter="*.h" {
}
}
Child1's path is "~/my_project/c_code" because ~/my_project is inherited. It
also inherits the CD from Parent. Since Parent has CD=., the Parent's cwd is
"~/my_project". Child1 therefore inherits a CD of "~/my_project". Finally,
Child1 inherits the filter from Parent. The flags are not inherited.
Child2 only inherits the "~/my_project" from Parent.
Thus, the example above is exactly equivalent to this:
>
Parent=~/my_project CD=. filter="Make* *.mk" flags=r {
Child1=~/my_project/c_code CD=~/my_project filter="Make* *.mk" {
}
Child2=~/my_project/include CD=~/my_project/include filter="*.h" {
}
}
(For a real Project, Child1 would not want to inherit its parent's filter, but
this example shows the concept.) You can always enter \i to display what the
cursor's project inherits.
==============================================================================
MAPPINGS *project-mappings*
Map Action ~
\r Refreshes the Project fold that the cursor is in by placing in the
fold all the files that match the filter. The Project is refreshed
using an indent of one space for every foldlevel in the hierarchy.
You may place a "# pragma keep" (without the quotes) at the end of a
line, and the file entry on that line will not be removed when you
refresh. This is useful, for example, when you have . as an entry so
you can easily browse the directory.
Note that this mapping is actually <LocalLeader>r, and the default of
|<LocalLeader>| is \.
This does not work for Projects using |netrw|.
\R Executes \r recursively in the current fold and all folds below.
This does not work for Projects using |netrw|.
\c Creates a Project fold entry. It asks for the description, the path
to the files, the CD parameter, and the filename |glob()| pattern.
From this information, it will create the Project Entry below the
cursor.
This does not work for Projects using |netrw|.
\C Creates a Project fold entry like \c, but recursively includes all the
subdirectories.
<Return>
Select a file to open in the |CTRL-W_p| window or in a new window. If
the cursor is on a fold, open or close it.
<S-Return>
\s
Same as <Return> but horizontally split the target window.
<LocalLeader>s is provided for those terminals that don't recognize
<S-Return>.
\S
Load all files in a project by doing horizontal splits.
<C-Return>
\o
Same as <Return> but ensure that the opened file is the only other
window. <LocalLeader>o is provided for those terminals that don't
recognize <C-Return>.
<M-Return>
\v
Same as <Return> but only display the file--the cursor stays in the
Project Window.
<2-LeftMouse>
(Double-click) If on a closed fold, open it. If on an open fold
boundary, close it. If on a filename, open the file in the |CTRL-W_p|
window or in a new window.
<S-2-LeftMouse>
Same as <S-Return>.
<C-2-LeftMouse>
Same as <C-Return>.
<RightMouse>
Increase the width of the Project Window by g:proj_window_increment or
toggle between a width of
g:proj_window_width + g:proj_window_increment
and
g:proj_window_width.
Whether you toggle or monotonically increase the width is determined
by the 't' flag of the g:proj_flags variable (see |project-flags|).
Note that a Right Mouse click will not automatically place the cursor
in the Project Window if it is in a different window. The window will
go back to the g:proj_window_width width when you leave the window.
<space> Same as <RightMouse>
<CTRL-Up>
\<Up>
Move the text or fold under the cursor up one row. This may not work
in a terminal because the terminal is unaware of this key combination.
<LocalLeader><Up> is provided for those terminals that don't recognize
<C-Up>.
<CTRL-Down>
\<Down>
Move the text or fold under the cursor down one row. This may not work
in a terminal because the terminal is unaware of this key combination.
<LocalLeader><Down> is provided for those terminals that don't
recognize <C-Down>.
\i Show in the status line the completely resolved and inherited
parameters for the fold the cursor is in. This is intended for
debugging your relative path and inherited parameters for manually
entered Projects.
\I Show in the status line the completely resolved filename. Uses the
Project_GetFname(line('.')) function.
\1 - \9
Run the command specified in g:proj_run{x} where {x} is the number
of the key. See the documentation of g:proj_run1 below.
\f1-\f9
Run the command specified in g:proj_run_fold{x} where {x} is the
number of the key. The command is run on the files at the current
Project level. See the |project-settings| below.
\F1-\F9
Run the command specified in g:proj_run_fold{x} where {x} is the
number of the key. The command is run on the files at the current
Project level and all Subprojects. See the |project-settings| below.
\0 Display the commands that are defined for \1 through \9.
\f0 Display the commands that are defined for \f1 through \f9 and \F1
through \F0. Same as \F0.
\l Load all the files in the current Project level into Vim. While files
are being loaded, you may press any key to stop.
\L Load all the files in the current Project and all Subprojects into
Vim. Use this mapping with caution--I wouldn't suggest using \L to
load a Project with thousands of files. (BTW, my Project file has more
than 5,300 files in it!) While files are being loaded, you may press
any key to stop.
\w Wipe all the files in the current Project level from Vim. (If files
are modified, they will be saved first.) While files are being wiped,
you may press any key to stop.
\W Wipe all the files in the current Project and all Subprojects from
Vim. (If files are modified, they will be saved first.) While files
are being wiped, you may press any key to stop.
\g Grep all the files in the current Project level.
\G Grep all the files in the current Project level and all Subprojects.
\e Set up the Environment for the Project File as though you had selected
it with <Return>. This allows you to do a \e and a :make without
having to open any files in the project.
\E Explore (using |file-explorer|) the directory of the project the
cursor is in. Does not work with netrw.
<F12> When the 'g' flag is present in g:proj_flags (see |project-flags|)
this key toggles the Project Window open and closed. You may remap
this toggle function by putting the following in your vimrc and
replacing <Leader>P with whatever key combination you wish:
nmap <silent> <Leader>P <Plug>ToggleProject
Note that the Project Plugin remaps :help because the Help Window and the
Project Window get into a fight over placement. The mapping avoids the
problem.
==============================================================================
ADDING MAPPINGS *project-adding-mappings*
You can add your own mappings or change the mappings of the plugin by placing
them in the file $HOME/.vimproject_mappings. This file, if it exists, will be
sourced when the plugin in loaded. Here is an example that will count the
number of entries in a project when you press \K (Kount, C is taken :-): >
function! s:Wc()
let b:loadcount=0
function! SpawnExec(infoline, fname, lineno, data)
let b:loadcount = b:loadcount + 1
if getchar(0) != 0 | let b:stop_everything=1 | endif
endfunction
call Project_ForEach(1, line('.'), "*SpawnExec", 0, '')
delfunction SpawnExec
echon b:loadcount." Files\r"
unlet b:loadcount
if exists("b:stop_everything")
unlet b:stop_everything
echon "Aborted.\r"
endif
endfunction
nnoremap <buffer> <silent> <LocalLeader>K :call <SID>Wc()<CR>
Here's another example of how I integrated the use of perforce with the plugin
in my $HOME/.vimproject_mappings:
>
function! s:DoP4(cmd)
let name=Project_GetFname(line('.'))
let dir=substitute(name, '\(.*\)/.*', '\1', 'g')
exec 'cd '.dir
exec "!".a:cmd.' '.Project_GetFname(line('.'))
cd -
endfunction
nmap <buffer> <silent> \pa :call <SID>DoP4("p4add")<CR>
nmap <buffer> <silent> \pe :call <SID>DoP4("p4edit")<CR>
<
(Note that I CD to the directory the file is in so I can pick of the $P4CONFIG
file. See the perforce documentation.)
This creates the mappings \pe to check out the file for edit and \pa to add
the file to the depot.
Here is another example where I remap the <Return> mapping to use an external
program to launch a special kind of file (in this case, it launches ee to view
a jpg file). It is a bit contrived, but it works.
>
let s:sid = substitute(maparg('<Return>', 'n'), '.*\(<SNR>.\{-}\)_.*', '\1', '')
function! s:LaunchOrWhat()
let fname=Project_GetFname(line('.'))
if fname =~ '\.jpg$'
exec 'silent! !ee "'.fname.'"&'
else
call {s:sid}_DoFoldOrOpenEntry('', 'e')
endif
endfunction
nnoremap <buffer> <silent> <Return> \|:call <SID>LaunchOrWhat()<CR>
<
If the file ends in .jpg, the external program is launched, otherwise the
original mapping of <Return> is run.
==============================================================================
SETTINGS *project-settings*
You can set these variables in your vimrc file before the plugin is loaded to
change its default behavior
g:proj_window_width
The width of the Project Window that the plugin attempts to maintain.
Default: 24
The Project Plugin is not always successful in keeping the window
where I want it with the size specified here, but it does a decent
job.
g:proj_window_increment
The increment by which to increase the width of the Project Window
when pressing <space> or clicking the <LeftMouse>. Default: 100
(See |project-mappings|.)
*project-flags*
g:proj_flags
Default: "imst"
Various flags to control the behavior of the Project Plugin. This
variable can contain any of the following character flags.
flag Description ~
b When present, use the |browse()| when selecting directories
for \c and \C. This is off by default for Windows, because
the windows browser does not allow you to select directories.
c When present, the Project Window will automatically close when
you select a file.
F Float the Project Window. That is, turn off automatic
resizing and placement. This allows placement between other
windows that wish to share similar placement at the side of
the screen. It is also particularly helpful for external
window managers.
g When present, the mapping for <F12> will be created to toggle
the Project Window open and closed.
i When present, display the filename and the current working
directory in the command line when a file is selected for
opening.
l When present, the Project Plugin will use the |:lcd| command
rather than |:cd| to change directories when you select a file
to open. This flag is really obsolete and not of much use
because of L below.
L Similar to l, but install a BufEnter/Leave |:autocommand| to
ensure that the current working directory is changed to the
one specified in the fold CD specification whenever that
buffer is active. (|:lcd| only changes the CWD for a window,
not a buffer.)
m Turn on mapping of the |CTRL-W_o| and |CTRL-W_CTRL_O| normal
mode commands to make the current buffer the only visible
buffer, but keep the Project Window visible, too.
n When present, numbers will be turned on for the project
window.
s When present, the Project Plugin will use syntax highlighting
in the Project Window.
S Turn on sorting for refresh and create.
t When present, toggle the size of the window rather than just
increase the size when pressing <space> or right-clicking.
See the entry for <RightMouse> in |project-mappings|.
T When present, put Subproject folds at the top of the fold when
refreshing.
v When present, use :vimgrep rather than :grep when using \G.
g:proj_run1 ... g:proj_run9
Contains a Vim command to execute on the file. See the
mappings of \1 to \9 above.
%f is replaced with the full path and filename
%F is replaced with the full path and filename with spaces
quoted
%n is replaced with the filename alone
%N is replaced with the filename alone with spaces quoted
%h is replaced with the home directory
%H is replaced with the home directory with spaces quoted
%r is replaced with the directory relative to the CD path
%R is replaced with the directory relative to the CD path
with spaces quoted
%d is replaced with the CD directory.
%D is replaced with the CD directory.with spaces quoted
%% is replaced with a single % that is not used in
expansion.
(Deprecated: %s is also replaced with the full path and
filename for backward compatibility.)
For example, gvim will be launched on the file under the
cursor when you enter \3 if the following is in your vimrc
file: >
let g:proj_run3='silent !gvim %f'
< Here are a few other examples: >
let g:proj_run1='!p4 edit %f'
let g:proj_run2='!p4 add %f'
let g:proj_run4="echo 'Viewing %f'|sil !xterm -e less %f &"
<
On Windows systems you will want to put the %f, %h, and %d in
single quotes to avoid \ escaping.
g:proj_run_fold1 ... g:proj_run_fold9
Contains a Vim command to execute on the files in a fold. See
the mappings of \f1 to \f9 and \F1 to \F9 above.
%f is the filename, %h is replaced with the project home
directory, and %d is replaced with the CD directory. Multiple
filenames can be handled in two ways:
The first (default) way is to have %f replaced with all the
absolute filenames, and the command is run once. The second
is to have the command run for each of the non-absolute
filenames (%f is replaced with one filename at a time). To
select the second behavior, put an '*' character at the
beginning of the g:proj_run_fold{x} variable. (The '*' is
stripped before the command is run.)
For example, note the difference between the following: >
let g:proj_run_fold3="*echo '%h/%f'"
let g:proj_run_fold4="echo '%f'"
<
Note that on Windows systems, you will want the %f, %h, and %c
within single quotes, or the \ in the paths will cause
problems. The alternative is to put them in |escape()|.
==============================================================================
PROJECT EXAMPLE FILE *project-example*
Here is an example ~/.vimprojects file: >
1 My Project=~/c/project CD=. in=in.vim out=out.vim flags=r {
2 Makefile
3 in.vim
4 out.vim
5 GUI Files=. filter="gui*.c gui*.h" {
6 gui_window.c
7 gui_dialog.c
8 gui_list.c
9 gui.h # Header file
10 }
11 Database Files=. filter="data*.c data*.h" {
12 data_read.c
13 data_write.c
14 data.h
15 }
16 OS-Specific Files {
17 Win32=. filter="os_win32*.c os_win32*.h" {
18 os_win32_gui.c
19 os_win32_io.c
20 }
21 Unix=. filter="os_unix*.c os_unix*.h" {
22 os_unix_gui.c
23 os_unix_io.c
24 }
25 }
26 }
(Don't type in the line numbers, of course.)
==============================================================================
TIPS ON USING PROJECT PLUGIN *project-tips*
1. You can create a Project Entry by entering this: >
Label=~/wherever CD=. filter="*.c *.h" {
}
<
Then you can put the cursor in the fold and press \r. The script will fill
in the files (C files in this case) from this directory for you. This is
equivalent to \c without any dialogs.
2. You can edit the Project File at any time to add, remove, or reorder files
in the Project list.
3. If the Project Window ever gets closed, you can just enter >
:Project
< to bring it back again. (You don't need to give it the filename; the
plugin remembers.)
If you have the 'm' flag set in g:proj_flags, then you get the Project
Window to show up again by pressing |CTRL-W_o|. This, of course, will
close any other windows that may be open that the cursor is not in.
4. Adding files to a Project is very easy. To add, for example, the 'more.c'
file to the Project, just insert the filename in the Project Entry then
hit <Return> on it.
5. When |quickfix| loads files, it is not equivalent to pressing <Return> on
a filename, so the directory will not be changed and the scripts will not
be run. (If I could make this otherwise, I would.) The solution is to use
the \L key to load all of the files in the Project before running
quickfix.
6. If the Project window gets a bit cluttered with folds partially
open/closed, you can press |zM| to close everything and tidy it up.
7. For advanced users, I am exporting the function Project_GetAllFnames()
which returns all the filenames within a fold and optionally all its
Subprojects. Also, I export Project_ForEach() for running a function for
each filename in the project. See the code for examples on how to use
these. Finally, I export Project_GetFname(line_number) so that you can
write your own mappings and get the filename for it.
8. Some people have asked how to do a global mapping to take the cursor to
the Project window. One of my goals for the plugin is for it to be as
self-contained as possible, so I'm not going to add it by default. But you
can put this in your vimrc:
>
nmap <silent> <Leader>P :Project<CR>
<
9. You can put the . entry in a project, and it will launch the
|file-explorer| plugin on the directory. To avoid removal when you
refresh, make the entry look like this:
>
. # pragma keep
<
==============================================================================
THANKS
The following people have sent me patches to help with the Project
Plugin development:
Tomas Zellerin
Lawrence Kesteloot
Dave Eggum
A Harrison
Thomas Link
Richard Bair
Eric Arnold
Peter Jones
Eric Van Dewoestine
vim:ts=8 sw=8 noexpandtab tw=78 ft=help:

1501
.vim/doc/taglist.txt Normal file

File diff suppressed because it is too large Load Diff

229
.vim/doc/tags Normal file
View File

@ -0,0 +1,229 @@
'Tlist_Auto_Highlight_Tag' taglist.txt /*'Tlist_Auto_Highlight_Tag'*
'Tlist_Auto_Open' taglist.txt /*'Tlist_Auto_Open'*
'Tlist_Auto_Update' taglist.txt /*'Tlist_Auto_Update'*
'Tlist_Close_On_Select' taglist.txt /*'Tlist_Close_On_Select'*
'Tlist_Compact_Format' taglist.txt /*'Tlist_Compact_Format'*
'Tlist_Ctags_Cmd' taglist.txt /*'Tlist_Ctags_Cmd'*
'Tlist_Display_Prototype' taglist.txt /*'Tlist_Display_Prototype'*
'Tlist_Display_Tag_Scope' taglist.txt /*'Tlist_Display_Tag_Scope'*
'Tlist_Enable_Fold_Column' taglist.txt /*'Tlist_Enable_Fold_Column'*
'Tlist_Exit_OnlyWindow' taglist.txt /*'Tlist_Exit_OnlyWindow'*
'Tlist_File_Fold_Auto_Close' taglist.txt /*'Tlist_File_Fold_Auto_Close'*
'Tlist_GainFocus_On_ToggleOpen' taglist.txt /*'Tlist_GainFocus_On_ToggleOpen'*
'Tlist_Highlight_Tag_On_BufEnter' taglist.txt /*'Tlist_Highlight_Tag_On_BufEnter'*
'Tlist_Inc_Winwidth' taglist.txt /*'Tlist_Inc_Winwidth'*
'Tlist_Max_Submenu_Items' taglist.txt /*'Tlist_Max_Submenu_Items'*
'Tlist_Max_Tag_Length' taglist.txt /*'Tlist_Max_Tag_Length'*
'Tlist_Process_File_Always' taglist.txt /*'Tlist_Process_File_Always'*
'Tlist_Show_Menu' taglist.txt /*'Tlist_Show_Menu'*
'Tlist_Show_One_File' taglist.txt /*'Tlist_Show_One_File'*
'Tlist_Sort_Type' taglist.txt /*'Tlist_Sort_Type'*
'Tlist_Use_Horiz_Window' taglist.txt /*'Tlist_Use_Horiz_Window'*
'Tlist_Use_Right_Window' taglist.txt /*'Tlist_Use_Right_Window'*
'Tlist_Use_SingleClick' taglist.txt /*'Tlist_Use_SingleClick'*
'Tlist_WinHeight' taglist.txt /*'Tlist_WinHeight'*
'Tlist_WinWidth' taglist.txt /*'Tlist_WinWidth'*
:CVSEdit vcscommand.txt /*:CVSEdit*
:CVSEditors vcscommand.txt /*:CVSEditors*
:CVSUnedit vcscommand.txt /*:CVSUnedit*
:CVSWatch vcscommand.txt /*:CVSWatch*
:CVSWatchAdd vcscommand.txt /*:CVSWatchAdd*
:CVSWatchOff vcscommand.txt /*:CVSWatchOff*
:CVSWatchOn vcscommand.txt /*:CVSWatchOn*
:CVSWatchRemove vcscommand.txt /*:CVSWatchRemove*
:CVSWatchers vcscommand.txt /*:CVSWatchers*
:NERDTree NERD_tree.txt /*:NERDTree*
:NERDTreeToggle NERD_tree.txt /*:NERDTreeToggle*
:TlistAddFiles taglist.txt /*:TlistAddFiles*
:TlistAddFilesRecursive taglist.txt /*:TlistAddFilesRecursive*
:TlistClose taglist.txt /*:TlistClose*
:TlistDebug taglist.txt /*:TlistDebug*
:TlistHighlightTag taglist.txt /*:TlistHighlightTag*
:TlistLock taglist.txt /*:TlistLock*
:TlistMessages taglist.txt /*:TlistMessages*
:TlistOpen taglist.txt /*:TlistOpen*
:TlistSessionLoad taglist.txt /*:TlistSessionLoad*
:TlistSessionSave taglist.txt /*:TlistSessionSave*
:TlistShowPrototype taglist.txt /*:TlistShowPrototype*
:TlistShowTag taglist.txt /*:TlistShowTag*
:TlistToggle taglist.txt /*:TlistToggle*
:TlistUndebug taglist.txt /*:TlistUndebug*
:TlistUnlock taglist.txt /*:TlistUnlock*
:TlistUpdate taglist.txt /*:TlistUpdate*
:VCSAdd vcscommand.txt /*:VCSAdd*
:VCSAnnotate vcscommand.txt /*:VCSAnnotate*
:VCSBlame vcscommand.txt /*:VCSBlame*
:VCSCommit vcscommand.txt /*:VCSCommit*
:VCSDelete vcscommand.txt /*:VCSDelete*
:VCSDiff vcscommand.txt /*:VCSDiff*
:VCSGotoOriginal vcscommand.txt /*:VCSGotoOriginal*
:VCSInfo vcscommand.txt /*:VCSInfo*
:VCSLock vcscommand.txt /*:VCSLock*
:VCSLog vcscommand.txt /*:VCSLog*
:VCSRemove vcscommand.txt /*:VCSRemove*
:VCSRevert vcscommand.txt /*:VCSRevert*
:VCSReview vcscommand.txt /*:VCSReview*
:VCSStatus vcscommand.txt /*:VCSStatus*
:VCSUnlock vcscommand.txt /*:VCSUnlock*
:VCSUpdate vcscommand.txt /*:VCSUpdate*
:VCSVimDiff vcscommand.txt /*:VCSVimDiff*
NERDChristmasTree NERD_tree.txt /*NERDChristmasTree*
NERDTree NERD_tree.txt /*NERDTree*
NERDTree-! NERD_tree.txt /*NERDTree-!*
NERDTree-? NERD_tree.txt /*NERDTree-?*
NERDTree-C NERD_tree.txt /*NERDTree-C*
NERDTree-F NERD_tree.txt /*NERDTree-F*
NERDTree-H NERD_tree.txt /*NERDTree-H*
NERDTree-J NERD_tree.txt /*NERDTree-J*
NERDTree-K NERD_tree.txt /*NERDTree-K*
NERDTree-O NERD_tree.txt /*NERDTree-O*
NERDTree-P NERD_tree.txt /*NERDTree-P*
NERDTree-R NERD_tree.txt /*NERDTree-R*
NERDTree-T NERD_tree.txt /*NERDTree-T*
NERDTree-U NERD_tree.txt /*NERDTree-U*
NERDTree-X NERD_tree.txt /*NERDTree-X*
NERDTree-c-j NERD_tree.txt /*NERDTree-c-j*
NERDTree-c-k NERD_tree.txt /*NERDTree-c-k*
NERDTree-contents NERD_tree.txt /*NERDTree-contents*
NERDTree-e NERD_tree.txt /*NERDTree-e*
NERDTree-f NERD_tree.txt /*NERDTree-f*
NERDTree-go NERD_tree.txt /*NERDTree-go*
NERDTree-gtab NERD_tree.txt /*NERDTree-gtab*
NERDTree-m NERD_tree.txt /*NERDTree-m*
NERDTree-o NERD_tree.txt /*NERDTree-o*
NERDTree-p NERD_tree.txt /*NERDTree-p*
NERDTree-q NERD_tree.txt /*NERDTree-q*
NERDTree-r NERD_tree.txt /*NERDTree-r*
NERDTree-t NERD_tree.txt /*NERDTree-t*
NERDTree-tab NERD_tree.txt /*NERDTree-tab*
NERDTree-u NERD_tree.txt /*NERDTree-u*
NERDTree-x NERD_tree.txt /*NERDTree-x*
NERDTreeAuthor NERD_tree.txt /*NERDTreeAuthor*
NERDTreeAutoCenter NERD_tree.txt /*NERDTreeAutoCenter*
NERDTreeAutoCenterThreshold NERD_tree.txt /*NERDTreeAutoCenterThreshold*
NERDTreeCaseSensitiveSort NERD_tree.txt /*NERDTreeCaseSensitiveSort*
NERDTreeChDirMode NERD_tree.txt /*NERDTreeChDirMode*
NERDTreeChangelog NERD_tree.txt /*NERDTreeChangelog*
NERDTreeCommands NERD_tree.txt /*NERDTreeCommands*
NERDTreeCredits NERD_tree.txt /*NERDTreeCredits*
NERDTreeFilesysMenu NERD_tree.txt /*NERDTreeFilesysMenu*
NERDTreeFunctionality NERD_tree.txt /*NERDTreeFunctionality*
NERDTreeHighlightCursorline NERD_tree.txt /*NERDTreeHighlightCursorline*
NERDTreeIgnore NERD_tree.txt /*NERDTreeIgnore*
NERDTreeMappings NERD_tree.txt /*NERDTreeMappings*
NERDTreeMouseMode NERD_tree.txt /*NERDTreeMouseMode*
NERDTreeOptionDetails NERD_tree.txt /*NERDTreeOptionDetails*
NERDTreeOptionSummary NERD_tree.txt /*NERDTreeOptionSummary*
NERDTreeOptions NERD_tree.txt /*NERDTreeOptions*
NERDTreePublicFunctions NERD_tree.txt /*NERDTreePublicFunctions*
NERDTreeShowFiles NERD_tree.txt /*NERDTreeShowFiles*
NERDTreeShowHidden NERD_tree.txt /*NERDTreeShowHidden*
NERDTreeSortOrder NERD_tree.txt /*NERDTreeSortOrder*
NERDTreeSplitVertical NERD_tree.txt /*NERDTreeSplitVertical*
NERDTreeTodo NERD_tree.txt /*NERDTreeTodo*
NERDTreeWinPos NERD_tree.txt /*NERDTreeWinPos*
NERDTreeWinSize NERD_tree.txt /*NERDTreeWinSize*
NERD_tree.txt NERD_tree.txt /*NERD_tree.txt*
OmniCpp_DefaultNamespaces omnicppcomplete.txt /*OmniCpp_DefaultNamespaces*
OmniCpp_DisplayMode omnicppcomplete.txt /*OmniCpp_DisplayMode*
OmniCpp_GlobalScopeSearch omnicppcomplete.txt /*OmniCpp_GlobalScopeSearch*
OmniCpp_LocalSearchDecl omnicppcomplete.txt /*OmniCpp_LocalSearchDecl*
OmniCpp_MayCompleteArrow omnicppcomplete.txt /*OmniCpp_MayCompleteArrow*
OmniCpp_MayCompleteDot omnicppcomplete.txt /*OmniCpp_MayCompleteDot*
OmniCpp_MayCompleteScope omnicppcomplete.txt /*OmniCpp_MayCompleteScope*
OmniCpp_NamespaceSearch omnicppcomplete.txt /*OmniCpp_NamespaceSearch*
OmniCpp_SelectFirstItem omnicppcomplete.txt /*OmniCpp_SelectFirstItem*
OmniCpp_ShowAccess omnicppcomplete.txt /*OmniCpp_ShowAccess*
OmniCpp_ShowPrototypeInAbbr omnicppcomplete.txt /*OmniCpp_ShowPrototypeInAbbr*
OmniCpp_ShowScopeInAbbr omnicppcomplete.txt /*OmniCpp_ShowScopeInAbbr*
Tlist_Get_Tag_Prototype_By_Line() taglist.txt /*Tlist_Get_Tag_Prototype_By_Line()*
Tlist_Get_Tagname_By_Line() taglist.txt /*Tlist_Get_Tagname_By_Line()*
Tlist_Set_App() taglist.txt /*Tlist_Set_App()*
Tlist_Update_File_Tags() taglist.txt /*Tlist_Update_File_Tags()*
VCSCommandCVSDiffOpt vcscommand.txt /*VCSCommandCVSDiffOpt*
VCSCommandCVSExec vcscommand.txt /*VCSCommandCVSExec*
VCSCommandCommitOnWrite vcscommand.txt /*VCSCommandCommitOnWrite*
VCSCommandDeleteOnHide vcscommand.txt /*VCSCommandDeleteOnHide*
VCSCommandDiffSplit vcscommand.txt /*VCSCommandDiffSplit*
VCSCommandDisableExtensionMappings vcscommand.txt /*VCSCommandDisableExtensionMappings*
VCSCommandDisableMappings vcscommand.txt /*VCSCommandDisableMappings*
VCSCommandEdit vcscommand.txt /*VCSCommandEdit*
VCSCommandEnableBufferSetup vcscommand.txt /*VCSCommandEnableBufferSetup*
VCSCommandResultBufferNameExtension vcscommand.txt /*VCSCommandResultBufferNameExtension*
VCSCommandResultBufferNameFunction vcscommand.txt /*VCSCommandResultBufferNameFunction*
VCSCommandSVKExec vcscommand.txt /*VCSCommandSVKExec*
VCSCommandSVNDiffExt vcscommand.txt /*VCSCommandSVNDiffExt*
VCSCommandSVNDiffOpt vcscommand.txt /*VCSCommandSVNDiffOpt*
VCSCommandSVNExec vcscommand.txt /*VCSCommandSVNExec*
VCSCommandSplit vcscommand.txt /*VCSCommandSplit*
b:VCSCommandCommand vcscommand.txt /*b:VCSCommandCommand*
b:VCSCommandOriginalBuffer vcscommand.txt /*b:VCSCommandOriginalBuffer*
b:VCSCommandSourceFile vcscommand.txt /*b:VCSCommandSourceFile*
b:VCSCommandVCSType vcscommand.txt /*b:VCSCommandVCSType*
cvscommand-changes vcscommand.txt /*cvscommand-changes*
loaded_nerd_tree NERD_tree.txt /*loaded_nerd_tree*
omnicpp-download omnicppcomplete.txt /*omnicpp-download*
omnicpp-faq omnicppcomplete.txt /*omnicpp-faq*
omnicpp-features omnicppcomplete.txt /*omnicpp-features*
omnicpp-history omnicppcomplete.txt /*omnicpp-history*
omnicpp-installation omnicppcomplete.txt /*omnicpp-installation*
omnicpp-limitations omnicppcomplete.txt /*omnicpp-limitations*
omnicpp-may-complete omnicppcomplete.txt /*omnicpp-may-complete*
omnicpp-options omnicppcomplete.txt /*omnicpp-options*
omnicpp-overview omnicppcomplete.txt /*omnicpp-overview*
omnicpp-popup omnicppcomplete.txt /*omnicpp-popup*
omnicpp-thanks omnicppcomplete.txt /*omnicpp-thanks*
omnicppcomplete omnicppcomplete.txt /*omnicppcomplete*
omnicppcomplete.txt omnicppcomplete.txt /*omnicppcomplete.txt*
project project.txt /*project*
project-adding-mappings project.txt /*project-adding-mappings*
project-example project.txt /*project-example*
project-flags project.txt /*project-flags*
project-inheritance project.txt /*project-inheritance*
project-invoking project.txt /*project-invoking*
project-mappings project.txt /*project-mappings*
project-plugin project.txt /*project-plugin*
project-settings project.txt /*project-settings*
project-syntax project.txt /*project-syntax*
project-tips project.txt /*project-tips*
project.txt project.txt /*project.txt*
taglist-commands taglist.txt /*taglist-commands*
taglist-debug taglist.txt /*taglist-debug*
taglist-extend taglist.txt /*taglist-extend*
taglist-faq taglist.txt /*taglist-faq*
taglist-functions taglist.txt /*taglist-functions*
taglist-install taglist.txt /*taglist-install*
taglist-internet taglist.txt /*taglist-internet*
taglist-intro taglist.txt /*taglist-intro*
taglist-keys taglist.txt /*taglist-keys*
taglist-license taglist.txt /*taglist-license*
taglist-menu taglist.txt /*taglist-menu*
taglist-options taglist.txt /*taglist-options*
taglist-requirements taglist.txt /*taglist-requirements*
taglist-session taglist.txt /*taglist-session*
taglist-todo taglist.txt /*taglist-todo*
taglist-using taglist.txt /*taglist-using*
taglist.txt taglist.txt /*taglist.txt*
vcscommand vcscommand.txt /*vcscommand*
vcscommand-buffer-management vcscommand.txt /*vcscommand-buffer-management*
vcscommand-buffer-variables vcscommand.txt /*vcscommand-buffer-variables*
vcscommand-bugs vcscommand.txt /*vcscommand-bugs*
vcscommand-commands vcscommand.txt /*vcscommand-commands*
vcscommand-config vcscommand.txt /*vcscommand-config*
vcscommand-contents vcscommand.txt /*vcscommand-contents*
vcscommand-customize vcscommand.txt /*vcscommand-customize*
vcscommand-events vcscommand.txt /*vcscommand-events*
vcscommand-install vcscommand.txt /*vcscommand-install*
vcscommand-intro vcscommand.txt /*vcscommand-intro*
vcscommand-manual vcscommand.txt /*vcscommand-manual*
vcscommand-mappings vcscommand.txt /*vcscommand-mappings*
vcscommand-mappings-override vcscommand.txt /*vcscommand-mappings-override*
vcscommand-naming vcscommand.txt /*vcscommand-naming*
vcscommand-options vcscommand.txt /*vcscommand-options*
vcscommand-ssh vcscommand.txt /*vcscommand-ssh*
vcscommand-ssh-config vcscommand.txt /*vcscommand-ssh-config*
vcscommand-ssh-env vcscommand.txt /*vcscommand-ssh-env*
vcscommand-ssh-other vcscommand.txt /*vcscommand-ssh-other*
vcscommand-ssh-wrapper vcscommand.txt /*vcscommand-ssh-wrapper*
vcscommand-statusline vcscommand.txt /*vcscommand-statusline*
vcscommand.txt vcscommand.txt /*vcscommand.txt*

771
.vim/doc/vcscommand.txt Normal file
View File

@ -0,0 +1,771 @@
*vcscommand.txt* vcscommand
Copyright (c) 2007 Bob Hiestand
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
For instructions on installing this file, type
:help add-local-help
inside Vim.
Author: Bob Hiestand <bob.hiestand@gmail.com>
Credits: Benji Fisher's excellent MatchIt documentation
==============================================================================
1. Contents *vcscommand-contents*
Installation : |vcscommand-install|
vcscommand Intro : |vcscommand|
vcscommand Manual : |vcscommand-manual|
Customization : |vcscommand-customize|
SSH "integration" : |vcscommand-ssh|
Changes from cvscommand : |cvscommand-changes|
Bugs : |vcscommand-bugs|
==============================================================================
2. vcscommand Installation *vcscommand-install*
The vcscommand plugin comprises five files: vcscommand.vim, vcssvn.vim,
vcscvs.vim, vcssvk.vim and vcscommand.txt (this file). In order to install
the plugin, place the vcscommand.vim, vcssvn.vim, vcssvk.vim, and vcscvs.vim
files into a plugin directory in your runtime path (please see
|add-global-plugin| and |'runtimepath'|.
This help file can be included in the VIM help system by copying it into a
'doc' directory in your runtime path and then executing the |:helptags|
command, specifying the full path of the 'doc' directory. Please see
|add-local-help| for more details.
vcscommand may be customized by setting variables, creating maps, and
specifying event handlers. Please see |vcscommand-customize| for more
details.
==============================================================================
3. vcscommand Intro *vcscommand*
*vcscommand-intro*
The vcscommand plugin provides global ex commands for manipulating
version-controlled source files, currently those controlled either by CVS or
Subversion. In general, each command operates on the current buffer and
accomplishes a separate source control function, such as update, commit, log,
and others (please see |vcscommand-commands| for a list of all available
commands). The results of each operation are displayed in a scratch buffer.
Several buffer variables are defined for those scratch buffers (please see
|vcscommand-buffer-variables|).
The notion of "current file" means either the current buffer, or, in the case
of a directory buffer (such as Explorer or netrw buffers), the directory (and
all subdirectories) represented by the the buffer.
For convenience, any vcscommand invoked on a vcscommand scratch buffer acts as
though it was invoked on the original file and splits the screen so that the
output appears in a new window.
Many of the commands accept revisions as arguments. By default, most operate
on the most recent revision on the current branch if no revision is specified.
Each vcscommand is mapped to a key sequence starting with the <Leader>
keystroke. The default mappings may be overridden by supplying different
mappings before the plugin is loaded, such as in the vimrc, in the standard
fashion for plugin mappings. For examples, please see
|vcscommand-mappings-override|.
The vcscommand plugin may be configured in several ways. For more details,
please see |vcscommand-customize|.
==============================================================================
4. vcscommand Manual *vcscommand-manual*
4.1 vcscommand commands *vcscommand-commands*
vcscommand defines the following commands:
|:VCSAdd|
|:VCSAnnotate|
|:VCSBlame|
|:VCSCommit|
|:VCSDelete|
|:VCSDiff|
|:VCSGotoOriginal|
|:VCSLog|
|:VCSRemove|
|:VCSRevert|
|:VCSReview|
|:VCSStatus|
|:VCSUpdate|
|:VCSVimDiff|
The following commands are specific to CVS files:
|:CVSEdit|
|:CVSEditors|
|:CVSUnedit|
|:CVSWatch|
|:CVSWatchAdd|
|:CVSWatchOn|
|:CVSWatchOff|
|:CVSWatchRemove|
|:CVSWatchers|
:VCSAdd *:VCSAdd*
This command adds the current file to source control. Please note, this does
not commit the newly-added file. All parameters to the command are passed to
the underlying VCS.
:VCSAnnotate *:VCSAnnotate*
This command displays the current file with each line annotated with the
version in which it was most recently changed. If an argument is given, the
argument is used as a revision number to display. If not given an argument,
it uses the most recent version of the file (on the current branch, if under
CVS control). Additionally, if the current buffer is a VCSAnnotate buffer
already, the version number on the current line is used.
For CVS buffers, the 'VCSCommandCVSAnnotateParent' option, if set to non-zero,
will cause the above behavior to change. Instead of annotating the version on
the current line, the parent revision is used instead, crossing branches if
necessary.
The filetype of the vcscommand scratch buffer is set to one of 'CVSAnnotate',
'SVNAnnotate', or 'SVKAnnotate' as appropriate, to take advantage of the
bundled syntax files.
:VCSBlame *:VCSBlame*
Alias for |:VCSAnnotate|.
:VCSCommit[!] *:VCSCommit*
This command commits changes to the current file to source control.
If called with arguments, the arguments are the log message.
If '!' is used, an empty log message is committed.
If called with no arguments, this is a two-step command. The first step opens
a buffer to accept a log message. When that buffer is written, it is
automatically closed and the file is committed using the information from that
log message. The commit can be abandoned if the log message buffer is deleted
or wiped before being written.
Alternatively, the mapping that is used to invoke :VCSCommit (by default
<Leader>cc) can be used in the log message buffer to immediately commit. This
is useful if the |VCSCommandCommitOnWrite| variable is set to 0 to disable the
normal commit-on-write behavior.
:VCSDelete *:VCSDelete*
Deletes the current file and removes it from source control. All parameters
to the command are passed to the underlying VCS.
:VCSDiff *:VCSDiff*
With no arguments, this displays the differences between the current file and
its parent version under source control in a new scratch buffer.
With one argument, the diff is performed on the current file against the
specified revision.
With two arguments, the diff is performed between the specified revisions of
the current file.
For CVS, this command uses the |VCSCommandCVSDiffOpt| variable to specify diff
options. If that variable does not exist, a plugin-specific default is used.
If you wish to have no options, then set it to the empty string.
For SVN, this command uses the |VCSCommandSVNDiffOpt| variable to specify diff
options. If that variable does not exist, the SVN default is used.
Additionally, |VCSCommandSVNDiffExt| can be used to select an external diff
application.
:VCSGotoOriginal *:VCSGotoOriginal*
This command jumps to the source buffer if the current buffer is a VCS scratch
buffer.
:VCSGotoOriginal!
Like ":VCSGotoOriginal" but also executes :bufwipeout on all VCS scrach
buffers associated with the original file.
:VCSInfo *:VCSInfo*
This command displays extended information about the current file in a new
scratch buffer.
:VCSLock *:VCSLock*
This command locks the current file in order to prevent other users from
concurrently modifying it. The exact semantics of this command depend on the
underlying VCS. This does nothing in CVS. All parameters are passed to the
underlying VCS.
:VCSLog *:VCSLog*
Displays the version history of the current file in a new scratch buffer. If
there is one parameter supplied, it is taken as as a revision parameters to be
passed through to the underlying VCS. Otherwise, all parameters are passed to
the underlying VCS.
:VCSRemove *:VCSRemove*
Alias for |:VCSDelete|.
:VCSRevert *:VCSRevert*
This command replaces the current file with the most recent version from the
repository in order to wipe out any undesired changes.
:VCSReview *:VCSReview*
Displays a particular version of the current file in a new scratch buffer. If
no argument is given, the most recent version of the file on the current
branch is retrieved.
:VCSStatus *:VCSStatus*
Displays versioning information about the current file in a new scratch
buffer. All parameters are passed to the underlying VCS.
:VCSUnlock *:VCSUnlock*
Unlocks the current file in order to allow other users from concurrently
modifying it. The exact semantics of this command depend on the underlying
VCS. All parameters are passed to the underlying VCS.
:VCSUpdate *:VCSUpdate*
Updates the current file with any relevant changes from the repository. This
intentionally does not automatically reload the current buffer, though vim
should prompt the user to do so if the underlying file is altered by this
command.
:VCSVimDiff *:VCSVimDiff*
Uses vimdiff to display differences between versions of the current file.
If no revision is specified, the most recent version of the file on the
current branch is used. With one argument, that argument is used as the
revision as above. With two arguments, the differences between the two
revisions is displayed using vimdiff.
With either zero or one argument, the original buffer is used to perform the
vimdiff. When the scratch buffer is closed, the original buffer will be
returned to normal mode.
Once vimdiff mode is started using the above methods, additional vimdiff
buffers may be added by passing a single version argument to the command.
There may be up to 4 vimdiff buffers total.
Using the 2-argument form of the command resets the vimdiff to only those 2
versions. Additionally, invoking the command on a different file will close
the previous vimdiff buffers.
:CVSEdit *:CVSEdit*
This command performs "cvs edit" on the current file. Yes, the output buffer
in this case is almost completely useless.
:CVSEditors *:CVSEditors*
This command performs "cvs edit" on the current file.
:CVSUnedit *:CVSUnedit*
Performs "cvs unedit" on the current file. Again, yes, the output buffer here
is basically useless.
:CVSWatch *:CVSWatch*
This command takes an argument which must be one of [on|off|add|remove]. The
command performs "cvs watch" with the given argument on the current file.
:CVSWatchAdd *:CVSWatchAdd*
This command is an alias for ":CVSWatch add"
:CVSWatchOn *:CVSWatchOn*
This command is an alias for ":CVSWatch on"
:CVSWatchOff *:CVSWatchOff*
This command is an alias for ":CVSWatch off"
:CVSWatchRemove *:CVSWatchRemove*
This command is an alias for ":CVSWatch remove"
:CVSWatchers *:CVSWatchers*
This command performs "cvs watchers" on the current file.
4.2 Mappings *vcscommand-mappings*
By default, a mapping is defined for each command. These mappings execute the
default (no-argument) form of each command.
<Leader>ca VCSAdd
<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
Only for CVS buffers:
<Leader>ce CVSEdit
<Leader>cE CVSEditors
<Leader>ct CVSUnedit
<Leader>cwv CVSWatchers
<Leader>cwa CVSWatchAdd
<Leader>cwn CVSWatchOn
<Leader>cwf CVSWatchOff
<Leader>cwf CVSWatchRemove
*vcscommand-mappings-override*
The default mappings can be overriden by user-provided instead by mapping to
<Plug>CommandName. This is especially useful when these mappings collide with
other existing mappings (vim will warn of this during plugin initialization,
but will not clobber the existing mappings).
For instance, to override the default mapping for :VCSAdd to set it to '\add',
add the following to the vimrc:
nmap \add <Plug>VCSAdd
4.3 Automatic buffer variables *vcscommand-buffer-variables*
Several buffer variables are defined in each vcscommand result buffer. These
may be useful for additional customization in callbacks defined in the event
handlers (please see |vcscommand-events|).
The following variables are automatically defined:
b:VCSCommandOriginalBuffer *b:VCSCommandOriginalBuffer*
This variable is set to the buffer number of the source file.
b:VCSCommandCommand *b:VCSCommandCommand*
This variable is set to the name of the vcscommand that created the result
buffer.
b:VCSCommandSourceFile *b:VCSCommandSourceFile*
This variable is set to the name of the original file under source control.
b:VCSCommandVCSType *b:VCSCommandVCSType*
This variable is set to the type of the source control. This variable is also
set on the original file itself.
==============================================================================
5. Configuration and customization *vcscommand-customize*
*vcscommand-config*
The vcscommand plugin can be configured in several ways: by setting
configuration variables (see |vcscommand-options|) or by defining vcscommand
event handlers (see |vcscommand-events|). Additionally, the vcscommand plugin
supports a customized status line (see |vcscommand-statusline| and
|vcscommand-buffer-management|).
5.1 vcscommand configuration variables *vcscommand-options*
Several variables affect the plugin's behavior. These variables are checked
at time of execution, and may be defined at the window, buffer, or global
level and are checked in that order of precedence.
The following variables are available:
|VCSCommandCommitOnWrite|
|VCSCommandCVSDiffOpt|
|VCSCommandCVSExec|
|VCSCommandDeleteOnHide|
|VCSCommandDiffSplit|
|VCSCommandDisableMappings|
|VCSCommandDisableExtensionMappings|
|VCSCommandEdit|
|VCSCommandEnableBufferSetup|
|VCSCommandResultBufferNameExtension|
|VCSCommandResultBufferNameFunction|
|VCSCommandSplit|
|VCSCommandSVKExec|
|VCSCommandSVNDiffExt|
|VCSCommandSVNDiffOpt|
|VCSCommandSVNExec|
VCSCommandCommitOnWrite *VCSCommandCommitOnWrite*
This variable, if set to a non-zero value, causes the pending commit
to take place immediately as soon as the log message buffer is written.
If set to zero, only the VCSCommit mapping will cause the pending commit to
occur. If not set, it defaults to 1.
VCSCommandCVSExec *VCSCommandCVSExec*
This variable controls the executable used for all CVS commands If not set,
it defaults to "cvs".
VCSCommandDeleteOnHide *VCSCommandDeleteOnHide*
This variable, if set to a non-zero value, causes the temporary result buffers
to automatically delete themselves when hidden.
VCSCommandCVSDiffOpt *VCSCommandCVSDiffOpt*
This variable, if set, determines the options passed to the diff command of
CVS. If not set, it defaults to 'u'.
VCSCommandDiffSplit *VCSCommandDiffSplit*
This variable overrides the |VCSCommandSplit| variable, but only for buffers
created with |:VCSVimDiff|.
VCSCommandDisableMappings *VCSCommandDisableMappings*
This variable, if set to a non-zero value, prevents the default command
mappings from being set. This supercedes
|VCSCommandDisableExtensionMappings|.
VCSCommandDisableExtensionMappings *VCSCommandDisableExtensionMappings*
This variable, if set to a non-zero value, prevents the default command
mappings from being set for commands specific to an individual VCS.
VCSCommandEdit *VCSCommandEdit*
This variable controls whether the original buffer is replaced ('edit') or
split ('split'). If not set, it defaults to 'split'.
VCSCommandEnableBufferSetup *VCSCommandEnableBufferSetup*
This variable, if set to a non-zero value, activates VCS buffer management
mode see (|vcscommand-buffer-management|). This mode means that the
'VCSCommandBufferInfo' variable is filled with version information if the file
is VCS-controlled. This is useful for displaying version information in the
status bar.
VCSCommandResultBufferNameExtension *VCSCommandResultBufferNameExtension*
This variable, if set to a non-blank value, is appended to the name of the VCS
command output buffers. For example, '.vcs'. Using this option may help
avoid problems caused by autocommands dependent on file extension.
VCSCommandResultBufferNameFunction *VCSCommandResultBufferNameFunction*
This variable, if set, specifies a custom function for naming VCS command
output buffers. This function is expected to return the new buffer name, and
will be passed the following arguments:
command - name of the VCS command being executed (such as 'Log' or
'Diff').
originalBuffer - buffer number of the source file.
vcsType - type of VCS controlling this file (such as 'CVS' or 'SVN').
statusText - extra text associated with the VCS action (such as version
numbers).
VCSCommandSplit *VCSCommandSplit*
This variable controls the orientation of the various window splits that
may occur.
If set to 'horizontal', the resulting windows will be on stacked on top of
one another. If set to 'vertical', the resulting windows will be
side-by-side. If not set, it defaults to 'horizontal' for all but
VCSVimDiff windows.
VCSCommandSVKExec *VCSCommandSVKExec*
This variable controls the executable used for all SVK commands If not set,
it defaults to "svk".
VCSCommandSVNDiffExt *VCSCommandSVNDiffExt*
This variable, if set, is passed to SVN via the --diff-cmd command to select
an external application for performing the diff.
VCSCommandSVNDiffOpt *VCSCommandSVNDiffOpt*
This variable, if set, determines the options passed with the '-x' parameter
to the SVN diff command. If not set, no options are passed.
VCSCommandSVNExec *VCSCommandSVNExec*
This variable controls the executable used for all SVN commands If not set,
it defaults to "svn".
5.2 VCSCommand events *vcscommand-events*
For additional customization, vcscommand can trigger user-defined events.
Event handlers are provided by defining User event autocommands (see
|autocommand|, |User|) in the vcscommand group with patterns matching the
event name.
For instance, the following could be added to the vimrc to provide a 'q'
mapping to quit a vcscommand scratch buffer:
augroup VCSCommand
au User VCSBufferCreated silent! nmap <unique> <buffer> q: bwipeout<cr>
augroup END
The following hooks are available:
VCSBufferCreated This event is fired just after a vcscommand
result buffer is created and populated. It is
executed within the context of the vcscommand
buffer. The vcscommand buffer variables may
be useful for handlers of this event (please
see |vcscommand-buffer-variables|).
VCSBufferSetup This event is fired just after vcscommand buffer
setup occurs, if enabled.
VCSPluginInit This event is fired when the vcscommand plugin
first loads.
VCSPluginFinish This event is fired just after the vcscommand
plugin loads.
VCSVimDiffFinish This event is fired just after the VCSVimDiff
command executes to allow customization of,
for instance, window placement and focus.
Additionally, there is another hook which is used internally to handle loading
the multiple scripts in order. This hook should probably not be used by an
end user without a good idea of how it works. Among other things, any events
associated with this hook are cleared after they are executed (during
vcscommand.vim script initialization).
VCSLoadExtensions This event is fired just before the
VCSPluginFinish. It is used internally to
execute any commands from the VCS
implementation plugins that needs to be
deferred until the primary plugin is
initialized.
5.3 vcscommand buffer naming *vcscommand-naming*
vcscommand result buffers use the following naming convention:
[{VCS type} {VCS command} {Source file name}]
If additional buffers are created that would otherwise conflict, a
distinguishing number is added:
[{VCS type} {VCS command} {Source file name}] (1,2, etc)
5.4 vcscommand status line support *vcscommand-statusline*
It is intended that the user will customize the |'statusline'| option to
include vcscommand result buffer attributes. A sample function that may be
used in the |'statusline'| option is provided by the plugin,
VCSCommandGetStatusLine(). In order to use that function in the status line, do
something like the following:
set statusline=%<%f\ %{VCSCommandGetStatusLine()}\ %h%m%r%=%l,%c%V\ %P
of which %{VCSCommandGetStatusLine()} is the relevant portion.
The sample VCSCommandGetStatusLine() function handles both vcscommand result
buffers and VCS-managed files if vcscommand buffer management is enabled
(please see |vcscommand-buffer-management|).
5.5 vcscommand buffer management *vcscommand-buffer-management*
The vcscommand plugin can operate in buffer management mode, which means that
it attempts to set a buffer variable ('VCSCommandBufferInfo') upon entry into
a buffer. This is rather slow because it means that the VCS will be invoked
at each entry into a buffer (during the |BufEnter| autocommand).
This mode is disabled by default. In order to enable it, set the
|VCSCommandEnableBufferSetup| variable to a true (non-zero) value. Enabling
this mode simply provides the buffer variable mentioned above. The user must
explicitly include information from the variable in the |'statusline'| option
if they are to appear in the status line (but see |vcscommand-statusline| for
a simple way to do that).
The 'VCSCommandBufferInfo' variable is a list which contains, in order, the
revision of the current file, the latest revision of the file in the
repository, and (for CVS) the name of the branch. If those values cannot be
determined, the list is a single element: 'Unknown'.
==============================================================================
6. SSH "integration" *vcscommand-ssh*
The following instructions are intended for use in integrating the
vcscommand.vim plugin with an SSH-based CVS environment.
Familiarity with SSH and CVS are assumed.
These instructions assume that the intent is to have a message box pop up in
order to allow the user to enter a passphrase. If, instead, the user is
comfortable using certificate-based authentication, then only instructions
6.1.1 and 6.1.2 (and optionally 6.1.4) need to be followed; ssh should then
work transparently.
6.1 Environment settings *vcscommand-ssh-env*
6.1.1 CVSROOT should be set to something like:
:ext:user@host:/path_to_repository
6.1.2 CVS_RSH should be set to:
ssh
Together, those settings tell CVS to use ssh as the transport when
performing CVS calls.
6.1.3 SSH_ASKPASS should be set to the password-dialog program. In my case,
running gnome, it's set to:
/usr/libexec/openssh/gnome-ssh-askpass
This tells SSH how to get passwords if no input is available.
6.1.4 OPTIONAL. You may need to set SSH_SERVER to the location of the cvs
executable on the remote (server) machine.
6.2 CVS wrapper program *vcscommand-ssh-wrapper*
Now you need to convince SSH to use the password-dialog program. This means
you need to execute SSH (and therefore CVS) without standard input. The
following script is a simple perl wrapper that dissasociates the CVS command
from the current terminal. Specific steps to do this may vary from system to
system; the following example works for me on linux.
#!/usr/bin/perl -w
use strict;
use POSIX qw(setsid);
open STDIN, '/dev/null';
fork and do {wait; exit;};
setsid;
exec('cvs', @ARGV);
6.3 Configuring vcscommand.vim *vcscommand-ssh-config*
At this point, you should be able to use your wrapper script to invoke CVS with
various commands, and get the password dialog. All that's left is to make CVS
use your newly-created wrapper script.
6.3.1 Tell vcscommand.vim what CVS executable to use. The easiest way to do this
is globally, by putting the following in your .vimrc:
let VCSCommandCVSExec=/path/to/cvs/wrapper/script
6.4 Where to go from here *vcscommand-ssh-other*
The script given above works even when non-SSH CVS connections are used,
except possibly when interactively entering the message for CVS commit log
(depending on the editor you use... VIM works fine). Since the vcscommand.vim
plugin handles that message without a terminal, the wrapper script can be used
all the time.
This allows mixed-mode operation, where some work is done with SSH-based CVS
repositories, and others with pserver or local access.
It is possible, though beyond the scope of the plugin, to dynamically set the
CVS executable based on the CVSROOT for the file being edited. The user
events provided (such as VCSBufferCreated and VCSBufferSetup) can be used to
set a buffer-local value (b:VCSCommandCVSExec) to override the CVS executable
on a file-by-file basis. Alternatively, much the same can be done (less
automatically) by the various project-oriented plugins out there.
It is highly recommended for ease-of-use that certificates with no passphrase
or ssh-agent are employed so that the user is not given the password prompt
too often.
==============================================================================
7. Changes from cvscommandi *cvscommand-changes*
1. Require Vim 7 in order to leverage several convenient features; also
because I wanted to play with Vim 7.
2. Renamed commands to start with 'VCS' instead of 'CVS'. The exceptions are
the 'CVSEdit' and 'CVSWatch' family of commands, which are specific to CVS.
3. Renamed options, events to start with 'VCSCommand'.
4. Removed option to jump to the parent version of the current line in an
annotated buffer, as opposed to the version on the current line. This made
little sense in the branching scheme used by subversion, where jumping to a
parent branch required finding a different location in the repository. It
didn't work consistently in CVS anyway.
5. Removed option to have nameless scratch buffers.
6. Changed default behavior of scratch buffers to split the window instead of
displaying in the current window. This may still be overridden using the
'VCSCommandEdit' option.
7. Split plugin into multiple plugins.
8. Added 'VCSLock' and 'VCSUnlock' commands. These are implemented for
subversion but not for CVS. These were not kept specific to subversion as they
seemed more general in nature and more likely to be supported by any future VCS
supported by this plugin.
9. Changed name of buffer variables set by commands.
'b:cvsOrigBuffNR' became 'b:VCSCommandOriginalBuffer'
'b:cvscmd' became 'b:VCSCommandCommand'
10. Added new automatic variables to command result buffers.
'b:VCSCommandSourceFile'
'b:VCSCommandVCSType'
==============================================================================
8. Known bugs *vcscommand-bugs*
Please let me know if you run across any.
CVSUnedit may, if a file is changed from the repository, provide prompt text
to determine whether the changes should be thrown away. Currently, that text
shows up in the CVS result buffer as information; there is no way for the user
to actually respond to the prompt and the CVS unedit command does nothing. If
this really bothers anyone, please let me know.
VCSVimDiff, when using the original (real) source buffer as one of the diff
buffers, uses some hacks to try to restore the state of the original buffer
when the scratch buffer containing the other version is destroyed. There may
still be bugs in here, depending on many configuration details.
vim:tw=78:ts=8:ft=help

70
.vim/ftplugin/git.vim Normal file
View File

@ -0,0 +1,70 @@
"=============================================================================
" Copyright: Copyright © Pierre Habouzit
" Permission is hereby granted to use and distribute this code,
" with or without modifications, provided that this copyright
" notice is copied with it. Like anything else that's free,
" bufexplorer.vim is provided *as is* and comes with no
" warranty of any kind, either expressed or implied. In no
" event will the copyright holder be liable for any damages
" resulting from the use of this software.
" Description: git-commit(1) helper
" Maintainer: Pierre Habouzit <madcoder@debian.org>
" Last Changed: Mon, 26 Nov 2007 10:06:15 +0100
" Usage: This file should live in your ftplugin directory.
"
" The configurations variables are:
"
" g:git_diff_opts - options to add to git diff,
" (default "-C -C")
" g:git_diff_spawn_mode - use auto-split on commit ?
" * 1 == hsplit
" * 2 == vsplit
" * none else (default)
"
" The default keymaping is:
"
" <Leader>gd - view the diff in a hsplit
" <Leader>ghd - view the diff in a hsplit
" <Leader>gvd - view the diff in a vsplit
"========================================================================={{{=
if exists("b:did_ftplugin") | finish | endif
let b:did_ftplugin = 1
setlocal tw=74
setlocal nowarn nowb
function! Git_diff_windows(vertsplit, auto, opts)
if a:vertsplit
rightbelow vnew
else
rightbelow new
endif
silent! setlocal ft=diff previewwindow bufhidden=delete nobackup noswf nobuflisted nowrap buftype=nofile
exe "normal :r!LANG=C git diff --stat -p --cached ".a:opts."\no\<esc>1GddO\<esc>"
setlocal nomodifiable
noremap <buffer> q :bw<cr>
if a:auto
redraw!
wincmd p
redraw!
endif
endfunction
noremap <buffer> <Leader>gd :call Git_diff_windows(0, 0, g:git_diff_opts)<cr>
noremap <buffer> <Leader>ghd :call Git_diff_windows(0, 0, g:git_diff_opts)<cr>
noremap <buffer> <Leader>gvd :call Git_diff_windows(1, 0, g:git_diff_opts)<cr>
if !exists("g:git_diff_opts")
let g:git_diff_opts = "-C -C"
endif
if exists("g:git_diff_spawn_mode")
if g:git_diff_spawn_mode == 1
call Git_diff_windows(0, 1, g:git_diff_opts)
elseif g:git_diff_spawn_mode == 2
call Git_diff_windows(1, 1, g:git_diff_opts)
endif
endif
" }}}

57
.vim/ftplugin/svn.vim Normal file
View File

@ -0,0 +1,57 @@
" made by Michael Scherer ( misc@mandrake.org )
" $Id: svn.vim 282 2005-01-31 21:24:55Z misc $
"
" 2004-09-13 : Lukas Ruf ( lukas.ruf@lpr.ch )
" - re-ordered windows
" - set focus on svn-commit.tmp (that's where one has to write)
" - set buffer type of new window to 'nofile' to fix 'TODO'
"
" 2005-01-31 :
" - autoclose on exit, thanks to Gintautas Miliauskas ( gintas@akl.lt )
" and tips from Marius Gedminas ( mgedmin@b4net.lt )
"
" 2005-02-08 :
" - rewrite in pure vim function, from Kyosuke Takayama ( support@mc.neweb.ne.jp )
" - simplified installation instruction, from Marius Gedminas ( mgedmin@b4net.lt )
"
" 2005-02-11 :
" - reindent with space, asked by Marius Gedminas ( mgedmin@b4net.lt )
" - do not preview if no file are diffed, patch from Marius Gedminas.
"
" to use it, place it in ~/.vim/ftplugins
function! Svn_diff_windows()
let i = 0
let list_of_files = ''
while i <= line('$')
let line = getline(i)
if line =~ '^M'
let file = substitute(line, '\v^MM?\s*(.*)\s*$', '\1', '')
let list_of_files = list_of_files . ' '.file
endif
let i = i + 1
endwhile
if list_of_files == ""
return
endif
new
silent! setlocal ft=diff previewwindow bufhidden=delete nobackup noswf nobuflisted nowrap buftype=nofile
exe 'normal :r!LANG=C svn diff ' . list_of_files . "\n"
setlocal nomodifiable
goto 1
redraw!
wincmd R
wincmd p
goto 1
redraw!
endfunction
set nowarn
set nosplitbelow
call Svn_diff_windows()
set nowb

2913
.vim/plugin/NERD_tree.vim Normal file

File diff suppressed because it is too large Load Diff

1293
.vim/plugin/project.vim Normal file

File diff suppressed because it is too large Load Diff

1255
.vim/plugin/vcscommand.vim Normal file

File diff suppressed because it is too large Load Diff

437
.vim/plugin/vcscvs.vim Normal file
View File

@ -0,0 +1,437 @@
" 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 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
return VCSCommandDoCommand(fullCmd, a:cmdName, a:statusText, a:options)
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
" 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', 'ce'],
\['CVSEditors', 'CVSEditors', 'cE'],
\['CVSUnedit', 'CVSUnedit', 'ct'],
\['CVSWatchers', 'CVSWatchers', 'cwv'],
\['CVSWatchAdd', 'CVSWatch add', 'cwa'],
\['CVSWatchOff', 'CVSWatch off', 'cwf'],
\['CVSWatchOn', 'CVSWatch on', 'cwn'],
\['CVSWatchRemove', 'CVSWatch remove', 'cwr']
\]
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
silent! aunmenu Plugin.VCS.CVS
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

254
.vim/plugin/vcsgit.vim Executable file
View File

@ -0,0 +1,254 @@
" 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 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
" Section: Plugin Registration {{{1
call VCSCommandRegisterModule('git', expand('<sfile>'), s:gitFunctions, [])
let &cpo = s:save_cpo

258
.vim/plugin/vcssvk.vim Normal file
View File

@ -0,0 +1,258 @@
" 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 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

284
.vim/plugin/vcssvn.vim Normal file
View File

@ -0,0 +1,284 @@
" 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 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' . 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 -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'] + 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'] + 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 -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'] + a:argList, ' '), 'info', join(a:argList, ' '), {})
endfunction
" Function: s:svnFunctions.Lock(argList) {{{2
function! s:svnFunctions.Lock(argList)
return s:DoCommand(join(['lock'] + a:argList, ' '), 'lock', join(a:argList, ' '), {})
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', '-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' . 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'] + options, ' '), 'status', join(options, ' '), {})
endfunction
" Function: s:svnFunctions.Unlock(argList) {{{2
function! s:svnFunctions.Unlock(argList)
return s:DoCommand(join(['unlock'] + a:argList, ' '), 'unlock', join(a:argList, ' '), {})
endfunction
" Function: s:svnFunctions.Update(argList) {{{2
function! s:svnFunctions.Update(argList)
return s:DoCommand('update', 'update', '', {})
endfunction
" Section: Plugin Registration {{{1
call VCSCommandRegisterModule('SVN', expand('<sfile>'), s:svnFunctions, [])
let &cpo = s:save_cpo

View File

@ -0,0 +1,45 @@
" Vim syntax file
" Language: CVS annotate output
" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
" Remark: Used by the cvscommand plugin. Originally written by Mathieu
" Clabaut
" License:
" Copyright (c) 2007 Bob Hiestand
"
" Permission is hereby granted, free of charge, to any person obtaining a copy
" of this software and associated documentation files (the "Software"), to
" deal in the Software without restriction, including without limitation the
" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
" sell copies of the Software, and to permit persons to whom the Software is
" furnished to do so, subject to the following conditions:
"
" The above copyright notice and this permission notice shall be included in
" all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
" IN THE SOFTWARE.
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
syn match cvsDate /\d\d-...-\d\d/ contained
syn match cvsName /(\S* /hs=s+1,he=e-1 contained nextgroup=cvsDate
syn match cvsVer /^\d\+\(\.\d\+\)\+/ contained nextgroup=cvsName
syn region cvsHead start="^\d\+\.\d\+" end="):" contains=cvsVer,cvsName,cvsDate
if !exists("did_cvsannotate_syntax_inits")
let did_cvsannotate_syntax_inits = 1
hi link cvsDate Comment
hi link cvsName Type
hi link cvsVer Statement
endif
let b:current_syntax="CVSAnnotate"

View File

@ -0,0 +1,42 @@
" Vim syntax file
" Language: SVK annotate output
" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
" Remark: Used by the vcscommand plugin.
" License:
" Copyright (c) 2007 Bob Hiestand
"
" Permission is hereby granted, free of charge, to any person obtaining a copy
" of this software and associated documentation files (the "Software"), to
" deal in the Software without restriction, including without limitation the
" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
" sell copies of the Software, and to permit persons to whom the Software is
" furnished to do so, subject to the following conditions:
"
" The above copyright notice and this permission notice shall be included in
" all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
" IN THE SOFTWARE.
if exists("b:current_syntax")
finish
endif
syn match svkDate /\d\{4}-\d\{1,2}-\d\{1,2}/ skipwhite contained
syn match svkName /(\s*\zs\S\+/ contained nextgroup=svkDate skipwhite
syn match svkVer /^\s*\d\+/ contained nextgroup=svkName skipwhite
syn region svkHead start=/^/ end="):" contains=svkVer,svkName,svkDate oneline
if !exists("did_svkannotate_syntax_inits")
let did_svkannotate_syntax_inits = 1
hi link svkName Type
hi link svkDate Comment
hi link svkVer Statement
endif
let b:current_syntax="svkAnnotate"

View File

@ -0,0 +1,40 @@
" Vim syntax file
" Language: SVN annotate output
" Maintainer: Bob Hiestand <bob.hiestand@gmail.com>
" Remark: Used by the vcscommand plugin.
" License:
" Copyright (c) 2007 Bob Hiestand
"
" Permission is hereby granted, free of charge, to any person obtaining a copy
" of this software and associated documentation files (the "Software"), to
" deal in the Software without restriction, including without limitation the
" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
" sell copies of the Software, and to permit persons to whom the Software is
" furnished to do so, subject to the following conditions:
"
" The above copyright notice and this permission notice shall be included in
" all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
" IN THE SOFTWARE.
if exists("b:current_syntax")
finish
endif
syn match svnName /\S\+/ contained
syn match svnVer /^\s\+\zs\d\+/ contained nextgroup=svnName skipwhite
syn match svnHead /^\s\+\d\+\s\+\S\+/ contains=svnVer,svnName
if !exists("did_svnannotate_syntax_inits")
let did_svnannotate_syntax_inits = 1
hi link svnName Type
hi link svnVer Statement
endif
let b:current_syntax="svnAnnotate"

36
.vim/syntax/git.vim Normal file
View File

@ -0,0 +1,36 @@
" Vim syntax file
" Language: git commit message
" Quit when a (custom) syntax file was already loaded
if exists("b:current_syntax")
finish
endif
syn region gitSignedOff start=/^Signed-off-by:/ end=/$/ contains=gitAuthor,gitEmail
syn region gitAuthor contained start=/\s/ end=/$/
syn region gitLine start=/^#/ end=/$/
syn region gitCommit start=/^# Changes to be committed:$/ end=/^#$/ contains=gitHead,gitCommitFile
syn region gitHead contained start=/^# (.*)/ end=/^#$/
syn region gitChanged start=/^# Changed but not updated:/ end=/^#$/ contains=gitHead,gitChangedFile
syn region gitUntracked start=/^# Untracked files:/ end=/^#$/ contains=gitHead,gitUntrackedFile
syn match gitCommitFile contained /^#\t.*/hs=s+2
syn match gitChangedFile contained /^#\t.*/hs=s+2
syn match gitUntrackedFile contained /^#\t.*/hs=s+2
hi def link gitSignedOff Keyword
hi def link gitAuthor Normal
hi def link gitLine Comment
hi def link gitCommit Comment
hi def link gitChanged Comment
hi def link gitHead Comment
hi def link gitUntracked Comment
hi def link gitCommitFile Type
hi def link gitChangedFile Constant
hi def link gitUntrackedFile Constant
let b:current_syntax = "git"
" vim: ts=8 sw=2

31
.vim/syntax/vcscommit.vim Normal file
View File

@ -0,0 +1,31 @@
" Vim syntax file
" Language: VCS commit file
" Maintainer: Bob Hiestand (bob.hiestand@gmail.com)
" License:
" Copyright (c) 2007 Bob Hiestand
"
" Permission is hereby granted, free of charge, to any person obtaining a copy
" of this software and associated documentation files (the "Software"), to
" deal in the Software without restriction, including without limitation the
" rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
" sell copies of the Software, and to permit persons to whom the Software is
" furnished to do so, subject to the following conditions:
"
" The above copyright notice and this permission notice shall be included in
" all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
" IN THE SOFTWARE.
if exists("b:current_syntax")
finish
endif
syntax region vcsComment start="^VCS: " end="$"
highlight link vcsComment Comment
let b:current_syntax = "vcscommit"