diff --git a/.netrwhist b/.netrwhist new file mode 100644 index 0000000..1350802 --- /dev/null +++ b/.netrwhist @@ -0,0 +1,5 @@ +let g:netrw_dirhistmax =10 +let g:netrw_dirhist_cnt =3 +let g:netrw_dirhist_1='/home/whuang' +let g:netrw_dirhist_2='/home' +let g:netrw_dirhist_3='/' diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/after/ftplugin/c.vim b/after/ftplugin/c.vim new file mode 100644 index 0000000..66dfc5e --- /dev/null +++ b/after/ftplugin/c.vim @@ -0,0 +1,2 @@ +" OmniCppComplete initialization +call omni#cpp#complete#Init() diff --git a/after/ftplugin/cpp.vim b/after/ftplugin/cpp.vim new file mode 100644 index 0000000..66dfc5e --- /dev/null +++ b/after/ftplugin/cpp.vim @@ -0,0 +1,2 @@ +" OmniCppComplete initialization +call omni#cpp#complete#Init() diff --git a/autoload/omni/common/debug.vim b/autoload/omni/common/debug.vim new file mode 100644 index 0000000..eded649 --- /dev/null +++ b/autoload/omni/common/debug.vim @@ -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 diff --git a/autoload/omni/common/utils.vim b/autoload/omni/common/utils.vim new file mode 100644 index 0000000..c880ad2 --- /dev/null +++ b/autoload/omni/common/utils.vim @@ -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 diff --git a/autoload/omni/cpp/complete.vim b/autoload/omni/cpp/complete.vim new file mode 100644 index 0000000..a7e4edc --- /dev/null +++ b/autoload/omni/cpp/complete.vim @@ -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 omni#cpp#maycomplete#Complete() + inoremap . omni#cpp#maycomplete#Dot() + inoremap > omni#cpp#maycomplete#Arrow() + inoremap : 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 diff --git a/autoload/omni/cpp/includes.vim b/autoload/omni/cpp/includes.vim new file mode 100644 index 0000000..10a89bc --- /dev/null +++ b/autoload/omni/cpp/includes.vim @@ -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 + + diff --git a/autoload/omni/cpp/items.vim b/autoload/omni/cpp/items.vim new file mode 100644 index 0000000..b943ad4 --- /dev/null +++ b/autoload/omni/cpp/items.vim @@ -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(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 diff --git a/autoload/omni/cpp/maycomplete.vim b/autoload/omni/cpp/maycomplete.vim new file mode 100644 index 0000000..610526b --- /dev/null +++ b/autoload/omni/cpp/maycomplete.vim @@ -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 = "\\" + + " 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 .= "\" + 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 .= "\" + let szOmniMapping .= "\=pumvisible() ? \"\\\" : \"\"\" + 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 diff --git a/autoload/omni/cpp/namespaces.vim b/autoload/omni/cpp/namespaces.vim new file mode 100644 index 0000000..386b3f9 --- /dev/null +++ b/autoload/omni/cpp/namespaces.vim @@ -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 diff --git a/autoload/omni/cpp/settings.vim b/autoload/omni/cpp/settings.vim new file mode 100644 index 0000000..6683d3a --- /dev/null +++ b/autoload/omni/cpp/settings.vim @@ -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 diff --git a/autoload/omni/cpp/tokenizer.vim b/autoload/omni/cpp/tokenizer.vim new file mode 100644 index 0000000..16e0be2 --- /dev/null +++ b/autoload/omni/cpp/tokenizer.vim @@ -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 diff --git a/autoload/omni/cpp/utils.vim b/autoload/omni/cpp/utils.vim new file mode 100644 index 0000000..5d74d34 --- /dev/null +++ b/autoload/omni/cpp/utils.vim @@ -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 && startCmt0 + 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\=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 diff --git a/c-support/codesnippets/Makefile b/c-support/codesnippets/Makefile new file mode 100644 index 0000000..96bc7a0 --- /dev/null +++ b/c-support/codesnippets/Makefile @@ -0,0 +1,204 @@ +#=============================================================================== +# +# Filename: Makefile +# Description: +# +# Usage: make (generate executable ) +# make clean (remove objects, executable, prerequisits ) +# make tarball (generate compressed archive ) +# make zip (generate compressed archive ) +# +# Version: 1.0 +# Created: +# Revision: --- +# +# Author: +# Company: +# Email: +# +# Notes: This is a GNU make (gmake) makefile. +# C extension : c +# C++ extensions : cc cpp C +# C and C++ sources can be mixed. +# Prerequisites are generated automatically; makedepend is not +# needed (see documentation for GNU make Version 3.81, April 2006, +# section 4.13). The utility sed is used. +#========================================== makefile template version 1.9 ====== + +# DEBUG can be set to YES to include debugging info, or NO otherwise +DEBUG := YES + +# PROFILE can be set to YES to include profiling info, or NO otherwise +PROFILE := NO + +# ------------ name of the executable ---------------------------------------- +EXECUTABLE := main + +# ------------ list of all source files -------------------------------------- +SOURCES := main.c + +# ------------ compiler ------------------------------------------------------ +CC := gcc +CXX := g++ + +# ------------ compiler flags ------------------------------------------------ +DEBUG_CFLAGS := -Wall -ansi -pedantic -O0 -g +RELEASE_CFLAGS := -Wall -ansi -pedantic -O3 + +# ------------ linker flags -------------------------------------------------- +DEBUG_LDFLAGS := -g +RELEASE_LDFLAGS := + +ifeq (YES, ${DEBUG}) + CFLAGS := ${DEBUG_CFLAGS} + CXXFLAGS := ${DEBUG_CXXFLAGS} + LDFLAGS := ${DEBUG_LDFLAGS} +else + CFLAGS := ${RELEASE_CFLAGS} + CXXFLAGS := ${RELEASE_CXXFLAGS} + LDFLAGS := ${RELEASE_LDFLAGS} +endif + +ifeq (YES, ${PROFILE}) + CFLAGS := ${CFLAGS} -pg -O3 + CXXFLAGS := ${CXXFLAGS} -pg -O3 + LDFLAGS := ${LDFLAGS} -pg +endif + +# ------------ additional system include directories ------------------------- +GLOBAL_INC_DIR = + +# ------------ private include directories ----------------------------------- +LOCAL_INC_DIR = $(HOME)/include + +# ------------ system libraries (e.g. -lm ) --------------------------------- +SYS_LIBS = -lm + +# ------------ additional system library directories ------------------------- +GLOBAL_LIB_DIR = + +# ------------ additional system libraries ----------------------------------- +GLOBAL_LIBS = + +# ------------ private library directories ----------------------------------- +LOCAL_LIB_DIR = $(HOME)/lib + +# ------------ private libraries (e.g. libxyz.a ) --------------------------- +LOCAL_LIBS = + +# ------------ archive generation --------------------------------------------- +TARBALL_EXCLUDE = *.{o,gz,zip} +ZIP_EXCLUDE = *.{o,gz,zip} + +# ------------ run executable out of this Makefile (yes/no) ----------------- +# ------------ cmd line parameters for this executable ----------------------- +EXE_START = no +EXE_CMDLINE = + +#=============================================================================== +# The following statements usually need not to be changed +#=============================================================================== + +C_SOURCES = $(filter %.c, $(SOURCES)) +CPP_SOURCES = $(filter-out %.c, $(SOURCES)) +ALL_INC_DIR = $(addprefix -I, $(LOCAL_INC_DIR) $(GLOBAL_INC_DIR)) +ALL_LIB_DIR = $(addprefix -L, $(LOCAL_LIB_DIR) $(GLOBAL_LIB_DIR)) +GLOBAL_LIBSS = $(addprefix $(GLOBAL_LIB_DIR)/, $(GLOBAL_LIBS)) +LOCAL_LIBSS = $(addprefix $(LOCAL_LIB_DIR)/, $(LOCAL_LIBS)) +ALL_CFLAGS = $(CFLAGS) $(ALL_INC_DIR) +ALL_LFLAGS = $(LDFLAGS) $(ALL_LIB_DIR) +BASENAMES = $(basename $(SOURCES)) + +# ------------ generate the names of the object files ------------------------ +OBJECTS = $(addsuffix .o,$(BASENAMES)) + +# ------------ generate the names of the hidden prerequisite files ----------- +PREREQUISITES = $(addprefix .,$(addsuffix .d,$(BASENAMES))) + +# ------------ make the executable (the default goal) ------------------------ +$(EXECUTABLE): $(OBJECTS) +ifeq ($(strip $(CPP_SOURCES)),) + $(CC) $(ALL_LFLAGS) -o $(EXECUTABLE) $(OBJECTS) $(LOCAL_LIBSS) $(GLOBAL_LIBSS) $(SYS_LIBS) +else + $(CXX) $(ALL_LFLAGS) -o $(EXECUTABLE) $(OBJECTS) $(LOCAL_LIBSS) $(GLOBAL_LIBSS) $(SYS_LIBS) +endif +ifeq ($(EXE_START),yes) + ./$(EXECUTABLE) $(EXE_CMDLINE) +endif + +# ------------ include the automatically generated prerequisites ------------- +# ------------ if target is not clean, tarball or zip ------------- +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(MAKECMDGOALS),tarball) +ifneq ($(MAKECMDGOALS),zip) +-include $(PREREQUISITES) +endif +endif +endif + +# ------------ make the objects ---------------------------------------------- +%.o: %.c + $(CC) -c $(ALL_CFLAGS) $< + +%.o: %.cc + $(CXX) -c $(ALL_CFLAGS) $< + +%.o: %.cpp + $(CXX) -c $(ALL_CFLAGS) $< + +%.o: %.C + $(CXX) -c $(ALL_CFLAGS) $< + +# ------------ make the prerequisites ---------------------------------------- +# +.%.d: %.c + @$(make-prerequisite-c) + +.%.d: %.cc + @$(make-prerequisite-cplusplus) + +.%.d: %.cpp + @$(make-prerequisite-cplusplus) + +.%.d: %.C + @$(make-prerequisite-cplusplus) + +# canned command sequences +# echoing of the sed command is suppressed by the leading @ + +define make-prerequisite-c + @$(CC) -MM $(ALL_CFLAGS) $< > $@.$$$$; \ + sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' < $@.$$$$ > $@; \ + rm -f $@.$$$$; +endef + +define make-prerequisite-cplusplus + @$(CXX) -MM $(ALL_CFLAGS) $< > $@.$$$$; \ + sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' < $@.$$$$ > $@; \ + rm -f $@.$$$$; +endef + +# ------------ remove generated files ---------------------------------------- +# ------------ remove hidden backup files ------------------------------------ +clean: + -rm --force $(EXECUTABLE) $(OBJECTS) $(PREREQUISITES) *~ + +# ------------ tarball generation ---------------------------------------------- +tarball: + @lokaldir=`pwd`; lokaldir=$${lokaldir##*/}; \ + rm --force $$lokaldir.tar.gz; \ + tar --exclude=$(TARBALL_EXCLUDE) \ + --create \ + --gzip \ + --verbose \ + --file $$lokaldir.tar.gz * + +# ------------ zip ------------------------------------------------------------- +zip: + @lokaldir=`pwd`; lokaldir=$${lokaldir##*/}; \ + zip -r $$lokaldir.zip * -x $(ZIP_EXCLUDE) + +.PHONY: clean tarball zip + +# ============================================================================== +# vim: set tabstop=2: set shiftwidth=2: diff --git a/c-support/codesnippets/Makefile.multi-target.template b/c-support/codesnippets/Makefile.multi-target.template new file mode 100644 index 0000000..75da8dd --- /dev/null +++ b/c-support/codesnippets/Makefile.multi-target.template @@ -0,0 +1,70 @@ +#=============================================================================== +# +# File: Makefile +# Description: +# +# Usage: make (generate executable(s) ) +# make clean (remove objects, executables, prerequisits ) +# make tarball (generate compressed archive ) +# make zip (generate compressed archive ) +# +# Author: Dr.-Ing. Fritz Mehner +# Email: mehner@mfh-iserlohn.de +# Created: +# +#=============================================================================== + + +CC = gcc +CCP = g++ +CFLAGS = -c -g -Wall +LFLAGS = -g +SYS_LIBS = -lm +TARBALL_EXCLUDE = "*.{o,gz,zip}" +ZIP_EXCLUDE = *.o *.gz *.zip + +TARGETS = target_1 target_2 + +#---------- targets -------------------------------------- +all: $(TARGETS) + +%.o: %.c + $(CC) $(CFLAGS) $*.c + +%.o: %.cc + $(CCP) $(CFLAGS) $*.cc + +#---------- target 1 ------------------------------------- +# C target +target_1: target_1.o + $(CC) $(LFLAGS) -o $@ $@.o $(SYS_LIBS) + +#---------- target 2 ------------------------------------- +# C++ target +target_2: target_2.o + $(CCP) $(LFLAGS) -o $@ $@.o $(SYS_LIBS) + + +#---------- target 3 ------------------------------------- + + + +#---------- tarball -------------------------------------- +tarball: + lokaldir=`pwd`; lokaldir=$${lokaldir##*/}; \ + rm --force $$lokaldir.tar.gz; \ + tar --exclude=$(TARBALL_EXCLUDE) \ + --create \ + --gzip \ + --verbose \ + --file $$lokaldir.tar.gz * + +#---------- zip ------------------------------------------ +zip: + lokaldir=`pwd`; lokaldir=$${lokaldir##*/}; \ + zip -r $$lokaldir.zip * -x $(ZIP_EXCLUDE) + +#---------- clear up ------------------------------------- +clean: + rm --force $(EXECUTABLE) $(OBJECTS) $(PREREQUISITES) + diff --git a/c-support/codesnippets/calloc_double_matrix.c b/c-support/codesnippets/calloc_double_matrix.c new file mode 100644 index 0000000..bfa263a --- /dev/null +++ b/c-support/codesnippets/calloc_double_matrix.c @@ -0,0 +1,36 @@ + +/* + * === FUNCTION ====================================================================== + * Name: calloc_double_matrix + * Description: Allocate a dynamic double-matrix of size rows*columns; + * return a pointer. + * ===================================================================================== + */ + double** +calloc_double_matrix ( int rows, int columns ) +{ + int i; + double **m; + m = calloc ( rows, sizeof(double*) ); /* allocate pointer array */ + assert( m != NULL ); /* abort if allocation failed */ + *m = calloc ( rows*columns, sizeof(double) );/* allocate data array */ + assert(*m != NULL ); /* abort if allocation failed */ + for ( i=1; i +#include +#include +#include +#include + +/* + * === FUNCTION ====================================================================== + * Name: main + * Description: main function + * ===================================================================================== + */ + int +main ( int argc, char *argv[] ) +{ + printf ("\nProgram %s\n\n", argv[0] ); + + return EXIT_SUCCESS; +} /* ---------- end of function main ---------- */ + diff --git a/c-support/codesnippets/main.cc b/c-support/codesnippets/main.cc new file mode 100644 index 0000000..8c58cc0 --- /dev/null +++ b/c-support/codesnippets/main.cc @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +using namespace std; + +// === FUNCTION ====================================================================== +// Name: main +// Description: main function +// ===================================================================================== + int +main ( int argc, char *argv[] ) +{ + cout << "\nProgram " << argv[0] << endl << endl; + + return EXIT_SUCCESS; +} // ---------- end of function main ---------- + diff --git a/c-support/codesnippets/print_array.cc.noindent b/c-support/codesnippets/print_array.cc.noindent new file mode 100644 index 0000000..f0c6389 --- /dev/null +++ b/c-support/codesnippets/print_array.cc.noindent @@ -0,0 +1,28 @@ +// === FUNCTION ====================================================================== +// Name: print_array +// Description: Print an array with one dimension. +// Use +// print_array( *matrix, n1*n2, n2, "matrix" ); +// for +// T matrix[n1][n2]; +// ===================================================================================== + template < class T, unsigned width, unsigned precision > +void print_array ( T *array, // array to print + int n, // number of elements to print + int nrow, // number of elements per row + string arrayname // array name + ) +{ + string line(" index | content\n ------+-"); + + cout << "\n\n array \"" << arrayname << "\", length " << n << endl << endl; + cout << line.append(width*nrow, '-'); + for ( int i=0; i \rma , \ri -> \rpa , \re -> \rka (better to remember). +- 'long long' added to the for-idioms. +- Bugfixes: for-idiom shows type as variable name if no variable name was given. +- Bugfixes: for-idiom inserts standard types with 2+ words wrong. +- Bugfixes: multiline end-of-line comments have wrong position in some cases. +- Bugfixes: local installation looks like a system-wide installation in seldom cases. + +================================================================================ + RELEASE NOTES FOR VERSION 5.10 +================================================================================ +- The plugin now handles different template styles without editing and + reloading the main template file. +- The number of template styles is not limited. +- New hotkey and ex-command to switch template styles. +- Template styles can automatically be related to file extensions. +- indent(1) errors will be presented in a quickfix error window. +- Comment alignment improved. +- Minor improvements. + +================================================================================ + RELEASE NOTES FOR VERSION 5.9 +================================================================================ ++ Two additional hotkeys (+ ex commands) for preprocessor statements. ++ Compile-link-run: improved error detection. ++ Menu Run: hardcopy can print any buffer. ++ Several minor improvements and bugfixes. + +================================================================================ + RELEASE NOTES FOR VERSION 5.8 +================================================================================ ++ Hotkeys are shown in the menus. ++ File browser for code snippets and templates choosable (2 global variables). ++ Two new hotkeys: include file description (implementation, header). ++ New menu item: namespace alias ++ Bugfix: wrapper script for use of a xterm could not handle parameters containing blanks. ++ Several minor improvements. + +================================================================================ + RELEASE NOTES FOR VERSION 5.7 +================================================================================ ++ 4 new hotkeys : insert file section comments (C/C++/H), special comments, + keyword comments. ++ Adjusting end-of-line comment adjustment improved. + +================================================================================ + RELEASE NOTES FOR VERSION 5.6 +================================================================================ ++ Jump targets (templates) and mapping Ctrl-j can be switched off. ++ Yet unused jump targets will be highlighted after a file is opened. ++ Statements menu: else block (key mapping \se). ++ Handling of improved (templates). ++ Minor improvements. + +================================================================================ + RELEASE NOTES FOR VERSION 5.5 +================================================================================ ++ Additional plugin-tags (jump targets in templates): <+text+>, <-text->. ++ Additional mapping Ctrl-j : jump to these new targets. ++ Template-file: additional macro |STYLE| and IF-ENDIF-construct to easily + choose between sets of templates. ++ Additional mapping: auto-complete classical C comment (also multi-line). ++ Additional mapping: auto-complete open block starting with { . ++ Visual mode for date and time insertion (menu 'Comments'). ++ Visual mode for tags (submenu 'Comments->tags (plugin)'). ++ Bugfix: hotkey \ica not working ++ Bugfix: hotkey Shift-F2 for the alternate-plugin disappeared. + +======================================================================================= + RELEASE NOTES FOR VERSION 5.4 +======================================================================================= ++ New hotkey \+co inserts ' cout << << endl;' ++ New menu item C++-menu: 'cout' replaces 'cout variable' and 'cout string'. ++ Hotkey \c/ removed ( \cc does the same). ++ Bugfix: after an unsuccessful compilation screen sometimes garbled. + +======================================================================================= + RELEASE NOTES FOR VERSION 5.3 +======================================================================================= ++ Insertions work properly when folding is used. ++ Menu items Idioms->for(...) : type declaration for loop variable possible (tab completion). ++ Specification of command line arguments (Run->cmd. line arg.): filename completion active. ++ New main menu item 'show manual' (hotkey \hm): read manual for word under cursor. ++ One hotkey renamed: \h -> \hp (help plugin) + +======================================================================================= + RELEASE NOTES FOR VERSION 5.2.1 +======================================================================================= ++ Bugfix: stray characters whith three dialogs ++ Bugfix: Missing parameter in 2 internal function calls ++ Menu items 'Snippets->edit local/global templates' start an file browser (convenience). + +======================================================================================= + RELEASE NOTES FOR VERSION 5.2 +======================================================================================= ++ Superfluous control characters for mode switching (menus, hotkeys) removed. Caused beeps. ++ Template files (local/global) can be opened from the snippet menu. ++ Three new preprocessor statements. ++ v-mode for RTTI-entries. + +======================================================================================= + RELEASE NOTES FOR VERSION 5.1 +======================================================================================= ++ Definition and implementation of classes have now different templates and menu entries. ++ Accessor methods (get/set) can be generated. ++ New templates: everything other than language keywords comes from a template + (and is user changeable). + +======================================================================================= + RELEASE NOTES FOR VERSION 5.0.5 +======================================================================================= ++ Bugfix: on a few systems doubling of path components in the run command (F9). + Skip this upgrade if you do not have this problem. + +======================================================================================= + RELEASE NOTES FOR VERSION 5.0.4 +======================================================================================= ++ Format for the macros |DATE|, |TIME|, and |YEAR| can be defined by the user. ++ Help text improved. + +======================================================================================= + RELEASE NOTES FOR VERSION 5.0.3 +======================================================================================= ++ Code snippets can now be used in the console mode (Vim without GUI). ++ Bugfix: Possible conflict with 'indent' removed when inserting templates. + +======================================================================================= + RELEASE NOTES FOR VERSION 5.0.2 +======================================================================================= ++ Bugfix: Prototype picker did not alway delete no longer used prototypes. ++ Bugfix: Prototype picker removed template specializations from parameter lists. + +======================================================================================= + RELEASE NOTES FOR VERSION 5.0.1 +======================================================================================= ++ Bugfix: autocmd setting can influence autocmd settings of OTHER plugins. + +======================================================================================= + RELEASE NOTES FOR VERSION 5.0 +======================================================================================= ++ Completely new template system. Now every menu item is user definable. ++ Changes to allow a system-wide installation. ++ A few hotkeys added and renamed. + +======================================================================================= + RELEASE NOTES FOR VERSION 4.6.1 +======================================================================================= ++ New global variable to control the filetype of *.h header files (default is now 'cpp'). ++ Bugfix: properly resetting 'compiler' after using make, splint, and CodeCheck. + +======================================================================================= + RELEASE NOTES FOR VERSION 4.6 +======================================================================================= ++ New insert mode mappings (comments, statements, preprocessing, idioms, C++). ++ Some mappings renamed (easier to remember). ++ New tag (basename of a file reduced to characters allowed in names). + +======================================================================================= + RELEASE NOTES FOR VERSION 4.5 +======================================================================================= ++ New menu item and hotkey for the (re)alignement of end-of-line comments. ++ Hotkey \cn removed. Only one menu item for end-of-line comments left. ++ Changed hotkeys: \ce -> \cl and \cl -> \cs . ++ Three new tags (giving the basename of a file) for writing template files. ++ Prototype picker handles template methods. ++ Bugfix: splint works now under Windows. ++ Minor improvements. + +======================================================================================= + RELEASE NOTES FOR VERSION 4.4 +======================================================================================= ++ Plugin directories rearranged. ++ main- and for-idiom have a visual mode now. ++ Four new commands (command line) to control the comment style. ++ Comment style (C/C++) can automatically follow the filetype. ++ Bugfix: empty new file after removing the header template can't be closed. ++ Bugfix : Tools entry missing when root menu not shown from the start. ++ Minor improvements. + +======================================================================================= + RELEASE NOTES FOR VERSION 4.3 +======================================================================================= ++ CodeCheck (TM) integrated (source code analysing tool). ++ New key mappings for preprocessor statements. ++ New preprocessor menu. ++ Bugfix: indent under Windows. ++ Minor improvements. + +======================================================================================= + RELEASE NOTES FOR VERSION 4.2.1 +======================================================================================= ++ Bugfix: change needed for some menu names after patch 7.0.054 . + +======================================================================================= + RELEASE NOTES FOR VERSION 4.2 +======================================================================================= ++ Setting the starting column for trailing comments improved. ++ Small bug in block uncommenting fixed. ++ Mac OS X : circumvent a Vim bug which caused a crash when loading plugin version 4.1. ++ File syntax/c.vim removed (but see help in csupport.txt). + +======================================================================================= + RELEASE NOTES FOR VERSION 4.1 +======================================================================================= ++ A complete switch statement can be made from a list of labels. ++ Additional cases can be made from a list of labels. ++ Small bug in line end commenting fixed. ++ Some minor improvements. + +======================================================================================= + RELEASE NOTES FOR VERSION 4.0 +======================================================================================= + ++ Kernighan & Ritchie style for block statements can be enabled. ++ Changes to make it compatible with Vim 7. ++ Set C/C++ file type for source files which should not be preprocessed (*.i, *.ii). ++ Some minor improvements. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.11 +======================================================================================= + ++ Hotkeys and an accompanying reference card added. ++ Preparation for syntax based folding. ++ Some minor improvements. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.10 +======================================================================================= + ++ Remove "#if 0 ... #endif" from the inside. ++ Change C comments to C++ comments and vice versa. ++ try..catch / catch / catch(...) now can be set surround a marked area. ++ Prototype picking improved (for C++). ++ A hardcopy shows the localized date and time in the header line. ++ New help menu entry in the main menu of this plugin (shows the plugin documentation). ++ Switch between corresponding source and header files with if the plugin a.vim + is present. ++ Plugin can be used with autocompletion for (, [, and { . + +======================================================================================= + RELEASE NOTES FOR VERSION 3.9.1 +======================================================================================= + ++ Doubling of file header for new c- and h-files under Windows fixed (Thanks to + Fabricio C A Oliveira). ++ Tiny bug in the file open idioms fixed. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.9 +======================================================================================= + ++ Formatter 'indent' integrated. ++ Bugfix in the automatic header insertion. ++ Assert idiom added. ++ #if 0 ... #endif statement for blocking out code added. ++ Minor stylistic improvements in some idioms. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.8.2 +======================================================================================= + ++ Screen update problem solved: color inversion under FC4 (Thanks to Bernie Barton). ++ RTTI menu : additional v-mode. ++ Statement menu and C++ menu rearranged. ++ Include guard : name generation improved. ++ File header templates will be included for additional file extensions (cp, cxx, c++, ...). + +======================================================================================= + RELEASE NOTES FOR VERSION 3.8.1 +======================================================================================= + ++ More C++ output manipulators, manipulator insertion more intuitive. ++ Output into buffer: cursor goes to top of file. ++ Makefile template improved (code snippet). ++ Some internal improvements. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.8 +======================================================================================= + ++ Windows support. Most features are now available under Windows. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.7.2 +======================================================================================= + ++ Run buffer through splint (A tool for statically checking C programs; see + http://www.splint.org). An error window will be opened; quickfix commands can be used. ++ Set buffer related command line arguments for splint. ++ Line end comments start in a fixed column (can be set from the menu). ++ Spaces in path names and file names are now possible. ++ Template files and snippet files are no longer kept in the list of alternate files. ++ Some minor improvements. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.7.1 +======================================================================================= + ++ Bug fixed (command line arguments not passed to the executable). ++ File extension for executables can be set. ++ Minor improvements. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.7 +======================================================================================= + ++ Running a program: + (1) Run program from the gVim command line. + (2) Run program and direct the output into a window with name "C-Output". + This buffer and its content will disappear when closing the window. + The buffer is reused when still open. + (3) Run program in an xterm (adjustable). ++ Command line arguments are now buffer related (each buffer can have its own arguments). ++ Code snippets can be protected from being indented during insertion. ++ Picked up prototypes will be deleted after insertion. ++ A code snippet with the file name extension "ni" or "noindent" will not be + indented on insertion. ++ for- and calloc-/malloc-idioms improved. ++ Bug fixed (word list handling). + + +======================================================================================= + RELEASE NOTES FOR VERSION 3.6 +======================================================================================= + ++ Installation simplified. ++ for-loop-idiom asks for control variable, initial value, ... ++ malloc-idiom asks for pointer variable and size. ++ Toggling the comment style works correct again. ++ Empty error windows will be closed. ++ Prototype picker removes trailing parts of the function body if marked. ++ The dialog windows (GUI) have been replaced by more flexible command line inputs. ++ The undocumented and unnecessary hot key F12 has been removed. ++ Extension to ctags + taglist shows makefile targets and qmake targets. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.5 +======================================================================================= + ++ Aligned line end comments for consecutive lines. ++ Improved prototype picker removes comments. ++ Picked up prototypes can be shown. ++ Uncomment more than one block at once. ++ 3 new idioms. ++ Help file improved . + +======================================================================================= + RELEASE NOTES FOR VERSION 3.4 +======================================================================================= + ++ Two new global variables: C_Dictionary_File, C_MenuHeader . ++ The preprocessor statements #if... and the function idiom include marked + lines when invoked in visual mode. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.3 +======================================================================================= + ++ The C/C++ root menu can be disabled. + +======================================================================================= + RELEASE NOTES FOR VERSION 3.2 +======================================================================================= + ++ Only one C/C++ entry in the gVim root menu. ++ All hotkeys are only defined for C/C++ files (file type plugin added). ++ The following constructs are now read as templates from files: + class, class using new, + template class, template class using new, + error class ++ Install script added. ++ Customization improved. ++ Documentation improved (help file added). ++ Bug fix (template file handling) + +======================================================================================= + RELEASE NOTES FOR VERSION 3.1 +======================================================================================= + ++ When the comment style "C" is active the menu entry "Comments.code->comment" + turns a marked region in one multiline C-comment. ++ The menu entry "Comments.comment->code" turns marked multiline C-comment + back into code. ++ A marked region can be surrounded by a for-, if, if-else, while-, do-while-statement + (with indentation). ++ The menu entry "Snippets.make prototype" makes a C- or C++-prototype from + the current line or marked region and puts it in an internal buffer. ++ The menu entry "Snippets.add prototype" also makes a C- or C++-prototype from + the current line or a marked region and adds it to the internal buffer. ++ The menu entry "Snippets.put prototype" inserts all gathered prototypes + below the current line. ++ Tag substitution rewritten (Some characters in a substitution text for a tag + prevented the tag from being substituted). + +======================================================================================= + RELEASE NOTES FOR VERSION 3.0 +======================================================================================= + ++ C-style comments AND C++-style comments are supported now. ++ The menu entry 'Comments->Comment style ..' switches the styles (toggle). ++ Block comments are now read as templates or skeletons from files: + Frame Block, Function Description, Method Description, + Class Description, H+file header, C/C++-file header ++ These templates can contain tags like |FILENAME|, |AUTHOR| etc. which are replaced + after reading (KDevelop templates can be used without any change). ++ indentation: multiline inserts and code snippets will be indented after insertion. ++ Most menu entries are now also active in normal mode. ++ new menu items: + includes for the C99 header, + includes for the standard C++ header, + includes for the C++ version of the Standard C Library header, + multiline C comment + vim modeline ++ Reading the templates is done in one function which can be called in an autocmd. ++ Code cleanup: register z no longer used. Most function calls are silent now. + + diff --git a/c-support/doc/c-hotkeys.pdf b/c-support/doc/c-hotkeys.pdf new file mode 100644 index 0000000..bd22af1 Binary files /dev/null and b/c-support/doc/c-hotkeys.pdf differ diff --git a/c-support/doc/c-hotkeys.tex b/c-support/doc/c-hotkeys.tex new file mode 100644 index 0000000..b223594 --- /dev/null +++ b/c-support/doc/c-hotkeys.tex @@ -0,0 +1,355 @@ +%%===================================================================================== +%% +%% File: c-hotkeys.tex +%% +%% Description: c-support.vim : Key mappings for Vim without GUI. +%% +%% +%% Author: Dr.-Ing. Fritz Mehner +%% Email: mehner@fh-swf.de +%% Copyright: Copyright (C) 2006-2010 Dr.-Ing. Fritz Mehner (mehner@fh-swf.de) +%% Version: 1.0 +%% Created: 10.11.2006 +%% Revision: $Id: c-hotkeys.tex,v 1.48 2011/12/27 21:09:44 mehner Exp $ +%% +%% Notes: +%% +%%===================================================================================== + +\documentclass[oneside,11pt,landscape,DIV17]{scrartcl} + +\usepackage[english]{babel} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{times} +\usepackage{lastpage} +\usepackage{multicol} +\usepackage{setspace} + +\setlength\parindent{0pt} + +\newcommand{\Pluginversion}{5.17} +\newcommand{\ReleaseDate}{ December 2011} +\newcommand{\Rep}{{\tiny{[n]}}} + +%%---------------------------------------------------------------------- +%% luximono : Type1-font +%% Makes keyword stand out by using semibold letters. +%%---------------------------------------------------------------------- +\usepackage[scaled]{luximono} + +%%---------------------------------------------------------------------- +%% fancyhdr +%%---------------------------------------------------------------------- +\usepackage{fancyhdr} +\pagestyle{fancyplain} +\fancyfoot[L]{\small \ReleaseDate} +\fancyfoot[C]{c-support.vim} +\fancyfoot[R]{\small \textbf{Page \thepage{} / \pageref{LastPage}}} +\renewcommand{\headrulewidth}{0.0pt} + +%%---------------------------------------------------------------------- +%% hyperref +%%---------------------------------------------------------------------- +\usepackage[ps2pdf]{hyperref} +\hypersetup{pdfauthor={Dr.-Ing. Fritz Mehner, FH Südwestfalen, Iserlohn, Germany}} +\hypersetup{pdfkeywords={Vim, C/C++}} +\hypersetup{pdfsubject={Vim-plugin, c-support.vim, hot keys}} +\hypersetup{pdftitle={Vim-plugin, c-support.vim, hot keys}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% START OF DOCUMENT +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{document}% + +\begin{multicols}{3} +% +%%====================================================================== +%% title +%%====================================================================== +\begin{center} +\textbf{\textsc{\small{Vim-Plugin}}}\\ +\textbf{\LARGE{c-support.vim}}\\ +\textbf{\textsc{\small{Version \Pluginversion}}}\\ +\textbf{\textsc{\Huge{Hot keys}}}\\ +Key mappings for Vim with and without GUI.\\ +Plugin: http://vim.sourceforge.net\\ +\vspace{3.0mm} +{\normalsize (i)} insert mode, {\normalsize (n)} normal mode, {\normalsize (v)} visual mode\\ +\vspace{5.0mm} +% +%%====================================================================== +%% SIDE 1 +%%====================================================================== +%%~~~~~ TABULAR : begin ~~~~~~~~~~ +\begin{tabular}[]{|p{10mm}|p{60mm}|} +% +\hline +\multicolumn{2}{|r|}{\textsl{\textbf{C}omments}} \\ +\hline \Rep\verb'\cl' & end-of-line comment \hfill (n,v,i)\\ +\hline \Rep\verb'\cj' & adjust end-of-line comment \hfill (n,v,i)\\ +\hline \verb'\cs' & set end-of-line comment column \hfill (n) \\ +\hline \Rep\verb'\c*' & code $\Rightarrow$ comment \verb'/* */' \hfill (n,v) \\ +\hline \Rep\verb'\cc' & code $\Rightarrow$ comment \verb'//' \hfill (n,v,o)\\ +\hline \Rep\verb'\co' & comment $\Rightarrow$ code \hfill (n,v,o)\\ + +\hline \verb'\cfr' & frame comment \hfill (n,i)\\ +\hline \verb'\cfu' & function comment \hfill (n,i)\\ +\hline \verb'\cme' & method description \hfill (n,i)\\ +\hline \verb'\ccl' & class description \hfill (n,i)\\ +\hline \verb'\cfdi'& file description (implementation) \hfill (n,i)\\ +\hline \verb'\cfdh'& file description (header) \hfill (n,i)\\ + +\hline \verb'\ccs'& C/C++--file sections\hspace{3mm}\footnotesize{(tab compl.)} \hfill \normalsize{(n,i)}\\ +\hline \verb'\chs'& H--file sections\hspace{10mm}\footnotesize{(tab compl.)} \hfill \normalsize{(n,i)}\\ +\hline \verb'\ckc'& keyword comment\hspace{5mm}\footnotesize{(tab compl.)} \hfill \normalsize{(n,i)}\\ +\hline \verb'\csc'& special comment\hspace{7,5mm}\footnotesize{(tab compl.)} \hfill \normalsize{(n,i)}\\ + +\hline \verb'\cd' & date \hfill (n,v,i)\\ +\hline \verb'\ct' & date \& time \hfill (n,v,i)\\ +\hline \Rep\verb'\cx' & toggle comments: C $\leftrightarrow$ C++ \hfill (n,v,i)\\ +\hline +\end{tabular}\\ +%%~~~~~ TABULAR : end ~~~~~~~~~~ +% +%%====================================================================== +%% table, middle part +%%====================================================================== +% +%%~~~~~ TABULAR : begin ~~~~~~~~~~ +\begin{tabular}[]{|p{15mm}|p{55mm}|} +%%---------------------------------------------------------------------- +%% menu statements +%%---------------------------------------------------------------------- +\hline +\multicolumn{2}{|r|}{\textsl{\textbf{S}tatements}} \\ +\hline \verb'\sd' & \verb'do { } while' \hfill (n,v,i)\\ +\hline \verb'\sf' & \verb'for' \hfill (n,i)\\ +\hline \verb'\sfo' & \verb'for { }' \hfill (n,v,i)\\ +\hline \verb'\si' & \verb'if' \hfill (n,i)\\ +\hline \verb'\sif' & \verb'if { }' \hfill (n,v,i)\\ +\hline \verb'\sie' & \verb'if else' \hfill (n,v,i)\\ +\hline \verb'\sife'& \verb'if { } else { }' \hfill (n,v,i)\\ +\hline \verb'\se' & \verb'else { }' \hfill (n,v,i)\\ +\hline \verb'\sw' & \verb'while' \hfill (n,i)\\ +\hline \verb'\swh' & \verb'while { }' \hfill (n,v,i)\\ +\hline \verb'\ss' & \verb'switch' \hfill (n,v,i)\\ +\hline \verb'\sc' & \verb'case' \hfill (n,i)\\ +\hline \verb'\s{ \sb' & \verb'{ }' \hfill (n,v,i)\\ +\hline +%%---------------------------------------------------------------------- +%% preprocessor menu +%%---------------------------------------------------------------------- +\hline +\multicolumn{2}{|r|}{\textsl{\textbf{P}reprocessor}} \\ +\hline \verb'\ps' & choose a Std. Lib. include \hfill (n,i)\\ +\hline \verb'\pc' & choose a C99 include \hfill (n,i)\\ +\hline \verb'\p<' & \verb$#include<...>$ \hfill (n,i)\\ +\hline \verb'\p"' & \verb$#include"..."$ \hfill (n,i)\\ +\hline \verb'\pd' & \verb'#define' \hfill (n,i)\\ +\hline \verb'\pu' & \verb'#undef' \hfill (n,i)\\ +\hline \verb'\pif' & \verb'#if #endif' \hfill (n,v,i)\\ +\hline \verb'\pie' & \verb'#if #else #endif' \hfill (n,v,i)\\ +\hline \verb'\pid' & \verb'#ifdef #else #endif' \hfill (n,v,i)\\ +\hline \verb'\pin' & \verb'#ifndef #else #endif' \hfill (n,v,i)\\ +\hline \verb'\pind' & \verb'#ifndef #def #endif' \hfill (n,v,i)\\ +\hline \verb'\pi0' & \verb'#if 0 #endif' \hfill (n,v,i)\\ +\hline \verb'\pr0' & remove \verb'#if 0 #endif' \hfill (n,i)\\ +\hline \verb'\pe' & \verb'#error ' \hfill (n,i)\\ +\hline \verb'\pl' & \verb'#line ' \hfill (n,i)\\ +\hline \verb'\pp' & \verb'#pragma' \hfill (n,i)\\ +\hline +\end{tabular} \\ +%%~~~~~ TABULAR : end ~~~~~~~~~~ + +%%====================================================================== +%% table, right part +%%====================================================================== +% +%%~~~~~ TABULAR : begin ~~~~~~~~~~ +\begin{tabular}[]{|p{11mm}|p{60mm}|} +%%---------------------------------------------------------------------- +%% snippet menu +%%---------------------------------------------------------------------- +\hline +\multicolumn{2}{|r|}{\textsl{S\textbf{n}ippet}} \\ +\hline \verb'\nr' & read code snippet \hfill (n,i)\\ +\hline \verb'\nw' & write code snippet \hfill (n,v,i)\\ +\hline \verb'\ne' & edit code snippet \hfill (n,i)\\ +\hline \Rep\verb'\nf' \Rep\verb'\np' & pick up function prototype \hfill (n,v,i)\\ +\hline \Rep\verb'\nm' & pick up method prototype \hfill (n,v,i)\\ +\hline \verb'\ni' & insert prototype(s) \hfill (n,i)\\ +\hline \verb'\nc' & clear prototype(s) \hfill (n,i)\\ +\hline \verb'\ns' & show prototype(s) \hfill (n,i)\\ +% +\hline \verb'\ntl' & edit local templates \hfill (n,i)\\ +\hline \verb'\ntg' & edit global templates$^1$ \hfill (n,i)\\ +\hline \verb'\ntr' & reread the templates \hfill (n,i)\\ +\hline \verb'\nts' & change templates style \hfill (n,i)\\ +\hline +%%---------------------------------------------------------------------- +%% idioms menu +%%---------------------------------------------------------------------- +\hline +\multicolumn{2}{|r|}{\textsl{\textbf{I}dioms}} \\ +\hline \verb'\if' & function \hfill (n,v,i)\\ +\hline \verb'\isf' & static function \hfill (n,v,i)\\ +\hline \verb'\im' & \verb'main()' \hfill (n,v,i)\\ +\hline \Rep\verb'\i0' & \verb'for( x=0; x=0; x-=1 )' \hfill (n,v,i)\\ +\hline \verb'\ie' & \verb'enum' + \verb'typedef' \hfill (n,v,i)\\ +\hline \verb'\is' & \verb'struct' + \verb'typedef' \hfill (n,v,i)\\ +\hline \verb'\iu' & \verb'union' + \verb'typedef' \hfill (n,v,i)\\ +\hline \verb'\ip' & \verb'printf()' \hfill (n,i)\\ +\hline \verb'\isc' & \verb'scanf()' \hfill (n,i)\\ +\hline \verb'\ica' & \verb'p=calloc()' \hfill (n,i)\\ +\hline \verb'\ima' & \verb'p=malloc()' \hfill (n,i)\\ +\hline \verb'\ire' & \verb'p=realloc()' \hfill (n,i)\\ +\hline \verb'\isi' & \verb'sizeof()' \hfill (n,v,i)\\ +\hline \verb'\ias' & \verb'assert()' \hfill (n,v,i)\\ +\hline \verb'\ii' & open input file \hfill (n,v,i)\\ +\hline \verb'\io' & open output file \hfill (n,v,i)\\ +\hline \verb'\ifs' & fscanf \hfill (n,i)\\ +\hline \verb'\ifp' & fprintf \hfill (n,i)\\ +\hline +\end{tabular}\\ +% +\begin{minipage}[b]{64mm}% +\scriptsize{% +\vspace{1mm} +%\hrulefill\\ +$^1$ {system-wide installation only}\\ +}% +\end{minipage} +% +% +%%====================================================================== +%% SIDE 2 +%%====================================================================== +% +%%~~~~~ TABULAR : begin ~~~~~~~~~~ +\begin{tabular}[]{|p{12mm}|p{60mm}|} +%%---------------------------------------------------------------------- +%% C++ menu +%%---------------------------------------------------------------------- +\hline +\multicolumn{2}{|r|}{\textsl{C\textbf{++}}} \\ +\hline \verb'\+co' & \verb'cout << << endl; ' \hfill (n,i)\\ +\hline \verb'\+"' & \verb'<< ""' \hfill (n,i)\\ +\hline \verb'\+c' & class \hfill (n,i)\\ +\hline \verb'\+ps' & \verb$#include<...> STL$ \hfill (n,i)\\ +\hline \verb'\+pc' & \verb$#include C$ \hfill (n,i)\\ +\hline \verb'\+cn' & class (using \verb'new') \hfill (n,i)\\ +\hline \verb'\+ci' & class implementation \hfill (n,i)\\ +\hline \verb'\+cni' & class (using \verb'new') implementation \hfill (n,i)\\ +\hline \verb'\+mi' & method implementation \hfill (n,i)\\ +\hline \verb'\+ai' & accessor implementation \hfill (n,i)\\ +\hline \verb'\+tc' & template class \hfill (n,i)\\ +\hline \verb'\+tcn' & template class (using \verb'new') \hfill (n,i)\\ +\hline \verb'\+tci' & template class implementation \hfill (n,i)\\ +\hline \verb'\+tcni'& template class (using \verb'new') impl. \hfill (n,i)\\ +\hline \verb'\+tmi' & template method implementation \hfill (n,i)\\ +\hline \verb'\+tai' & template accessor implementation \hfill (n,i)\\ +\hline \verb'\+tf' & template function \hfill (n,i)\\ +\hline \verb'\+ec' & error class \hfill (n,i)\\ +\hline \verb'\+tr' & \verb'try' \dots \verb'catch' \hfill (n,v,i)\\ +\hline \verb'\+ca' & \verb'catch' \hfill (n,v,i)\\ +\hline \verb'\+c.' & \verb'catch(...)' \hfill (n,v,i)\\ +\hline +%% +%%---------------------------------------------------------------------- +%% show plugin help +%%---------------------------------------------------------------------- +\hline +\multicolumn{2}{|r|}{\textsl{\textbf{H}elp and Menus}}\\ +\hline \verb'\hm' & show manual \hfill (n,i)\\ +\hline \verb'\hp' & help (c-support) \hfill (n,i)\\ +\hline \verb'\lcs' & load Menus\hfill \scriptsize{(n \& GUI only)}\\ +\hline \verb'\ucs' & unload Menus\hfill \scriptsize{(n \& GUI only)}\\ +\hline +\end{tabular} +\vspace{100mm} +%%~~~~~ TABULAR : begin ~~~~~~~~~~ +\begin{tabular}[]{|p{12mm}|p{58mm}|} +%%---------------------------------------------------------------------- +%% run menu +%%---------------------------------------------------------------------- +\hline +\multicolumn{2}{|r|}{\textsl{\textbf{R}un}} \\ +\hline \verb'\rc' & save and compile \hfill (n,i)\\ +\hline \verb'\rl' & link \hfill (n,i)\\ +\hline \verb'\rr' & run \hfill (n,i)\\ +\hline \verb'\ra' & set comand line arguments \hfill (n,i)\\ +\hline \verb'\rm' & run \texttt{ make}$^1$ \hfill (n,i)\\ +\hline \verb'\rmc' & run \texttt{ make clean}$^1$ \hfill (n,i)\\ +\hline \verb'\rcm' & choose a makefile $^1$ \hfill (n,i)\\ +\hline \verb'\rme' & executable\ to\ run$^1$ \hfill (n,i)\\ +\hline \verb'\rma' & cmd.\ line arg.\ for \texttt{make}$^1$ \hfill (n,i)\\ +% +\hline \verb'\rp' & run \texttt{ splint}$^2$ \hfill (n,i)\\ +\hline \verb'\rpa' & cmd.\ line arg.\ for \texttt{splint} \hfill (n,i)\\ +% +\hline \verb'\rk' & run \texttt{ CodeCheck}$^3$ \hfill (n,i)\\ +\hline \verb'\rka' & cmd.\ line arg.\ for \texttt{CodeCheck} \hfill (n,i)\\ +% +\hline \verb'\rd' & run \texttt{ indent} \hfill (n,i)\\ +\hline \Rep\verb'\rh' & hardcopy buffer \hfill (n,i,v)\\ +\hline \verb'\rs' & show plugin settings \hfill (n,i)\\ +\hline \verb'\rx' & set xterm size \hfill (n,i, only Unix \& GUI)\\ +\hline \verb'\ro' & change output destination \hfill (n,i)\\ +\hline +%\end{tabular} +%\begin{spacing}{1.2} +%\begin{tabular}[]{|p{12mm}|p{58mm}|} +\hline +\multicolumn{2}{|r|}{\textbf{Additional Mappings}}\\ +\hline +\hline \textbf{typing} & \textbf{expansion}\\ +\hline \verb'/*' & \verb'/* */' \hfill (i)\\ +\hline \verb'/*' & \verb'/* '\fbox{\small{(multiline) marked text}}\verb' */' \hfill (v)\\ +\hline \verb'/*' & \verb'/*'\hfill (i)\newline\verb' * |'\newline\verb' */'\\ +\hline \verb'{' & \verb'{'\hfill (i)\newline\verb' |'\newline\verb'}' \\ +\hline \verb'{' & \verb'{'\hfill (v)\newline\verb' '\fbox{\small{(multiline) marked text}}\newline\verb'}'\\ +\hline +\end{tabular} +%\end{spacing} +%%~~~~~ TABULAR : end ~~~~~~~~~~ +%\vspace{60mm} +% +% +\begin{minipage}[b]{60mm}% +%\vspace{10mm} +% +\begin{flushleft} +% +\textit{Ex commands:} +\begin{description} +% +\item [CFileSection] C/C++--file sections (same as \verb'\ccs') +\item [HFileSection] H--file sections (same as \verb'\chs') +\item [KeywordComment] keyword comment (same as \verb'\ckc') +\item [SpecialComment] special comment (same as \verb'\csc') +\item [IncludeStdLibrary] standard library includes (same as \verb'\ps') +\item [IncludeC99Library] C99 includes (same as \verb'\pc') +\item [IncludeCppLibrary] STL includes (same as \verb'\+ps') +\item [IncludeCppCLibrary] C includes (same as \verb'\+pc') +\item [CStyle] C99 include (same as \verb'\nts') +% +\end{description} +% +\scriptsize{Use tab expansion to show the items to choose from.} +% +\end{flushleft} +\scriptsize{% +%\vspace{10mm} +\hrulefill\\ +$^1$ also working for filetype \textbf{make}\\ +$^2$ \textit{www.splint.org}\\ +$^3$ \textbf{CodeCheck}$^{TM}$ is a product of Abraxas Software, Inc. +}% +% +\end{minipage} +% +\end{center} +\end{multicols} +\end{document} diff --git a/c-support/rc/customization.ctags b/c-support/rc/customization.ctags new file mode 100644 index 0000000..323cbbc --- /dev/null +++ b/c-support/rc/customization.ctags @@ -0,0 +1,8 @@ + +--regex-make=/^([^:# \t]+)[ \t]*:($|[^=]+)/\1/t,targets/ +--regex-make=/^include[ \t]+(.+)/\1/i,includes/ + +--langdef=qmake +--langmap=qmake:+.pro +--regex-qmake=/^([[:upper:]_]+)/\1/t,SystemVariables/ + diff --git a/c-support/rc/customization.gvimrc b/c-support/rc/customization.gvimrc new file mode 100644 index 0000000..31befe7 --- /dev/null +++ b/c-support/rc/customization.gvimrc @@ -0,0 +1,57 @@ +"=================================================================================== +" FILE: .gvimrc +" DESCRIPTION: suggestion for a personal configuration file ~/.gvimrc +" AUTHOR: Dr.-Ing. Fritz Mehner +" VERSION: 1.0 +" CREATED: 04.04.2009 +" REVISION: $Id: customization.gvimrc,v 1.3 2009/04/04 08:26:21 mehner Exp $ +"=================================================================================== +" +"=================================================================================== +" GENERAL SETTINGS +"=================================================================================== +set cmdheight=2 " Make command line two lines high +set mousehide " Hide the mouse when typing text + +highlight Normal guibg=grey90 +highlight Cursor guibg=Blue guifg=NONE +highlight lCursor guibg=Cyan guifg=NONE +highlight NonText guibg=grey80 +highlight Constant gui=NONE guibg=grey95 +highlight Special gui=NONE guibg=grey95 +" +let c_comment_strings=1 " highlight strings inside C comments +" +"------------------------------------------------------------------------------- +" Moving cursor to other windows +" +" shift down : change window focus to lower one (cyclic) +" shift up : change window focus to upper one (cyclic) +" shift left : change window focus to one on left +" shift right : change window focus to one on right +"------------------------------------------------------------------------------- +nmap w +nmap W +nmap h +nmap l +" +"------------------------------------------------------------------------------- +" some additional hot keys +"------------------------------------------------------------------------------- +" S-F3 - call gvim file browser +"------------------------------------------------------------------------------- + map :silent browse confirm e +imap :silent browse confirm e +" +"------------------------------------------------------------------------------- +" toggle insert mode <--> 'normal mode with the -key +"------------------------------------------------------------------------------- +" +nmap +imap +" +"------------------------------------------------------------------------------- +" use font with clearly distinguishable brackets : ()[]{} +"------------------------------------------------------------------------------- +"set guifont=Luxi\ Mono\ 14 +" diff --git a/c-support/rc/customization.indent.pro b/c-support/rc/customization.indent.pro new file mode 100644 index 0000000..95f6081 --- /dev/null +++ b/c-support/rc/customization.indent.pro @@ -0,0 +1,8 @@ +--blank-lines-after-procedures +--brace-indent0 +--comment-indentation49 +--declaration-comment-column49 +--declaration-indentation10 +--space-after-parentheses +--swallow-optional-blank-lines +--tab-size2 diff --git a/c-support/rc/customization.vimrc b/c-support/rc/customization.vimrc new file mode 100644 index 0000000..917018a --- /dev/null +++ b/c-support/rc/customization.vimrc @@ -0,0 +1,222 @@ +"=================================================================================== +" FILE: .vimrc +" DESCRIPTION: suggestion for a personal configuration file ~/.vimrc +" AUTHOR: Dr.-Ing. Fritz Mehner +" CREATED: 04.04.2009 +" REVISION: $Id: customization.vimrc,v 1.6 2009/10/03 12:24:30 mehner Exp $ +"=================================================================================== +" +"=================================================================================== +" GENERAL SETTINGS +"=================================================================================== + +"------------------------------------------------------------------------------- +" Use Vim settings, rather then Vi settings. +" This must be first, because it changes other options as a side effect. +"------------------------------------------------------------------------------- +set nocompatible +" +"------------------------------------------------------------------------------- +" Enable file type detection. Use the default filetype settings. +" Also load indent files, to automatically do language-dependent indenting. +"------------------------------------------------------------------------------- +filetype plugin on +filetype indent on +" +"------------------------------------------------------------------------------- +" Switch syntax highlighting on. +"------------------------------------------------------------------------------- +syntax on +" +" Platform specific items: +" - central backup directory (has to be created) +" - default dictionary +" Uncomment your choice. +if has("win16") || has("win32") || has("win64") || + \ has("win95") || has("win32unix") + " +" runtime mswin.vim +" set backupdir =$VIM\vimfiles\backupdir +" set dictionary=$VIM\vimfiles\wordlists/german.list +else +" set backupdir =$HOME/.vim.backupdir +" set dictionary=$HOME/.vim/wordlists/german.list +endif +" +" Using a backupdir under UNIX/Linux: you may want to include a line similar to +" find $HOME/.vim.backupdir -name "*" -type f -mtime +60 -exec rm -f {} \; +" in one of your shell startup files (e.g. $HOME/.profile) +" +"------------------------------------------------------------------------------- +" Various settings +"------------------------------------------------------------------------------- +set autoindent " copy indent from current line +set autoread " read open files again when changed outside Vim +set autowrite " write a modified buffer on each :next , ... +set backspace=indent,eol,start " backspacing over everything in insert mode +set backup " keep a backup file +set browsedir=current " which directory to use for the file browser +set complete+=k " scan the files given with the 'dictionary' option +set history=50 " keep 50 lines of command line history +set hlsearch " highlight the last used search pattern +set incsearch " do incremental searching +set listchars=tab:>.,eol:\$ " strings to use in 'list' mode +set mouse=a " enable the use of the mouse +set nowrap " do not wrap lines +set popt=left:8pc,right:3pc " print options +set ruler " show the cursor position all the time +set shiftwidth=2 " number of spaces to use for each step of indent +set showcmd " display incomplete commands +set smartindent " smart autoindenting when starting a new line +set tabstop=2 " number of spaces that a counts for +set visualbell " visual bell instead of beeping +set wildignore=*.bak,*.o,*.e,*~ " wildmenu: ignore these extensions +set wildmenu " command-line completion in an enhanced mode +" +"=================================================================================== +" BUFFERS, WINDOWS +"=================================================================================== +" +"------------------------------------------------------------------------------- +" The current directory is the directory of the file in the current window. +"------------------------------------------------------------------------------- +if has("autocmd") + autocmd BufEnter * :lchdir %:p:h +endif +" +"------------------------------------------------------------------------------- +" close window (conflicts with the KDE setting for calling the process manager) +"------------------------------------------------------------------------------- + noremap :close +inoremap :close +" +"------------------------------------------------------------------------------- +" Fast switching between buffers +" The current buffer will be saved before switching to the next one. +" Choose :bprevious or :bnext +"------------------------------------------------------------------------------- + noremap :if &modifiable && !&readonly && + \ &modified :write :endif:bprevious +inoremap :if &modifiable && !&readonly && + \ &modified :write :endif:bprevious +" +"------------------------------------------------------------------------------- +" Leave the editor with Ctrl-q (KDE): Write all changed buffers and exit Vim +"------------------------------------------------------------------------------- +nnoremap :wqall +" +"------------------------------------------------------------------------------- +" When editing a file, always jump to the last known cursor position. +" Don't do it when the position is invalid or when inside an event handler +" (happens when dropping a file on gvim). +"------------------------------------------------------------------------------- +if has("autocmd") + autocmd BufReadPost * + \ if line("'\"") > 0 && line("'\"") <= line("$") | + \ exe "normal! g`\"" | + \ endif +endif " has("autocmd") +" +"------------------------------------------------------------------------------- +" some additional hot keys +"------------------------------------------------------------------------------- +" F2 - write file without confirmation +" F3 - call file explorer Ex +" F4 - show tag under curser in the preview window (tagfile must exist!) +" F5 - open quickfix error window +" F6 - close quickfix error window +" F7 - display previous error +" F8 - display next error +"------------------------------------------------------------------------------- +" +map :write +map :Explore +nmap :exe ":ptag ".expand("") +map :copen +map :cclose +map :cp +map :cn +" +imap :write +imap :Explore +imap :exe ":ptag ".expand("") +imap :copen +imap :cclose +imap :cp +imap :cn +" +"------------------------------------------------------------------------------- +" Fast switching between buffers +" The current buffer will be saved before switching to the next one. +" Choose :bprevious or :bnext +"------------------------------------------------------------------------------- +" + map :if &modifiable && !&readonly && + \ &modified :write :endif:bprevious +imap :if &modifiable && !&readonly && + \ &modified :write :endif:bprevious +" +"------------------------------------------------------------------------------- +" Leave the editor with Ctrl-q : Write all changed buffers and exit Vim +"------------------------------------------------------------------------------- +nmap :wqa +" +"------------------------------------------------------------------------------- +" comma always followed by a space +"------------------------------------------------------------------------------- +inoremap , , +" +"------------------------------------------------------------------------------- +" autocomplete parenthesis, brackets and braces +"------------------------------------------------------------------------------- +inoremap ( () +inoremap [ [] +inoremap { {} +" +vnoremap ( s()P% +vnoremap [ s[]P% +vnoremap { s{}P% +" +"------------------------------------------------------------------------------- +" autocomplete quotes (visual and select mode) +"------------------------------------------------------------------------------- +xnoremap ' s''P +xnoremap " s""P +xnoremap ` s``P +" +"------------------------------------------------------------------------------- +" Change the working directory to the directory containing the current file +"------------------------------------------------------------------------------- +if has("autocmd") + autocmd BufEnter * :lchdir %:p:h +endif " has("autocmd") +" +"=================================================================================== +" VARIOUS PLUGIN CONFIGURATIONS +"=================================================================================== +" +"------------------------------------------------------------------------------- +" c.vim +"------------------------------------------------------------------------------- +" +" --empty -- +" +"------------------------------------------------------------------------------- +" taglist.vim : toggle the taglist window +" taglist.vim : define the title texts for make +" taglist.vim : define the title texts for qmake +"------------------------------------------------------------------------------- + noremap :Tlist +inoremap :Tlist + +let Tlist_GainFocus_On_ToggleOpen = 1 +let Tlist_Close_On_Select = 1 + +let tlist_make_settings = 'make;m:makros;t:targets' +let tlist_qmake_settings = 'qmake;t:SystemVariables' + +if has("autocmd") + " ---------- qmake : set filetype for *.pro ---------- + autocmd BufNewFile,BufRead *.pro set filetype=qmake +endif " has("autocmd") + diff --git a/c-support/scripts/wrapper.sh b/c-support/scripts/wrapper.sh new file mode 100755 index 0000000..f78861c --- /dev/null +++ b/c-support/scripts/wrapper.sh @@ -0,0 +1,30 @@ +#!/bin/bash +#=============================================================================== +# FILE: wrapper.sh +# USAGE: ./wrapper.sh executable [cmd-line-args] +# DESCRIPTION: Wraps the execution of a programm or script. +# Use with xterm: xterm -e wrapper.sh executable cmd-line-args +# This script is used by the plugins c.vim +# OPTIONS: --- +# REQUIREMENTS: --- +# BUGS: --- +# NOTES: --- +# AUTHOR: Dr.-Ing. Fritz Mehner (Mn), mehner@fh-swf.de +# COMPANY: Fachhochschule Südwestfalen, Iserlohn +# CREATED: 23.11.2004 18:04:01 CET +# REVISION: $Id: wrapper.sh,v 1.5 2009/06/03 17:47:06 mehner Exp $ +#=============================================================================== + +executable="${1}" # name of the executable + +if [ ${#} -ge 1 ] && [ -x "$executable" ] +then + "${@}" + returncode=$? + [ $returncode -ne 0 ] && printf "'${@}' returned ${returncode}\n" +else + printf "\n !! file \"${executable}\" does not exist or is not executable !!\n" + returncode=126 # command invoked cannot execute +fi +read -p " ... press return key ... " dummy +exit $returncode diff --git a/c-support/templates/Templates b/c-support/templates/Templates new file mode 100644 index 0000000..d99ea91 --- /dev/null +++ b/c-support/templates/Templates @@ -0,0 +1,30 @@ +$ +$ ============================================================= +$ ========== USER MACROS ====================================== +$ ============================================================= +$ +|AUTHOR| = Wei Huang +|AUTHORREF| = +|EMAIL| = wh.huang@mail.utoronto.ca +|COMPANY| = University of Toronto +|COPYRIGHT| = Copyright (c) |YEAR|, |AUTHOR| +|STYLE| = default +$ +$ ============================================================= +$ ========== FILE INCLUDES ==================================== +$ ============================================================= +$ +|includefile| = c.comments.template +|includefile| = c.cpp.template +|includefile| = c.idioms.template +|includefile| = c.preprocessor.template +|includefile| = c.statements.template +$ +== IF |STYLE| IS CPP == +|includefile| = cpp.comments.template +|includefile| = cpp.cpp.template +|includefile| = cpp.idioms.template +|includefile| = cpp.preprocessor.template +|includefile| = cpp.statements.template +== ENDIF == +$ diff --git a/c-support/templates/Templates~ b/c-support/templates/Templates~ new file mode 100644 index 0000000..74bcd9f --- /dev/null +++ b/c-support/templates/Templates~ @@ -0,0 +1,30 @@ +$ +$ ============================================================= +$ ========== USER MACROS ====================================== +$ ============================================================= +$ +|AUTHOR| = YOUR NAME +|AUTHORREF| = +|EMAIL| = +|COMPANY| = +|COPYRIGHT| = Copyright (c) |YEAR|, |AUTHOR| +|STYLE| = default +$ +$ ============================================================= +$ ========== FILE INCLUDES ==================================== +$ ============================================================= +$ +|includefile| = c.comments.template +|includefile| = c.cpp.template +|includefile| = c.idioms.template +|includefile| = c.preprocessor.template +|includefile| = c.statements.template +$ +== IF |STYLE| IS CPP == +|includefile| = cpp.comments.template +|includefile| = cpp.cpp.template +|includefile| = cpp.idioms.template +|includefile| = cpp.preprocessor.template +|includefile| = cpp.statements.template +== ENDIF == +$ diff --git a/c-support/templates/c.comments.template b/c-support/templates/c.comments.template new file mode 100644 index 0000000..1501628 --- /dev/null +++ b/c-support/templates/c.comments.template @@ -0,0 +1,179 @@ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.end-of-line-comment == append == +/* */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.frame == +/*----------------------------------------------------------------------------- + * + *-----------------------------------------------------------------------------*/ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.function == +/* + * === FUNCTION ====================================================================== + * Name: |?FUNCTION_NAME| + * Description: + * ===================================================================================== + */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.method == +/* + *-------------------------------------------------------------------------------------- + * Class: |?CLASSNAME| + * Method: |?CLASSNAME| :: |?METHODNAME| + * Description: + *-------------------------------------------------------------------------------------- + */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.class == +/* + * ===================================================================================== + * Class: |?CLASSNAME| + * Description: + * ===================================================================================== + */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-description == start == +/* + * ===================================================================================== + * + * Filename: |FILENAME| + * + * Description: + * + * Version: 1.0 + * Created: |DATE| |TIME| + * Revision: none + * Compiler: gcc + * + * Author: |AUTHOR| (|AUTHORREF|), |EMAIL| + * Organization: |ORGANIZATION| + * + * ===================================================================================== + */ +#include +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-description-header == start == +/* + * ===================================================================================== + * + * Filename: |FILENAME| + * + * Description: + * + * Version: 1.0 + * Created: |DATE| |TIME| + * Revision: none + * Compiler: gcc + * + * Author: |AUTHOR| (|AUTHORREF|), |EMAIL| + * Organization: |ORGANIZATION| + * + * ===================================================================================== + */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-header-includes == +/* ##### HEADER FILE INCLUDES ################################################### */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-macros == +/* ##### MACROS - LOCAL TO THIS SOURCE FILE ################################### */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-typedefs == +/* ##### TYPE DEFINITIONS - LOCAL TO THIS SOURCE FILE ######################### */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-data-types == +/* ##### DATA TYPES - LOCAL TO THIS SOURCE FILE ############################### */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-class-defs == +/* ##### CLASS DEFINITIONS - LOCAL TO THIS SOURCE FILE ######################## */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-local-variables == +/* ##### VARIABLES - LOCAL TO THIS SOURCE FILE ################################ */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-prototypes == +/* ##### PROTOTYPES - LOCAL TO THIS SOURCE FILE ############################### */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-function-defs-exported == +/* ##### FUNCTION DEFINITIONS - EXPORTED FUNCTIONS ############################ */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-function-defs-local == +/* ##### FUNCTION DEFINITIONS - LOCAL TO THIS SOURCE FILE ##################### */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-class-implementations-exported == +/* ##### CLASS IMPLEMENTATIONS - EXPORTED CLASSES ############################# */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-class-implementations-local == +/* ##### CLASS IMPLEMENTATIONS - LOCAL CLASSES ################################ */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-header-includes == +/* ##### HEADER FILE INCLUDES ################################################### */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-macros == +/* ##### EXPORTED MACROS ######################################################## */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-exported-typedefs == +/* ##### EXPORTED TYPE DEFINITIONS ############################################## */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-exported-data-types == +/* ##### EXPORTED DATA TYPES #################################################### */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-exported-class-defs == +/* ##### EXPORTED CLASS DEFINITIONS ############################################# */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-exported-variables == +/* ##### EXPORTED VARIABLES ##################################################### */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-exported-function-declarations == +/* ##### EXPORTED FUNCTION DECLARATIONS ######################################### */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.keyword-bug == append == + /* :BUG:|DATE| |TIME|:|AUTHORREF|: */ +== comment.keyword-compiler == append == + /* :COMPILER:|DATE| |TIME|:|AUTHORREF|: */ +== comment.keyword-todo == append == + /* :TODO:|DATE| |TIME|:|AUTHORREF|: */ +== comment.keyword-tricky == append == + /* :TRICKY:|DATE| |TIME|:|AUTHORREF|: */ +== comment.keyword-warning == append == + /* :WARNING:|DATE| |TIME|:|AUTHORREF|: */ +== comment.keyword-workaround == append == + /* :WORKAROUND:|DATE| |TIME|:|AUTHORREF|: */ +== comment.keyword-keyword == append == + /* :|?KEYWORD:u|:|DATE| |TIME|:|AUTHORREF|: */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.special-empty == append == + /* EMPTY */ +== comment.special-fall-through == append == + /* FALL THROUGH */ +== comment.special-implicit-type-conversion == append == + /* IMPLICIT TYPE CONVERSION */ +== comment.special-no-return == append == + /* NO RETURN */ +== comment.special-not-reached == append == + /* NOT REACHED */ +== comment.special-remains-to-be-implemented == append == + /* REMAINS TO BE IMPLEMENTED */ +== comment.special-constant-type-is-long == append == + /* constant type is long */ +== comment.special-constant-type-is-unsigned == append == + /* constant type is unsigned */ +== comment.special-constant-type-is-unsigned-long == append == + /* constant type is unsigned long */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/c-support/templates/c.cpp.template b/c-support/templates/c.cpp.template new file mode 100644 index 0000000..40fb829 --- /dev/null +++ b/c-support/templates/c.cpp.template @@ -0,0 +1,484 @@ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +$ +== cpp.cin == +cin >> ; +$ +== cpp.cout == insert == +cout << << endl; +$ +== cpp.cout-operator == insert == +<< "" +$ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.output-manipulator-boolalpha == insert == +<< boolalpha +== cpp.output-manipulator-dec == insert == +<< dec +== cpp.output-manipulator-endl == insert == +<< endl +== cpp.output-manipulator-fixed == insert == +<< fixed +== cpp.output-manipulator-flush == insert == +<< flush +== cpp.output-manipulator-hex == insert == +<< hex +== cpp.output-manipulator-internal == insert == +<< internal +== cpp.output-manipulator-left == insert == +<< left +== cpp.output-manipulator-oct == insert == +<< oct +== cpp.output-manipulator-right == insert == +<< right +== cpp.output-manipulator-scientific == insert == +<< scientific +== cpp.output-manipulator-setbase == insert == +<< setbase(10) +== cpp.output-manipulator-setfill == insert == +<< setfill() +== cpp.output-manipulator-setiosflag == insert == +<< setiosflags() +== cpp.output-manipulator-setprecision == insert == +<< setprecision(6) +== cpp.output-manipulator-setw == insert == +<< setw(0) +== cpp.output-manipulator-showbase == insert == +<< showbase +== cpp.output-manipulator-showpoint == insert == +<< showpoint +== cpp.output-manipulator-showpos == insert == +<< showpos +== cpp.output-manipulator-uppercase == insert == +<< uppercase +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.method-implementation == +void +|?CLASSNAME|::|?METHODNAME| ( <+argument list+> ) +{ + return ; +} /* ----- end of method |CLASSNAME|::|?METHODNAME| ----- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.accessor-implementation == +/* + *-------------------------------------------------------------------------------------- + * Class: |?CLASSNAME| + * Method: get_|?ATTRIBUTE| + *-------------------------------------------------------------------------------------- + */ +inline |?RETURNTYPE| +|CLASSNAME|::get_|ATTRIBUTE| ( ) const +{ + return |ATTRIBUTE|; +} /* ----- end of method |CLASSNAME|::get_|ATTRIBUTE| ----- */ + +/* + *-------------------------------------------------------------------------------------- + * Class: |CLASSNAME| + * Method: set_|ATTRIBUTE| + *-------------------------------------------------------------------------------------- + */ +inline void +|CLASSNAME|::set_|ATTRIBUTE| ( |RETURNTYPE| value ) +{ + |ATTRIBUTE| = value; + return ; +} /* ----- end of method |CLASSNAME|::set_|ATTRIBUTE| ----- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.class-definition == +/* + * ===================================================================================== + * Class: |?CLASSNAME:c| + * Description: + * ===================================================================================== + */ +class |CLASSNAME| +{ + public: + /* ==================== LIFECYCLE ======================================= */ + |CLASSNAME| (); /* constructor */ + + /* ==================== ACCESSORS ======================================= */ + + /* ==================== MUTATORS ======================================= */ + + /* ==================== OPERATORS ======================================= */ + + protected: + /* ==================== DATA MEMBERS ======================================= */ + + private: + /* ==================== DATA MEMBERS ======================================= */ + +}; /* ----- end of class |CLASSNAME| ----- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.class-implementation == +/* + *-------------------------------------------------------------------------------------- + * Class: |?CLASSNAME:c| + * Method: |CLASSNAME| + * Description: constructor + *-------------------------------------------------------------------------------------- + */ +|CLASSNAME|::|CLASSNAME| () +{ +} /* ----- end of method |CLASSNAME|::|CLASSNAME| (constructor) ----- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.class-using-new-definition == +/* + * ===================================================================================== + * Class: |?CLASSNAME:c| + * Description: + * ===================================================================================== + */ +class |CLASSNAME| +{ + public: + /* ==================== LIFECYCLE ======================================= */ + |CLASSNAME| (); /* constructor */ + |CLASSNAME| ( const |CLASSNAME| &other ); /* copy constructor */ + ~|CLASSNAME| (); /* destructor */ + + /* ==================== ACCESSORS ======================================= */ + + /* ==================== MUTATORS ======================================= */ + + /* ==================== OPERATORS ======================================= */ + + |CLASSNAME|& operator = ( const |CLASSNAME| &other ); /* assignment operator */ + + protected: + /* ==================== DATA MEMBERS ======================================= */ + + private: + /* ==================== DATA MEMBERS ======================================= */ + +}; /* ----- end of class |CLASSNAME| ----- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.class-using-new-implementation == +/* + *-------------------------------------------------------------------------------------- + * Class: |?CLASSNAME:c| + * Method: |CLASSNAME| + * Description: constructor + *-------------------------------------------------------------------------------------- + */ +|CLASSNAME|::|CLASSNAME| () +{ +} /* ----- end of method |CLASSNAME|::|CLASSNAME| (constructor) ----- */ + +/* + *-------------------------------------------------------------------------------------- + * Class: |CLASSNAME| + * Method: |CLASSNAME| + * Description: copy constructor + *-------------------------------------------------------------------------------------- + */ +|CLASSNAME|::|CLASSNAME| ( const |CLASSNAME| &other ) +{ +} /* ----- end of method |CLASSNAME|::|CLASSNAME| (copy constructor) ----- */ + +/* + *-------------------------------------------------------------------------------------- + * Class: |CLASSNAME| + * Method: ~|CLASSNAME| + * Description: destructor + *-------------------------------------------------------------------------------------- + */ +|CLASSNAME|::~|CLASSNAME| () +{ +} /* ----- end of method |CLASSNAME|::~|CLASSNAME| (destructor) ----- */ + +/* + *-------------------------------------------------------------------------------------- + * Class: |CLASSNAME| + * Method: operator = + * Description: assignment operator + *-------------------------------------------------------------------------------------- + */ +|CLASSNAME|& +|CLASSNAME|::operator = ( const |CLASSNAME| &other ) +{ + if ( this != &other ) { + } + return *this; +} /* ----- end of method |CLASSNAME|::operator = (assignment operator) ----- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.error-class == +/* + * ===================================================================================== + * Class: |?CLASSNAME:c| + * Description: + * ===================================================================================== + */ +class |CLASSNAME| +{ + public: |CLASSNAME| ( string msg = "|CLASSNAME|" ):message(msg) { } + virtual ~|CLASSNAME| ( ) { } + virtual string what ( ) const throw ( ) { return message; } + protected: string message; +}; /* ----- end of class |CLASSNAME| ----- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-method-implementation == +template < class T > +void |?CLASSNAME|::|?METHODNAME| ( <+argument list+> ) +{ + return ; +} /* ----- end of method |CLASSNAME|::|METHODNAME| ----- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-accessor-implementation == +/* + *-------------------------------------------------------------------------------------- + * Class: |?CLASSNAME| + * Method: get_|?ATTRIBUTE| + *-------------------------------------------------------------------------------------- + */ +template < class T > +inline |?RETURNTYPE| |CLASSNAME|::get_|ATTRIBUTE| ( ) const +{ + return |ATTRIBUTE|; +} /* ----- end of method |CLASSNAME|::get_|ATTRIBUTE| ----- */ + +/* + *-------------------------------------------------------------------------------------- + * Class: |CLASSNAME| + * Method: set_|ATTRIBUTE| + *-------------------------------------------------------------------------------------- + */ +template < class T > +inline void |CLASSNAME|::set_|ATTRIBUTE| ( |RETURNTYPE| value ) +{ + |ATTRIBUTE| = value; + return ; +} /* ----- end of method |CLASSNAME|::set_|ATTRIBUTE| ----- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-class-definition == +/* + * ===================================================================================== + * Class: |?CLASSNAME:c| + * Description: + * ===================================================================================== + */ +template < class T > +class |CLASSNAME| +{ + public: + /* ==================== LIFECYCLE ======================================= */ + |CLASSNAME| (); /* constructor */ + + /* ==================== ACCESSORS ======================================= */ + + /* ==================== MUTATORS ======================================= */ + + /* ==================== OPERATORS ======================================= */ + + protected: + /* ==================== DATA MEMBERS ======================================= */ + + private: + /* ==================== DATA MEMBERS ======================================= */ + +}; /* ---------- end of template class |CLASSNAME| ---------- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-class-implementation == +/* + *-------------------------------------------------------------------------------------- + * Class: |?CLASSNAME:c| + * Method: |CLASSNAME| + * Description: + *-------------------------------------------------------------------------------------- + */ +template < class T > +|CLASSNAME| < T >::|CLASSNAME| () +{ +} /* ---------- end of constructor of template class |CLASSNAME| ---------- */ + + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-class-using-new-definition == +/* + * ===================================================================================== + * Class: |?CLASSNAME:c| + * Description: + * ===================================================================================== + */ + +template < class T > +class |CLASSNAME| +{ + public: + // ==================== LIFECYCLE ======================================= + |CLASSNAME| (); /* constructor */ + |CLASSNAME| ( const |CLASSNAME| &other ); /* copy constructor */ + ~|CLASSNAME| (); /* destructor */ + + /* ==================== ACCESSORS ======================================= */ + + /* ==================== MUTATORS ======================================= */ + + /* ==================== OPERATORS ======================================= */ + + |CLASSNAME|& operator = ( const |CLASSNAME| &other ); // assignment operator + + protected: + /* ==================== DATA MEMBERS ======================================= */ + + private: + /* ==================== DATA MEMBERS ======================================= */ + +}; /* ----- end of template class |CLASSNAME| ----- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-class-using-new-implementation == +/* + *-------------------------------------------------------------------------------------- + * Class: |?CLASSNAME:c| + * Method: |CLASSNAME| + * Description: constructor + *-------------------------------------------------------------------------------------- + */ +template < class T > +|CLASSNAME|< T >::|CLASSNAME| () +{ +} /* ---------- end of constructor of template class |CLASSNAME| ---------- */ + +/* + *-------------------------------------------------------------------------------------- + * Class: |CLASSNAME| + * Method: |CLASSNAME| + * Description: copy constructor + *-------------------------------------------------------------------------------------- + */ +template < class T > +|CLASSNAME|< T >::|CLASSNAME| ( const |CLASSNAME| &other ) +{ +} /* ---------- end of copy constructor of template class |CLASSNAME| ---------- */ + +/* + *-------------------------------------------------------------------------------------- + * Class: |CLASSNAME| + * Method: ~|CLASSNAME| + * Description: destructor + *-------------------------------------------------------------------------------------- + */ +template < class T > +|CLASSNAME|< T >::~|CLASSNAME| () +{ +} /* ---------- end of destructor of template class |CLASSNAME| ---------- */ + +/* + *-------------------------------------------------------------------------------------- + * Class: |CLASSNAME| + * Method: operator = + * Description: assignment operator + *-------------------------------------------------------------------------------------- + */ +template < class T > +|CLASSNAME|< T >& |CLASSNAME|< T >::operator = ( const |CLASSNAME| &other ) +{ + return *this; +} /* ---------- end of assignment operator of template class |CLASSNAME| ---------- */ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-function == +template +void |?TEMPALTE_FUNCTION_NAME| ( <+argument list+> ) +{ + return ; +} /* ----- end of template function |?TEMPALTE_FUNCTION_NAME| ----- */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.operator-in == +ostream & +operator << ( ostream & os, const |?CLASSNAME| & obj ) +{ + os << obj. ; + return os; +} /* ----- end of function operator << ----- */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.operator-out == +istream & +operator >> ( istream & is, |?CLASSNAME| & obj ) +{ + is >> obj. ; + return is; +} /* ----- end of function operator >> ----- */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.try-catch == +try { +} +catch ( const &ExceptObj ) { /* handle exception: */ +} +catch (...) { /* handle exception: unspecified */ +} + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.catch == +catch ( const &ExceptObj ) { /* handle exception: */ +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.catch-points == +catch (...) { /* handle exception: unspecified */ +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.extern == +extern "C" { +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.open-input-file == +string ifs_file_name = ""; /* input file name */ +ifstream ifs; /* create ifstream object */ + +ifs.open ( ifs_file_name.c_str() ); /* open ifstream */ +if (!ifs) { + cerr << "\nERROR : failed to open input file " << ifs_file_name << endl; + exit (EXIT_FAILURE); +} +{-continue here-} +ifs.close (); /* close ifstream */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.open-output-file == +string ofs_file_name = ""; /* input file name */ +ofstream ofs; /* create ofstream object */ + +ofs.open ( ofs_file_name.c_str() ); /* open ofstream */ +if (!ofs) { + cerr << "\nERROR : failed to open output file " << ofs_file_name << endl; + exit (EXIT_FAILURE); +} +{-continue here-} +ofs.close (); /* close ofstream */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.namespace-std == +using namespace std; +== cpp.namespace == +using namespace |?NAMESPACE|; +== cpp.namespace-block == +namespace |?NAMESPACE| { +} /* ----- end of namespace |NAMESPACE| ----- */ +== cpp.namespace-alias == +namespace |?NAMESPACE_ALIAS| = {-original namespace name-}; +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.rtti-typeid == insert == +typeid() +$ +== cpp.rtti-static-cast == insert == +static_cast<>() +$ +== cpp.rtti-const-cast == insert == +const_cast<>() +$ +== cpp.rtti-reinterpret-cast == insert == +reinterpret_cast<>() +$ +== cpp.rtti-dynamic-cast == insert == +dynamic_cast<>() +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/c-support/templates/c.idioms.template b/c-support/templates/c.idioms.template new file mode 100644 index 0000000..1ae6940 --- /dev/null +++ b/c-support/templates/c.idioms.template @@ -0,0 +1,141 @@ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.function == +/* + * === FUNCTION ====================================================================== + * Name: |?FUNCTION_NAME| + * Description: + * ===================================================================================== + */ +void +|FUNCTION_NAME| ( <+argument list+> ) +{ + return <+return value+>; +} /* ----- end of function |FUNCTION_NAME| ----- */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.function-static == +/* + * === FUNCTION ====================================================================== + * Name: |?FUNCTION_NAME| + * Description: + * ===================================================================================== + */ +static void +|FUNCTION_NAME| ( <+argument list+> ) +{ + return <+return value+>; +} /* ----- end of static function |FUNCTION_NAME| ----- */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.main == +#include + +/* + * === FUNCTION ====================================================================== + * Name: main + * Description: + * ===================================================================================== + */ +int +main ( int argc, char *argv[] ) +{ + return EXIT_SUCCESS; +} /* ---------- end of function main ---------- */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.enum == +enum |?ENUM_NAME| { +}; /* ---------- end of enum |ENUM_NAME| ---------- */ + +typedef enum |ENUM_NAME| |ENUM_NAME:c|; +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.struct == +struct |?STRUCT_NAME| { +}; /* ---------- end of struct |STRUCT_NAME| ---------- */ + +typedef struct |STRUCT_NAME| |STRUCT_NAME:c|; +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.union == +union |?UNION_NAME| { +}; /* ---------- end of union |UNION_NAME| ---------- */ + +typedef union |UNION_NAME| |UNION_NAME:c|; +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.printf == insert == +printf ( "\n" ); +== idioms.scanf == insert == +scanf ( "", & ); +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.calloc == +|?POINTER| = calloc ( (size_t)(<+COUNT+>), sizeof(<+TYPE+>) ); +if ( |POINTER|==NULL ) { + fprintf ( stderr, "\ndynamic memory allocation failed\n" ); + exit (EXIT_FAILURE); +} + +free (|POINTER|); +|POINTER| = NULL; + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.malloc == +|?POINTER| = malloc ( sizeof(<+TYPE+>) ); +if ( |POINTER|==NULL ) { + fprintf ( stderr, "\ndynamic memory allocation failed\n" ); + exit (EXIT_FAILURE); +} + +free (|POINTER|); +|POINTER| = NULL; + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.realloc == +|?POINTER| = realloc ( |POINTER|, sizeof(<+TYPE+>) ); +if ( |POINTER|==NULL ) { + fprintf ( stderr, "\ndynamic memory reallocation failed\n" ); + exit (EXIT_FAILURE); +} + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.sizeof == insert == +sizeof() +== idioms.assert == insert == +assert(); +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.open-input-file == +FILE *|?FILEPOINTER|; /* input-file pointer */ +char *|FILEPOINTER|_file_name = ""; /* input-file name */ + +|FILEPOINTER| = fopen( |FILEPOINTER|_file_name, "r" ); +if ( |FILEPOINTER| == NULL ) { + fprintf ( stderr, "couldn't open file '%s'; %s\n", + |FILEPOINTER|_file_name, strerror(errno) ); + exit (EXIT_FAILURE); +} +{-continue here-} +if( fclose(|FILEPOINTER|) == EOF ) { /* close input file */ + fprintf ( stderr, "couldn't close file '%s'; %s\n", + |FILEPOINTER|_file_name, strerror(errno) ); + exit (EXIT_FAILURE); +} + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.open-output-file == +FILE *|?FILEPOINTER|; /* output-file pointer */ +char *|FILEPOINTER|_file_name = ""; /* output-file name */ + +|FILEPOINTER| = fopen( |FILEPOINTER|_file_name, "w" ); +if ( |FILEPOINTER| == NULL ) { + fprintf ( stderr, "couldn't open file '%s'; %s\n", + |FILEPOINTER|_file_name, strerror(errno) ); + exit (EXIT_FAILURE); +} +{-continue here-} +if( fclose(|FILEPOINTER|) == EOF ) { /* close output file */ + fprintf ( stderr, "couldn't close file '%s'; %s\n", + |FILEPOINTER|_file_name, strerror(errno) ); + exit (EXIT_FAILURE); +} + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.fprintf == insert == +fprintf ( |?FILEPOINTER|, "\n", ); +== idioms.fscanf == insert == +fscanf ( |?FILEPOINTER|, "", & ); +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/c-support/templates/c.preprocessor.template b/c-support/templates/c.preprocessor.template new file mode 100644 index 0000000..27c6356 --- /dev/null +++ b/c-support/templates/c.preprocessor.template @@ -0,0 +1,54 @@ +$------------------------------------------------------------------------- +== preprocessor.include-global == insert == +#include <> +$------------------------------------------------------------------------- +== preprocessor.include-local == insert == +#include "" +$------------------------------------------------------------------------- +== preprocessor.define == insert == +#define /* */ +$------------------------------------------------------------------------- +== preprocessor.undefine == insert == +#undef /* */ +$------------------------------------------------------------------------- +== preprocessor.if-endif == +#if |?CONDITION:u| + +#endif /* ----- |CONDITION| ----- */ +$------------------------------------------------------------------------- +== preprocessor.if-else-endif == +#if |?CONDITION:u| + +#else /* ----- not |CONDITION| ----- */ +<+ELSE PART+> +#endif /* ----- not |CONDITION| ----- */ +$------------------------------------------------------------------------- +== preprocessor.ifdef-else-endif == +#ifdef |?CONDITION:u| + +#else /* ----- not |CONDITION| ----- */ +<+ELSE PART+> +#endif /* ----- not |CONDITION| ----- */ +$------------------------------------------------------------------------- +== preprocessor.ifndef-else-endif == +#ifndef |?CONDITION:u| + +#else /* ----- not |CONDITION| ----- */ +<+ELSE PART+> +#endif /* ----- not |CONDITION| ----- */ +$------------------------------------------------------------------------- +== preprocessor.ifndef-def-endif == +#ifndef |?BASENAME:L|_INC +#define |BASENAME|_INC + +#endif /* ----- #ifndef |BASENAME|_INC ----- */ +$------------------------------------------------------------------------- +== preprocessor.error == +#error "" /* */ +$------------------------------------------------------------------------- +== preprocessor.line == +#line /* */ +$------------------------------------------------------------------------- +== preprocessor.pragma == +#pragma /* */ +$------------------------------------------------------------------------- diff --git a/c-support/templates/c.statements.template b/c-support/templates/c.statements.template new file mode 100644 index 0000000..574366d --- /dev/null +++ b/c-support/templates/c.statements.template @@ -0,0 +1,69 @@ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.do-while == +do { +} while ( ); /* ----- end do-while ----- */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.for == +for ( ; ; ) +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.for-block == +for ( ; ; ) { +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.if == +if ( ) +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.if-block == +if ( ) { +<-IF PART-> +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.if-else == +if ( ) +else +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.if-block-else == +if ( ) { +<-IF PART-> +} +else { +<-ELSE PART-> +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.else-block == +else { + +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.while == +while ( ) +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.while-block == +while ( ) { +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.switch == +switch ( ) { + case <-LABEL->: + break; + + case <-LABEL->: + break; + + case <-LABEL->: + break; + + default: + break; +} /* ----- end switch ----- */ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.case == +case : +break; + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.block == +{ + +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/c-support/templates/cpp.comments.template b/c-support/templates/cpp.comments.template new file mode 100644 index 0000000..5cb19db --- /dev/null +++ b/c-support/templates/cpp.comments.template @@ -0,0 +1,168 @@ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.end-of-line-comment == append == +// +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.frame == +//---------------------------------------------------------------------- +// +//---------------------------------------------------------------------- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.function == +// === FUNCTION ====================================================================== +// Name: |?FUNCTION_NAME| +// Description: +// ===================================================================================== +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.method == +//-------------------------------------------------------------------------------------- +// Class: |?CLASSNAME| +// Method: |?METHODNAME| +// Description: +//-------------------------------------------------------------------------------------- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.class == +// ===================================================================================== +// Class: |?CLASSNAME| +// Description: +// ===================================================================================== +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-description == start == +// ===================================================================================== +// +// Filename: |FILENAME| +// +// Description: +// +// Version: 1.0 +// Created: |DATE| |TIME| +// Revision: none +// Compiler: g++ +// +// Author: |AUTHOR| (|AUTHORREF|), |EMAIL| +// Company: |ORGANIZATION| +// +// ===================================================================================== +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-description-header == start == +// ===================================================================================== +// +// Filename: |FILENAME| +// +// Description: +// +// Version: 1.0 +// Created: |DATE| |TIME| +// Revision: none +// Compiler: g++ +// +// Author: |AUTHOR| (|AUTHORREF|), |EMAIL| +// Company: |ORGANIZATION| +// +// ===================================================================================== +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-header-includes == +// ##### HEADER FILE INCLUDES ################################################### + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-macros == +// ##### MACROS - LOCAL TO THIS SOURCE FILE ################################### + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-typedefs == +// ##### TYPE DEFINITIONS - LOCAL TO THIS SOURCE FILE ######################### + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-data-types == +// ##### DATA TYPES - LOCAL TO THIS SOURCE FILE ############################### + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-class-defs == +// ##### CLASS DEFINITIONS - LOCAL TO THIS SOURCE FILE ######################## + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-local-variables == +// ##### VARIABLES - LOCAL TO THIS SOURCE FILE ################################ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-prototypes == +// ##### PROTOTYPES - LOCAL TO THIS SOURCE FILE ############################### + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-function-defs-exported == +// ##### FUNCTION DEFINITIONS - EXPORTED FUNCTIONS ############################ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-function-defs-local == +// ##### FUNCTION DEFINITIONS - LOCAL TO THIS SOURCE FILE ##################### + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-class-implementations-exported == +// ##### CLASS IMPLEMENTATIONS - EXPORTED CLASSES ############################# + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-cpp-class-implementations-local == +// ##### CLASS IMPLEMENTATIONS - LOCAL CLASSES ################################ + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-header-includes == +// ##### HEADER FILE INCLUDES ################################################### + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-macros == +// ##### EXPORTED MACROS ######################################################## + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-exported-typedefs == +// ##### EXPORTED TYPE DEFINITIONS ############################################## + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-exported-data-types == +// ##### EXPORTED DATA TYPES #################################################### + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-exported-class-defs == +// ##### EXPORTED CLASS DEFINITIONS ############################################# + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-exported-variables == +// ##### EXPORTED VARIABLES ##################################################### + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.file-section-hpp-exported-function-declarations == +// ##### EXPORTED FUNCTION DECLARATIONS ######################################### + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.keyword-bug == append == + // :BUG:|DATE| |TIME|:|AUTHORREF|: +== comment.keyword-compiler == append == + // :COMPILER:|DATE| |TIME|:|AUTHORREF|: +== comment.keyword-todo == append == + // :TODO:|DATE| |TIME|:|AUTHORREF|: +== comment.keyword-tricky == append == + // :TRICKY:|DATE| |TIME|:|AUTHORREF|: +== comment.keyword-warning == append == + // :WARNING:|DATE| |TIME|:|AUTHORREF|: +== comment.keyword-workaround == append == + // :WORKAROUND:|DATE| |TIME|:|AUTHORREF|: +== comment.keyword-keyword == append == + // :|?KEYWORD:u|:|DATE| |TIME|:|AUTHORREF|: +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== comment.special-empty == append == + // EMPTY +== comment.special-fall-through == append == + // FALL THROUGH +== comment.special-implicit-type-conversion == append == + // IMPLICIT TYPE CONVERSION +== comment.special-no-return == append == + // NO RETURN +== comment.special-not-reached == append == + // NOT REACHED +== comment.special-remains-to-be-implemented == append == + // REMAINS TO BE IMPLEMENTED +== comment.special-constant-type-is-long == append == + // constant type is long +== comment.special-constant-type-is-unsigned == append == + // constant type is unsigned +== comment.special-constant-type-is-unsigned-long == append == + // constant type is unsigned long +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/c-support/templates/cpp.cpp.template b/c-support/templates/cpp.cpp.template new file mode 100644 index 0000000..ddcaada --- /dev/null +++ b/c-support/templates/cpp.cpp.template @@ -0,0 +1,447 @@ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +$ +== cpp.cin == +cin >> ; +$ +== cpp.cout == insert == +cout << << endl; +$ +== cpp.cout-operator == insert == +<< "" +$ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.output-manipulator-boolalpha == insert == +<< boolalpha +== cpp.output-manipulator-dec == insert == +<< dec +== cpp.output-manipulator-endl == insert == +<< endl +== cpp.output-manipulator-fixed == insert == +<< fixed +== cpp.output-manipulator-flush == insert == +<< flush +== cpp.output-manipulator-hex == insert == +<< hex +== cpp.output-manipulator-internal == insert == +<< internal +== cpp.output-manipulator-left == insert == +<< left +== cpp.output-manipulator-oct == insert == +<< oct +== cpp.output-manipulator-right == insert == +<< right +== cpp.output-manipulator-scientific == insert == +<< scientific +== cpp.output-manipulator-setbase == insert == +<< setbase(10) +== cpp.output-manipulator-setfill == insert == +<< setfill() +== cpp.output-manipulator-setiosflag == insert == +<< setiosflags() +== cpp.output-manipulator-setprecision == insert == +<< setprecision(6) +== cpp.output-manipulator-setw == insert == +<< setw(0) +== cpp.output-manipulator-showbase == insert == +<< showbase +== cpp.output-manipulator-showpoint == insert == +<< showpoint +== cpp.output-manipulator-showpos == insert == +<< showpos +== cpp.output-manipulator-uppercase == insert == +<< uppercase +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.method-implementation == +void +|?CLASSNAME|::|?METHODNAME| ( <+argument list+> ) +{ + return ; +} // ----- end of method |CLASSNAME|::|METHODNAME| ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.accessor-implementation == +//-------------------------------------------------------------------------------------- +// Class: |?CLASSNAME| +// Method: get_|?ATTRIBUTE| +//-------------------------------------------------------------------------------------- +inline |?RETURNTYPE| +|CLASSNAME|::get_|ATTRIBUTE| ( ) const +{ + return |ATTRIBUTE|; +} // ----- end of method |CLASSNAME|::get_|ATTRIBUTE| ----- + +//-------------------------------------------------------------------------------------- +// Class: |CLASSNAME| +// Method: set_|ATTRIBUTE| +//-------------------------------------------------------------------------------------- +inline void +|CLASSNAME|::set_|ATTRIBUTE| ( |RETURNTYPE| value ) +{ + |ATTRIBUTE| = value; + return ; +} // ----- end of method |CLASSNAME|::set_|ATTRIBUTE| ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.class-definition == +// ===================================================================================== +// Class: |?CLASSNAME:c| +// Description: +// ===================================================================================== +class |CLASSNAME| +{ + public: + // ==================== LIFECYCLE ======================================= + |CLASSNAME| (); // constructor + + // ==================== ACCESSORS ======================================= + + // ==================== MUTATORS ======================================= + + // ==================== OPERATORS ======================================= + + protected: + // ==================== DATA MEMBERS ======================================= + + private: + // ==================== DATA MEMBERS ======================================= + +}; // ----- end of class |CLASSNAME| ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.class-implementation == +//-------------------------------------------------------------------------------------- +// Class: |?CLASSNAME| +// Method: |CLASSNAME| +// Description: constructor +//-------------------------------------------------------------------------------------- +|CLASSNAME|::|CLASSNAME| () +{ +} // ----- end of method |CLASSNAME|::|CLASSNAME| (constructor) ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.class-using-new-definition == +// ===================================================================================== +// Class: |?CLASSNAME:c| +// Description: +// ===================================================================================== +class |CLASSNAME| +{ + public: + // ==================== LIFECYCLE ======================================= + |CLASSNAME| (); // constructor + |CLASSNAME| ( const |CLASSNAME| &other ); // copy constructor + ~|CLASSNAME| (); // destructor + + // ==================== ACCESSORS ======================================= + + // ==================== MUTATORS ======================================= + + // ==================== OPERATORS ======================================= + + |CLASSNAME|& operator = ( const |CLASSNAME| &other ); // assignment operator + + protected: + // ==================== DATA MEMBERS ======================================= + + private: + // ==================== DATA MEMBERS ======================================= + +}; // ----- end of class |CLASSNAME| ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.class-using-new-implementation == +//-------------------------------------------------------------------------------------- +// Class: |?CLASSNAME| +// Method: |CLASSNAME| +// Description: constructor +//-------------------------------------------------------------------------------------- +|CLASSNAME|::|CLASSNAME| () +{ +} // ----- end of method |CLASSNAME|::|CLASSNAME| (constructor) ----- + +//-------------------------------------------------------------------------------------- +// Class: |CLASSNAME| +// Method: |CLASSNAME| +// Description: copy constructor +//-------------------------------------------------------------------------------------- +|CLASSNAME|::|CLASSNAME| ( const |CLASSNAME| &other ) +{ +} // ----- end of method |CLASSNAME|::|CLASSNAME| (copy constructor) ----- + +//-------------------------------------------------------------------------------------- +// Class: |CLASSNAME| +// Method: ~|CLASSNAME| +// Description: destructor +//-------------------------------------------------------------------------------------- +|CLASSNAME|::~|CLASSNAME| () +{ +} // ----- end of method |CLASSNAME|::~|CLASSNAME| (destructor) ----- + +//-------------------------------------------------------------------------------------- +// Class: |CLASSNAME| +// Method: operator = +// Description: assignment operator +//-------------------------------------------------------------------------------------- +|CLASSNAME|& +|CLASSNAME|::operator = ( const |CLASSNAME| &other ) +{ + if ( this != &other ) { + } + return *this; +} // ----- end of method |CLASSNAME|::operator = (assignment operator) ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.error-class == +// ===================================================================================== +// Class: |?CLASSNAME:c| +// Description: +// ===================================================================================== +class |CLASSNAME| +{ + public: |CLASSNAME| ( string msg = "|CLASSNAME|" ):message(msg) { } + virtual ~|CLASSNAME| ( ) { } + virtual string what ( ) const throw ( ) { return message; } + protected: string message; +}; // ---------- end of class |CLASSNAME| ---------- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-method-implementation == +template < class T > +void |?CLASSNAME|::|?METHODNAME| ( <+argument list+> ) +{ + return ; +} // ----- end of method |CLASSNAME|::|METHODNAME| ----- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-accessor-implementation == +//-------------------------------------------------------------------------------------- +// Class: |?CLASSNAME| +// Method: get_|?ATTRIBUTE| +//-------------------------------------------------------------------------------------- +template < class T > +inline |?RETURNTYPE| |CLASSNAME|::get_|ATTRIBUTE| ( ) const +{ + return |ATTRIBUTE|; +} // ----- end of method |CLASSNAME|::get_|ATTRIBUTE| ----- + +//-------------------------------------------------------------------------------------- +// Class: |CLASSNAME| +// Method: set_|ATTRIBUTE| +//-------------------------------------------------------------------------------------- +template < class T > +inline void |CLASSNAME|::set_|ATTRIBUTE| ( |RETURNTYPE| value ) +{ + |ATTRIBUTE| = value; + return ; +} // ----- end of method |CLASSNAME|::set_|ATTRIBUTE| ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-class-definition == +// ===================================================================================== +// Class: |?CLASSNAME:c| +// Description: +// ===================================================================================== + +template < class T > +class |CLASSNAME| +{ + public: + // ==================== LIFECYCLE ======================================= + |CLASSNAME| (); // constructor + + // ==================== ACCESSORS ======================================= + + // ==================== MUTATORS ======================================= + + // ==================== OPERATORS ======================================= + + protected: + // ==================== DATA MEMBERS ======================================= + + private: + // ==================== DATA MEMBERS ======================================= + +}; // ----- end of template class |CLASSNAME| ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-class-implementation == +//-------------------------------------------------------------------------------------- +// Class: |?CLASSNAME| +// Method: |CLASSNAME| +// Description: constructor +//-------------------------------------------------------------------------------------- +template < class T > +|CLASSNAME| :: |CLASSNAME| () +{ +} // ----- end of constructor of template class |CLASSNAME| ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-class-using-new-definition == +// ===================================================================================== +// Class: |?CLASSNAME:c| +// Description: +// ===================================================================================== + +template < class T > +class |CLASSNAME| +{ + public: + // ==================== LIFECYCLE ======================================= + |CLASSNAME| (); // constructor + |CLASSNAME| ( const |CLASSNAME| &other ); // copy constructor + ~|CLASSNAME| (); // destructor + + // ==================== ACCESSORS ======================================= + + // ==================== MUTATORS ======================================= + + // ==================== OPERATORS ======================================= + + |CLASSNAME|& operator = ( const |CLASSNAME| &other ); // assignment operator + + protected: + // ==================== DATA MEMBERS ======================================= + + private: + // ==================== DATA MEMBERS ======================================= + +}; // ----- end of template class |CLASSNAME| ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-class-using-new-implementation == +//-------------------------------------------------------------------------------------- +// Class: |?CLASSNAME| +// Method: |CLASSNAME| +// Description: constructor +//-------------------------------------------------------------------------------------- +template < class T > +|CLASSNAME|::|CLASSNAME| () +{ +} // ----- end of constructor of template class |CLASSNAME| ----- + +//-------------------------------------------------------------------------------------- +// Class: |CLASSNAME| +// Method: |CLASSNAME| +// Description: copy constructor +//-------------------------------------------------------------------------------------- +template < class T > +|CLASSNAME|::|CLASSNAME| ( const |CLASSNAME| &other ) +{ +} // ----- end of copy constructor of template class |CLASSNAME| ----- + +//-------------------------------------------------------------------------------------- +// Class: |CLASSNAME| +// Method: ~|CLASSNAME| +// Description: destructor +//-------------------------------------------------------------------------------------- +template < class T > +|CLASSNAME|::~|CLASSNAME| () +{ +} // ----- end of destructor of template class |CLASSNAME| ----- + +//-------------------------------------------------------------------------------------- +// Class: |CLASSNAME| +// Method: operator = +// Description: assignment operator +//-------------------------------------------------------------------------------------- +template < class T > +|CLASSNAME|& |CLASSNAME|::operator = ( const |CLASSNAME| &other ) +{ + if ( this != &other ) { + } + return *this; +} // ----- end of assignment operator of template class |CLASSNAME| ----- + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.template-function == +template +void |?TEMPALTE_FUNCTION_NAME| ( <+argument list+> ) +{ + return ; +} // ----- end of template function |?TEMPALTE_FUNCTION_NAME| ----- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.operator-in == +ostream & +operator << ( ostream & os, const |?CLASSNAME| & obj ) +{ + os << obj. ; + return os; +} // ----- end of function operator << ----- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.operator-out == +istream & +operator >> ( istream & is, |?CLASSNAME| & obj ) +{ + is >> obj. ; + return is; +} // ----- end of function operator >> ----- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.try-catch == +try { +} +catch ( const &ExceptObj ) { // handle exception: +} +catch (...) { // handle exception: unspecified +} + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.catch == +catch ( const &ExceptObj ) { // handle exception: +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.catch-points == +catch (...) { // handle exception: unspecified +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.extern == +extern "C" { +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.open-input-file == +string ifs_file_name = ""; // input file name +ifstream ifs; // create ifstream object + +ifs.open ( ifs_file_name.c_str() ); // open ifstream +if (!ifs) { + cerr << "\nERROR : failed to open input file " << ifs_file_name << endl; + exit (EXIT_FAILURE); +} +{-continue here-} +ifs.close (); // close ifstream +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.open-output-file == +string ofs_file_name = ""; // input file name +ofstream ofs; // create ofstream object + +ofs.open ( ofs_file_name.c_str() ); // open ofstream +if (!ofs) { + cerr << "\nERROR : failed to open output file " << ofs_file_name << endl; + exit (EXIT_FAILURE); +} +{-continue here-} +ofs.close (); // close ofstream +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.namespace-std == +using namespace std; +== cpp.namespace == +using namespace |?NAMESPACE|; +== cpp.namespace-block == +namespace |?NAMESPACE| { +} // ----- end of namespace |NAMESPACE| ----- +== cpp.namespace-alias == +namespace |?NAMESPACE_ALIAS| = {-original namespace name-}; +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== cpp.rtti-typeid == insert == +typeid() +$ +== cpp.rtti-static-cast == insert == +static_cast<>() +$ +== cpp.rtti-const-cast == insert == +const_cast<>() +$ +== cpp.rtti-reinterpret-cast == insert == +reinterpret_cast<>() +$ +== cpp.rtti-dynamic-cast == insert == +dynamic_cast<>() +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/c-support/templates/cpp.idioms.template b/c-support/templates/cpp.idioms.template new file mode 100644 index 0000000..911592d --- /dev/null +++ b/c-support/templates/cpp.idioms.template @@ -0,0 +1,117 @@ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.function == +void +|?FUNCTION_NAME| ( <+argument list+> ) +{ + return <+return value+>; +} // ----- end of function |FUNCTION_NAME| ----- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.function-static == +static void +|?FUNCTION_NAME| ( <+argument list+> ) +{ + return <+return value+>; +} // ----- end of static function |FUNCTION_NAME| ----- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.main == +#include + +int +main ( int argc, char *argv[] ) +{ + return EXIT_SUCCESS; +} // ---------- end of function main ---------- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.enum == +enum |?ENUM_NAME| { +}; // ---------- end of enum |ENUM_NAME| ---------- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.struct == +struct |?STRUCT_NAME| { +}; // ---------- end of struct |STRUCT_NAME| ---------- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.union == +union |?UNION_NAME| { +}; // ---------- end of union |UNION_NAME| ---------- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.printf == insert == +printf ( "\n" ); +== idioms.scanf == insert == +scanf ( "", & ); +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.calloc == +|?POINTER| = calloc ( (size_t)(<+COUNT+>), sizeof(<+TYPE+>) ); +if ( |POINTER|==NULL ) { + fprintf ( stderr, "\ndynamic memory allocation failed\n" ); + exit (EXIT_FAILURE); +} + +free (|POINTER|); +|POINTER| = NULL; + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.malloc == +|?POINTER| = malloc ( sizeof(<+TYPE+>) ); +if ( |POINTER|==NULL ) { + fprintf ( stderr, "\ndynamic memory allocation failed\n" ); + exit (EXIT_FAILURE); +} + +free (|POINTER|); +|POINTER| = NULL; + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.realloc == +|?POINTER| = realloc ( |POINTER|, sizeof(<+TYPE+>) ); +if ( |POINTER|==NULL ) { + fprintf ( stderr, "\ndynamic memory reallocation failed\n" ); + exit (EXIT_FAILURE); +} + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.sizeof == insert == +sizeof() +== idioms.assert == insert == +assert(); +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.open-input-file == +FILE *|?FILEPOINTER|; // input-file pointer +char *|FILEPOINTER|_file_name = ""; // input-file name + +|FILEPOINTER| = fopen( |FILEPOINTER|_file_name, "r" ); +if ( |FILEPOINTER| == NULL ) { + fprintf ( stderr, "couldn't open file '%s'; %s\n", + |FILEPOINTER|_file_name, strerror(errno) ); + exit (EXIT_FAILURE); +} +{-continue here-} +if( fclose(|FILEPOINTER|) == EOF ) { // close input file + fprintf ( stderr, "couldn't close file '%s'; %s\n", + |FILEPOINTER|_file_name, strerror(errno) ); + exit (EXIT_FAILURE); +} + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.open-output-file == +FILE *|?FILEPOINTER|; // output-file pointer +char *|FILEPOINTER|_file_name = ""; // output-file name + +|FILEPOINTER| = fopen( |FILEPOINTER|_file_name, "w" ); +if ( |FILEPOINTER| == NULL ) { + fprintf ( stderr, "couldn't open file '%s'; %s\n", + |FILEPOINTER|_file_name, strerror(errno) ); + exit (EXIT_FAILURE); +} +{-continue here-} +if( fclose(|FILEPOINTER|) == EOF ) { // close output file + fprintf ( stderr, "couldn't close file '%s'; %s\n", + |FILEPOINTER|_file_name, strerror(errno) ); + exit (EXIT_FAILURE); +} + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== idioms.fprintf == insert == +fprintf ( |?FILEPOINTER|, "\n", ); +== idioms.fscanf == insert == +fscanf ( |?FILEPOINTER|, "", & ); +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/c-support/templates/cpp.preprocessor.template b/c-support/templates/cpp.preprocessor.template new file mode 100644 index 0000000..8aba79d --- /dev/null +++ b/c-support/templates/cpp.preprocessor.template @@ -0,0 +1,54 @@ +$------------------------------------------------------------------------- +== preprocessor.include-global == +#include <> +$------------------------------------------------------------------------- +== preprocessor.include-local == +#include "" +$------------------------------------------------------------------------- +== preprocessor.define == +#define // +$------------------------------------------------------------------------- +== preprocessor.undefine == +#undef // +$------------------------------------------------------------------------- +== preprocessor.if-endif == +#if |?CONDITION:u| + +#endif // ----- |CONDITION| ----- +$------------------------------------------------------------------------- +== preprocessor.if-else-endif == +#if |?CONDITION:u| + +#else // ----- not |CONDITION| ----- +<+ELSE PART+> +#endif // ----- not |CONDITION| ----- +$------------------------------------------------------------------------- +== preprocessor.ifdef-else-endif == +#ifdef |?CONDITION:u| + +#else // ----- not |CONDITION| ----- +<+ELSE PART+> +#endif // ----- not |CONDITION| ----- +$------------------------------------------------------------------------- +== preprocessor.ifndef-else-endif == +#ifndef |?CONDITION:u| + +#else // ----- not |CONDITION| ----- +<+ELSE PART+> +#endif // ----- not |CONDITION| ----- +$------------------------------------------------------------------------- +== preprocessor.ifndef-def-endif == +#ifndef |?BASENAME:L|_INC +#define |BASENAME|_INC + +#endif // ----- #ifndef |BASENAME|_INC ----- +$------------------------------------------------------------------------- +== preprocessor.error == +#error "" // +$------------------------------------------------------------------------- +== preprocessor.line == +#line // +$------------------------------------------------------------------------- +== preprocessor.pragma == +#pragma // +$------------------------------------------------------------------------- diff --git a/c-support/templates/cpp.statements.template b/c-support/templates/cpp.statements.template new file mode 100644 index 0000000..c2fdecb --- /dev/null +++ b/c-support/templates/cpp.statements.template @@ -0,0 +1,72 @@ +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.do-while == +do { +} while ( ); // ----- end do-while ----- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.for == +for ( ; ; ) +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.for-block == +for ( ; ; ) { +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.if == +if ( ) +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.if-block == +if ( ) { +<-IF PART-> +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.if-else == +if ( ) +else +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.if-block-else == +if ( ) { +<-IF PART-> +} +else { +<+ELSE PART+> +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.else-block == +else { + +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.while == +while ( ) +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.while-block == +while ( ) { +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.switch == +switch ( ) { + case 1: + break; + + case 2: + break; + + case 3: + break; + + case 4: + break; + + default: + break; +} // ----- end switch ----- +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.case == +case : +break; + +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +== statements.block == +{ + +} +$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/c-support/wordlists/c-c++-keywords.list b/c-support/wordlists/c-c++-keywords.list new file mode 100644 index 0000000..4bcd27a --- /dev/null +++ b/c-support/wordlists/c-c++-keywords.list @@ -0,0 +1,220 @@ +adjustfield +basefield +boolalpha +floatfield +internal +scientific +setbase +setiosflags +setprecision +showbase +showpoint +showpos +uppercase + +auto +break +case +char +const +continue +default +double +else +enum +extern +float +goto +inline +long +register +restrict +return +short +signed +sizeof +static +struct +switch +typedef +union +unsigned +void +volatile +while +_Bool +_Complex +_Imaginary +EXIT_FAILURE +EXIT_SUCCESS +size_t + +alignas +alignof +bool +catch +char16_t +char32_t +class +constexpr +const_cast +decltype +delete +dynamic_cast +explicit +export +false +friend +mutable +namespace +new +neexcept +nullptr +operator +private +protected +public +reinterpret_cast +static_assert +static_cast +template +this +thread_local +throw +true +typeid +typename +using +virtual +wchar_t + +and_eq +bitand +bitor +compl +not_eq +or_eq +xor_eq + +define +defined +elif +endif +error +ifdef +ifndef +include +pragma +undef + +exception +bad_alloc +bad_exception +bad_cast +bad_typeid +ios_base::failure +logic_error +domain_error +invalid_argument +length_error +out_of_range +runtime_error +range_error +overflow_error +underflow_error +uncaught_exception + +__DATE__ +__FILE__ +__LINE__ +__STDC__ +__STDC_HOSTED__ +__STDC_IEC_559__ +__STDC_IEC_559_COMPLEX__ +__STDC_ISO_10646__ +__STDC_VERSION__ +__TIME__ +__func__ +__cplusplus + +__BORLANDC__ +__CYGWIN__ +__CYGWIN32__ +__GNUC__ +__WIN32__ +__WINDOWS__ + +assert +ctype +errno +float +limits +locale +math +setjmp +signal +stdarg +stddef +stdio +stdlib +string +time + +complex +fenv +inttypes +iso646 +stdbool +stdint +tgmath +wchar +wctype + +algorithm +bitset +complex +deque +exception +fstream +functional +iomanip +ios +iosfwd +iostream +istream +iterator +limits +list +locale + +map +memory +numeric +ostream +queue +set +sstream +stack +stdexcept +streambuf +string +typeinfo +utility +valarray +vector + +cassert +cctype +cerrno +cfloat +climits +clocale +cmath +csetjmp +csignal +cstdarg +cstddef +cstdio +cstdlib +cstring +ctime diff --git a/c-support/wordlists/k+r.list b/c-support/wordlists/k+r.list new file mode 100644 index 0000000..805756a --- /dev/null +++ b/c-support/wordlists/k+r.list @@ -0,0 +1,108 @@ +address +allocator +allocation +argument +arithmetic +array +assignement +bitwise +block +character +command +condition +conditional +constant +conversion +declaration +decrement +defined +definition +descriptor +description +dimension +evaluation +expression +external +format +formatted +function +global +handling +identifier +implementation +increment +initialization +input +interface +label +lexical +local +logical +lookup +loop +lvalue +miscellaneous +notation +numerical +operator +operation +output +pointer +precedence +preprocessor +preprocessing +program +random +recursion +recursive +reference +referential +relational +scope +standard +statement +string +structure +system +undefined +variable + +abstract +algorithm +alignment +application +assignment +asynchronous +binary +buffer +component +constructor +container +destructor +difference +enumeration +exception +floating-point +horizontal +inheritance +instantiation +integer +internal +invariant +iterator +localization +overflow +overload +override +overwrite +polymorphic +portability +position +postcondition +precision +precondition +prototype +subscript +underflow +vertical +whitespace diff --git a/c-support/wordlists/stl_index.list b/c-support/wordlists/stl_index.list new file mode 100644 index 0000000..b5d98a3 --- /dev/null +++ b/c-support/wordlists/stl_index.list @@ -0,0 +1,202 @@ +accumulate +adjacent_difference +adjacent_find +advance +append +assign +auto_ptr +back +back_inserter +basic_string +bidirectional_iterator +bidirectional_iterator_tag +binary_compose +binary_function +binary_negate +binary_search +bind1st +bind2nd +bit_vector +bitset +capacity +char_producer +char_traits +char_type +compare +construct +copy +copy_backward +copy_n +count +count_if +deque +destroy +distance +distance_type +divides +equal +equal_range +equal_to +erase +fill +fill_n +find +find_end +find_first_not_of +find_first_of +find_if +find_last_not_of +find_last_of +for_each +forward_iterator +forward_iterator_tag +front +front_inserter +generate +generate_n +get_temporary_buffer +greater +greater_equal +hash +hash_map +hash_multimap +hash_multiset +hash_set +identity +includes +inner_product +inplace_merge +input_iterator +input_iterator_tag +insert +insert_iterator +inserter +int_type +iota +is_heap +is_sorted +istream_iterator +istream_type +istreambuf_iterator +iter_swap +iterator_category +iterator_traits +less +less_equal +lexicographical_compare +lexicographical_compare_3way +list +logical_and +logical_not +logical_or +lower_bound +make_heap +make_pair +map +max +max_element +mem_fun1_ref_t +mem_fun1_t +mem_fun_ref_t +mem_fun_t +merge +min +min_element +minus +mismatch +modulus +multimap +multiplies +multiset +negate +next_permutation +not_equal_to +nth_element +operator +ostream_iterator +ostreambuf_iterator +output_iterator +output_iterator_tag +pair +partial_sort +partial_sort_copy +partial_sum +partition +plus +pointer_to_binary_function +pointer_to_unary_function +pop_back +pop_front +pop_heap +power +prev_permutation +priority_queue +project1st +project2nd +ptr_fun +push_back +push_front +push_heap +queue +random_access_iterator +random_access_iterator_tag +random_sample +random_sample_n +random_shuffle +raw_storage_iterator +release +remove +remove_copy +remove_copy_if +remove_if +replace +replace_copy +replace_copy_if +replace_if +reset +resize +return_temporary_buffer +reverse +reverse_bidirectional_iterator +reverse_copy +reverse_iterator +rfind +rope +rotate +rotate_copy +search +search_n +select1st +select2nd +sequence_buffer +set +set_difference +set_intersection +set_symmetric_difference +set_union +slist +sort +sort_heap +stable_partition +stable_sort +stack +streambuf_type +substr +subtractive_rng +swap +swap_ranges +temporary_buffer +transform +unary_compose +unary_function +unary_negate +uninitialized_copy +uninitialized_copy_n +uninitialized_fill +uninitialized_fill_n +unique +unique_copy +upper_bound +value_comp +value_type +vector diff --git a/doc/NERD_tree.txt b/doc/NERD_tree.txt new file mode 100644 index 0000000..85737c0 --- /dev/null +++ b/doc/NERD_tree.txt @@ -0,0 +1,1095 @@ +*NERD_tree.txt* A tree explorer plugin that owns your momma! + + + + omg its ... ~ + + ________ ________ _ ____________ ____ __________ ____________~ + /_ __/ / / / ____/ / | / / ____/ __ \/ __ \ /_ __/ __ \/ ____/ ____/~ + / / / /_/ / __/ / |/ / __/ / /_/ / / / / / / / /_/ / __/ / __/ ~ + / / / __ / /___ / /| / /___/ _, _/ /_/ / / / / _, _/ /___/ /___ ~ + /_/ /_/ /_/_____/ /_/ |_/_____/_/ |_/_____/ /_/ /_/ |_/_____/_____/ ~ + + + Reference Manual~ + + + + +============================================================================== +CONTENTS *NERDTree-contents* + + 1.Intro...................................|NERDTree| + 2.Functionality provided..................|NERDTreeFunctionality| + 2.1.Global commands...................|NERDTreeGlobalCommands| + 2.2.Bookmarks.........................|NERDTreeBookmarks| + 2.2.1.The bookmark table..........|NERDTreeBookmarkTable| + 2.2.2.Bookmark commands...........|NERDTreeBookmarkCommands| + 2.2.3.Invalid bookmarks...........|NERDTreeInvalidBookmarks| + 2.3.NERD tree mappings................|NERDTreeMappings| + 2.4.The filesystem menu...............|NERDTreeFilesysMenu| + 3.Options.................................|NERDTreeOptions| + 3.1.Option summary....................|NERDTreeOptionSummary| + 3.2.Option details....................|NERDTreeOptionDetails| + 4.Hacking the NERD tree...................|NERDTreeHacking| + 5.About...................................|NERDTreeAbout| + 6.Changelog...............................|NERDTreeChangelog| + 7.Credits.................................|NERDTreeCredits| + 8.License.................................|NERDTreeLicense| + +============================================================================== +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. + +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 + * executable 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 + * ... + * Directories and files can be bookmarked. + * Most NERD tree navigation can also be done with the mouse + * Filtering of tree content (can be toggled at runtime) + * 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/move file and directory nodes as well as copy (for + supported OSs) + * 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, share trees across tabs, + or a mix of both. + * By default the script overrides the default file browser (netw), so if + you :edit a directory a (slighly modified) NERD tree will appear in the + current window + +============================================================================== +2. Functionality provided *NERDTreeFunctionality* + +------------------------------------------------------------------------------ +2.1. Global Commands *NERDTreeGlobalCommands* + +:NERDTree [ | ] *:NERDTree* + Opens a fresh NERD tree. The root of the tree depends on the argument + given. There are 3 cases: If no argument is given, the current directory + will be used. If a directory is given, that will be used. If a bookmark + name is given, the corresponding directory will be used. For example: > + :NERDTree /home/marty/vim7/src + :NERDTree foo (foo is the name of a bookmark) +< +:NERDTreeFromBookmark *:NERDTreeFromBookmark* + Opens a fresh NERD tree with the root initialized to the dir for + . This only reason to use this command over :NERDTree is for + the completion (which is for bookmarks rather than directories). + +:NERDTreeToggle [ | ] *: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. + +:NERDTreeMirror *:NERDTreeMirror* + Shares an existing NERD tree, from another tab, in the current tab. + Changes made to one tree are reflected in both as they are actually the + same buffer. + + If only one other NERD tree exists, that tree is automatically mirrored. If + more than one exists, the script will ask which tree to mirror. + +:NERDTreeClose *:NERDTreeClose* + Close the NERD tree in this tab. + +------------------------------------------------------------------------------ +2.2. Bookmarks *NERDTreeBookmarks* + +Bookmarks in the NERD tree are a way to tag files or directories of interest. +For example, you could use bookmarks to tag all of your project directories. + +------------------------------------------------------------------------------ +2.2.1. The Bookmark Table *NERDTreeBookmarkTable* + +If the bookmark table is active (see |NERDTree-B| and +|'NERDTreeShowBookmarks'|), it will be rendered above the tree. You can double +click bookmarks or use the |NERDTree-o| mapping to activate them. See also, +|NERDTree-t| and |NERDTree-T| + +------------------------------------------------------------------------------ +2.2.2. Bookmark commands *NERDTreeBookmarkCommands* + +Note that the following commands are only available in the NERD tree buffer. + +:Bookmark + Bookmark the current node as . If there is already a + bookmark, it is overwritten. must not contain spaces. + +:BookmarkToRoot + Make the directory corresponding to the new root. If a treenode + corresponding to is already cached somewhere in the tree then + the current tree will be used, otherwise a fresh tree will be opened. + Note that if points to a file then its parent will be used + instead. + +:RevealBookmark + If the node is cached under the current root then it will be revealed + (i.e. directory nodes above it will be opened) and the cursor will be + placed on it. + +:OpenBookmark + must point to a file. The file is opened as though |NERDTree-o| + was applied. If the node is cached under the current root then it will be + revealed and the cursor will be placed on it. + +:ClearBookmarks [] + Remove all the given bookmarks. If no bookmarks are given then remove all + bookmarks on the current node. + +:ClearAllBookmarks + Remove all bookmarks. + +:ReadBookmarks + Re-read the bookmarks in the |'NERDTreeBookmarksFile'|. + +See also |:NERDTree| and |:NERDTreeFromBookmark|. + +------------------------------------------------------------------------------ +2.2.3. Invalid Bookmarks *NERDTreeInvalidBookmarks* + +If invalid bookmarks are detected, the script will issue an error message and +the invalid bookmarks will become unavailable for use. + +These bookmarks will still be stored in the bookmarks file (see +|'NERDTreeBookmarksFile'|), down the bottom. There will always be a blank line +after the valid bookmarks but before the invalid ones. + +Each line in the bookmarks file represents one bookmark. The proper format is: + + +After you have corrected any invalid bookmarks, either restart vim, or go +:ReadBookmarks from the NERD tree window. + +------------------------------------------------------------------------------ +2.3. NERD tree Mappings *NERDTreeMappings* + +Default Description~ help-tag~ +Key~ + +o.......Open files, directories and bookmarks....................|NERDTree-o| +go......Open selected file, but leave cursor in the NERDTree.....|NERDTree-go| +t.......Open selected node/bookmark in a new tab.................|NERDTree-t| +T.......Same as 't' but keep the focus on the current tab........|NERDTree-T| +i.......Open selected file in a split window.....................|NERDTree-i| +gi......Same as i, but leave the cursor on the NERDTree..........|NERDTree-gi| +s.......Open selected file in a new vsplit.......................|NERDTree-s| +gs......Same as s, but leave the cursor on the NERDTree..........|NERDTree-gs| +!.......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.......Edit the current dif.....................................|NERDTree-e| + +...............same as |NERDTree-o|. +double-click.......same as the |NERDTree-o| map. +middle-click.......same as |NERDTree-i| for files, same as + |NERDTree-e| for dirs. + +D.......Delete the current bookmark .............................|NERDTree-D| + +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| +...Jump down to the next sibling of the current directory...|NERDTree-C-J| +...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| + +I.......Toggle whether hidden files displayed....................|NERDTree-I| +f.......Toggle whether the file filters are used.................|NERDTree-f| +F.......Toggle whether files are displayed.......................|NERDTree-F| +B.......Toggle whether the bookmark table is displayed...........|NERDTree-B| + +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. + +If a bookmark that links to a directory is selected then that directory +becomes the new root. + +If a bookmark that links to a file is selected then that file is opened in the +previous window. + +------------------------------------------------------------------------------ + *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 fresh +NERD Tree for that directory is opened in a new tab. + +If a bookmark which points to a directory is selected, open a NERD tree for +that directory in a new tab. If the bookmark points to a file, open that file +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-i* +Default key: i +Map option: NERDTreeMapOpenSplit +Applies to: files. + +Opens the selected file in a new split window and puts the cursor in the new +window. + +------------------------------------------------------------------------------ + *NERDTree-gi* +Default key: gi +Map option: None +Applies to: files. + +The same as |NERDTree-i| except that the cursor is not moved. + +The key combo for this mapping is always "g" + NERDTreeMapOpenSplit (see +|NERDTree-i|). + +------------------------------------------------------------------------------ + *NERDTree-s* +Default key: s +Map option: NERDTreeMapOpenVSplit +Applies to: files. + +Opens the selected file in a new vertically split window and puts the cursor in +the new window. + +------------------------------------------------------------------------------ + *NERDTree-gs* +Default key: gs +Map option: None +Applies to: files. + +The same as |NERDTree-s| except that the cursor is not moved. + +The key combo for this mapping is always "g" + NERDTreeMapOpenVSplit (see +|NERDTree-s|). + +------------------------------------------------------------------------------ + *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 its contents are not +cached. 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. + +|:edit|s the selected directory, or the selected file's directory. This could +result in a NERD tree or a netrw being opened, depending on +|'NERDTreeHijackNetrw'|. + +------------------------------------------------------------------------------ + *NERDTree-D* +Default key: D +Map option: NERDTreeMapDeleteBookmark +Applies to: lines in the bookmarks table + +Deletes the currently selected bookmark. + +------------------------------------------------------------------------------ + *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: +Map option: NERDTreeMapJumpNextSibling +Applies to: files and directories. + +Jump to the next sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C-K* +Default key: +Map option: NERDTreeMapJumpPrevSibling +Applies to: files and directories. + +Jump to the previous sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C* +Default key: C +Map option: NERDTreeMapChdir +Applies to: directories. + +Make the selected directory node the new tree root. If a file is selected, its +parent is used. + +------------------------------------------------------------------------------ + *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-cd* +Default key: cd +Map option: NERDTreeMapChdir +Applies to: files and directories. + +Change vims current working directory to that of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-I* +Default key: I +Map option: NERDTreeMapToggleHidden +Applies to: no restrictions. + +Toggles whether hidden files (i.e. "dot files") are displayed. + +------------------------------------------------------------------------------ + *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-B* +Default key: B +Map option: NERDTreeMapToggleBookmarks +Applies to: no restrictions. + +Toggles whether the bookmarks table is 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. + +|'NERDTreeHijackNetrw'| Tell the NERD tree whether to replace the netrw + autocommands for exploring local directories. + +|'NERDTreeIgnore'| Tells the NERD tree which files to ignore. + +|'NERDTreeBookmarksFile'| Where the bookmarks are stored. + +|'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse + clicks. + +|'NERDTreeQuitOnOpen'| Closes the tree window after opening a file. + +|'NERDTreeShowBookmarks'| Tells the NERD tree whether to display the + bookmarks table on startup. + +|'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. + +|'NERDTreeShowLineNumbers'| Tells the NERD tree whether to display line + numbers in the tree window. + +|'NERDTreeSortOrder'| Tell the NERD tree how to sort the nodes in + the tree. + +|'NERDTreeStatusline'| Set a statusline for NERD tree windows. + +|'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: 0. + +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. + +------------------------------------------------------------------------------ + *'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. + +------------------------------------------------------------------------------ + *'NERDTreeHijackNetrw'* +Values: 0 or 1. +Default: 1. + +If set to 1, doing a > + :edit +< +will open up a "secondary" NERD tree instead of a netrw in the target window. + +Secondary NERD trees behaves slighly different from a regular trees in the +following respects: + 1. 'o' will open the selected file in the same window as the tree, + replacing it. + 2. you can have as many secondary tree as you want in the same tab. + +------------------------------------------------------------------------------ + *'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. + +------------------------------------------------------------------------------ + *'NERDTreeBookmarksFile'* +Values: a path +Default: $HOME/.NERDTreeBookmarks + +This is where bookmarks are saved. See |NERDTreeBookmarkCommands|. + +------------------------------------------------------------------------------ + *'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'. + +------------------------------------------------------------------------------ + *'NERDTreeQuitOnOpen'* + +Values: 0 or 1. +Default: 0 + +If set to 1, the NERD tree window will close after opening a file with the +|NERDTree-o| or |NERDTree-i| mappings. + +------------------------------------------------------------------------------ + *'NERDTreeShowBookmarks'* +Values: 0 or 1. +Default: 0. + +If this option is set to 1 then the bookmarks table will be displayed. + +This option can be toggled dynamically, per tree, with the |NERDTree-B| +mapping. + +------------------------------------------------------------------------------ + *'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, per tree, 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, per tree, with the |NERDTree-I| mapping. Use one +of the follow lines to set this option: > + let NERDTreeShowHidden=0 + let NERDTreeShowHidden=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeShowLineNumbers'* +Values: 0 or 1. +Default: 0. + +This option tells vim whether to display line numbers for the NERD tree +window. Use one of the follow lines to set this option: > + let NERDTreeShowLineNumbers=0 + let NERDTreeShowLineNumbers=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. Everything 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. + +------------------------------------------------------------------------------ + *'NERDTreeStatusline'* +Values: Any valid statusline setting. +Default: %{b:NERDTreeRoot.path.strForOS(0)} + +Tells the script what to use as the |'statusline'| setting for NERD tree +windows. + +Note that the statusline is set using |:let-&| not |:set| so escaping spaces +isn't necessary. + +Setting this option to -1 will will deactivate it so that your global +statusline setting is used instead. + +------------------------------------------------------------------------------ + *'NERDTreeWinPos'* +Values: "left" or "right" +Default: "left". + +This option is used to determine where NERD tree window is placed on the +screen. + +This option makes it possible to use two different explorer 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. + +============================================================================== +4. Hacking the NERD tree *NERDTreeHacking* + +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 files/directories the tree nodes represent. + +The NERD tree filetype ~ + +NERD tree buffers have a filetype of "nerdtree". You can use this to hack the +NERD tree via autocommands (on |FileType|) or via an ftplugin. + +For example, putting this code in ~/.vim/ftplugin/nerdtree.vim would override +the o mapping, making it open the selected node in a new gvim instance. > + + nnoremap o :call openInNewVimInstance() + function! s:openInNewVimInstance() + let p = NERDTreeGetCurrentPath() + if p != {} + silent exec "!gvim " . p.strForOS(1) . "&" + endif + endfunction +< +This way you can add new mappings or :commands or override any existing +mapping. + +============================================================================== +5. About *NERDTreeAbout* + +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 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 ;) + +The latest stable versions can be found at + http://www.vim.org/scripts/script.php?script_id=1658 + +The latest dev versions are on github + http://github.com/scrooloose/nerdtree + + +============================================================================== +6. Changelog *NERDTreeChangelog* + +3.1.1 + - fix a bug where a non-listed no-name buffer was getting created every + time the tree windows was created, thanks to Derek Wyatt and owen1 + - make behave the same as the 'o' mapping + - some helptag fixes in the doc, thanks strull + - fix a bug when using :set nohidden and opening a file where the previous + buf was modified. Thanks iElectric + - other minor fixes + +3.1.0 + New features: + - add mappings to open files in a vsplit, see :help NERDTree-s and :help + NERDTree-gs + - make the statusline for the nerd tree window default to something + hopefully more useful. See :help 'NERDTreeStatusline' + Bugfixes: + - make the hijack netrw functionality work when vim is started with "vim + " (thanks to Alf Mikula for the patch). + - fix a bug where the CWD wasnt being changed for some operations even when + NERDTreeChDirMode==2 (thanks to Lucas S. Buchala) + - add -bar to all the nerd tree :commands so they can chain with other + :commands (thanks to tpope) + - fix bugs when ignorecase was set (thanks to nach) + - fix a bug with the relative path code (thanks to nach) + - fix a bug where doing a :cd would cause :NERDTreeToggle to fail (thanks nach) + + +3.0.1 + Bugfixes: + - fix bugs with :NERDTreeToggle and :NERDTreeMirror when 'hidden + was not set + - fix a bug where :NERDTree would fail if was relative and + didnt start with a ./ or ../ Thanks to James Kanze. + - make the q mapping work with secondary (:e style) trees, + thanks to jamessan + - fix a bunch of small bugs with secondary trees + + More insane refactoring. + +3.0.0 + - hijack netrw so that doing an :edit will put a NERD tree in + the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw' + - allow sharing of trees across tabs, see :help :NERDTreeMirror + - remove "top" and "bottom" as valid settings for NERDTreeWinPos + - change the '' mapping to 'i' + - change the 'H' mapping to 'I' + - lots of refactoring + +============================================================================== +7. Credits *NERDTreeCredits* + +Thanks to the following people for testing, bug reports, ideas etc. Without +you I probably would have got bored of the hacking the NERD tree and +just downloaded pr0n instead. + + Tim Carey-Smith (halorgium) + Vigil + Nick Brettell + Thomas Scott Urban + Terrance Cohen + Yegappan Lakshmanan + Jason Mills + Michael Geddes (frogonwheels) + Yu Jun + Michael Madsen + AOYAMA Shotaro + Zhang Weiwu + Niels Aan de Brugh + Olivier Yiptong + Zhang Shuhan + Cory Echols + Piotr Czachur + Yuan Jiang + Matan Nassau + Maxim Kim + Charlton Wang + Matt Wozniski (godlygeek) + knekk + Sean Chou + Ryan Penn + Simon Peter Nicholls + Michael Foobar + Tomasz Chomiuk + Denis Pokataev + Tim Pope (tpope) + James Kanze + James Vega (jamessan) + Frederic Chanal (nach) + Alf Mikula + Lucas S. Buchala + +============================================================================== +8. License *NERDTreeLicense* + +The NERD tree is released under the wtfpl. +See http://sam.zoy.org/wtfpl/COPYING. diff --git a/doc/alternate.txt b/doc/alternate.txt new file mode 100644 index 0000000..1369494 --- /dev/null +++ b/doc/alternate.txt @@ -0,0 +1,177 @@ + +*alternate.txt* Alternate Plugin Sat May 13 15:35:38 CDT 2006 + +Author: Michael Sharpe +Copyright: (c) 2000-2006 Michael Sharpe + We grant permission to use, copy modify, distribute, and sell this + software for any purpose without fee, provided that the above + copyright notice and this text are not removed. We make no guarantee + about the suitability of this software for any purpose and we are + not liable for any damages resulting from its use. Further, we are + under no obligation to maintain or extend this software. It is + provided on an "as is" basis without any expressed or implied + warranty. + +============================================================================== +1. Contents *AS* *AV* *AT* *AN* *IH* *IHS* *IHV* *IHT* *IHN* *alternate* + + 1. Contents...........................: |alternate| + 2. Purpose............................: |alternate-purpose| + 3. Commands...........................: |alternate-commands| + 4. Configuration......................: |alternate-config| + 5. Installation.......................: |alternate-installation| + 6. Bugs/Enhancements..................: |alternate-support| + 7. Acknowledgments....................: |alternate-acknowledgments| + +============================================================================== +2. Purpose *alternate-purpose* + +The purpose of a.vim is to allow quick and easy switching between source files +and corresponding header files. Many languages (C, C++, ada, ocaml, lex/yacc) +have the concept of source/header files or the like. It is quite common during +development or review to need to edit both files together. This plugin attempts +to simplify that process. There are commands which while editing a source +file allow for the quick switching to the corresponding header and vice versa. +The only difference between the commands is how the switch occurs. More recent +functionality allow the switching to a file under the cursor too. In the +following sections the commands, configuration and installation procedures are +described. + +============================================================================== +3. Commands *alternate-commands* + +There are 4 commands provided by this plugin. They are + +:A switches to the header file corresponding to the source file in the current + buffer (or vice versa). + +:AS similar to :A except the current buffer is split horizontally such that the + source file is on one split and the header is in the other. + +:AV similar to :AS except that the split is vertical + +:AT similar to :AS and :AV except a new tab is opened instead of a split + +:IH switches to the file under cursor (or the file specified with the + command). This command uses the builtin a.vim search path support and the + &path variable in conjunction. + +:IHS similar to :IH execpt the current buffer is split horizontally first + +:IHS similar to :IH execpt the current buffer is split vertically first + +:IHS similar to :IH execpt a new tab is created for the file being switched to + +:IHN switches to the next matching file for the original selection + +In all cases if the corresponding alternate file is already loaded that buffer +is preferred. That is this plugin will never load the same file twice. + +Some maps are also provided for the IH command (mainly for example purposes) +ih - switches to the file under the cursor using the :IHS command +is - switches to the source file of the header file under the cursor + using the :IHS command and the :A command +ihn - switches to the next match in the sequence. + +============================================================================== +4. Configuration *alternate-config* + +It is possible to configure three separate pieces of behaviour of this plugin. + +a) Extensions: Each language has different extensions for identifying the +source and header files. Many languages support multiple different but related +extensions. As such this plugin allow for the complete specification of how +source and header files correspond to each other via extension maps. There are +a number of maps built in. For example, the following variable setting + + g:alternateExtensions_CPP = "inc,h,H,HPP,hpp" + +indicates that any file with a .CPP exetension can have a corresponding file +with any of the .inc, .h, .H, .HPP, .hpp extension. The inverse is not +specified by this map though. Typically each extension will have a mapping. So +there would exist maps for .h, .inc, .H, .HPP, .hpp too. Extension maps should +be specified before loading this plugin. Some of the builtin extension maps are +as follows, + +C and C++ +g:alternateExtensions_h = "c,cpp,cxx,cc,CC" +g:alternateExtensions_H' = "C,CPP,CXX,CC" +g:alternateExtensions_cpp' = "h,hpp" +g:alternateExtensions_CPP' = "H,HPP" +g:alternateExtensions_c' = "h" +g:alternateExtensions_C' = "H" +g:alternateExtensions_cxx' = "h" + +Ada +g:alternateExtensions_adb' = "ads" +g:alternateExtensions_ads' = "adb" + +Lex/Yacc +g:alternateExtensions_l' = "y,yacc,ypp" +g:alternateExtensions_lex' = "yacc,y,ypp" +g:alternateExtensions_lpp' = "ypp,y,yacc" +g:alternateExtensions_y' = "l,lex,lpp" +g:alternateExtensions_yacc' = "lex,l,lpp" +g:alternateExtensions_ypp' = "lpp,l,lex" + +b) Search Paths: In many projects the location of the source files and the +corresponding header files is not always the same directory. This plugin allows +the search path it uses to locate source and header files to be configured. +The search path is specified by setting the g:alternateSearchPath variable. The +default setting is as follows, + + g:alternateSearchPath = 'sfr:../source,sfr:../src,sfr:../include,sfr:../inc' + +This indicates that the corresponding file will be searched for in ../source, +../src. ../include and ../inc all relative to the current file being switched +from. The value of the g:alternateSearchPath variable is simply a comma +separated list of prefixes and directories. The "sfr:" prefix indicates that +the path is relative to the file. Other prefixes are "wdr:" which indicates +that the directory is relative to the current working directory and "abs:" +which indicates the path is absolute. If no prefix is specified "sfr:" is +assumed. + +c) Regex Paths: Another type of prefix which can appear in the +g:alternateSearchPath variable is that of "reg:". It is used to apply a regex +to the path of the file in the buffer being switched from to locate the +alternate file. E.g. 'reg:/inc/src/g/' will replace every instance of 'inc' +with 'src' in the source file path. It is possible to use match variables so +you could do something like: 'reg:|src/\([^/]*\)|inc/\1||' (see |substitute|, +|help pattern| and |sub-replace-special| for more details. The exact syntax of +a "reg:" specification is + reg: + + seperator character, we often use one of [/|%#] + is what you are looking for + is the output pattern + can be g for global replace or empty + +d) No Alternate Behaviour: When attempting to alternate/switch from a +source/header to its corresponding file it is possible that the corresponding +file does not exist. In this case this plugin will create the missing alternate +file in the same directory as the current file. Some users find this behaviour +irritating. This behaviour can be disabled by setting +g:alternateNoDefaultAlternate to 1. When this variable is not 0 a message will +be displayed indicating that no alternate file exists. + +============================================================================== +5. Installation *alternate-installation* + +To install this plugin simply drop the a.vim file in to $VIMRUNTIME/plugin +(global or local) or simply source the file from the vimrc file. Ensure that +any configuration occurs before the plugin is loaded/sourced. + +============================================================================== +6. Bugs/Enhancements *alternate-support* + +Whilst no formal support is provided for this plugin the author is always happy +to receive bug reports and enhancement requests. Please email all such +reports/requests to feline@irendi.com. + +============================================================================== +7. Acknowledgments *alternate-acknowledgments* + +The author would like to thank everyone who has submitted bug reports and +feature enhancement requests in the past. In particular Bindu Wavell provided +much of the original code implementing the search path and regex functionality. +vim:tw=78:ts=8:ft=help diff --git a/doc/csupport.txt b/doc/csupport.txt new file mode 100644 index 0000000..c7b9113 --- /dev/null +++ b/doc/csupport.txt @@ -0,0 +1,2257 @@ +*csupport.txt* C/C++ Support December 28 2011 + +C/C++ Support *c-support* *csupport* + Plugin version 5.17 + for Vim version 7.0 and above + Fritz Mehner + +C/C++-IDE for Vim/gVim. It is written to considerably speed up writing code in +a consistent style. This is done by inserting complete statements,idioms, +code snippets, templates, and comments. Syntax checking, compiling, running +a program, running a code checker or a reformatter can be done with a +keystroke. + + 1. Usage |csupport-usage-gvim| + 1.1 Menu 'Comments' |csupport-comm| + 1.1.1 Append aligned comments |csupport-comm-aligned| + 1.1.2 Adjust end-of-line comments |csupport-comm-realign| + 1.1.3 Code to comment |csupport-code-to-comm| + 1.1.4 Comment to code |csupport-comm-to-code| + 1.1.5 Frame comments, file header, ... |csupport-comm-frame| + 1.1.6 File section comments .. |csupport-comm-sections| + 1.1.7 Keyword comment, special comment |csupport-comm-keyword| + 1.1.8 Tags (plugin) |csupport-comm-tags| + 1.1.9 Date and date+time |csupport-comm-date| + 1.1.10 C to C++ comments and vice versa |csupport-comm-c-cpp| + 1.2 Menu 'Statements' |csupport-stat| + 1.2.1 Normal mode, insert mode. |csupport-stat-normal-mode| + 1.2.2 Visual mode. |csupport-stat-visual-mode| + 1.3 Menu 'Preprocessor' |csupport-prep| + 1.3.1 Normal mode, insert mode. |csupport-prep-normal-mode| + 1.3.2 Visual mode. |csupport-prep-visual-mode| + 1.3.3 Block out code with #if 0 .. #endif |csupport-prep-if0| + 1.3.4 Ex-commands |csupport-prep-ex| + 1.4 Menu 'Idioms' |csupport-idioms| + 1.4.1 Item 'function' |csupport-idioms-function| + 1.4.2 for-loop control |csupport-idioms-for-loop| + 1.4.3 Item 'open input file' |csupport-idioms-input| + 1.4.4 Item 'open output file' |csupport-idioms-output| + 1.5 Menu 'Snippets' |csupport-snippets| + 1.5.1 Code snippets |csupport-snippets| + 1.5.2 Picking up prototypes |csupport-proto| + 1.5.3 Code templates |csupport-templates-menu| + 1.6 Menu 'C++' |csupport-c++| + 1.6.1 Normal mode, insert mode. |csupport-c++-normal-mode| + 1.6.2 Visual mode. |csupport-c++-visual-mode| + 1.6.3 Method implementation |csupport-c++-method-impl| + 1.6.4 Ex commands |csupport-c++-ex| + 1.7 Menu 'Run' |csupport-run| + 1.7.1 Minimal make functionality |csupport-run-buffer| + 1.7.2 Command line arguments |csupport-run-cmdline-args| + 1.7.3 Run make |csupport-run-make| + 1.7.4 Choose Makefile |csupport-choose-makefile| + 1.7.4 Executable to run |csupport-run-make-run| + 1.7.6 Run make clean |csupport-run-make-clean| + 1.7.7 Command line arguments for make |csupport-run-make-args| + 1.7.8 Splint |csupport-run-splint| + 1.7.9 CodeCheck |csupport-run-codecheck| + 1.7.10 Indent |csupport-run-indent| + 1.7.11 Hardcopy |csupport-run-hardcopy| + 1.7.12 Rebuild templates |csupport-run-templates| + 1.7.13 Xterm size |csupport-run-xterm| + 1.7.14 Output redirection |csupport-run-output| + 1.8 Help |csupport-help| + + 2. Usage without GUI |csupport-usage-vim| + 3. Hotkeys |csupport-hotkeys| + 4. Customization and configuration |csupport-custom| + 4.1 Global variables |csupport-custom-glob-vars| + 4.2 The root menu |csupport-custom-root| + 4.3 System-wide installation |csupport-system-wide| + 5. Template files and tags |csupport-templates| + 5.1 Template files |csupport-templates-files| + 5.2 Macros |csupport-templates-macros| + 5.2.1 User defined formats for date and time |csupport-templates-date| + 5.3 Templates |csupport-templates-names| + 5.3.1 Template names |csupport-templates-names| + 5.3.2 Template definition |csupport-templates-definition| + 5.3.3 Template expansion |csupport-templates-expansion| + 5.3.4 The macros <+text+> etc. |csupport-templates-jump| + 5.3.5 Command Ctrl-j |csupport-Ctrl-j| + 5.4 Switching between template sets |csupport-templates-sets| + 5.5 Binding a style to a file extension |csupport-templates-bind| + 6. C/C++ Dictionaries |csupport-dictionary| + 7. Extend ctags |csupport-ctags| + 7.1 Make and qmake |csupport-ctags-make| + 7.2 Templates |csupport-ctags-templates| + 8. Folding |csupport-folding| + 9 Additional Mappings |csupport-ad-mappings| + 10. Windows particularities |csupport-windows| + 11. Additional tips |csupport-tips| + 12. Troubleshooting |csupport-troubleshooting| + 13. Release Notes /Change Log |csupport-release-notes| + + How to add this help file to Vim's help |add-local-help| + + +============================================================================== +1. USAGE WITH GUI (gVim) *csupport-usage-gvim* +============================================================================== + +If the root menu 'C/C++' is not visible call it with the item "Load C Support" +from the standard Tools-menu. +The item "Load C Support" can also be used to unload the C/C++-root menu. + +Nearly all menu entries insert code snippets or comments. All of these are +contained within template files and can be changed by the user to meet their +requirements (see|csupport-templates|). + +------------------------------------------------------------------------------ +1.1 MENU 'Comments' *csupport-comm* +------------------------------------------------------------------------------ + +1.1.1 APPEND ALIGNED COMMENTS TO CONSECUTIVE LINES *csupport-comm-aligned* + +In NORMAL MODE, the menu item 'end-of-line comment' will append a comment to +the current line. +In VISUAL MODE, this item will append aligned comments to all marked lines. +Marking the first 4 lines + + print_double_array ( double array[], + int n, + int columns, + char* arrayname + ) + +and choosing 'end-of-line com. /**/' will yield. + + print_double_array ( double array[], /* */ + int n, /* */ + int columns, /* */ + char* arrayname /* */ + ) /* */ + +If one or more lines go beyond the starting column (s.below), the comments +will start at the second column after the longest line. The cursor will then +be positioned inside the first comment. + +The default starting column is 49 ( = (multiple of 2,4, or 8) + 1 ). This can +be changed by setting a global variable in the file ~/.vimrc , e.g. : + + let g:C_LineEndCommColDefault = 45 + +The starting column can also be set by the menu item +'Comments->set end-of-line com. col'. Just position the cursor in an +arbitrary column (column number is shown in the Vim status line) and choose +this menu item. This setting is buffer related. + +If the cursor was at the end of a line you will be asked for a column number +because this position is most likely not the desired starting column. +Your choice will be confirmed. + +------------------------------------------------------------------------------ + +1.1.2 ADJUST END-OF-LINE COMMENTS *csupport-comm-realign* + +After some changes end-of-line comments may be no longer aligned: + + print_double_array ( double array[], /* */ + long int n, /* */ + unsigned int columns, /* */ + char* a_name /* */ + ) /* */ + +Realignment can be achieved with the menu item 'adjust end-of-line com.' In +normal mode the comment (if any) in the current line will be aligned to the +end-of-line comment column (see above) if possible. In visual mode the +comments in the marked block will be aligned: + + print_double_array ( double array[], /* */ + long int n, /* */ + unsigned int columns, /* */ + char* a_name /* */ + ) /* */ + +The realignment will not be done for comments with nothing else than leading +whitespaces. These comments are usually captions: + + max = other.max; /* the maximum value */ + len = other.len; /* the length */ + /* ===== the next section ===== */ + pos = (x+y+z)/3.0; /* the next position */ + +After the alignment we have: + + max = other.max; /* the maximum value */ + len = other.len; /* the length */ + /* ===== the next section ===== */ + pos = (x+y+z)/3.0; /* the next position */ + +------------------------------------------------------------------------------ + +1.1.3 CODE TO COMMENT *csupport-code-to-comm* + +The marked block + +xxxxxxxx +xxxxxxxx +xxxxxxxx + +will be changed by the menu item 'code->comment /**/' into the multiline +comment (all (partially) marked lines): + +/* xxxxxxxx + * xxxxxxxx + * xxxxxxxx + */ + +The marked block will be changed by the menu item 'code->comment //' into the +multiline comment + +//xxxxxxxx +//xxxxxxxx +//xxxxxxxx + +The menu items works also for a single line. A single line needs not to be +marked. + +------------------------------------------------------------------------------ + +1.1.4 COMMENT TO CODE *csupport-comm-to-code* + +If one (or more) complete comment (i.e. all lines belonging to the comment) is +marked the item 'comment->code' will uncomment it. If the following lines +are marked + + * printf ("\n"); + */ + + printf ("\n"); + + // printf ("\n"); + // + + /* + * printf ("\n"); + */ + +uncommenting will yield + + * printf ("\n"); + */ + + printf ("\n"); + + printf ("\n"); + + + + printf ("\n"); + +The first 2 lines are only a part of a C-comment and remain unchanged. +A C-comment can start with /* , /** or /*! . + +The menu item works also for a single line with a leading // . A single line +needs not to be marked. + +------------------------------------------------------------------------------ + +1.1.5 FRAME COMMENTS, FILE HEADER, ... *csupport-comm-frame* + +Frame comments, file header comments and function, methods, class descriptions +are read as templates from the appropriate files (see |csupport-templates|). + +There are two file description templates (menu items 'file description (impl.)' +and 'file description (header)', see also |csupport-templates|): + + comment.file-description : files *.c *.cc *.cp *.cxx *.cpp *.CPP *.c++ + *.C *.i *.ii + + comment.file-description-header : everything else with filetype 'c' or 'cpp' + +The appropriate template will also be included into a new file. The plugin +decides on the basis of the file extension. The default is shown above. You +can change the list by setting a global variable in '~/.vimrc': + + au BufRead,BufNewFile *.XYZ set filetype=c + + let g:C_SourceCodeExtensions = 'XYZ c cc cp cxx cpp CPP c++ C i ii' + +A new file named 'test.XYZ' will now be considered a C implementation file. + +------------------------------------------------------------------------------ + +1.1.6 FILE SECTION COMMENTS *csupport-comm-sections* + +File section comments can be uses to separate typical C- and H-file sections +with comments of similar appearance, e.g. + +/* ##### HEADER FILE INCLUDES ################################################### */ + +/* ##### MACROS - LOCAL TO THIS SOURCE FILE ################################### */ + +/* ##### TYPE DEFINITIONS - LOCAL TO THIS SOURCE FILE ######################### */ + +These section comments can also be inserted using the hotkey \ccs for C/C++ +files, or \chs for H-files. These hotkeys will start the command +'CFileSection' or 'HFileSection' on the command line: + + :CFileSection + :HFileSection + +Now type a to start the selection menu to choose from. + +------------------------------------------------------------------------------ + +1.1.7 KEYWORD COMMENT, SPECIAL COMMENT *csupport-comm-keyword* + +Keword comments are end-of-line comments: + + /* :::: */ + +Keywords are + + BUG COMPILER TODO TRICKY WARNING WORKAROUND user-defined-keyword + +These are preliminary comments to document places where work will be resumed +shortly. They are usually not meant for the final documentation. These +comments are easily found by searching for the keyword. +The keyword comments can also be inserted using the hotkey \ckc . This hotkey +starts the command 'KeywordComment' on the command line: + + :KeywordComment + +Now type a to start the selection menu to choose from. + +Special comments are occasionally used to mark special features of a code +construct (e.g. a fall through cases in a switch statement, an empty loop): + + /* EMPTY */ + /* NOT REACHED */ + /* REMAINS TO BE IMPLEMENTED */ + .... + +The special comments can also be inserted using the hotkey \csc . This hotkey +starts the command 'SpecialComment' on the command line: + + :SpecialComment + +Now type a to start the selection menu to choose from. + +------------------------------------------------------------------------------ + +1.1.8 TAGS (PLUGIN) *csupport-comm-tags* + +The submenu 'tags (plugin)' let you insert the predefined macros from the +template system (see|csupport-templates-macros|). In visual mode the marked +string will be replaced by the macro. + +------------------------------------------------------------------------------ + +1.1.9 DATE AND DATE+TIME *csupport-comm-date* + +The format for 'date' and 'date time' can be defined by the user (see +|csupport-templates-date|). In visual mode the marked string will be replaced +by the macro (e.g. to update date and time). + +------------------------------------------------------------------------------ + +1.1.10 C TO C++ COMMENTS AND VICE VERSA *csupport-comm-c-cpp* + +The menu item '/* xxx */ <-> // xxx' changes a C++ comment into a C comment +and a C++ comment into a C comment (toggle). +This is done for the current line in normal or insert mode and for a marked +area of lines in visual mode. +The hotkey \cx does the same. It can be used with a range: + 3\cx +changes the current line and the next 2 lines. + +------------------------------------------------------------------------------ +1.2 MENU 'Statements' *csupport-stat* +------------------------------------------------------------------------------ + +1.2.1 NORMAL MODE, INSERT MODE. *csupport-stat-normal-mode* + +An empty statement will be inserted and properly indented. The item 'if{}' +will insert an if-statement: + +if ( ) +{ +} + + +1.2.2 VISUAL MODE. *csupport-stat-visual-mode* + +STATEMENTS WITH BLOCKS AND CASE LABEL. +-------------------------------------- +The highlighted area + +xxxxx +xxxxx + +can be surrounded by one of the following statements: + + +----------------------------+-----------------------------+ + | if ( ) | if ( ) | + | { | { | + | xxxxx | xxxxx | + | xxxxx | xxxxx | + | } | } | + | | else | + | | { | + | | } | + +----------------------------+-----------------------------+ + | for ( ; ; ) | while ( ) | + | { | { | + | xxxxx | xxxxx | + | xxxxx | xxxxx | + | } | } | + +----------------------------+-----------------------------+ + | do | | + | { | { | + | xxxxx | xxxxx | + | xxxxx | xxxxx | + | } | } | + | while ( ); | | + +----------------------------+-----------------------------+ + | switch ( ) { | + | case : | + | break; | + | | + | case : | + | break; | + | | + | case : | + | break; | + | | + | case : | + | break; | + | | + | default: | + | break; | + | } | + +----------------------------+-----------------------------+ + +The whole statement will be indented after insertion. + + +STATEMENTS WITHOUT BLOCKS. +-------------------------- +One of the following statements can be inserted: + + +-------------------------------+--------------------------+ + | if ( ) | for ( ; ; ) | + +-------------------------------+--------------------------+ + | if ( ) | while ( ) | + | else | | + +-------------------------------+--------------------------+ + | case : | | + | break; | | + +-------------------------------+--------------------------+ + + +------------------------------------------------------------------------------ +1.3 MENU 'Preprocessor' *csupport-prep* +------------------------------------------------------------------------------ + +1.3.1 NORMAL MODE, INSERT MODE. *csupport-prep-normal-mode* + +The preprocessor statements will be inserted and properly indented. + +1.3.2 VISUAL MODE. *csupport-prep-visual-mode* + +STATEMENTS WITH BLOCKS +---------------------- +The highlighted area + +xxxxx +xxxxx + +can be surrounded by one of the following statements: + + +----------------------------+-----------------------------+ + | #if CONDITION | + | xxxxx | + | xxxxx | + | #else /* ----- #if CONDITION ----- */ | + | | + | #endif /* ----- #if CONDITION ----- */ | + +----------------------------------------------------------+ + | #ifdef CONDITION | + | xxxxx | + | xxxxx | + | #else /* ----- #ifdef CONDITION ----- */ | + | | + | #endif /* ----- #ifdef CONDITION ----- */ | + +----------------------------------------------------------+ + | #ifndef CONDITION | + | xxxxx | + | xxxxx | + | #else /* ----- #ifndef CONDITION ----- */ | + | | + | #endif /* ----- #ifndef CONDITION ----- */ | + +----------------------------------------------------------+ + | #ifndef INC_TEST | + | #define INC_TEST | + | xxxxx | + | xxxxx | + | #endif /* ----- #ifndef INC_TEST ----- */ | + +----------------------------------------------------------+ + | #if 0 /* ----- #if 0 : If0Label_1 ----- */ | + | | + | #endif /* ----- #if 0 : If0Label_1 ----- */ | + +----------------------------------------------------------+ + +The macro name for an include guard (e.g. INC_TEST above) will be derived as a +suggestion from the file name. + +1.3.3 BLOCK OUT CODE WITH #if 0 ... #endif *csupport-prep-if0* + +The menu item #if 0 #endif inserts the lines + + #if 0 /* ----- #if 0 : If0Label_1 ----- */ + + #endif /* ----- #if 0 : If0Label_1 ----- */ + +In visual mode the marked block of lines will be surrounded by these lines. + +This is usually done to temporarily block out some code. The label names like +If0Label_1 are automatically inserted into the comments. The trailing numbers +are automatically incremented. These numbers can be changed by the user. The +next number will be one above the highest number found in the current buffer. + +A corresponding label can be found by searching with the vim star command (*). +All labels can be found with a global search like :g/If0Label_/ or +:g/If0Label_\d\+/. All corresponding lines can be deleted with :g/If0Label_/d . + + +REMOVE THE ENCLOSING #if 0 ... #endif -CONSTRUCT. + +The menu item 'remove #if #endif' removes such a construct if the cursor is +in the middle of such a section or on one of the two enclosing lines. Nested +constructs will be untouched. + +1.3.4 EX-COMMANDS *csupport-prep-ex* + +There are 4 additional Ex command which can be used to insert include +statements: + + Ex command hotkey includes + ------------------------------------------------------------------------- + :IncludeStdLibrary \ps C standard library + :IncludeC99Library \pc C99 library + :IncludeCppLibrary \+ps C++ standard library + :IncludeCppCLibrary \+pc C standard library ( #include ) + +Type :Inc and choose one of the commands. Now type an additional space +and a to show the whole list list or type a space and a few leading +characters to reduce this list. + +------------------------------------------------------------------------------ +1.4 MENU 'Idioms' *csupport-idioms* +------------------------------------------------------------------------------ + +1.4.1 Item 'function' *csupport-idioms-function* + +NORMAL MODE, INSERT MODE: +The name of the function is asked for and the following lines (for function +name "f") will be inserted: + + void + f ( ) + { + return ; + } /* ---------- end of function f ---------- */ + +VISUAL MODE: +Main or [static] function: the highlighted lines will go inside the new +function or main. +for-loops: the highlighted lines will be set in braces. + +1.4.2 for-loop control *csupport-idioms-for-loop* + +The menu items 'for( x=0; ... )' and 'for( x=n-1; ... )' can be used to write +the control statement for a for-loop counting upward or downward. These items +start an input dialog + + [TYPE (expand)] VARIABLE [START [END [INCR.]]] : + +asking for at least the name of the loop variable. The other parameters are +optional. The type is restricted to the following integral data types: + + char + int + long + long int + long long + long long int + short + short int + size_t + unsigned + unsigned char + unsigned int + unsigned long + unsigned long int + unsigned long long + unsigned long long int + unsigned short + unsigned short int + +One of these types can be specified by typing it completely or by typing zero +or more characters of its name and completing them to the full name by using +the tab key (tab completion). If the start of the type name is ambiguous (e.g. +'uns') a list of completion candidates is provided to choose from. + +1.4.3 Item 'open input file' *csupport-idioms-input* + +The item 'open input file' will create the statements to open and close an +input file (e.g. with the file pointer 'infile'). + +1.4.4 Item 'open output file' *csupport-idioms-output* + +The item 'open output file' will create the statements to open and close an +output file (e.g. with the file pointer 'outfile'). + +------------------------------------------------------------------------------ +1.5 MENU 'Snippets' *csupport-snippets* +------------------------------------------------------------------------------ + +1.5.1 CODE SNIPPETS + +Code snippets are pieces of code which are kept in separate files in a special +directory (e.g. a few lines of code or a complete template for a Makefile). +File names are used to identify the snippets. The snippet directory will be +created during the installation ( $HOME/.vim/codesnippets-c is the default). +Snippets are managed with the 3 items + + C/C++ -> Snippets -> read code snippet + C/C++ -> Snippets -> write code snippet + C/C++ -> Snippets -> edit code snippet + +from the Snippets submenu. + +CREATING A NEW SNIPPET +When nothing is marked, "write code snippet" will write the whole buffer +to a snippet file, otherwise the marked area will be written to a file. + +INSERT A SNIPPET +Select the appropriate file from the snippet directory ("read code snippet"). +The inserted lines will be indented. + +EDIT A SNIPPET +This is a normal edit. + +INDENTATION / NO INDENTATION +Code snippets are normally indented after insertion. To suppress indentation +add the file extension "ni" or "noindent" to the snippet file name, e.g. + + parameter_handling.c.noindent + +Snippet browser +--------------- +Under a GUI a file requester will be put up. Without GUI the filename will be +read from the command line. You can change this behavior by setting a global +variable in your ~/.vimrc : + + let g:C_GuiSnippetBrowser = 'commandline' + +The default value is 'gui'. + + +1.5.2 PICKING UP PROTOTYPES *csupport-proto* + +PICK UP FUNCTION PROTOTYPES (key mappings \np, \nf). + +To make a prototype from a function head mark the function head and choose +'Snippets -> pick up funct. prototype'. From the first six lines of + + void + print_double_array ( double array[], /* array to print */ + int n, /* number of elements to print */ + int columns, /* number of elements per column */ + char* arrayname /* array name */ + ) + { + ... + } /* ---------- end of function print_double_array ---------- */ + +the prototype + + void print_double_array ( double array[], int n, int columns, char* arrayname ); + +is produced and put in an internal buffer. +- Leading and trailing whitespaces are removed. +- All inner whitespaces are squeezed. +- All comments will be discarded. +- Trailing parts of the function body (e.g a '{' ) will also be removed. +- The class name and the scope resolution operator will be removed (C++ method + implementations). +Further prototypes can be picked up and gathered in the buffer. + +PICK UP METHOD PROTOTYPES (key mapping \nm). + +For C++ methods the menu item 'Snippets -> pick up method prototype' should be +used. Namespace names and class names will be removed (exception: 'std::' ). +The first two lines of + + std::string + ROBOT::Robot::get_name ( void ) + { + return type_name; + } /* ----- end of method Robot::get_name ----- */ + +result in the prototype + + std::string get_name ( void ); + +The 3 lines + + template + const Stack& + Stack::operator = ( const Stack &other ) + +result in the prototype + + const Stack& operator = ( const Stack &other ); + +Folding may help picking up prototypes (see |csupport-folding|). + + +INSERT PROTOTYPES +With 'Snippets -> insert prototype(s)' all picked up prototypes currently in +the buffer will be inserted below the cursor. +The prototype buffer will be cleared after insertion. + + +DISCARD PROTOTYPES +The prototype buffer can be cleared with 'Snippets -> clear prototype(s)' . + + +SHOW PROTOTYPES +The list of gathered prototypes can be shown with +'Snippets -> show prototype(s)'. The number and the filename are shown, e.g. + + (1) matrix.c # double** calloc_double_matrix ( int rows, int columns ); + (2) matrix.c # void free_double_matrix ( double **m ); + (3) foomain.c # void foo ( ); + + +REMARK. Generating prototypes this way is nice in a small project. You may +want to use an extractor like cextract or something else. + + +1.5.3 Code Templates *csupport-templates-menu* +--------------------- +Nearly all menu entries insert code snippets or comments. All these stuff is +taken from template files and can be changed by the user to meet his +requirements (see|csupport-templates|on how to use the template system). + +The menu item 'edit local templates' opens the main template file in a local +plugin installation. This is usually the file +'~/.vim/c-support/templates/Templates'. There may be dependent files +loaded from the main file. Now change whatever file you want, save it, and +click on the menu item 'reread templates' to read in the file(s) and to +rebuild the internal representation of the templates. + +The menu item 'edit global templates' opens the main template file in a +system-wide plugin installation (see |csupport-system-wide|). This is +usually the file '$VIM./vimfiles/c-support/templates/Templates'. + +Template browser +---------------- +Under a GUI a file requester will be put up. Without GUI the filename will be +read from the command line. You can change this behavior by setting a global +variable in your ~/.vimrc : + + let g:C_GuiTemplateBrowser = 'explorer' + +The default value is 'gui'. 'explorer' will start the file explorer +(see help|:Explore|). To use the commandline asign 'commandline'. + +------------------------------------------------------------------------------ +1.6 MENU 'C++' *csupport-c++* +------------------------------------------------------------------------------ + +1.6.1 NORMAL MODE, INSERT MODE. *csupport-c++-normal-mode* + +An empty statement will be inserted and in some cases properly indented. The +item 'try .. catch' will insert the following lines: + + try { + } + catch ( const &ExceptObj ) { // handle exception: + } + catch (...) { // handle exception: unspecified + } + +The cursor will go into the try block. + +1.6.2 VISUAL MODE. *csupport-c++-visual-mode* + +The highlighted area can be surrounded by one of the following statements: + + try - catch + catch + catch(...) + namespace { } + extern "C" { } + +The whole statement will be indented after insertion. + +1.6.3 METHOD IMPLEMENTATION *csupport-c++-method-impl* + +The menu item 'method implement.' asks for a method name. If this item is +called the first time you will see just an scope resolution operator. If you +specify the scope this is used the next time you call this item. If you use +one of the menu items to generate a class (see |csupport-templates|) the +scope will be extracted and used for the next method. + +1.6.4 EX COMMANDS *csupport-c++-ex* + +There are 4 additional Ex command which can be used to insert include +statements. Please see |csupport-prep-ex|. + +------------------------------------------------------------------------------ +1.7 MENU 'Run' *csupport-run* +------------------------------------------------------------------------------ + +1.7.1 MINIMAL MAKE FUNCTIONALITY *csupport-run-buffer* + +The 'Run' menu provides a minimal make functionality for single file projects +(e.g. in education) : + +SAVE AND COMPILE +'save and compile' saves the buffer and run the compiler with the given +options (see |csupport-custom-glob-vars|). + +An error window will be opened if the compiler reports errors and/or warnings. +Quickfix commands can now be used to jump to an error location. + +Consider using maps like + map :cprevious + map :cnext +in your ~/.vimrc file to jump over the error locations and make navigation +easier. The error list and the error locations in your source buffer will be +synchronized. + +The filename extension for an object file can be set in ~.vimrc : + + let g:C_ObjExtension = '.obj' + +The default is '.o' ('.obj' for Windows). + +LINK +'link' makes an executable from the current buffer. If the buffer is not +saved, or no object is available or the object is older then the source step +'save and compile' is executed first. +The linkging will only be tried if the current buffer contains a main +function. + +The behavior of the compiler / linker is determined by the options assigned to +the variables described in |csupport-custom-glob-vars| (4.group). + +RUN +'run' runs the executable with the same name as the current buffer. If the +buffer is not saved, or no executable is available or the executable is older +then the source steps 'save and compile' and 'link' are executed first. + +The filename extension for an executable can be set in ~.vimrc : + + let g:C_ExeExtension = '.exe' + +The default is the empty string. + +1.7.2 COMMAND LINE ARGUMENTS *csupport-run-cmdline-args* + +The item 'command line arguments' calls an input dialog which asks for command +line arguments. These arguments are forwarded to the program which is run by +the 'run' item. The arguments are kept until you change them. +For the first and only the first argument file name expansion will work (use +the Tab-key). Only the first string of the input can be expanded due to a +restriction of the Vim input function. To expand two or more filenames +specify them in reverse order: type the first characters of the last filename +and expand them. Go to the start of the input and type the beginning of the +last but one filename and expand it. + +The arguments belong to the current buffer (that is, each buffer can have its +own arguments). +If the buffer gets a new name with "save as" the arguments will now belong to +the buffer with the new name. + +The command line arguments can be followed by pipes and redirections: + + 11 22 | sort -rn | head -10 > out + +Caveat: If you look for the current arguments by calling this menu item again +be sure to leave it with a CR (not Esc !). Due to a limitation of an internal +Vim function CR will keep the arguments, Esc will discard them. + + +1.7.3 RUN make *csupport-run-make* + +The item 'make' runs the external make program. An error window will be +opened if the compiler or linker reports errors or warnings during the make +process. Quickfix commands can now be used to jump to an error location. +Make looks for a makefile in the current directory (but see below). + +When inside a makefile the hotkeys \rm, \rmc, \rcm, and \rma are working (see +|csupport-usage-vim|). +The snippets collection contains a sample makefile which can easily adepted +for small projcts. + + +1.7.4 Choose Makefile *csupport-choose-makefile* + +The menu item 'choose makefile' let you specify a makefile in another +directory than the current one. Now this makefile will be used instead of the +one in the current directory (if any). Make is started from the directory in +which the makefile is contained. The working directory for the current buffer +will not be changed. + + +1.7.5 EXECUTABLE TO RUN *csupport-run-make-run* + +The item 'executable to run' asks for the name of the executable built by +make. If the name given is nonempty this executable will be run by the menu +item 'run' (\rr, C-F9). +To return to the default behavior (see |csupport-run-buffer|) remove the name +with the another 'executable to run'. + + +1.7.6 RUN make clean *csupport-run-make-clean* + +The item 'make' runs the external make program with the standard target +'clean'. If an alternate makefile has been chosen +(see|csupport-choose-makefile|), this one will be run from the directory in +which the makefile is contained. + + +1.7.7 COMMAND LINE ARGUMENTS FOR make *csupport-run-make-args* + +The item 'command line arguments for make' calls an input dialog which asks +for command line arguments for make. These arguments are forwarded to make +when called by the menu item 'make'. +For the first and only the first argument the file name expansion will work +(use the Tab-key). + + +1.7.8 SPLINT *csupport-run-splint* + +Splint is a tool for statically checking C programs (see http://www.splint.org). +Of course it has to be installed in order to be used within Vim. The menu +item 'Run->splint' will run the current buffer through splint. + +An error window will be opened if splint has something to complain about. +Quickfix commands can now be used to jump to an error location. For easier +navigation see tip under 'SAVE AND COMPILE' |csupport-run-buffer|. + +Splint has many options. Presumably the best way is to keep the options in an +option file (~/.splintrc). For a quick try you can use the menu item +'Run->cmd. line arg. for splint' to specify some buffer related options. + +When vim is started this plugin will check whether splint is executable. If +not, the menu item will *NOT' be visible. + + +1.7.9 CODECHECK *csupport-run-codecheck* + +CodeCheck (TM) is a commercial code analyzing tool produced by Abraxas +Software, Inc. (www.abraxas-software.com). +Of course it has to be installed in order to be used within Vim. The menu +item 'Run->CodeCheck' will run the current buffer through CodeCheck. + +An error window will be opened if CodeCheck has something to complain about. +Quickfix commands can now be used to jump to an error location. For easier +navigation see tip under 'SAVE AND COMPILE' |csupport-run-buffer|. + +CodeCheck has many options. For a quick try you can use the menu item +'Run->cmd. line arg. for CodeCheck' to specify some buffer related options. + +CodeCheck will be run with default options (see |csupport-custom-glob-vars|). +The default options can be overwritten by placing a global variable in +~/.vimrc , e.g. + + let g:C_CodeCheckOptions = "-K13 -Rmeyers" + +The default name for the executable is 'check'. There are other names in use +on different platforms. The name can be changed by placing a global variable +in ~/.vimrc , e.g. + + let g:C_CodeCheckExeName = "chknt.exe" + +When vim is started this plugin will check whether CodeCheck is executable. If +not, the menu item will *NOT' be visible. + + +1.7.10 INDENT *csupport-run-indent* + +The formatter 'indent' can be run over the whole buffer. Before formatting a +buffer this buffer will be saved to disk and you will be asked for a +confirmation. + +Indent has many options. These are kept in the file '.indent.pro' in your home +directory. See the indent manual for more information. + + +1.7.11 HARDCOPY *csupport-run-hardcopy* + +Generates a PostScript file from the whole buffer or from a marked region. +On a Windows system a printer dialog is displayed. +The hardcopy goes to the current working directory. If the buffer contains +documentation or other material from non-writable directories the hardcopy +goes to the HOME directory. The output destination will be shown in a message. + +The print header contains date and time for the current locale. The definition +used is + + let s:C_Printheader = "%<%f%h%m%< %=%{strftime('%x %X')} Page %N" + +The current locale can be overwritten by changing the language, e.g. + + :language C + +or by setting a global variable in the file ~/.vimrc , e.g. : + + let g:C_Printheader = "%<%f%h%m%< %=%{strftime('%x %X')} SEITE %N" + +See :h printheader and :h strftime() for more details. + + +1.7.12 REBUILD TEMPLATES *csupport-run-templates* + +After editing one or more template files a click on this item rereads the +template files and rebuilds all templates. + + +1.7.13 XTERM SIZE *csupport-run-xterm* + +The size of the xterm used for running a program (below) can be set by this +menu item. The default is 80 columns with 24 lines. +This feature is not available under Windows. + + +1.7.14 OUTPUT REDIRECTION *csupport-run-output* + +Running a program can be done in one of three ways: +(1) Run the program from the gVim command line. + This is for interactive programs with little input and output. +(2) Run the program and direct the output into a window with name "C-Output". + The buffer and its content will disappear when the window is closed and + reused otherwise. + This is for non-interactive programs with little to very much output. + You have unlimited line length, regex search, navigation, ... + The tabstop value will be set to 8 for "C-Output". +(3) Run the program in an xterm. + +The output method can be chosen from the menu item 'Run->output: ...'. +This menu has three states: + + output: VIM->buffer->xterm + output: BUFFER->xterm->vim + output: XTERM->vim->buffer + +The first (uppercase) item shows the current method. The default is 'vim'. +This can be changed by setting the variable g:C_OutputGvim to another value. +Possible values are 'vim', 'buffer' and 'xterm' . + +The xterm defaults can be set in ~/.vimrc by the variable g:C_XtermDefaults . +The default is "-fa courier -fs 12 -geometry 80x24" : + font name : -fa courier + font size : -fs 12 + terminal size : -geometry 80x24 +See 'xterm -help' for more options. Xterms are not available under Windows. + +------------------------------------------------------------------------------ +1.8 'help' *csupport-help* +------------------------------------------------------------------------------ +Plugin help +----------- +The root menu item 'help (plugin)' shows this plugin help in a help window. +The help tags must have been generated with + :helptags ~/.vim/doc +The hotkey is \hp (for "help plugin"). + +Displaying a manual +------------------- +The root menu item 'show manual' shows the manual for the word under the +cursor. If there is more than one manual a selection list will be presented. +If there is no word under the cursor you can type in a name. An interface to +the on-line reference manuals must be installed (usually man(1) for +Linux/Unix, see|csupport-custom-glob-vars|). +The hotkey is \hm (for "help manual"). + +============================================================================== +2. USAGE WITHOUT GUI (Vim) *csupport-usage-vim* +============================================================================== + +The frequently used constructs can be inserted with key mappings. The +mappings are also described in the document c-hot-keys.pdf (reference card, +part of this package). +Hint: Typing speed matters. The combination of a leader ('\') and the +following character(s) will only be recognized for a short time. +Some mappings can be used with range (of lines). In normal mode + \cl +appends a end-of-line comment to the current line, whereas + 4\cl +appends end-of-line comments to the 4 lines starting with the current line. + +Legend: (i) insert mode, (n) normal mode, (v) visual mode + [n] range + + -- Help --------------------------------------------------------------- + + \hm show manual for word under the cursor (n,i) + \hp show plugin help (n,i) + + -- Comments ----------------------------------------------------------- + + [n]\cl end-of-line comment (n,v,i) + [n]\cj adjust end-of-line comment(s) (n,v,i) + \cs set end-of-line comment column (n) + [n]\c* code -> comment /* */ (n,v) + [n]\cc code -> comment // (n,v) + [n]\co comment -> code (n,v) + \cfr frame comment (n,i) + \cfu function comment (n,i) + \cme method description (n,i) + \ccl class description (n,i) + \cfdi file description (implementation) (n,i) + \cfdh file description (header) (n,i) + \ccs C/C++-file section (tab. compl.) (n,i) + \chs H-file section (tab. compl.) (n,i) + \ckc keyword comment (tab. compl.) (n,i) + \csc special comment (tab. compl.) (n,i) + \cd date (n,v,i) + \ct date \& time (n,v,i) + [n]\cx toggle comments: C <--> C++ (n,v,i) + + -- Statements --------------------------------------------------------- + + \sd do { } while (n,v,i) + \sf for (n,i) + \sfo for { } (n,v,i) + \si if (n,i) + \sif if { } (n,v,i) + \sie if else (n,v,i) + \sife if { } else { } (n,v,i) + \se else { } (n,v,i) + \sw while (n,i) + \swh while { } (n,v,i) + \ss switch (n,v,i) + \sc case (n,i) + \s{ \sb { } (n,v,i) + + -- Preprocessor ------------------------------------------------------- + + \ps choose a standard library include (n,i) + \pc choose a C99 include (n,i) + \p< #include <> (n,i) + \p" #include "" (n,i) + \pd #define (n,i) + \pu #undef (n,i) + \pif #if #endif (n,v,i) + \pie #if #else #endif (n,v,i) + \pid #ifdef #else #endif (n,v,i) + \pin #ifndef #else #endif (n,v,i) + \pind #ifndef #def #endif (n,v,i) + \pi0 #if 0 #endif (n,v,i) + \pr0 remove #if 0 #endif (n,i) + \pe #error (n,i) + \pl #line (n,i) + \pp #pragma (n,i) + + -- Idioms ------------------------------------------------------------- + + \if function (n,v,i) + \isf static function (n,v,i) + \im main() (n,v,i) + [n]\i0 for( x=0; x=0; x-=1 ) (n,v,i) + \ie enum + typedef (n,i) + \is struct + typedef (n,i) + \iu union + typedef (n,i) + \ip printf() (n,i) + \isc scanf() (n,i) + \ica p=calloc() (n,i) + \ima p=malloc() (n,i) + \ire p=realloc() (n,i) + \isi sizeof() (n,v,i) + \ias assert() (n,v) + \ii open input file (n,i) + \io open output file (n,i) + \ifs fscanf (n,i) + \ifp fprintf (n,i) + + -- Snippets ----------------------------------------------------------- + + \nr read code snippet (n,i) + \nw write code snippet (n,v,i) + \ne edit code snippet (n,i) + [n]\nf pick up function prototype (n,v,i) + [n]\np pick up function prototype (n,v,i) + [n]\nm pick up method prototype (n,v,i) + \ni insert prototype(s) (n,i) + \nc clear prototype(s) (n,i) + \ns show prototype(s) (n,i) + \ntl edit local templates (n,i) + \ntg edit global templates (n,i) + \ntr rebuild templates (n,i) + + -- C++ ---------------------------------------------------------------- + + \+co cout << << endl; (n,i) + \+" << "" (n,i) + \+c class (n,i) + \+ps #include <...> STL (n,i) + \+pc #include C (n,i) + \+cn class (using new) (n,i) + \+ci class implementation (n,i) + \+cni class (using new) implementation (n,i) + \+mi method implementation (n,i) + \+ai accessor implementation (n,i) + + \+tc template class (n,i) + \+tcn template class (using new) (n,i) + \+tci template class implementation (n,i) + \+tcni template class (using new) impl. (n,i) + \+tmi template method implementation (n,i) + \+tai template accessor implementation (n,i) + + \+tf template function (n,i) + \+ec error class (n,i) + \+tr try ... catch (n,v,i) + \+ca catch (n,v,i) + \+c. catch(...) (n,v,i) + + -- Run ---------------------------------------------------------------- + + \rc save and compile (n,i) + \rl link (n,i) + \rr run (n,i) + \ra set comand line arguments (n,i) + \rm run make (n,i) + \rmc run 'make clean' (n,i) + \rcm choose makefile (n,i) + \rme executable to run (n,i) + \rma cmd. line arg. for make (n,i) + \rp run splint (n,i) + \rpa cmd. line arg. for splint (n,i) + \rk run CodeCheck (TM) (n,i) + \rka cmd. line arg. for CodeCheck (TM) (n,i) + \rd run indent (n,v,i) + [n]\rh hardcopy buffer (n,v,i) + \rs show plugin settings (n,i) + \rx set xterm size (n, only Linux/UNIX & GUI) + \ro change output destination (n,i) + + -- Load / Unload C/C++ Support ---------------------------------------- + + \lcs Load C/C++ Support Menus (n, GUI only) + \ucs Unload C/C++ Support Menus (n, GUI only) + +The hotkeys are defined in the file type plugin c.vim (part of this csupport +plugin package) and described in the document c-hot-keys.pdf + +Changing the default map leader '\' +----------------------------------- +The map leader can be changed by the user by setting a global variable in the +file .vimrc + + let g:C_MapLeader = ',' + +The map leader is now a comma. The 'line end comment' command is now defined +as ',cl'. This setting will be used as a so called local leader and influences +only files with filetype 'c' and 'cpp'. + +============================================================================== +3. HOTKEYS *csupport-hotkeys* +============================================================================== + +The following hotkeys are defined in normal, visual and insert mode: + + F9 compile and link + Alt-F9 write buffer and compile + Ctrl-F9 run executable + Shift-F9 set command line arguments + + Shift-F2 switch between source files and header files + +The hotkeys are defined in the file type plugin c.vim. All hotkeys from the +non-GUI mode also work for gVim (see |csupport-usage-vim|). + +Shift-F2 can be used to switch between source files and header files if the +plugin a.vim (http://vim.sourceforge.net/scripts/script.php?script_id=31) is +present. To suppress the creation of a new header file when switching from a +source file the file ~/.vimrc should contain a line + + let g:alternateNoDefaultAlternate = 1 + +A header file will only be opened if it already exists. + +The Shift-key is dead when you are working with Vim in a console terminal +(non-Gui). You could add + + noremap \a :A + inoremap \a :A + +to get a hot key for this case. + +============================================================================== +4. CUSTOMIZATION *csupport-custom* +============================================================================== + +------------------------------------------------------------------------------ +4.1 GLOBAL VARIABLES *csupport-custom-glob-vars* +------------------------------------------------------------------------------ + +Several global variables are checked by the script to customize it: + + ---------------------------------------------------------------------------- + GLOBAL VARIABLE DEFAULT VALUE TAG (see below) + ---------------------------------------------------------------------------- + g:C_GlobalTemplateFile plugin_dir.'c-support/templates/Templates' + g:C_LocalTemplateFile $HOME.'/.vim/c-support/templates/Templates' + g:C_TemplateOverwrittenMsg 'yes' + g:C_Ctrl_j 'on' + + g:C_CodeSnippets plugin_dir.'/c-support/codesnippets/' + g:C_Dictionary_File '' + g:C_LoadMenus 'yes' + g:C_MenuHeader 'yes' + g:C_OutputGvim 'vim' + g:C_Root '&C\/C\+\+.' + g:C_XtermDefaults '-fa courier -fs 12 -geometry 80x24' + g:C_Printheader "%<%f%h%m%< %=%{strftime('%x %X')} Page %N" + g:C_MapLeader '\' + g:C_GuiSnippetBrowser 'gui' + g:C_GuiTemplateBrowser 'gui' + + Linux/UNIX: + g:C_ObjExtension '.o' + g:C_ExeExtension '' + g:C_CCompiler 'gcc' + g:C_CplusCompiler 'g++' + g:C_Man 'man' + Windows: + g:C_ObjExtension '.obj' + g:C_ExeExtension '.exe' + g:C_CCompiler 'gcc.exe' + g:C_CplusCompiler 'g++.exe' + g:C_Man 'man.exe' + g:C_VimCompilerName gcc + g:C_CFlags '-Wall -g -O0 -c' + g:C_LFlags '-Wall -g -O0' + g:C_Libs '-lm' + g:C_LineEndCommColDefault 49 + g:C_CExtension 'c' + g:C_TypeOfH 'cpp' + g:C_SourceCodeExtensions 'c cc cp cxx cpp CPP c++ C i ii' + + g:C_CodeCheckExeName 'check' + g:C_CodeCheckOptions '-K13' + +The variable plugin_dir will automatically be set to one of the following values: + $HOME.'/.vim/' for Linux/Unix + $VIM.'/vimfiles/' for Windows + + ---------------------------------------------------------------------------- + + 1. group: g:C_GlobalTemplateFile : Sets the master template file (see|csupport-templates|) + g:C_LocalTemplateFile : Sets the local template file (see|csupport-templates|) + g:C_TemplateOverwrittenMsg : message if template is overwritten + g:C_Ctrl_j : hotkey Ctrl-j 'on'/'off' (see|csupport-Ctrl-j|) + + 2. group: g:C_CodeSnippets : The name of the code snippet directory + (see |csupport-snippets|). + g:C_Dictionary_File : The name(s) of the dictionary file(s) used for + word completion (see also |csupport-dictionary|) + g:C_LoadMenus : Load menus and mappings ("yes", "no") at startup. + g:C_MenuHeader : Switch the submenu header on/off. + g:C_OutputGvim : when program is running output goes to the vim + command line ("vim"), to a buffer ("buffer") or to + an xterm ("xterm"). + g:C_Root : The name of the root menu entry of this plugin + (see |csupport-custom-root|). + g:C_XtermDefaults : the xterm defaults + g:C_Printheader : hardcopy: definition of the page header + g:C_MapLeader : the map leader for hotkeys (see|csupport-usage-vim|) + g:C_GuiSnippetBrowser : code snippet browser: 'gui', 'commandline' + g:C_GuiTemplateBrowser : code template browser: 'gui', 'explorer', 'commandline' + + 3. group: g:C_CExtension : Extension of C files. Everything else is C++. + g:C_TypeOfH : filetype of header files with extension 'h' (c,cpp) + g:C_SourceCodeExtensions : filename extensions for C/C++ + implementation files + g:C_CCompiler : The name of the C compiler. + g:C_CplusCompiler : The name of the C++ compiler. + g:C_VimCompilerName : the compiler name used by :compiler + g:C_Man : The name of the man utility. + g:C_CFlags : Compiler flags used for a compilation. + g:C_LFlags : Compiler flags used for linkage. + g:C_Libs : Libraries to link with. + g:C_ObjExtension : C/C+ file extension for objects + (leading point required if not empty) + g:C_ExeExtension : C/C+ file extension for executables + (leading point required if not empty) + g:C_LineEndCommColDefault : Default starting column for end-of-line comments. + g:C_CodeCheckExeName : The name of the CodeCheck (TM) executable + (the default is 'check') + g:C_CodeCheckOptions : Default options for CodeCheck (TM) + (see |csupport-run-codecheck|). + +To override the default add appropriate assignments to ~/.vimrc . + +------------------------------------------------------------------------------ +4.2 THE ROOT MENU *csupport-custom-root* +------------------------------------------------------------------------------ + +The variable g:C_Root, if set (in '.vimrc' or in '.gvimrc'), gives the name +of the single gVim root menu entry in which the C/C++ submenus will be put. +The default is + + '&C\/C\+\+.' + '' +Note the terminating dot. + +If you want to set the plugin root menu into another menu, e.g. 'Plugin', +this is done by the following line in '.vimrc' + + let g:C_Root = '&Plugin.&C\/C\+\+.' + +------------------------------------------------------------------------------ +4.3 SYSTEM-WIDE INSTALLATION *csupport-system-wide* +------------------------------------------------------------------------------ + +A system-wide installation (one installation for all users) is done as +follows. + +As *** SUPERUSER *** : + +(1) Find the Vim installation directory. +The Vim Ex command ':echo $VIM' gives '/usr/local/share/vim' or something like +that. Beyond this directory you will find the Vim installation, e.g. in +'/usr/local/share/vim/vim73' if Vim version 7.3 has been installed +(Windows: 'C:\Program Files\Vim'). + +(2) Create a new subdirectory 'vimfiles', e.g. '/usr/local/share/vim/vimfiles' +(Windows: 'C:\Program Files\Vim\vimfiles'). + +(3) Install C/C++ Support +Copy the archive cvim.zip to this new directory and unpack it: + unzip cvim.zip + +(4) Generate the help tags: + :helptags $VIM/vimfiles/doc + +SPECIAL CASES. Some Linux distributions use non-standard names for Vim +directories. SUSE has a directory '/usr/share/vim/site' to put plugins in. +These directories will not be found automatically. After installing the +plugin below '/usr/share/vim/site' the use of the templates will be enabled by +the following line in '~/.vimrc': + + let g:C_GlobalTemplateFile = '/usr/share/vim/site/c-support/templates/Templates' + +As *** USER *** : + +Create your private snippet directory: + + mkdir --parents ~/.vim/c-support/codesnippets + +You may want to copy the snippets coming with this plugin (in +$VIM/vimfiles/c-support/codesnippets) into the new directory or to set a +link to the global directory. + +Create your private template directory: + + mkdir --parents ~/.vim/c-support/templates + +Create a private template file 'Templates' (compulsory) in this directory to +overwrite some macros, e.g. + + *|AUTHOR|* = your name + *|AUTHORREF|* = ... + *|EMAIL|* = ... + *|COMPANY|* = ... + *|COPYRIGHT|* = ... + +You can also have local templates which overwrite the global ones. To suppress +the messages in this case set a global variable in '~/.vimrc' (Windows: +'~\_vimrc') : + + let g:C_TemplateOverwrittenMsg= 'no' + +The default is 'yes'. + +============================================================================== +5. TEMPLATE FILES AND TAGS *csupport-templates* +============================================================================== + +------------------------------------------------------------------------------ +5.1 TEMPLATE FILES *csupport-templates-files* +------------------------------------------------------------------------------ + +Nearly all menu entries insert code snippets or comments. All of these are +contained within template files and can be changed by the user to meet their +requirements. + +The master template file is '$HOME/.vim/c-support/templates/Templates' for a +user installation and '$VIM/vimfiles/c-support/templates/Templates' for a +system-wide installation (see|csupport-system-wide|). + +The master template file starts with a macro section followed by templates for +single menu items or better by including other template files grouping the +templates according to the menu structure of this plugin. The master file +could look like this: + + $ + $ ============================================================= + $ ========== USER MACROS ====================================== + $ ============================================================= + $ + *|AUTHOR|* = Dr. Fritz Mehner + *|AUTHORREF|* = mn + *|EMAIL|* = mehner@fh-swf.de + *|COMPANY|* = FH Südwestfalen, Iserlohn + *|COPYRIGHT|* = Copyright (c)*|YEAR|,|AUTHOR|* + $ + $ ============================================================= + $ ========== FILE INCLUDES ==================================== + $ ============================================================= + $ + *|includefile|* = c.comments.template + *|includefile|* = c.cpp.template + *|includefile|* = c.idioms.template + *|includefile|* = c.preprocessor.template + *|includefile|* = c.statements.template + +Lines starting with a dollar sign are comments. The section starting +with *|AUTHOR|* assigns values to predefined tags +(see|csupport-templates-macros|) to personalize some templates. Other +predefined tags with given default values can be used (e.g. *|YEAR|* ). + +User defined tags are possible. They have the following syntax: + + *|macroname|* = replacement + +A macroname starts with a letter (uppercase or lowercase) followed by zero or +more letters, digits or underscores. + +------------------------------------------------------------------------------ +5.2 MACROS *csupport-templates-macros* +------------------------------------------------------------------------------ + +The following macro names are predefined. The first group is used to +personalize templates. + + ---------------------------------------------------------------------------- + PREDEFINED MACROS DEFAULT VALUE + ---------------------------------------------------------------------------- +*|AUTHOR|* "" +*|AUTHORREF|* "" +*|EMAIL|* "" +*|COMPANY|* "" +*|PROJECT|* "" +*|COPYRIGHTHOLDER|* "" +*|STYLE|* "" +*|includefile|* "" + +*|BASENAME|* filename without path and suffix +*|DATE|* the preferred date representation for the current locale + without the time +*|FILENAME|* filename without path +*|PATH|* path without filename +*|SUFFIX|* filename suffix +*|TIME|* the preferred time representation for the current locale + without the date and the time zone or name or abbreviation +*|YEAR|* the year as a decimal number including the century + +The macro *|includefile|* can be used to include an additional template file. +A file will be included only once. Commenting and uncommenting include macros +is a simple way to switch between several sets of templates (see also +|csupport-run-templates|). Overwriting existing macros and templates is +possible. + + ---------------------------------------------------------------------------- + PREDEFINED TAGS + ---------------------------------------------------------------------------- + ,{CURSOR} The cursor position after insertion of a template + <+text+>,<-text->, Jump targets in templates. Jump with Ctrl-j. + {+text+},{-text-} See |csupport-templates-jump|. + + The split point when inserting in visual mode + (see|csupport-templates-definition|) + +A dependent template file can start with its own macro section. There is no +need to have all user defined macros in the master file. +When the first template definition is found (see below) macro definitions are +no longer recognized. +Use the tag variant with curly braces if the indentation of the following line +is wrong after template insertion. + +------------------------------------------------------------------------------ +5.2.1 USER DEFINED FORMATS FOR DATE AND TIME *csupport-templates-date* +------------------------------------------------------------------------------ +The format for *|DATE|* ,*|TIME|* , and*|YEAR|* can be set by the user. The +defaults are + *|DATE|* '%x' + *|TIME|* '%X' + *|YEAR|* '%Y' +See the manual page of the C function strftime() for the format. The accepted +format depends on your system, thus this is not portable! The maximum length +of the result is 80 characters. + +User defined formats can be set using the following global variables in +~/.vimrc , e.g. + let g:C_FormatDate = '%D' + let g:C_FormatTime = '%H:%M' + let g:C_FormatYear = 'year %Y' + +------------------------------------------------------------------------------ +5.3 TEMPLATES *csupport-templates-names* +------------------------------------------------------------------------------ + +5.3.1 Template names + +The template behind a menu entry is identified by a given name. The first part +of the name identifies the menu, the second part identifies the item. The +modes are also hard coded (see|csupport-templates-definition|for the use of +). + + TEMPLATE NAME MODES + -------------------------------------------------------------------------- + + comment.class normal + comment.end-of-line-comment normal + comment.file-description normal + comment.file-description-header normal + comment.file-section-cpp-class-defs normal + comment.file-section-cpp-class-implementations-exported normal + comment.file-section-cpp-class-implementations-local normal + comment.file-section-cpp-data-types normal + comment.file-section-cpp-function-defs-exported normal + comment.file-section-cpp-function-defs-local normal + comment.file-section-cpp-header-includes normal + comment.file-section-cpp-local-variables normal + comment.file-section-cpp-macros normal + comment.file-section-cpp-prototypes normal + comment.file-section-cpp-typedefs normal + comment.file-section-hpp-exported-class-defs normal + comment.file-section-hpp-exported-data-types normal + comment.file-section-hpp-exported-function-declarations normal + comment.file-section-hpp-exported-typedefs normal + comment.file-section-hpp-exported-variables normal + comment.file-section-hpp-header-includes normal + comment.file-section-hpp-macros normal + comment.frame normal + comment.function normal + comment.keyword-bug normal + comment.keyword-compiler normal + comment.keyword-keyword normal + comment.keyword-todo normal + comment.keyword-tricky normal + comment.keyword-warning normal + comment.keyword-workaround normal + comment.method normal + comment.special-constant-type-is-long normal + comment.special-constant-type-is-unsigned-long normal + comment.special-constant-type-is-unsigned normal + comment.special-empty normal + comment.special-fall-through normal + comment.special-implicit-type-conversion normal + comment.special-no-return normal + comment.special-not-reached normal + comment.special-remains-to-be-implemented normal + + cpp.accessor-implementation normal + cpp.catch normal, visual + cpp.catch-points normal, visual + cpp.cin normal + cpp.class-definition normal + cpp.class-implementation normal + cpp.class-using-new-definition normal + cpp.class-using-new-implementation normal + cpp.cout-operator normal + cpp.cout normal + cpp.error-class normal + cpp.extern normal, visual + cpp.method-implementation normal + cpp.namespace-block normal, visual + cpp.namespace normal + cpp.namespace-std normal + cpp.open-input-file normal + cpp.open-output-file normal + cpp.operator-in normal + cpp.operator-out normal + cpp.output-manipulator-boolalpha normal + cpp.output-manipulator-dec normal + cpp.output-manipulator-endl normal + cpp.output-manipulator-fixed normal + cpp.output-manipulator-flush normal + cpp.output-manipulator-hex normal + cpp.output-manipulator-internal normal + cpp.output-manipulator-left normal + cpp.output-manipulator-oct normal + cpp.output-manipulator-right normal + cpp.output-manipulator-scientific normal + cpp.output-manipulator-setbase normal + cpp.output-manipulator-setfill normal + cpp.output-manipulator-setiosflag normal + cpp.output-manipulator-setprecision normal + cpp.output-manipulator-setw normal + cpp.output-manipulator-showbase normal + cpp.output-manipulator-showpoint normal + cpp.output-manipulator-showpos normal + cpp.output-manipulator-uppercase normal + cpp.rtti-const-cast normal + cpp.rtti-dynamic-cast normal + cpp.rtti-reinterpret-cast normal + cpp.rtti-static-cast normal + cpp.rtti-typeid normal + cpp.template-accessor-implementation normal + cpp.template-class-definition normal + cpp.template-class-implementation normal + cpp.template-class-using-new-definition normal + cpp.template-class-using-new-implementation normal + cpp.template-function normal + cpp.template-method-implementation normal + cpp.try-catch normal, visual + + idioms.assert normal + idioms.calloc normal + idioms.enum normal, visual + idioms.fprintf normal + idioms.fscanf normal + idioms.function normal, visual + idioms.function-static normal, visual + idioms.main normal, visual + idioms.malloc normal + idioms.open-input-file normal + idioms.open-output-file normal + idioms.printf normal + idioms.scanf normal + idioms.sizeof normal + idioms.struct normal, visual + idioms.union normal, visual + + preprocessor.define normal + preprocessor.ifdef-else-endif normal, visual + preprocessor.if-else-endif normal, visual + preprocessor.ifndef-def-endif normal, visual + preprocessor.ifndef-else-endif normal, visual + preprocessor.include-global normal + preprocessor.include-local normal + preprocessor.undefine normal + + statements.block normal, visual + statements.case normal + statements.do-while normal, visual + statements.for-block normal + statements.for normal + statements.if-block-else normal, visual + statements.if-block normal, visual + statements.if-else normal, visual + statements.if normal + statements.switch normal, visual + statements.while-block normal, visual + statements.while normal + + +5.3.2 Template definition *csupport-templates-definition* + +A template definition starts with a template head line with the following +syntax: + + == templatename == [ position == ] + +The templatename is one of the above template identifiers. The position +attribute is optional. Possible attribute values are: + + above insert the template before the current line + append append the template to the current line + below insert the template below the current line + insert insert the template at the cursor position + start insert the template before the first line of the buffer + +An example: + + == comment.function == + /* + * === FUNCTION ======================================================= + * Name: + * Description: + * ====================================================================== + */ + +The definition of a template ends at the next head line or at the end of the +file. + +Templates for the visual mode can use . The text before will +than be inserted above the marked area, the text after will be +inserted behind the marked area. An example: + + == statements.if-block-else == + if ( ) { + } else { + } + +If applied to the marked block + + xxxxxxxxxxx + xxxxxxxxxxx + +this template yields + + if ( ) { + xxxxxxxxxxx + xxxxxxxxxxx + } else { + } + +The templates with a visual mode are shown in the table under +|csupport-templates-names|. + +5.3.3 Template expansion *csupport-templates-expansion* + +There are additional ways to control the expansion of a template. + +USER INPUT +---------- +If the usage of a yet undefined user macro starts with a question mark the +user will be asked for the replacement first, e.g. with the following template + + == idioms.function == + void + *|?FUNCTION_NAME|* ( ) + { + return ; + } /* ----- end of function*|FUNCTION_NAME|* ----- */ + +The user can specify the function name which then will be applied twice. If +the macro was already in use the old value will be suggested as default. + +MACRO MANIPULATION +------------------ + +A macro expansion can be controlled by the following attributes + + :l change macro text to lowercase + :u change macro text to uppercase + :c capitalize macro text + :L legalize name + +The include guard template is an example for the use of ':L' : + + == preprocessor.ifndef-def-endif == + #ifndef *|?BASENAME:L|_INC* + #define *|BASENAME|_INC* + + #endif // ----- #ifndef*|BASENAME|_INC* ----- + +The base name of the file shall be used as part of the include guard name. +The predefined macro*|BASENAME|* is used to ask for this part because this +macro has already a defined value. That value can accepted or replaced by the +user. For the filename 'test test++test.h' the legalized base name +'TEST_TEST_TEST' will be suggested. + +Legalization means: + - replace all whitespaces by underscores + - replace all non-word characters by underscores + - replace '+' and '-' by underscore + +5.3.4 The macros <+text+> etc. *csupport-templates-jump* + +There are four macro types which can be used as jump targets in templates: + + <+text+> Can be jumped to by hitting Ctrl-j. + {+text+} Same as <+text+>. Used in cases where indentation gives unwanted + results with the first one. + + <-text-> Same as the two above. Will be removed if the template is used + {-text-} in visual mode. + +The text inside the brackets is userdefined and can be empty. The text +can be composed from letters (uppercase and lowercase), digits, underscores +and blanks. After the insertion of an template these jump targets will be +highlighted. + +5.3.5 Command Ctrl-j *csupport-Ctrl-j* + +Use the command Ctrl-j to jump to the next target. The target will be removed +and the mode will switched to insertion. Ctrl-j works in normal and in insert +mode. + +The template for a function can be written as follows: + + == idioms.function == + void + |?FUNCTION_NAME| ( <+argument list+> ) + { + return <+return value+>; + } /* ----- end of function |FUNCTION_NAME| ----- */ + +The cursor will be set behind 'void'. You can remove 'void' easily with +Ctrl-w (delete word before cursor) and insert a new type. A Ctrl-j leads you +to the argument list. The target disappears and you can type on. When the +function body is written a final Ctrl-j brings you to the return statement. + +The following example shows the usage of the type {-text-}. The idiom for the +opening of a file marks the line before the file is closed. This is also the +line where the template will be split to surround a marked area. In this case +(visual mode) the target is not needed and therefore removed (minus signs as +mnemonic). In normal and insert mode the target is meaningful and will be +therefore be present. The form <-...-> would result in a wrong indentation of +the file close statement. The brace type will be handled as a block and the +indentation will be correct. + + == cpp.open-input-file == + char *ifs_file_name = ""; /* input file name */ + ifstream ifs; /* create ifstream object */ + + ifs.open (ifs_file_name); /* open ifstream */ + if (!ifs) { + cerr << "\nERROR : failed to open input file " << ifs_file_name << endl; + exit (EXIT_FAILURE); + } + {-continue here-} + ifs.close (); /* close ifstream */ + +Extra feature of Ctrl-j +----------------------- +If none of the above described targets is left Ctrl-j can be used to jump +behind closing brackets, parenthesis, braces, or string terminators ('"`). +This feature is limited to the current line. Ctrl-j does not jump behind the +last character in a line. + + +How to switch the mapping for Ctrl-j off +---------------------------------------- +The original meaning of Ctrl-j is 'move [n] lines downward' (see |CTRL-j|). +If you are accustomed to use the deafult and don't like these jump targets you +can switch them off. Put the following line in the file .vimrc : + + let g:C_Ctrl_j = 'off' + +The default value of g:C_Ctrl_j is 'on'. You do not have to change the +template files. All jump targets will be removed before a template will be +inserted. + +============================================================================== +5.4 SWITCHING BETWEEN TEMPLATE SETS *csupport-templates-sets* +============================================================================== + +This plugin comes with two sets of templates. These are suggestions. You may +want to have additional sets for different projects or occasionally want to +use doxygen style comments. To facilitate switching use the macro*|STYLE|* +(|csupport-templates-files|) to define a unique name and the +IF-ENDIF-construct to choose a particular set of files for example: + + ... + + *|STYLE|* = C + $ + $ ============================================================= + $ ========== FILE INCLUDES ==================================== + $ ============================================================= + $ + == IF *|STYLE|* IS C == + $ + |includefile| = c.comments.template + |includefile| = c.cpp.template + |includefile| = c.idioms.template + |includefile| = c.preprocessor.template + |includefile| = c.statements.template + $ + == ENDIF == + + ... + +The syntax is as follows: + + == IF macro_name IS macro_value == + + == ENDIF == + +Includes outside an IF-ENDIF construct are associated with the default style +'default'. A style set does not have to a complete set of templates. For an +incomplete set the other templates are taken from the default style. + +IF, IS, and ENDIF are keywords. + +HINT. Use these constructs to avoid overwriting your templates when updating +csupport. Copy and rename the set of files you want to change and surround the +includes with an appropriate IF-construct: + + *|STYLE|* = MY_C + $ + ... + $ + == IF *|STYLE|* IS MY_C == + |includefile| = my_c.comments.template + |includefile| = my_c.cpp.template + |includefile| = my_c.idioms.template + |includefile| = my_c.preprocessor.template + |includefile| = my_c.statements.template + == ENDIF == + +Keep a copy of the main template file 'Templates' because this file will be +overwritten if you do not update manually. + +============================================================================== +5.5 BINDING A STYLE TO A FILE EXTENSION *csupport-templates-bind* +============================================================================== + +You can bind the existing styles to one or more filename extensions. To do so +assign a Dictionary to the global variable g:C_Styles in '~/.vimrc' : + +let g:C_Styles = { '*.c,*.h' : 'default', '*.cc,*.cpp,*.hh' : 'CPP' } + +A Dictionary is created with a comma separated list of entries in curly +braces. Each entry has a key and a value, separated by a colon. Each key can +only appear once. The keys are themselves a comma separated list of filename +pattern. The values are existing styles defined in the template files. +The given style will be set automatically when switching to a buffer or +opening a new buffer with the associated filename pattern and supersedes the +macro *|STYLE|* . + +============================================================================== +6. C/C++ DICTIONARY *csupport-dictionary* +============================================================================== + +The files + + c-c++-keywords.list + k+r.list + stl_index.list + +are a part of this plugin and can be used (together with your own lists) as +dictionaries for automatic word completion. This feature is enabled by +default. The default word lists are + + plugin_dir/c-support/wordlists/c-c++-keywords.list + plugin_dir/c-support/wordlists/k+r.list + plugin_dir/c-support/wordlists/stl_index.list + +The variable plugin_dir will automatically be set by the plugin to one of the +following values: + $HOME.'/.vim/' for Linux/Unix + $VIM.'/vimfiles/' for Windows +If you want to use an additional list MyC.list put the following lines into + ~/.vimrc : + + let g:C_Dictionary_File = PLUGIN_DIR.'/c-support/wordlists/c-c++-keywords.list,'. + \ PLUGIN_DIR.'/c-support/wordlists/k+r.list,'. + \ PLUGIN_DIR.'/c-support/wordlists/stl_index.list,'. + \ PLUGIN_DIR.'/c-support/wordlists/MyC.list' + +When in file ~/.vimrc the name PLUGIN_DIR has to be replaced by $HOME or +$VIM (see above). Whitespaces in the pathnames have to be escaped with a +backslash. +The right side is a comma separated list of files. Note the point at the end +of the first line (string concatenation) and the backslash in front of the +second line (continuation line). +You can use Vim's dictionary feature CTRL-X, CTRL-K (and CTRL-P, CTRL-N). + +============================================================================== +7. EXTENDING ctags *csupport-ctags* +============================================================================== + +------------------------------------------------------------------------------ +7.1 make AND qmake *csupport-ctags-make* +------------------------------------------------------------------------------ + +The use of the Vim plugin taglist.vim (Author: Yegappan Lakshmanan) is highly +recommended. It uses the program ctags which generates tag files for 3 dozen +languages (Exuberant Ctags, Darren Hiebert, http://ctags.sourceforge.net). +With the following extensions the list of targets in a makefile can be shown +in the taglist window. + + 1) Append the file customization.ctags to the file $HOME/.ctags . + + 2) Add the following lines (from customization.vimrc) to $HOME/.vimrc : + + " + "------------------------------------------------------------------- + " taglist.vim : toggle the taglist window + " taglist.vim : define the title texts for make + " taglist.vim : define the title texts for qmake + "------------------------------------------------------------------- + noremap :Tlist + inoremap :Tlist + + let tlist_make_settings = 'make;m:makros;t:targets;i:includes' + let tlist_qmake_settings = 'qmake;t:SystemVariables' + + if has("autocmd") + " ---------- qmake : set file type for *.pro ---------- + autocmd BufNewFile,BufRead *.pro set filetype=qmake + endif " has("autocmd") + + 3) restart vim/gvim + +The two maps will toggle the taglist window (hotkey F11) in all editing modes. +The two assignments define the headings for the (q)make sections in the +taglist window. The autocmd set the file type 'qmake' for the filename +extension 'pro' (ctags needs this). + +------------------------------------------------------------------------------ +7.2 TEMPLATES *csupport-ctags-templates* +------------------------------------------------------------------------------ + +If you frequently change the plugin templates and you are using the taglist +plugin (section above) you may want to use this plugin for navigation. This is +achieved in two steps. First add a new language definition to the file +$HOME/.ctags : + + --langdef=template + --langmap=template:.template,TEMPLATE + --regex-template=/^==\s+([^=]+)\s+==\s*(\s+==\s+([^=]+)\s+==)?/\1/t,template/ + +Now add the following lines to the file $HOME/.vimrc : + + let tlist_template_settings = 'template;t:template' + "--------------------------------------------------------------- + " plugin templates : set filetype for *.template + "--------------------------------------------------------------- + if has("autocmd") + autocmd BufNewFile,BufRead Templates set filetype=template + autocmd BufNewFile,BufRead *.template set filetype=template + endif " has("autocmd") + +The assignment defines the heading for the template section in the taglist +window. The autocmds set the file type 'template' for the main template file +'Templates' and the includefiles '*.template' (if any). + +============================================================================== +8. FOLDING *csupport-folding* +============================================================================== + +This plugin can be used together with folding. + +There are a few peculiarities when the cursor is on a closed fold before +inserting a template: + +Normal mode +----------- +Inserting blocks of complete lines below and above a fold (e.g. frame +comments) and inserting at the top of a buffer (e.g. file description) works +as usual. +Insertions which go to the end of a line (e.g. end-of-line comments) and +insertions which go to the cursor position (e.g. 'sizeof()') will be suppressed +and a warning will be shown. + +Visual mode +----------- +A range of lines containing closed folds can be surrounded by constructs which +have a visual mode, e.g. a for-loop: + + for ( ; ; ) { + +--- 4 lines: {------------------------------------------------------------ + } + +See |folding| for more information on folding. + +============================================================================== +9. Additional Mappings *csupport-ad-mappings* +============================================================================== + +There are a few additional filetype specific key mappings defined in +'~/.vim/ftplugin/c.vim'. + +Complete a classical C comment: '/*' => '/* | */' (modes: i,v). + +Complete a classical C multi-line comment (mode: i): + '/*' => /* + * | + */ + +Open a block (modes: i,v): + '{' => { + | + } +In visual mode the content of the new block will be indented. + +============================================================================== +10. WINDOWS PARTICULARITIES *csupport-windows* +============================================================================== + +For a user installation the plugin should go into the directory structure below + $HOME/vimfiles/ +for a system installation below + $VIM/vimfiles/ + +The values of the two variables can be found from inside Vim: + :echo $VIM +or + :echo $HOME + +The configuration files for a user are + + $HOME/_vimrc and $HOME/_gvimrc + +for the system + + $VIM/_vimrc and $VIM/_gvimrc + +Compiler settings: + +It could be necessary to add further settings for your compiler. To compile +C++-programs using a Dev-C++ installation (http://www.bloodshed.net) the +following item in $VIM/_vimrc is needed (depends on the Dev-C++ install +directory): + + let g:C_CFlags = '-Wall -g -o0 -c -I c:\programs\dev-c++\include\g++' + +============================================================================== +11. ADDITIONAL TIPS *csupport-tips* +============================================================================== + +(1) gVim. Toggle 'insert mode' <--> 'normal mode' with the right mouse button + (see mapping in file costumization.gvimrc). + +(2) gVim. Use tear off menus. + +(3) Try 'Focus under mouse' as window behavior (No mouse click when the mouse + pointer is back from the menu item). + +(4) Use Emulate3Buttons "on" (X11) even for a 3-button mouse. Pressing left + and right button at the same time without moving your fingers is faster + then moving a finger to the middle button (often a wheel). + +============================================================================== +12. TROUBLESHOOTING *csupport-troubleshooting* +============================================================================== + +* I do not see any new main menu item. + - Was the archive extracted into the right directory? + +* How can I see what was loaded? + - Use ':scriptnames' from the Vim command line. + +* No main menu item. + - Loading of plugin files must be enabled. If not use + :filetype plugin on + This is the minimal content of the file '$HOME/.vimrc'. Create one if there + is none, or better use customization.vimrc. + +* Most key mappings do not work. + - They are defined in a filetype plugin in '$HOME/.vim/ftplugin/'. Use + ':filetype' to check if filetype plugins are enabled. If not, add the line + filetype plugin on + to the file '~/.vimrc'. + +* Some hotkeys do not work. + - The hotkeys might be in use by your graphical desktop environment. Under + KDE Ctrl-F9 is the hotkey which let you switch to the 9. desktop. The key + settings can usually be redefined. + +* Splint and/or CodeCheck menu item not visible. + - The program is not installed or not found (path not set) or not executable. + +============================================================================== +13. RELEASE NOTES *csupport-release-notes* +============================================================================== +See file c-support/doc/ChangeLog . + +============================================================================== +vim:tw=78:noet:ts=2:ft=help:norl: diff --git a/doc/omnicppcomplete.txt b/doc/omnicppcomplete.txt new file mode 100644 index 0000000..b11e006 --- /dev/null +++ b/doc/omnicppcomplete.txt @@ -0,0 +1,1078 @@ +*omnicppcomplete.txt* Plugin for C/C++ omnicompletion +*omnicppcomplete* + +Author: Vissale NEANG (fromtonrouge AT gmail DOT com) +Last Change: 26 sept. 2007 + +OmniCppComplete version 0.41 + +For Vim version 7.0 and above + +============================================================================== + +1. Overview |omnicpp-overview| +2. Downloads |omnicpp-download| +3. Installation |omnicpp-installation| +4. Options |omnicpp-options| +5. Features |omnicpp-features| +6. Limitations |omnicpp-limitations| +7. FAQ & TIPS |omnicpp-faq| +8. History |omnicpp-history| +9. Thanks |omnicpp-thanks| + +============================================================================== +1. Overview~ + *omnicpp-overview* +The purpose of this script is to provide an 'omnifunc' function for C and C++ +language. In a C++ file, while in insert mode, you can use CTRL-X CTRL-O to: + + * Complete namespaces, classes, structs and unions + * Complete attribute members and return type of functions + * Complete the "this" pointer + * Complete an object after a cast (C and C++ cast) + * Complete typedefs and anonymous types + +You can set a "may complete" behaviour to start a completion automatically +after a '.', '->' or '::'. Please see |omnicpp-may-complete| for more details. + +The script needs an |Exuberant_ctags| database to work properly. + +============================================================================== +2. Downloads~ + *omnicpp-download* +You can download the latest release of the script from this url : + + http://www.vim.org/scripts/script.php?script_id=1520 + +You can download |Exuberant_ctags| from : + + http://ctags.sourceforge.net + +============================================================================== +3. Installation~ + *omnicpp-installation* +3.1. Script installation~ + +Unzip the downloaded file in your personal |vimfiles| directory (~/.vim under +unix or %HOMEPATH%\vimfiles under windows). The 'omnifunc' will be +automatically set for C and C++ files. + +You also have to enable plugins by adding these two lines in your|.vimrc|file: > + + set nocp + filetype plugin on +< +Please see |cp| and |filetype-plugin-on| sections for more details. + +3.1.1. Files~ + +After installation you should find these files : + + after\ftplugin\cpp.vim + after\ftplugin\c.vim + + autoload\omni\common\debug.vim + \utils.vim + + autoload\omni\cpp\complete.vim + \includes.vim + \items.vim + \maycomplete.vim + \namespaces.vim + \settings.vim + \tokenizer.vim + \utils.vim + + doc\omnicppcomplete.txt + +3.2. Building the Exuberant Ctags database~ + +To extract C/C++ symbols information, the script needs an |Exuberant_ctags| +database. + +You have to build your database with at least the following options: + --c++-kinds=+p : Adds prototypes in the database for C/C++ files. + --fields=+iaS : Adds inheritance (i), access (a) and function + signatures (S) information. + --extra=+q : Adds context to the tag name. Note: Without this + option, the script cannot get class members. + +Thus to build recursively a ctags database from the current directory, the +command looks like this: +> + ctags -R --c++-kinds=+p --fields=+iaS --extra=+q . +< +You can add a map in your |.vimrc| file, eg: > + + map :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q . +< +Or you can add these options in your ctags config file (~/.ctags under unix or +%HOMEPATH%\ctags.cnf under windows) and execute the command : > + + :!ctags -R . +< +If your project contains files of other languages you may add the following +options: + --languages=c++ : Builds only the tags for C++ files. + +If your project contains macros you may also use the -I option. + +Please read the ctags help or ctags man page for more details. + +3.3. Setting the 'tags' option~ + +The default value of the option 'tags' is "./tags,tags" ("./tags,./TAGS,tags,TAGS" +when |+emacs_tags| is enabled), if you build your tag database with the cmd above, +you normally don't have to change this setting (The cmd used above generates a +file with the name "tags"). In this case your current working directory must be +the directory where the tags file reside. + +Note: When |+emacs_tags| is enabled, the script may display members twice, it's + recommended to set tags to "./tags,tags' or "./TAGS,TAGS". + +If your tags file is not named "tags" you have to add it in the 'tags' +option eg: > + + set tags+=/usr/tagsdir/mytagfile +< +You can ensure that the 'tags' option is set properly by executing the following +command: > + + :tselect MyClass +< +Where MyClass is a class of your project. This command should display all +possible tags for the type MyClass. + +3.4. Simple test~ + +Now you can do a simple test. Edit a C++ file and write the simplest case : > + + MyClass myObject; + myObject. +< +You should see class members of MyClass. + +============================================================================== +4. Options~ + *omnicpp-options* + +You can change completion behaviour by setting script options in your |.vimrc| +configuration file. + +4.1. Global scope search toggle~ + *OmniCpp_GlobalScopeSearch* + +You can enable/disable the global scope search by setting the +OmniCpp_GlobalScopeSearch option. + +Possible values are : + 0 = disabled + 1 = enabled + [default=1] > + + let OmniCpp_GlobalScopeSearch = 1 +< +4.2. Namespace search method~ + *OmniCpp_NamespaceSearch* + +You can change the 'using namespace' search behaviour by setting the +OmniCpp_NamespaceSearch option. + +Possible values are : + 0 = namespaces disabled + 1 = search namespaces in the current buffer + 2 = search namespaces in the current buffer and in included files + [default=1] > + + let OmniCpp_NamespaceSearch = 1 +< +When OmniCpp_NamespaceSearch is 2, "using namespace" declarations are parsed +in the current buffer and also in included files. To find included files, the +script use the vim env 'path', so you have to set it properly. + +Note: included files are searched with lvimgrep, thus the location list of the +current window is changed. + +Note: When the 'filetype' is "c", namespace search is always disabled even if +OmniCpp_NamespaceSearch != 0 + +4.3. Class scope completion mode~ + *OmniCpp_DisplayMode* + +When you are completing a class scope (eg: MyClass::), depending on +the current scope, you may see sometimes static, public, protected or private +members and sometimes you may see all members. By default the choice is done +automatically by the script but you can override it with the +OmniCpp_DisplayMode option. + +Note: This option can be use when you have friend classes in your project (the +script does not support friend classes). + +Possible values are : + 0 = auto + 1 = always show all members + [default=0] > + + let OmniCpp_DisplayMode = 0 +< +4.4. Show scope in abbreviation~ + *OmniCpp_ShowScopeInAbbr* + +By default, in the |omnicpp-popup| menu, you will see the scope of a match in +the last column. You can remove this column and add the scope at the beginning +of match abbreviation. +eg: + +OmniCpp_ShowScopeInAbbr = 0 + +-------------------------------------+ + |method1( f + MyNamespace::MyClass| + |_member1 m + MyNamespace::MyClass| + |_member2 m # MyNamespace::MyClass| + |_member3 m - MyNamespace::MyClass| + +-------------------------------------+ + +OmniCpp_ShowScopeInAbbr = 1 + +-------------------------------------+ + |MyNamespace::MyClass::method1( f + | + |MyNamespace::MyClass::_member1 m + | + |MyNamespace::MyClass::_member2 m # | + |MyNamespace::MyClass::_member3 m - | + +-------------------------------------+ + +Possible values are : + 0 = don't show scope in abbreviation + 1 = show scope in abbreviation and remove the last column + [default=0] > + + let OmniCpp_ShowScopeInAbbr = 0 +< +4.5. Show prototype in abbreviation~ + *OmniCpp_ShowPrototypeInAbbr* + +This option allows to display the prototype of a function in the abbreviation +part of the popup menu. + +Possible values are: + 0 = don't display prototype in abbreviation + 1 = display prototype in abbreviation + [default=0] > + + let OmniCpp_ShowPrototypeInAbbr = 0 +< +4.6. Show access~ + *OmniCpp_ShowAccess* + +This option allows to show/hide the access information ('+', '#', '-') in the +popup menu. + +Possible values are: + 0 = hide access + 1 = show access + [default=1] > + + let OmniCpp_ShowAccess = 1 + +4.7. Default using namespace list~ + *OmniCpp_DefaultNamespaces* + +When |OmniCpp_NamespaceSearch| is not 0, the script will parse using namespace +declarations in the current buffer and maybe in included files. +You can specify manually a default namespace list if you want with the +OmniCpp_DefaultNamespaces option. Each item in the list is a namespace name. +eg: If you have + + let OmniCpp_DefaultNamespaces = ["std", "MyNamespace"] + + It will be the same as inserting this declarations at the top of the + current buffer : + + using namespace std; + using namespace MyNamespace; + +This option can be use if you don't want to parse using namespace declarations +in included files and want to add namespaces that are always used in your +project. + +Possible values are : + List of String + [default=[]] > + + let OmniCpp_DefaultNamespaces = [] +< +4.8. May complete behaviour~ + *omnicpp-may-complete* + +This feature allows you to run automatically a completion after a '.', '->' +or '::'. By default, the "may complete" feature is set automatically for '.' +and '->'. The reason to not set this feature for the scope operator '::' is +sometimes you don't want to complete a namespace that contains many members. + +To enable/disable the "may complete" behaviour for dot, arrow and scope +operator, you can change the option OmniCpp_MayCompleteDot, +OmniCpp_MayCompleteArrow and OmniCpp_MayCompleteScope respectively. + + *OmniCpp_MayCompleteDot* +Possible values are : + 0 = May complete disabled for dot + 1 = May complete enabled for dot + [default=1] > + + let OmniCpp_MayCompleteDot = 1 +< + *OmniCpp_MayCompleteArrow* +Possible values are : + 0 = May complete disabled for arrow + 1 = May complete enabled for arrow + [default=1] > + + let OmniCpp_MayCompleteArrow = 1 +< + *OmniCpp_MayCompleteScope* +Possible values are : + 0 = May complete disabled for scope + 1 = May complete enabled for scope + [default=0] > + + let OmniCpp_MayCompleteScope = 0 +< + +Note: You can obviously continue to use + +4.9. Select/Don't select first popup item~ + *OmniCpp_SelectFirstItem* + +Note: This option is only used when 'completeopt' does not contain "longest". + +When 'completeopt' does not contain "longest", Vim automatically select the +first entry of the popup menu. You can change this behaviour with the +OmniCpp_SelectFirstItem option. + +Possible values are: + 0 = don't select first popup item + 1 = select first popup item (inserting it to the text) + 2 = select first popup item (without inserting it to the text) + [default=0] > + + let OmniCpp_SelectFirstItem = 0 + +4.10 Use local search function for variable definitions~ + *OmniCpp_LocalSearchDecl* + +The internal search function for variable definitions of vim requires that the +enclosing braces of the function are located in the first column. You can +change this behaviour with the OmniCpp_LocalSearchDecl option. The local +version works irrespective the position of braces. + +Possible values are: + 0 = use standard vim search function + 1 = use local search function + [default=0] > + +============================================================================== +5. Features~ + *omnicpp-features* +5.1. Popup menu~ + *omnicpp-popup* +Popup menu format: + +-------------------------------------+ + |method1( f + MyNamespace::MyClass| + |_member1 m + MyNamespace::MyClass| + |_member2 m # MyNamespace::MyClass| + |_member3 m - MyNamespace::MyClass| + +-------------------------------------+ + ^ ^ ^ ^ + (1) (2)(3) (4) + +(1) name of the symbol, when a match ends with '(' it's a function. + +(2) kind of the symbol, possible kinds are : + * c = classes + * d = macro definitions + * e = enumerators (values inside an enumeration) + * f = function definitions + * g = enumeration names + * m = class, struct, and union members + * n = namespaces + * p = function prototypes + * s = structure names + * t = typedefs + * u = union names + * v = variable definitions + +(3) access, possible values are : + * + = public + * # = protected + * - = private +Note: enumerators have no access information + +(4) scope where the symbol is defined. +Note: If the scope is empty it's a global symbol +Note: anonymous scope may end with __anon[number] +eg: If you have an anonymous enum in MyNamespace::MyClass : > + + namespace MyNamespace + { + class MyClass + { + private: + + enum + { + E_ENUM0, + E_ENUM1, + E_ENUM2 + }; + }; + } +< + +You should see : + + +----------------------------------------------+ + |E_ENUM0 e MyNamespace::MyClass::__anon1| + |E_ENUM1 e MyNamespace::MyClass::__anon1| + |E_ENUM2 e MyNamespace::MyClass::__anon1| + +----------------------------------------------+ + ^ + __anon[number] + +5.2. Global scope completion~ + +The global scope completion allows you to complete global symbols for the base +you are currently typing. The base can start with '::' or not. +Note: Global scope completion only works with a non empty base, if you run a +completion just after a '::' the completion will fail. The reason is that if +there is no base to complete the script will try to display all the tags in +the database. For small project it could be not a problem but for others you +may wait 5 minutes or more for a result. + +eg1 : > + + pthread_cr => pthread_create +< +Where pthread_create is a global function. +eg2: > + ::globa => ::global_func( + +----------------+ + |global_func( f| + |global_var1 v| + |global_var2 v| + +----------------+ +< +Where global_var1, global_var2 and global_func are global symbols +eg3: > + :: => [NO MATCH] +< +No match because a global completion from an empty base is not allowed. + +5.3. Namespace scope completion~ + +You can complete namespace members after a 'MyNamespace::'. Contrary to global +scope completion you can run a completion from an empty base. +Possible members are: + * Namespaces + * Classes + * Structs + * Unions + * Enums + * Functions + * Variables + * Typedefs + +eg: > + MyNamespace:: + +--------------------------------+ + |E_ENUM0 e MyNamespace| + |E_ENUM1 e MyNamespace| + |E_ENUM2 e MyNamespace| + |MyClass c MyNamespace| + |MyEnum g MyNamespace| + |MyStruct s MyNamespace| + |MyUnion u MyNamespace| + |SubNamespace n MyNamespace| + |doSomething( f MyNamespace| + |myVar v MyNamespace| + |something_t t MyNamespace| + +--------------------------------+ + +5.4. Class scope completion~ + +You can complete class members after a 'MyClass::'. Contrary to global scope +completion you can run a completion from an empty base. +By default, there is two behaviours for class scope completion. + + a) Completion of a base class of the current class scope + + When you are completing a base class of the current class scope, you + will see all members of this class in the popup menu. + eg: > + + class A + { + public: + enum + { + E_ENUM0, + E_ENUM1, + E_ENUM2, + }; + + void func1(); + static int _staticMember; + + private: + int _member; + }; + + class B : public A + { + public: + void doSomething(); + }; + + + void MyClassB::doSomething() + { + MyClassA:: + +---------------------------+ + |E_ENUM0 e MyClassA| + |E_ENUM1 e MyClassA| + |E_ENUM2 e MyClassA| + |func1( f + MyClassA| + |_member m - MyClassA| + |_staticMember m + MyClassA| + +---------------------------+ + } +< + + b) Completion of a non base class of the current class scope + + When you are completing a class that is not a base class of the + current class you will see only enumerators and static members. + eg: > + + class C + { + public: + void doSomething(); + }; + + void MyClassC::doSomething() + { + MyClassA:: + +---------------------------+ + |E_ENUM0 e MyClassA| + |E_ENUM1 e MyClassA| + |E_ENUM2 e MyClassA| + |_staticMember m + MyClassA| + +---------------------------+ + } +< +You can override the default behaviour by setting the +|OmniCpp_DisplayMode| option. + +5.5. Current scope completion~ + +When you start a completion from an empty instruction you are in "Current +scope completion" mode. You will see possible members of each context in +the context stack. +eg: > + void MyClass::doSomething() + { + using namespace MyNamespace; + using namespace SubNamespace; + + // You will see members of each context in the context stack + // 1) MyClass members + // 2) MyNamespace::SubNamespace members + // 3) MyNamespace members + + + +------------------------------------------+ + |_member1 m + MyClass | + |_member2 m # MyClass | + |func1( f MyNamespace::SubNamespace| + |var v MyNamespace::SubNamespace| + |func1( f MyNamespace | + |var v MyNamespace | + +------------------------------------------+ + } +< + +5.6. Class, Struct and Union members completion~ + +You can complete members of class, struct and union instances after a '->' or +'.'. +eg: > + MyClass myObject; + myObject. + +-----------------------+ + |_member1 m + MyClass | + |_member2 m # MyClass | + +-----------------------+ +< + +5.7. Attribute members and returned type completion~ + +You can complete a class member or a return type of a function. +eg: > + MyClass myObject; + + // Completion of the member _member1 + myObject._member1-> + +------------------------+ + |get( m + AnotherClass1| + +------------------------+ + + // Completion of the return type of the function get() + myObject._member1->get()-> + +--------------------------+ + |_member1 m + AnotherClass2| + |_member2 m # AnotherClass2| + |_member3 m - AnotherClass2| + +--------------------------+ + +5.8. Anonymous type completion~ + +Note: To use this feature you need at least|Exuberant_ctags| version 5.6 + +You can complete an anonymous type like this : > + struct + { + int a; + int b; + int c; + }globalVar; + + void func() + { + globalVar. + +---------------+ + |a m + __anon1| + |b m + __anon1| + |c m + __anon1| + +---------------+ + } +< +Where globalVar is a global variable of an anonymous type + +5.9. Typedef completion~ + +You can complete a typedef. The typedef is resolved recursively, thus typedef +of typedef of... may not be a problem. + +You can also complete a typedef of an anonymous type, eg : > + typedef struct + { + int a; + int b; + int c; + }something_t; + + something_t globalVar; + + void func() + { + globalVar. + +---------------+ + |a m + __anon1| + |b m + __anon1| + |c m + __anon1| + +---------------+ + } +< +Where globalVar is a global variable of typedef of an anonymous type. + +5.10. Completion of the "this" pointer~ + +You can complete the "this" pointer. +eg: > + this-> + +-----------------------+ + |_member1 m + MyClass | + |_member2 m # MyClass | + +-----------------------+ + + (*this). + +-----------------------+ + |_member1 m + MyClass | + |_member2 m # MyClass | + +-----------------------+ +< + +5.11. Completion after a cast~ + +You can complete an object after a C or C++ cast. +eg: > + // C cast style + ((AnotherStruct*)pStruct)-> + + // C++ cast style + static_cast(pStruct)-> +< + +5.12. Preview window~ + +If the 'completeopt' option contains the setting "preview" (this is the +default value), you will see a preview window during the completion. +This window shows useful information like function signature, filename where +the symbol is define etc... + +The preview window contains tag information, the list below is non exhaustive. + + * name : name of the tag + * cmd : regexp or line number that helps to find the tag + * signature : signature for prototypes and functions + * kind : kind of the tag (eg: namespace, class etc...) + * access : access information (eg: public, protected, private) + * inherits : list of base classes + * filename : filename where the tag is define + +5.13. Code tokenization~ + +When you start a completion, the current instruction is tokenized ignoring +spaces, tabs, carriage returns and comments. Thus you can complete a symbol +even if the current instruction is on multiple lines, has comments between +words etc... : +eg: this case is unrealistic but it's just for illustration > + + myObject [ 0 ]/* Why is there a comment here ?*/ + ->_member + -> +< + +============================================================================== +6. Limitations~ + *omnicpp-limitations* +Some C++ features are not supported by the script, some implemented features +may not work properly in some conditions. They are multiple reasons like a +lack of information in the database, performance issues and so on... + +6.1. Attribute members and returned type completion~ + +To work properly, the completion of attribute members and returned type of +functions depends on how you write your code in the class declaration. +Because the tags database does not contain information like return type or +type of a member, the script use the cmd information of the tag to determine +the type of an attribute member or the return type of a function. + +Thus, because the cmd is a regular expression (or line number for #define) if +you write your code like this : > + + class MyClass + { + public: + + MyOtherClass + _member; + }; +< +The type of _member will not be recognized, because the cmd will be +/^ _member;$/ and does not contain the type MyOtherClass. +The correct case should be : > + + class MyClass + { + public: + + MyOtherClass _member; + }; +< +It's the same problem for return type of function : > + + class MyClass + { + public: + + MyOtherClass + getOtherClass(); + }; +< +Here the cmd will be /^ getOtherClass();$/ and the script won't find the +return type. +The correct case should be : > + class MyClass + { + public: + + MyOtherClass getOtherClass(); + }; +< + +6.2. Static members~ + +It's the same problem as above, tags database does not contain information +about static members. The only fast way to get this information is to use the +cmd. + +6.3. Typedef~ + +It's the same problem as above, tags database does not contain information +about the type of a typedef. The script use the cmd information to resolve the +typedef. + +6.4. Restricted inheritance access~ + +Tags database contains inheritance information but unfortunately inheritance +access are not available. We could use the cmd but we often find code +indentation like this : > + + class A : + public B, + protected C, + private D + { + }; +< +Here the cmd will be /^class A :$/, we can't extract inheritance access. + +6.5. Using namespace parsing~ + +When you start a completion, using namespace declarations are parsed from the +cursor position to the first scope to detect local using namespace +declarations. After that, global using namespace declarations are parsed in the +file and included files. + +There is a limitation for global using namespace detection, for performance +issues only using namespace that starts a line will be detected. + +6.6. Friend classes~ + +Tags database does not contain information about friend classes. The script +does not support friend classes. + +6.7. Templates~ + +At the moment, |Exuberant_ctags| does not provide additional information for +templates. That's why the script does not handle templates. + +============================================================================== +7. FAQ & TIPS~ + *omnicpp-faq* + +* How to complete STL objects ? + If you have some troubles to generate a good ctags database for STL you + can try this solution : + + 1) Download SGI's STL from SGI's site + (http://www.sgi.com/tech/stl/download.html) + 2) Replace all __STL_BEGIN_NAMESPACE by "namespace std {" and + __STL_END_NAMESPACE by "}" from header and source files. (with Vim, + or with tar and sed or another tool) + 3) Run ctags and put the generated tags file in a directory eg: + ~/MyTags/stl.tags + 4) set tags+=~/MyTags/stl.tags + + The main problem is that you can't tell to ctags that + __STL_BEGIN_NAMESPACE = "namespace std {" even with the option -I. + That's why you need the step 2). + + Here is another solution if you have STL sources using _GLIBCXX_STD macro + (Tip by Nicola Bonelli) : > + + let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"] +< +* How to close automatically the preview window after a completion ? + (Tip by Kamil Renczewski) + + You can add to your |vimrc| the following lines : > + + autocmd CursorMovedI * if pumvisible() == 0|pclose|endif + autocmd InsertLeave * if pumvisible() == 0|pclose|endif +< +============================================================================== +8. History~ + *omnicpp-history* +Version O.41 + - It's recommended to update ctags to version 5.7 or higher + - The plugin is now activated for C files + - New value for OmniCpp_SelectFirstItem when the option is equal to + 2 the first item is selected without inserting it to + the text (patch from Marek Olszewski) + - Bug when completing union members fixed with ctags 5.7 + (reported by Willem-Jan de Hoog) + - New option OmniCpp_LocalSearchDecl (patch from Roland Kuck) + - Bug when tags=something,,somethingelse (reported by Tobias Pflug) + - Bug with nested structure (reported by Mikhail Daen) + - Bug where the script fails to detect the type of a variable when + the ignorecase option is on (reported by Alexey Vakhov) + - Error message when trying to use completion on a not yet saved + Vim buffer (reported by Neil Bird) + - Error message when trying to use completion on an file opened from + a tselect command (reported by Henrique Andrade) + +Version 0.4 + - The script is renamed to OmniCppComplete according to the library + script directory structure. + - OmniCpp_ClassScopeCompletionMethod renamed to OmniCpp_DisplayMode + - Fixed a bug where the quickfix list is modified after a completion. + - OmniCpp_ShowPrototypeInAbbr option added. It allows to show the + function signature in the abbreviation. + - OmniCpp_ShowAccess option added. It allows to hide the access + information in the popup menu. + - The tags database format must be a ctags 5.6 database if you want to + complete anonymous types. + - Fixed current scope detection not working properly in destructors. + - Don't show protected and private members according to the current scope. + - Overloaded functions are now filtered properly. + - New cache system using less memory. + - The class scope of a method is now resolved properly with "using + namespace" declarations. + - OmniCpp_SelectFirstItem option added. It allows to not select the first + item in the popup menu when 'completeopt' does not contain "longest". + - Fixed the bug where a "random" item in the popup menu is selected + by default when 'completeopt' does not contain "longest" option. + - The script is now split in library scripts. + - Cache added for 'using namespace' search in included files + - Default value for OmniCpp_NamespaceSearch is now 1 (search only in the + current buffer). + - Namespace search automatically disabled for C files even if + OmniCpp_NamespaceSearch != 0. + - To avoid linear search in tags files, the ignorecase option is now + disabled when getting tags datas (the user setting is restored after). + - Fixed a bug where friend functions may crash the script and also crash vim. + +Version 0.32 + - Optimizations in search members methods. + - 'May complete' behaviour is now set to default for dot '.' and arrow + '->' (mappings are set in after/ftplugin/cpp.vim) + - Fixed the option CppOmni_ShowScopeInAbbr not detected after the first + completion. + - Exceptions catched from taglist() when a tag file is corrupted. + - Fixed a bug where enumerators in global scope didn't appear in the + popup menu. + +Version 0.31 + WARNING: For this release and future releases you have to build your tags + database with this cmd : + "ctags -R --c++-kinds=+p --fields=+iaS --extra=+q ." + Please read installation instructions in the documentation for details + + - May complete added, please see installation notes for details. + - Fixed a bug where the completion works while in a comment or in a string. + +Version 0.3 + WARNING: For this release and future releases you have to build your tags + database with this cmd : + "ctags -R --c++-kinds=+p --fields=+iaS --extra=+q ." + Please read installation instructions in the documentation for details + + - Documentation added. + - Fixed a bug where typedefs were not correctly resolved in namespaces + in some cases. + - Fixed a bug where the type can not be detected when we have a decl + like this: class A {}globalVar; + - Fixed a bug in type detection where searchdecl() (gd) find + incorrect declaration instruction. + - Global scope completion now only works with non-empty base. + - Using namespace list is now parsed in the current buffer and in + included files. + - Fixed a bug where the completion fails in some cases when the user + sets the ignorecase to on + - Preview window information added + - Some improvements in type detection, the type can be properly detected + with a declaration like this: + 'Class1 *class1A = NULL, **class1B = NULL, class1C[9], class1D[1] = {};' + - Fixed a bug where parent scopes were not displayed in the popup menu + in the current scope completion mode. + - Fixed a bug where an error message was displayed when the last + instruction was not finished. + - Fixed a bug where the completion fails if a punctuator or operator was + immediately after the cursor. + - The script can now detect parent contexts at the cursor position + thanks to 'using namespace' declarations. + It can also detect ambiguous namespaces. They are not included in + the context list. + - Fixed a bug where the current scope is not properly detected when + a file starts with a comment + - Fixed a bug where the type is not detected when we have myObject[0] + - Removed the system() call in SearchMembers(), no more calls to the + ctags binary. The user have to build correctly his database with the cmd: + "ctags -R --c++-kinds=+p --fields=+iaS --extra=+q ." + - File time cache removed, the user have to rebuild his data base after a + modification. + +Version 0.22 + - Completion of unnamed type (eg: You can complete g_Var defined like + this 'struct {int a; int b;}g_Var;'). It also works for a typedef of + an unnamed type (eg: 'typedef struct {int a; int b;}t_mytype; t_mytype + g_Var;'). + - Tag file's time cache added, if a tag file has changed the global + scope result cache is cleared. + - Fixed a bug where the tokenization process enter in an infinite loop + when a file starts with '/*'. + +Version 0.21 + - Improvements on the global scope completion. + The user can now see the progression of the search and complete + matches are stored in a cache for optimization. The cache is cleared + when the tag env is modified. + - Within a class scope when the user complete an empty word, the popup + menu displays the members of the class then members of the global + scope. + - Fixed a bug where a current scope completion failed after a punctuator + or operator (eg: after a '=' or '!='). + +Version 0.2 + - Improvements in type detection (eg: when a variable is declared in a + parameter list, a catch clause, etc...) + - Code tokenization => ignoring spaces, tabs, carriage returns and comments + You can complete a code even if the instruction has bad + indentation, spaces or carriage returns between words + - Completion of class members added + - Detection of the current scope at the cursor position. + If you run a completion from en empty line, members of the current + scope are displayed. It works on the global namespace and the current + class scope (but there is not the combination of the 2 for the moment) + - Basic completion on the global namespace (very slow) + - Completion of returned type added + - this pointer completion added + - Completion after a cast added (C and C++ cast) + - Fixed a bug where the matches of the complete menu are not filtered + according to what the user typed + - Change the output of the popup menu. The type of the member + (function, member, enum etc...) is now display as a single letter. + The access information is display like this : '+' for a public member + '#' for a protected member and '-' for a private member. + The last information is the class, namespace or enum where the member is define. + +Version 0.12: + - Complete check added to the search process, you can now cancel + the search during a complete search. + +Version 0.1: + - First release + +============================================================================== +9. Thanks~ + *omnicpp-thanks* + * For advices, bug report, documentation, help, ideas : + Alexey Vakhov (bug report) + Arthur Axel "fREW" Schmidt (documentation) + Dennis Lubert (bug report) + Henrique Andrade (bug report) + Kamil Renczewski (tips) + Marek Olszewski (patch) + Markus Trenkwalder (bug report) + Martin Stubenschrott (bug report) + Mikhail Daen (bug report) + Neil Bird (bug report) + Nicola Bonelli (tips) + Robert Webb (bug report) + Roland Kuck (patch) + Tobias Pflug (bug report) + Willem-Jan de Hoog (bug report) + Yegappan Lakshmanan (advices) + + + * Darren Hiebert for Exuberant Ctags + + * All Vim devs for Vim + + * Bram Moolenaar for Vim + + * You for using this script :) + +============================================================================== + + vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl: diff --git a/doc/tags b/doc/tags new file mode 100644 index 0000000..92b191b --- /dev/null +++ b/doc/tags @@ -0,0 +1,222 @@ +'NERDChristmasTree' NERD_tree.txt /*'NERDChristmasTree'* +'NERDTreeAutoCenter' NERD_tree.txt /*'NERDTreeAutoCenter'* +'NERDTreeAutoCenterThreshold' NERD_tree.txt /*'NERDTreeAutoCenterThreshold'* +'NERDTreeBookmarksFile' NERD_tree.txt /*'NERDTreeBookmarksFile'* +'NERDTreeCaseSensitiveSort' NERD_tree.txt /*'NERDTreeCaseSensitiveSort'* +'NERDTreeChDirMode' NERD_tree.txt /*'NERDTreeChDirMode'* +'NERDTreeHighlightCursorline' NERD_tree.txt /*'NERDTreeHighlightCursorline'* +'NERDTreeHijackNetrw' NERD_tree.txt /*'NERDTreeHijackNetrw'* +'NERDTreeIgnore' NERD_tree.txt /*'NERDTreeIgnore'* +'NERDTreeMouseMode' NERD_tree.txt /*'NERDTreeMouseMode'* +'NERDTreeQuitOnOpen' NERD_tree.txt /*'NERDTreeQuitOnOpen'* +'NERDTreeShowBookmarks' NERD_tree.txt /*'NERDTreeShowBookmarks'* +'NERDTreeShowFiles' NERD_tree.txt /*'NERDTreeShowFiles'* +'NERDTreeShowHidden' NERD_tree.txt /*'NERDTreeShowHidden'* +'NERDTreeShowLineNumbers' NERD_tree.txt /*'NERDTreeShowLineNumbers'* +'NERDTreeSortOrder' NERD_tree.txt /*'NERDTreeSortOrder'* +'NERDTreeStatusline' NERD_tree.txt /*'NERDTreeStatusline'* +'NERDTreeWinPos' NERD_tree.txt /*'NERDTreeWinPos'* +'NERDTreeWinSize' NERD_tree.txt /*'NERDTreeWinSize'* +'loaded_nerd_tree' NERD_tree.txt /*'loaded_nerd_tree'* +:NERDTree NERD_tree.txt /*:NERDTree* +:NERDTreeClose NERD_tree.txt /*:NERDTreeClose* +:NERDTreeFromBookmark NERD_tree.txt /*:NERDTreeFromBookmark* +:NERDTreeMirror NERD_tree.txt /*:NERDTreeMirror* +:NERDTreeToggle NERD_tree.txt /*:NERDTreeToggle* +AN alternate.txt /*AN* +AS alternate.txt /*AS* +AT alternate.txt /*AT* +AV alternate.txt /*AV* +IH alternate.txt /*IH* +IHN alternate.txt /*IHN* +IHS alternate.txt /*IHS* +IHT alternate.txt /*IHT* +IHV alternate.txt /*IHV* +NERDTree NERD_tree.txt /*NERDTree* +NERDTree-! NERD_tree.txt /*NERDTree-!* +NERDTree-? NERD_tree.txt /*NERDTree-?* +NERDTree-B NERD_tree.txt /*NERDTree-B* +NERDTree-C NERD_tree.txt /*NERDTree-C* +NERDTree-C-J NERD_tree.txt /*NERDTree-C-J* +NERDTree-C-K NERD_tree.txt /*NERDTree-C-K* +NERDTree-D NERD_tree.txt /*NERDTree-D* +NERDTree-F NERD_tree.txt /*NERDTree-F* +NERDTree-I NERD_tree.txt /*NERDTree-I* +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-cd NERD_tree.txt /*NERDTree-cd* +NERDTree-contents NERD_tree.txt /*NERDTree-contents* +NERDTree-e NERD_tree.txt /*NERDTree-e* +NERDTree-f NERD_tree.txt /*NERDTree-f* +NERDTree-gi NERD_tree.txt /*NERDTree-gi* +NERDTree-go NERD_tree.txt /*NERDTree-go* +NERDTree-gs NERD_tree.txt /*NERDTree-gs* +NERDTree-i NERD_tree.txt /*NERDTree-i* +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-s NERD_tree.txt /*NERDTree-s* +NERDTree-t NERD_tree.txt /*NERDTree-t* +NERDTree-u NERD_tree.txt /*NERDTree-u* +NERDTree-x NERD_tree.txt /*NERDTree-x* +NERDTreeAbout NERD_tree.txt /*NERDTreeAbout* +NERDTreeBookmarkCommands NERD_tree.txt /*NERDTreeBookmarkCommands* +NERDTreeBookmarkTable NERD_tree.txt /*NERDTreeBookmarkTable* +NERDTreeBookmarks NERD_tree.txt /*NERDTreeBookmarks* +NERDTreeChangelog NERD_tree.txt /*NERDTreeChangelog* +NERDTreeCredits NERD_tree.txt /*NERDTreeCredits* +NERDTreeFilesysMenu NERD_tree.txt /*NERDTreeFilesysMenu* +NERDTreeFunctionality NERD_tree.txt /*NERDTreeFunctionality* +NERDTreeGlobalCommands NERD_tree.txt /*NERDTreeGlobalCommands* +NERDTreeHacking NERD_tree.txt /*NERDTreeHacking* +NERDTreeInvalidBookmarks NERD_tree.txt /*NERDTreeInvalidBookmarks* +NERDTreeLicense NERD_tree.txt /*NERDTreeLicense* +NERDTreeMappings NERD_tree.txt /*NERDTreeMappings* +NERDTreeOptionDetails NERD_tree.txt /*NERDTreeOptionDetails* +NERDTreeOptionSummary NERD_tree.txt /*NERDTreeOptionSummary* +NERDTreeOptions NERD_tree.txt /*NERDTreeOptions* +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* +WinManagerFileEdit winmanager.txt /*WinManagerFileEdit* +WinManagerForceReSize winmanager.txt /*WinManagerForceReSize* +WinManagerResumeAUs winmanager.txt /*WinManagerResumeAUs* +WinManagerSuspendAUs winmanager.txt /*WinManagerSuspendAUs* +alternate alternate.txt /*alternate* +alternate-acknowledgments alternate.txt /*alternate-acknowledgments* +alternate-commands alternate.txt /*alternate-commands* +alternate-config alternate.txt /*alternate-config* +alternate-installation alternate.txt /*alternate-installation* +alternate-purpose alternate.txt /*alternate-purpose* +alternate-support alternate.txt /*alternate-support* +alternate.txt alternate.txt /*alternate.txt* +c-support csupport.txt /*c-support* +csupport csupport.txt /*csupport* +csupport-Ctrl-j csupport.txt /*csupport-Ctrl-j* +csupport-ad-mappings csupport.txt /*csupport-ad-mappings* +csupport-c++ csupport.txt /*csupport-c++* +csupport-c++-ex csupport.txt /*csupport-c++-ex* +csupport-c++-method-impl csupport.txt /*csupport-c++-method-impl* +csupport-c++-normal-mode csupport.txt /*csupport-c++-normal-mode* +csupport-c++-visual-mode csupport.txt /*csupport-c++-visual-mode* +csupport-choose-makefile csupport.txt /*csupport-choose-makefile* +csupport-code-to-comm csupport.txt /*csupport-code-to-comm* +csupport-comm csupport.txt /*csupport-comm* +csupport-comm-aligned csupport.txt /*csupport-comm-aligned* +csupport-comm-c-cpp csupport.txt /*csupport-comm-c-cpp* +csupport-comm-date csupport.txt /*csupport-comm-date* +csupport-comm-frame csupport.txt /*csupport-comm-frame* +csupport-comm-keyword csupport.txt /*csupport-comm-keyword* +csupport-comm-realign csupport.txt /*csupport-comm-realign* +csupport-comm-sections csupport.txt /*csupport-comm-sections* +csupport-comm-tags csupport.txt /*csupport-comm-tags* +csupport-comm-to-code csupport.txt /*csupport-comm-to-code* +csupport-ctags csupport.txt /*csupport-ctags* +csupport-ctags-make csupport.txt /*csupport-ctags-make* +csupport-ctags-templates csupport.txt /*csupport-ctags-templates* +csupport-custom csupport.txt /*csupport-custom* +csupport-custom-glob-vars csupport.txt /*csupport-custom-glob-vars* +csupport-custom-root csupport.txt /*csupport-custom-root* +csupport-dictionary csupport.txt /*csupport-dictionary* +csupport-folding csupport.txt /*csupport-folding* +csupport-help csupport.txt /*csupport-help* +csupport-hotkeys csupport.txt /*csupport-hotkeys* +csupport-idioms csupport.txt /*csupport-idioms* +csupport-idioms-for-loop csupport.txt /*csupport-idioms-for-loop* +csupport-idioms-function csupport.txt /*csupport-idioms-function* +csupport-idioms-input csupport.txt /*csupport-idioms-input* +csupport-idioms-output csupport.txt /*csupport-idioms-output* +csupport-prep csupport.txt /*csupport-prep* +csupport-prep-ex csupport.txt /*csupport-prep-ex* +csupport-prep-if0 csupport.txt /*csupport-prep-if0* +csupport-prep-normal-mode csupport.txt /*csupport-prep-normal-mode* +csupport-prep-visual-mode csupport.txt /*csupport-prep-visual-mode* +csupport-proto csupport.txt /*csupport-proto* +csupport-release-notes csupport.txt /*csupport-release-notes* +csupport-run csupport.txt /*csupport-run* +csupport-run-buffer csupport.txt /*csupport-run-buffer* +csupport-run-cmdline-args csupport.txt /*csupport-run-cmdline-args* +csupport-run-codecheck csupport.txt /*csupport-run-codecheck* +csupport-run-hardcopy csupport.txt /*csupport-run-hardcopy* +csupport-run-indent csupport.txt /*csupport-run-indent* +csupport-run-make csupport.txt /*csupport-run-make* +csupport-run-make-args csupport.txt /*csupport-run-make-args* +csupport-run-make-clean csupport.txt /*csupport-run-make-clean* +csupport-run-make-run csupport.txt /*csupport-run-make-run* +csupport-run-output csupport.txt /*csupport-run-output* +csupport-run-splint csupport.txt /*csupport-run-splint* +csupport-run-templates csupport.txt /*csupport-run-templates* +csupport-run-xterm csupport.txt /*csupport-run-xterm* +csupport-snippets csupport.txt /*csupport-snippets* +csupport-stat csupport.txt /*csupport-stat* +csupport-stat-normal-mode csupport.txt /*csupport-stat-normal-mode* +csupport-stat-visual-mode csupport.txt /*csupport-stat-visual-mode* +csupport-system-wide csupport.txt /*csupport-system-wide* +csupport-templates csupport.txt /*csupport-templates* +csupport-templates-bind csupport.txt /*csupport-templates-bind* +csupport-templates-date csupport.txt /*csupport-templates-date* +csupport-templates-definition csupport.txt /*csupport-templates-definition* +csupport-templates-expansion csupport.txt /*csupport-templates-expansion* +csupport-templates-files csupport.txt /*csupport-templates-files* +csupport-templates-jump csupport.txt /*csupport-templates-jump* +csupport-templates-macros csupport.txt /*csupport-templates-macros* +csupport-templates-menu csupport.txt /*csupport-templates-menu* +csupport-templates-names csupport.txt /*csupport-templates-names* +csupport-templates-sets csupport.txt /*csupport-templates-sets* +csupport-tips csupport.txt /*csupport-tips* +csupport-troubleshooting csupport.txt /*csupport-troubleshooting* +csupport-usage-gvim csupport.txt /*csupport-usage-gvim* +csupport-usage-vim csupport.txt /*csupport-usage-vim* +csupport-windows csupport.txt /*csupport-windows* +csupport.txt csupport.txt /*csupport.txt* +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* +winmanager winmanager.txt /*winmanager* +winmanager-adding winmanager.txt /*winmanager-adding* +winmanager-bufexplorer-settings winmanager.txt /*winmanager-bufexplorer-settings* +winmanager-bug winmanager.txt /*winmanager-bug* +winmanager-commands winmanager.txt /*winmanager-commands* +winmanager-customizing winmanager.txt /*winmanager-customizing* +winmanager-details winmanager.txt /*winmanager-details* +winmanager-fileexplorer-settings winmanager.txt /*winmanager-fileexplorer-settings* +winmanager-hook-isvalid winmanager.txt /*winmanager-hook-isvalid* +winmanager-hook-refresh winmanager.txt /*winmanager-hook-refresh* +winmanager-hook-resize winmanager.txt /*winmanager-hook-resize* +winmanager-hook-start winmanager.txt /*winmanager-hook-start* +winmanager-hook-title winmanager.txt /*winmanager-hook-title* +winmanager-hooks winmanager.txt /*winmanager-hooks* +winmanager-installing winmanager.txt /*winmanager-installing* +winmanager-overview winmanager.txt /*winmanager-overview* +winmanager-plugin winmanager.txt /*winmanager-plugin* +winmanager-settings winmanager.txt /*winmanager-settings* +winmanager-thanks winmanager.txt /*winmanager-thanks* +winmanager-updates winmanager.txt /*winmanager-updates* diff --git a/doc/winmanager.txt b/doc/winmanager.txt new file mode 100644 index 0000000..fed5198 --- /dev/null +++ b/doc/winmanager.txt @@ -0,0 +1,503 @@ +*winmanager* Plugin for a classical Windows style IDE for Vim 6.0 + For Vim version 6.0. + Last Change: Sun Mar 31 11:00 PM 2002 PST + + By Srinath Avadhanula + (srinath@fastmail.fm) + + *winmanager-plugin* + +winmanager.vim is a plugin which implements a classical windows type IDE in +Vim-6.0, where the directory and buffer browsers are displayed in 2 windows on +the left and the current editing is done on the right. When you open up a new +vim window, simply type in :WMToggle. This will start up winmanager. + +Note This plugin is available only if 'compatible' is not set + You can avoid loading this plugin by setting the "loaded_winmanager" + variable > + :let loaded_winmanager = 1 + +{Vi does not have any of this} +=========================================================================== +OVERVIEW *winmanager-overview* + +|winmanager-installing| Please follow these instructions for installing + winmanager. + +|winmanager-customizing| Describes ways of customizing the window layout, i.e + how to club various explorers into groups, how to + change their relative position, etc. + +|winmanager-details| details of using winmanager. keyboard shortcuts + and other usage details. + +|winmanager-commands| commands provided to the user. its useful to + set keyboard shortcuts to these commands. + +|winmanager-settings| settings (typically made in ~/.vimrc) which + affect the behavior of winmanager. + +|winmanager-adding| one of the most important new features of this + version is the creation of a framework whereby adding + other plugins like explorer.vim or bufexplorer.vim to + winmanager. This section describes briefly the + implementation of winmanager and then describes how + to add a new plugin to winmanager + +|add-local-help| how to use this text file as a vim help file. +|winmanager-bug| bug reports are welcome. +|winmanager-thanks| thanks to the many people who helped! + +=========================================================================== +UPDATES *winmanager-updates* + +The official releases can be found at: > + http://vim.sourceforge.net/scripts/script.php?script_id=95 +However, I will only update the vim.sf.net version of winmanager.zip in case +of a major bug or new feature. For small (and not so bothersome) bug-fixes, I +will put the latest version at: > + http://robotics.eecs.berkeley.edu/~srinath/vim/winmanager-2.0.htm +and also announce it in vim@vim.org when an update occurs. +Therefore if you want to keep to be kept abreast of updates, you could +check occassionally at vim@vim.org. (you can also use your mail server's +filtering capability to effectively subscribe to the announcement). + +============================================================================ +INSTALLING *winmanager-installing* + +winmanager.vim should start working as soon as you restart vim after unzipping +the .zip file you got this from into ~/.vim (unix) or ~\vimfiles (dos) + +winmanager only recognizes plugins whose name appears in the global variable > + g:winManagerWindowLayout +< +By default this global variable has the value > + g:winManagerWindowLayout = 'FileExplorer,TagsExplorer|BufExplorer' +< +(which is the value which winmanager uses if its not set in the user's .vimrc) + +This global variable is responsible for making winmanager recognize the +existence of the explorers and simultaneously custome the window layout. See +the next section for how to set this variable for various custom layouts of +winmanager. + +============================================================================ +CUSTOMIZING *winmanager-customizing* + +The layout of winmanager is controlled by changing the value of the +"g:winManagerWindowLayout" variable. The general form of this variable is +> + g:winManagerWindowLayout = + 'Group1_Member1,Group1_Member2|Group2_Member_1,Group2_Member_2' +< +i.e, explorer "groups" are seperated by the '|' character. Within each group, +individual explorer plugin names are seperated by the comma (',') character. +What winmanager does is display only 1 member from each group in a window. The +user can go to a window and press to display the next explorer belonging +to that group. This ability to "group" windows is valuable to preserve screen +real-estate by using them only as needed. + +Thus for the default value of 'g:winManagerWindowLayout', winmanager will +split the vim window as follows: + +-----------+-------------------+ + | | | + | File | | + | explorer | File being | + | | edited | + | | | + +-----------+ | + | Buffer | | + | explorer | | + | | | + +-----------+-------------------+ + +The user can go the [File List] window and press to goto the +'TagsExplorer' view. + +Removing a plugin name from the 'g:winManagerWindowLayout' variable means +winmanager no longer sees that variable. + +============================================================================ +COMMANDS *winmanager-commands* + +:WMToggle :toggles the visibility of winmanager. This can + also be used to start winmanager for the first + time. A handy mapping is: > + :map :WMToggle +< mnemonic: window-toggle : + +:FirstExplorerWindow :directly takes you to the first explorer window + from the top left corner which is visible. > + :map :FirstExplorerWindow +< mnemonic: window-first : + +:BottomExplorerWindow :directly takes you to the last explorere window + from the top-left which is visible. > + :map :BottomExplorerWindow +< mnemonic: window-last : + +NOTE: winmanager does not provide any mappings by default. These have to set +in the user's .vimrc if you want to use mappings. + +============================================================================ +SETTINGS *winmanager-settings* + +The values of the following global variables should be set in your .vimrc +file if you want a different value than the default: + +g:persistentBehaviour: if set to 0, then as soon as you quit all the files + and only the explorer windows are the ones left, vim will quit. the + default is 1, which means that the explorer windows persist even if + they are the only ones visible. + +g:winManagerWidth: the width of the explorer areas. + (default 25) + +g:defaultExplorer: If you want winmanager to assume the functioning of the + default explorer.vim which ships with vim, set this variable to 0. + (default 1). If this variable is set to 1, then winmanager will behave as + follows: + . if the user starts off vim with a command such as + ":vim some/dir/" then winmanager starts off the window layout with + FileExplorer at the top left window. as of now it changes the + g:windowLayout variable so that file explorer appears in the top left + window. + . if on the other hand the user does ":e some/dir/" while _inside_ vim, + then the behavior is consistent with the original behavior of the + explorer.vim plugin which ships with vim, i.e, the directory is opened + in a buffer and the user can use that to open a file in that window. + Note that the commands ":Explore" and ":Sexplore" are still available if + you set this variable to 1. + winfileexplorer.vim, the modification of explorer.vim which ships with + this version is different from the standard explorer.vim in that it has + display caching. i.e, the directory is read and sorted only the first + time. From the second time on, the directory list is cached in a script + variable so display is faster. + + *winmanager-fileexplorer-settings* +See |explorer| for details. +NOTE: Some of the settings used in explorer.vim are not utlized in +winmanager. + *winmanager-bufexplorer-settings* +g:bufExplorerMaxHeight: the buffer list window dynamicall rescales itself to + occupy only the minimum space required to display all the windows. you + can set a maximum number of lines for this window. (defualt 15) +See |bufexplorer| for details on additional options. +NOTE: Some of the settings used in bufexplorer.vim are not utlized in +winmanager. + +============================================================================= +DETAILED HELP *winmanager-details* + +When winmanager starts up, it divides up the whole vim window into 2 +"regions". The region on the left is the "explorer area" where the various +explorer plugins are displayed. The region on the right is the "file editing +area", where the user works on his current editing session. + + +--------+-------------------+ + | | | + | | 2(i) | + | 1(i) | | + | +-------------------+ + | | | + +--------+ 2(ii) | + | 1(ii) | | + +--------+-------------------+ + +The explorer area (area 1) might contain multiple windows each of which might +contain multiple explorers. In the default configuration (for +g:winManagerWindowLayout = 'FileExplorer,TagsExplorer|BufExplorer'), the first +window can be thought of as containing 2 explorers, the file explorer plugin +and the tags explorer plugin, while the bottom window contains bufexplorer by +itself. + +When a window contains multiple explorers, then the user can cycle between +them by pressing (mnemonic: next) or (mnemonic: previous). + +This section describes the various keyboard shortcuts for the 3 plugins which +are used with winmanager by default. +NOTE: Other plugins might be distributed as add-ins to winmanager. In that +case, please refer to the help which ships with that plugin. + +1. File Explorer plugin +This plugin displays the current directory. Its a modification of the standard +explorer.vim which ships with vim6.0. The following keyboard shortcuts are +available with this plugin: + if on a directory, enters it and displays it in the same + area. If on a file, then opens it in the File Editing Area. + Attempts to open in the same window as the one visited + before, otherwise split open a new window horizontally. if + this sounds a bit confusing, it isnt. its the most intuitive + behaviour that one expects. +<2-leftmouse> (doubleclick) the same as + open the file or directory in a new window in the FileEditing + area. +c change the pwd to the directory currently displayed +C change the currently displayed directory to pwd (converse of + c) this helps in changing to different drives in windows. + i.e, if you are currently on the c: drive and you want to + change to the d: drive, you will have to do + cd d:\ + and then press 'C' in the file explorer area. +s select sort field (size, date, name) +r reverse direction of sort +f add current directory to list of favorites. +R rename file +D delete file (or range of files in visual mode) +- move up one level + refresh the file list + +2. Buffer Explorer plugin +See |bufexplorer-usage| for details. +NOTE: In addition to those shortcuts, winmanager adds the following: + Opens the buffer under the cursor in a split window even if + the current buffer is not modified. + +This window is dynamically rescaled and re-displayed. i.e, when a new window +opens somehwere, the buffer list is automatically updated. also, it tries to +occupy the minimum possible space required to display the files. + +3. File Editing Area +The area where normal editing takes place. The commands in the File Explorer +and Buffer Explorer shouldnt affect the layout of the windows here. Some +mappings which I find useful (which should be placed in your .vimrc if you +plan on using WManager often) is +> + map :BottomExplorerWindow + map :FirstExplorerWindow + map :WMToggle + +Pressing CTRL-W-B should then take you directly to the last explorer window +Similarly pressing CTRL-W-F should take you to the first explorer window. +CTRL-W-T will toggle between the winmanager visible and invisible. + +============================================================================= +ADDING NEW PLUGINS *winmanager-adding* + +This section is of interest only to people who might want to extend winmanager +by adding other plugins to it. The casual user can skip it. + +One of the most important new features of winmanager2.x is the ability to let +other users add IDE type plugins to winmanager.vim with a minimum of effort. +The way winmanager ships, it usually contains the following plugins: +> + (FileExplorer, TagsExplorer) + (BufExplorer) + +i.e, FileExplorer and TagsExplorer occupy one window as a single group, while +BufExplorer occupies another window. "Adding" a plugin means that you will be +able to add a seperate IDE plugin, (call it "YourPlugin" henceforth) either to +one of these groups or seperately by itself. This section describes how to +accomplish this. Although the section is somewhat lengthy, please rest assured +that its really quite simple to do. Have a look at |wintagexplorer|.vim for a +small plugin which accomplishes this. + +To better understand the process, its helpful to give a short description of +the workings of winmanager. When a user wants to use your plugin, he +"registers" it with winmanager, i.e he adds the "name" of the plugin to the +variable g:winManagerWindowLayout in his .vimrc as: + + " this line goes in the user's .vimrc + let g:winManagerWindowLayout = "FileExplorer,TagsExplorer|YourPlugin" + +When winmanager starts up, it remembers the string "YourPlugin" internally as +the plugins "name". (The reason for making this a part of the user's .vimrc +is that that way, he can customize the window layout according to his +preferences). + +In addition to registering, the plugin itself initializes a variable called +the "title" which starts with the name, such as: > + + " this line goes in your script file. + let g:YourPlugin_title = "[My Plugin Title]" + +< +NOTE: Just like the rest of the hooks provided by your plugin, this global +variable name is formed according the rule: g:_title. + +When winmanager starts up, it performs the following 2 actions: + 1. It opens a new file with the "title" provided by the plugin. This + automatically ensures that the same buffer is opened for multiple + invokations of the plugin. + NOTE: It is very important for this reason that the plugin's name be + distinct so that there is a low (ideally zero) probability of a file + with the same name existing on a user's system. + 2. It modifies the "name" string (in this case "YourPlugin") to form + "call YourPlugin_Start()" and then |exec|s this string. Thus winmanager + communicates with your plugin by using a number of such "hooks" or + global functions which all start with the string "YourPlugin" which are + defined in the script file you create. + +In order to enable the dynamic nature of winmanager, where you can have your +plugin change its display every time a |BufEnter| or |BufDelete| event occurs, +it is necessary to provide a few other hooks. Every time a BufEnter or +BufDelete event occurs, winmanager makes a loop over all the visible buffers. +Then it "refreshes" the display of that plugin if it is "invalid". The +following paragraphs describe the hooks that have to be provided to enable +this. + + *winmanager-hooks* + +The following is a list of hooks which should be provided. A few of them are +optional. Consider the case where you want to add a plugin which you have +named "YourPlugin". In the following discussion, a "hook" simply refers to a +globally visible function which is formed according to the rule that it start +with the string "YourPlugin_", where "YourPlugin" is the name of your plugin. + + *winmanager-hook-start* +YourPlugin_Start() This function is called during initialization. It +{Mandatory} can be assumed (and _should_ be) that the focus is + already in the buffer where stuff needs to be + displayed. i.e, the plugin shouldnt open some other + buffer during this function. (i.e, commands such as + ":e", ":vsplit", ":wincmd h" etc in this stage are + bad. If however, you absolutely need to switch + buffers or something which will cause |BufEnter| or + |BufDelete| events, then you need to temporarily + switch winmanager off by using + |WinManagerSuspendAUs|) + + *winmanager-hook-isvalid* +YourPlugin_IsValid() winmanager is dynamic in the sense that it allows the +{Mandatory} plugins to change their displays when a BufEnter event + occurs. At each BufEnter event, winmanager will cycle + through all the visible explorers asking them if + their display is "valid". If it isn't, then they will + be redrawn by calling the next function. + + For plugins such as bufexplorer which change with + every BufEnter, it is sufficient to make this always + return 1. For plugins such as fileexplorer, the + display never changes with the BufEnter even. hence + in its case, it will always return 0. + + *winmanager-hook-refresh* +YourPlugin_Refresh() If the YourPlugin_IsValid() function returns 0, then +{Optional} this function is called to update the display. if the + first function always returns 1, then this function + need not be defined. + NOTE: It is not clear at this time whether this + function is really necessary. It might be obsoleted + in the future. Future versions might call the + _Start() function instead. + NOTE: It has been obsoleted as of version 2.1 + + *winmanager-hook-resize* +YourPlugin_ReSize() The plugins can also be dynamically resizable. (the +{Optional} current bufexplorer which ships with the winmanager + exhibits this behavior). If a plugin creates such a + function, then it will be called after its Refresh() + function. The reason for not letting the plugin make + this a part of its Refresh() function is that + sometimes resizing is not allowed, such as in + instances where there is no window above or below the + plugin to take the slack of a resize. + + +In addition, the plugin should also initialize the following global variable + + *winmanager-hook-title* +g:YourPlugin_title This is the name of the buffer associated with + this plugin. The reason for a title in addition to a + name is that the name should be such that a global + function of that name can be defined. However, the + title can be more descriptive and contain spaces + etc. For example, the present distribution of + FileExplorer has the title "[File List]". Also, + winmanager opens a file with this name (using an + equivalent of ":e g:YourPlugin_title"), which + automatically ensures that new buffers are not eaten + up in multiple invokations of winmanager, toggling + visibility of buffers, etc. + NOTE: It is very important for this reason that the + plugin's name be distinct so that there is a low + (ideally zero) probability of a file with the same + name existing on a user's system. + +In addition to YourPlugin providing winmanager with hooks, winmanager also +provides the following hooks for use by YourPlugin: + + *WinManagerFileEdit* +WinManagerFileEdit({filename}, {split}) + This function _must_ be used when the plugin wants + to open a new file in the file editing area for + editing. Its not sufficient to do something like + ":wincmd p" and then ":e filename", because first of + all the ":wincmd p" command gets screwed + (unfortunately) in the presence of winmanager + because of the (sometimes) large movement winmanager + does over all visible windows to maintain the + dynamic nature. Secondly, doing a simple ":e + filename" will not preserve the @# and the @% + registers properly, causing handy commands such as + |CTRL-^| to totally mis-behave. + + The first argument should be (preferably) the + (complete) name of the file to be opened (including + the full path to it if possible). The second + argument decides whether winmanager should attempt + to open the file in the same window as the last + window or to split a new window to open the file. + + *WinManagerSuspendAUs* +WinManagerSuspendAUs() This makes winmanager stop responding to the + |BufEnter| or |BufDelete| autocommands like it + normally does. Please use this function with care. + You will need to use this when you are performing + some action which causes these events but you dont + want to have winmanager go through the whole + isvalid/refresh cycle. NOTE: Take care to definitely + reset the behavior by using the next function. + + *WinManagerResumeAUs* +WinManagerResumeAUs() This is the converse of |WinManagerSuspendAUs()|. It + makes winmanager start responding to events with the + usual isvalid/refresh cycle. + + *WinManagerForceReSize* +WinManagerForceReSize() Normally, winmanager calls the YourPlugin_ReSize() + function after the YourPlugin_Refresh(). However, + this happens only every |BufEnter| event. When the + plugin performs some function which requires it to + resize even when there was no |BufEnter| or + |BufDelete| event, use this function. Please avoid + making a call to YourPlugin_ReSize() because a + number of safety checks have to be performed before + a resizing is "legal". + +Finally, if you do plan on making an addin to winmanager, feel free to contact +me for help/comments/suggestions. You might also want to take a look at: > + http://robotics.eecs.berkeley.edu/~srinath/vim/explorerSample.vim +for a simple template of an add-in plugin. + +============================================================================= +BUGS *winmanager-bug* + +Please send any comments for improvements or bug-reports to > + srinath@fastmail.fm +If the bug is repeatable, then it will be of great help if a short description +of the events leading to the bug are also given. + +Note "I dont like winmanager" is not a bug report, only an opinion ;-) + +============================================================================= +THANKS *winmanager-thanks* + +I am really grateful to all those who emailed me with bug-reports and comments +for improvement. Most of all, a huge thanks to Xiangjiang Ma for his enormous +support and extremeley helpful QA. + +Other people who helped greatly: + Madoka Machitani: fixed a couple of typos and gave some ideas for making + things more robust. + Colin Dearing: gave many useful suggestions for improvement which lead to + the fast redraw capability of winmanager + Jeff Lanzarotta: for agreeing to make changes to bufexplorer.vim so that + bufexplorer.vim would be compatible with the latest version of + winmanager.vim + + and finally all the great support I got from vim@vim.org and comp.editors + helped a lot. + + +vim:tw=78:et:ts=4:ft=help:norl: diff --git a/ftplugin/c.vim b/ftplugin/c.vim new file mode 100644 index 0000000..16344da --- /dev/null +++ b/ftplugin/c.vim @@ -0,0 +1,487 @@ +" ------------------------------------------------------------------------------ +" +" Vim filetype plugin file +" +" Language : C / C++ +" Plugin : c.vim +" Maintainer : Fritz Mehner +" Revision : $Id: c.vim,v 1.71 2011/12/27 21:04:33 mehner Exp $ +" +" ------------------------------------------------------------------------------ +" +" Only do this when not done yet for this buffer +" +if exists("b:did_C_ftplugin") + finish +endif +let b:did_C_ftplugin = 1 +" +" ---------- system installation or local installation ---------- +" +let s:installation = 'local' +if match( expand(""), escape( $VIM, ' \' ) ) == 0 + let s:installation = 'system' +endif +" +" ---------- Do we have a mapleader other than '\' ? ------------ +" +if exists("g:C_MapLeader") + let maplocalleader = g:C_MapLeader +endif +" +" ---------- C/C++ dictionary ----------------------------------- +" This will enable keyword completion for C and C++ +" using Vim's dictionary feature |i_CTRL-X_CTRL-K|. +" Set the new dictionaries in front of the existing ones +" +if exists("g:C_Dictionary_File") + let save=&dictionary + silent! exe 'setlocal dictionary='.g:C_Dictionary_File + silent! exe 'setlocal dictionary+='.save +endif +" +" ---------- F-key mappings ------------------------------------ +" +" Alt-F9 write buffer and compile +" F9 compile and link +" Ctrl-F9 run executable +" Shift-F9 command line arguments +" + map :call C_Compile():call C_HlMessage() +imap :call C_Compile():call C_HlMessage() +" + map :call C_Link():call C_HlMessage() +imap :call C_Link():call C_HlMessage() +" + map :call C_Run() +imap :call C_Run() +" + map :call C_Arguments() +imap :call C_Arguments() +" +" ---------- alternate file plugin (a.vim) ---------------------- +" +if exists("loaded_alternateFile") + map :A +imap :A +endif +" +command! -nargs=1 -complete=customlist,C_CFileSectionList CFileSection call C_CFileSectionListInsert () +command! -nargs=1 -complete=customlist,C_HFileSectionList HFileSection call C_HFileSectionListInsert () +command! -nargs=1 -complete=customlist,C_KeywordCommentList KeywordComment call C_KeywordCommentListInsert () +command! -nargs=1 -complete=customlist,C_SpecialCommentList SpecialComment call C_SpecialCommentListInsert () +command! -nargs=1 -complete=customlist,C_StdLibraryIncludesList IncludeStdLibrary call C_StdLibraryIncludesInsert () +command! -nargs=1 -complete=customlist,C_C99LibraryIncludesList IncludeC99Library call C_C99LibraryIncludesInsert () +command! -nargs=1 -complete=customlist,C_CppLibraryIncludesList IncludeCppLibrary call C_CppLibraryIncludesInsert () +command! -nargs=1 -complete=customlist,C_CppCLibraryIncludesList IncludeCppCLibrary call C_CppCLibraryIncludesInsert() +command! -nargs=1 -complete=customlist,C_StyleList CStyle call C_Style () + +" ---------- KEY MAPPINGS : MENU ENTRIES ------------------------------------- +" ---------- comments menu ------------------------------------------------ +" + noremap cl :call C_EndOfLineComment() +inoremap cl :call C_EndOfLineComment() +vnoremap cl :call C_EndOfLineComment() +" +nnoremap cj :call C_AdjustLineEndComm() +vnoremap cj :call C_AdjustLineEndComm() +inoremap cj :call C_AdjustLineEndComm()a +" + noremap cs :call C_GetLineEndCommCol() + + noremap c* :call C_CodeToCommentC():nohlsearchj +vnoremap c* :call C_CodeToCommentC():nohlsearchj + + noremap cc :call C_CodeToCommentCpp():nohlsearchj +vnoremap cc :call C_CodeToCommentCpp():nohlsearchj + noremap co :call C_CommentToCode():nohlsearch +vnoremap co :call C_CommentToCode():nohlsearch + + noremap cfr :call C_InsertTemplate("comment.frame") + noremap cfu :call C_InsertTemplate("comment.function") + noremap cme :call C_InsertTemplate("comment.method") + noremap ccl :call C_InsertTemplate("comment.class") + noremap cfdi :call C_InsertTemplate("comment.file-description") + noremap cfdh :call C_InsertTemplate("comment.file-description-header") + +inoremap cfr :call C_InsertTemplate("comment.frame") +inoremap cfu :call C_InsertTemplate("comment.function") +inoremap cme :call C_InsertTemplate("comment.method") +inoremap ccl :call C_InsertTemplate("comment.class") +inoremap cfdi :call C_InsertTemplate("comment.file-description") +inoremap cfdh :call C_InsertTemplate("comment.file-description-header") + + noremap cd :call C_InsertDateAndTime('d') +inoremap cd :call C_InsertDateAndTime('d')a +vnoremap cd s:call C_InsertDateAndTime('d')a + noremap ct :call C_InsertDateAndTime('dt') +inoremap ct :call C_InsertDateAndTime('dt')a +vnoremap ct s:call C_InsertDateAndTime('dt')a +" + noremap cx :call C_CommentToggle( ) +inoremap cx :call C_CommentToggle( ) +vnoremap cx :call C_CommentToggle( ) +" +" call the above defined commands: +" + noremap ccs :CFileSection + noremap chs :HFileSection + noremap ckc :KeywordComment + noremap csc :SpecialComment +" +inoremap ccs :CFileSection +inoremap chs :HFileSection +inoremap ckc :KeywordComment +inoremap csc :SpecialComment +" +" ---------- statements menu ------------------------------------------------ +" + noremap sd :call C_InsertTemplate("statements.do-while") +vnoremap sd :call C_InsertTemplate("statements.do-while", "v") +inoremap sd :call C_InsertTemplate("statements.do-while") + + noremap sf :call C_InsertTemplate("statements.for") +inoremap sf :call C_InsertTemplate("statements.for") + + noremap sfo :call C_InsertTemplate("statements.for-block") +vnoremap sfo :call C_InsertTemplate("statements.for-block", "v") +inoremap sfo :call C_InsertTemplate("statements.for-block") + + noremap si :call C_InsertTemplate("statements.if") +inoremap si :call C_InsertTemplate("statements.if") + + noremap sif :call C_InsertTemplate("statements.if-block") +vnoremap sif :call C_InsertTemplate("statements.if-block", "v") +inoremap sif :call C_InsertTemplate("statements.if-block") + + noremap sie :call C_InsertTemplate("statements.if-else") +vnoremap sie :call C_InsertTemplate("statements.if-else", "v") +inoremap sie :call C_InsertTemplate("statements.if-else") + + noremap sife :call C_InsertTemplate("statements.if-block-else") +vnoremap sife :call C_InsertTemplate("statements.if-block-else", "v") +inoremap sife :call C_InsertTemplate("statements.if-block-else") + + noremap se :call C_InsertTemplate("statements.else-block") +vnoremap se :call C_InsertTemplate("statements.else-block", "v") +inoremap se :call C_InsertTemplate("statements.else-block") + + noremap sw :call C_InsertTemplate("statements.while") +inoremap sw :call C_InsertTemplate("statements.while") + + noremap swh :call C_InsertTemplate("statements.while-block") +vnoremap swh :call C_InsertTemplate("statements.while-block", "v") +inoremap swh :call C_InsertTemplate("statements.while-block") + + noremap ss :call C_InsertTemplate("statements.switch") +vnoremap ss :call C_InsertTemplate("statements.switch", "v") +inoremap ss :call C_InsertTemplate("statements.switch") + + noremap sc :call C_InsertTemplate("statements.case") +inoremap sc :call C_InsertTemplate("statements.case") + + noremap s{ :call C_InsertTemplate("statements.block") +vnoremap s{ :call C_InsertTemplate("statements.block", "v") +inoremap s{ :call C_InsertTemplate("statements.block") + + noremap sb :call C_InsertTemplate("statements.block") +vnoremap sb :call C_InsertTemplate("statements.block", "v") +inoremap sb :call C_InsertTemplate("statements.block") +" +" ---------- preprocessor menu ---------------------------------------------- +" + noremap ps :IncludeStdLibrary +inoremap ps :IncludeStdLibrary + noremap pc :IncludeC99Library +inoremap pc :IncludeC99Library + noremap +ps :IncludeCppLibrary +inoremap +ps :IncludeCppLibrary + noremap +pc :IncludeCppCLibrary +inoremap +pc :IncludeCppC9Library +" + noremap p< :call C_InsertTemplate("preprocessor.include-global") + noremap p" :call C_InsertTemplate("preprocessor.include-local") + noremap pd :call C_InsertTemplate("preprocessor.define") + noremap pu :call C_InsertTemplate("preprocessor.undefine") +" +inoremap p< :call C_InsertTemplate("preprocessor.include-global") +inoremap p" :call C_InsertTemplate("preprocessor.include-local") +inoremap pd :call C_InsertTemplate("preprocessor.define") +inoremap pu :call C_InsertTemplate("preprocessor.undefine") + + noremap pif :call C_InsertTemplate("preprocessor.if-endif") + noremap pie :call C_InsertTemplate("preprocessor.if-else-endif") + noremap pid :call C_InsertTemplate("preprocessor.ifdef-else-endif") + noremap pin :call C_InsertTemplate("preprocessor.ifndef-else-endif") + noremap pind :call C_InsertTemplate("preprocessor.ifndef-def-endif") + +vnoremap pif :call C_InsertTemplate("preprocessor.if-endif", "v") +vnoremap pie :call C_InsertTemplate("preprocessor.if-else-endif", "v") +vnoremap pid :call C_InsertTemplate("preprocessor.ifdef-else-endif", "v") +vnoremap pin :call C_InsertTemplate("preprocessor.ifndef-else-endif", "v") +vnoremap pind :call C_InsertTemplate("preprocessor.ifndef-def-endif", "v") + +inoremap pif :call C_InsertTemplate("preprocessor.if-endif") +inoremap pie :call C_InsertTemplate("preprocessor.if-else-endif") +inoremap pid :call C_InsertTemplate("preprocessor.ifdef-else-endif") +inoremap pin :call C_InsertTemplate("preprocessor.ifndef-else-endif") +inoremap pind :call C_InsertTemplate("preprocessor.ifndef-def-endif") + + noremap pi0 :call C_PPIf0("a")2ji +inoremap pi0 :call C_PPIf0("a")2ji +vnoremap pi0 :call C_PPIf0("v") + + noremap pr0 :call C_PPIf0Remove() +inoremap pr0 :call C_PPIf0Remove() +" + noremap pe :call C_InsertTemplate("preprocessor.error") + noremap pl :call C_InsertTemplate("preprocessor.line") + noremap pp :call C_InsertTemplate("preprocessor.pragma") +" +inoremap pe :call C_InsertTemplate("preprocessor.error") +inoremap pl :call C_InsertTemplate("preprocessor.line") +inoremap pp :call C_InsertTemplate("preprocessor.pragma") +" +" ---------- idioms menu ---------------------------------------------------- +" + noremap if :call C_InsertTemplate("idioms.function") +vnoremap if :call C_InsertTemplate("idioms.function", "v") +inoremap if :call C_InsertTemplate("idioms.function") + noremap isf :call C_InsertTemplate("idioms.function-static") +vnoremap isf :call C_InsertTemplate("idioms.function-static", "v") +inoremap isf :call C_InsertTemplate("idioms.function-static") + noremap im :call C_InsertTemplate("idioms.main") +vnoremap im :call C_InsertTemplate("idioms.main", "v") +inoremap im :call C_InsertTemplate("idioms.main") +" + noremap i0 :call C_CodeFor("up" ) +vnoremap i0 :call C_CodeFor("up" ) +inoremap i0 :call C_CodeFor("up" )i + noremap in :call C_CodeFor("down") +vnoremap in :call C_CodeFor("down") +inoremap in :call C_CodeFor("down")i +" + noremap ie :call C_InsertTemplate("idioms.enum") +vnoremap ie :call C_InsertTemplate("idioms.enum" , "v") +inoremap ie :call C_InsertTemplate("idioms.enum") + noremap is :call C_InsertTemplate("idioms.struct") +vnoremap is :call C_InsertTemplate("idioms.struct", "v") +inoremap is :call C_InsertTemplate("idioms.struct") + noremap iu :call C_InsertTemplate("idioms.union") +vnoremap iu :call C_InsertTemplate("idioms.union" , "v") +inoremap iu :call C_InsertTemplate("idioms.union") +" + noremap ip :call C_InsertTemplate("idioms.printf") +inoremap ip :call C_InsertTemplate("idioms.printf") + noremap isc :call C_InsertTemplate("idioms.scanf") +inoremap isc :call C_InsertTemplate("idioms.scanf") +" + noremap ica :call C_InsertTemplate("idioms.calloc") +inoremap ica :call C_InsertTemplate("idioms.calloc") + noremap ima :call C_InsertTemplate("idioms.malloc") +inoremap ima :call C_InsertTemplate("idioms.malloc") + noremap ire :call C_InsertTemplate("idioms.realloc") +inoremap ire :call C_InsertTemplate("idioms.realloc") +" + noremap isi :call C_InsertTemplate("idioms.sizeof") +inoremap isi :call C_InsertTemplate("idioms.sizeof") +vnoremap isi :call C_InsertTemplate("idioms.sizeof", "v") + + noremap ias :call C_InsertTemplate("idioms.assert") +vnoremap ias :call C_InsertTemplate("idioms.assert", "v") +inoremap ias :call C_InsertTemplate("idioms.assert") +" + noremap ii :call C_InsertTemplate("idioms.open-input-file") +inoremap ii :call C_InsertTemplate("idioms.open-input-file") +vnoremap ii :call C_InsertTemplate("idioms.open-input-file", "v") + noremap io :call C_InsertTemplate("idioms.open-output-file") +inoremap io :call C_InsertTemplate("idioms.open-output-file") +vnoremap io :call C_InsertTemplate("idioms.open-output-file", "v") +" + noremap ifs :call C_InsertTemplate("idioms.fscanf") +inoremap ifs :call C_InsertTemplate("idioms.fscanf") + noremap ifp :call C_InsertTemplate("idioms.fprintf") +inoremap ifp :call C_InsertTemplate("idioms.fprintf") +" +" ---------- snippet menu : snippets ----------------------------------------- +" + noremap nr :call C_CodeSnippet("r") + noremap nw :call C_CodeSnippet("w") +vnoremap nw :call C_CodeSnippet("wv") + noremap ne :call C_CodeSnippet("e") +" +inoremap nr :call C_CodeSnippet("r") +inoremap nw :call C_CodeSnippet("w") +inoremap ne :call C_CodeSnippet("e") +" +" ---------- snippet menu : prototypes --------------------------------------- +" + noremap np :call C_ProtoPick("function") +vnoremap np :call C_ProtoPick("function") +inoremap np :call C_ProtoPick("function") +" + noremap nf :call C_ProtoPick("function") +vnoremap nf :call C_ProtoPick("function") +inoremap nf :call C_ProtoPick("function") +" + noremap nm :call C_ProtoPick("method") +vnoremap nm :call C_ProtoPick("method") +inoremap nm :call C_ProtoPick("method") +" + noremap ni :call C_ProtoInsert() +inoremap ni :call C_ProtoInsert() +" + noremap nc :call C_ProtoClear() +inoremap nc :call C_ProtoClear() +" + noremap ns :call C_ProtoShow() +inoremap ns :call C_ProtoShow() +" +" ---------- snippet menu : templates ---------------------------------------- +" + noremap ntl :call C_BrowseTemplateFiles("Local") +inoremap ntl :call C_BrowseTemplateFiles("Local") + if s:installation == 'system' + noremap ntg :call C_BrowseTemplateFiles("Global") + inoremap ntg :call C_BrowseTemplateFiles("Global") + endif + noremap ntr :call C_RereadTemplates() + noremap nts :CStyle +inoremap ntr :call C_RereadTemplates() +inoremap nts :CStyle +" +" ---------- C++ menu ---------------------------------------------------- +" + noremap +" :call C_InsertTemplate("cpp.cout-operator") +inoremap +" :call C_InsertTemplate("cpp.cout-operator") + noremap +co :call C_InsertTemplate("cpp.cout") +inoremap +co :call C_InsertTemplate("cpp.cout") +" + noremap +c :call C_InsertTemplate("cpp.class-definition") +inoremap +c :call C_InsertTemplate("cpp.class-definition") + noremap +cn :call C_InsertTemplate("cpp.class-using-new-definition") +inoremap +cn :call C_InsertTemplate("cpp.class-using-new-definition") + + noremap +ci :call C_InsertTemplate("cpp.class-implementation") +inoremap +ci :call C_InsertTemplate("cpp.class-implementation") + noremap +cni :call C_InsertTemplate("cpp.class-using-new-implementation") +inoremap +cni :call C_InsertTemplate("cpp.class-using-new-implementation") + + noremap +mi :call C_InsertTemplate("cpp.method-implementation") +inoremap +mi :call C_InsertTemplate("cpp.method-implementation") + noremap +ai :call C_InsertTemplate("cpp.accessor-implementation") +inoremap +ai :call C_InsertTemplate("cpp.accessor-implementation") + + noremap +tc :call C_InsertTemplate("cpp.template-class-definition") +inoremap +tc :call C_InsertTemplate("cpp.template-class-definition") + noremap +tcn :call C_InsertTemplate("cpp.template-class-using-new-definition") +inoremap +tcn :call C_InsertTemplate("cpp.template-class-using-new-definition") + + noremap +tci :call C_InsertTemplate("cpp.template-class-implementation") +inoremap +tci :call C_InsertTemplate("cpp.template-class-implementation") + noremap +tcni :call C_InsertTemplate("cpp.template-class-using-new-implementation") +inoremap +tcni :call C_InsertTemplate("cpp.template-class-using-new-implementation") + + noremap +tmi :call C_InsertTemplate("cpp.template-method-implementation") +inoremap +tmi :call C_InsertTemplate("cpp.template-method-implementation") + noremap +tai :call C_InsertTemplate("cpp.template-accessor-implementation") +inoremap +tai :call C_InsertTemplate("cpp.template-accessor-implementation") + + noremap +tf :call C_InsertTemplate("cpp.template-function") +inoremap +tf :call C_InsertTemplate("cpp.template-function") + + noremap +ec :call C_InsertTemplate("cpp.error-class") +inoremap +ec :call C_InsertTemplate("cpp.error-class") + + noremap +tr :call C_InsertTemplate("cpp.try-catch") +vnoremap +tr :call C_InsertTemplate("cpp.try-catch", "v") +inoremap +tr :call C_InsertTemplate("cpp.try-catch") + + noremap +ca :call C_InsertTemplate("cpp.catch") +vnoremap +ca :call C_InsertTemplate("cpp.catch", "v") +inoremap +ca :call C_InsertTemplate("cpp.catch") + + noremap +c. :call C_InsertTemplate("cpp.catch-points") +vnoremap +c. :call C_InsertTemplate("cpp.catch-points", "v") +inoremap +c. :call C_InsertTemplate("cpp.catch-points") +" +" ---------- run menu -------------------------------------------------------- +" + map rc :call C_Compile():call C_HlMessage() + map rl :call C_Link():call C_HlMessage() + map rr :call C_Run() + map ra :call C_Arguments() + map rm :call C_Make() + map rcm :call C_ChooseMakefile() + map rmc :call C_MakeClean() + map rme :call C_MakeExeToRun() + map rma :call C_MakeArguments() + map rp :call C_SplintCheck():call C_HlMessage() + map rpa :call C_SplintArguments() + map rd :call C_Indent() + map rh :call C_Hardcopy() + map rs :call C_Settings() +" +vmap rh :call C_Hardcopy() +" +imap rc :call C_Compile():call C_HlMessage() +imap rl :call C_Link():call C_HlMessage() +imap rr :call C_Run() +imap ra :call C_Arguments() +imap rm :call C_Make() +imap rmc :call C_MakeClean() +imap rme :call C_MakeExeToRun() +imap rma :call C_MakeArguments() +imap rp :call C_SplintCheck():call C_HlMessage() +imap rpa :call C_SplintArguments() +imap rd :call C_Indent() +imap rh :call C_Hardcopy() +imap rs :call C_Settings() + if has("unix") + map rx :call C_XtermSize() + imap rx :call C_XtermSize() + endif + map ro :call C_Toggle_Gvim_Xterm() +imap ro :call C_Toggle_Gvim_Xterm() +" +" Abraxas CodeCheck (R) +" +if executable("check") + map rk :call C_CodeCheck():call C_HlMessage() + map rka :call C_CodeCheckArguments() + imap rk :call C_CodeCheck():call C_HlMessage() + imap rka :call C_CodeCheckArguments() +endif +" ---------- plugin help ----------------------------------------------------- +" + map hp :call C_HelpCsupport() +imap hp :call C_HelpCsupport() + map hm :call C_Help("m") +imap hm :call C_Help("m") +" +"------------------------------------------------------------------------------- +" additional mapping : complete a classical C comment: '/*' => '/* | */' +"------------------------------------------------------------------------------- +inoremap /* /**/ +vnoremap /* s/**/p +" +"------------------------------------------------------------------------------- +" additional mapping : complete a classical C multi-line comment: +" '/*' => /* +" * | +" */ +"------------------------------------------------------------------------------- +inoremap /* /*/kA +" +"------------------------------------------------------------------------------- +" additional mapping : { always opens a block +"------------------------------------------------------------------------------- +inoremap { {}O +vnoremap { S{}Pk=iB +" +" +if !exists("g:C_Ctrl_j") || ( exists("g:C_Ctrl_j") && g:C_Ctrl_j != 'off' ) + nmap i=C_JumpCtrlJ() + imap =C_JumpCtrlJ() +endif +" diff --git a/ftplugin/make.vim b/ftplugin/make.vim new file mode 100644 index 0000000..9c35243 --- /dev/null +++ b/ftplugin/make.vim @@ -0,0 +1,31 @@ +" ------------------------------------------------------------------------------ +" +" Vim filetype plugin file (part of the c.vim plugin) +" +" Language : make +" Plugin : c.vim +" Maintainer : Fritz Mehner +" Revision : $Id: make.vim,v 1.4 2011/12/27 21:04:33 mehner Exp $ +" +" ------------------------------------------------------------------------------ +" +" Only do this when not done yet for this buffer +" +if exists("b:did_make_ftplugin") + finish +endif +let b:did_make_ftplugin = 1 + + map :call C_Make() +imap :call C_Make() + map rm :call C_Make() +imap rm :call C_Make() + map rcm :call C_ChooseMakefile() +imap rcm :call C_ChooseMakefile() + map rmc :call C_MakeClean() +imap rmc :call C_MakeClean() + map rme :call C_MakeExeToRun() +imap rme :call C_MakeExeToRun() + map rma :call C_MakeArguments() +imap rma :call C_MakeArguments() + diff --git a/plugin/NERD_tree.vim b/plugin/NERD_tree.vim new file mode 100644 index 0000000..ea5ff80 --- /dev/null +++ b/plugin/NERD_tree.vim @@ -0,0 +1,3801 @@ +" ============================================================================ +" File: NERD_tree.vim +" Description: vim global plugin that provides a nice tree explorer +" Maintainer: Martin Grenfell +" Last Change: 7 Jun, 2009 +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +let s:NERD_tree_version = '3.1.1' + +" SECTION: Script init stuff {{{1 +"============================================================ +if exists("loaded_nerd_tree") + finish +endif +if v:version < 700 + echoerr "NERDTree: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!" + finish +endif +let loaded_nerd_tree = 1 + +"for line continuation - i.e dont want C in &cpo +let s:old_cpo = &cpo +set cpo&vim + +"Function: s:initVariable() function {{{2 +"This function is used to initialise a given variable to a given value. The +"variable is only initialised if it does not exist prior +" +"Args: +"var: the name of the var to be initialised +"value: the value to initialise var to +" +"Returns: +"1 if the var is set, 0 otherwise +function! s:initVariable(var, value) + if !exists(a:var) + exec 'let ' . a:var . ' = ' . "'" . a:value . "'" + return 1 + endif + return 0 +endfunction + +"SECTION: Init variable calls and other random constants {{{2 +call s:initVariable("g:NERDChristmasTree", 1) +call s:initVariable("g:NERDTreeAutoCenter", 1) +call s:initVariable("g:NERDTreeAutoCenterThreshold", 3) +call s:initVariable("g:NERDTreeCaseSensitiveSort", 0) +call s:initVariable("g:NERDTreeChDirMode", 0) +if !exists("g:NERDTreeIgnore") + let g:NERDTreeIgnore = ['\~$'] +endif +call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks') +call s:initVariable("g:NERDTreeHighlightCursorline", 1) +call s:initVariable("g:NERDTreeHijackNetrw", 1) +call s:initVariable("g:NERDTreeMouseMode", 1) +call s:initVariable("g:NERDTreeNotificationThreshold", 100) +call s:initVariable("g:NERDTreeQuitOnOpen", 0) +call s:initVariable("g:NERDTreeShowBookmarks", 0) +call s:initVariable("g:NERDTreeShowFiles", 1) +call s:initVariable("g:NERDTreeShowHidden", 0) +call s:initVariable("g:NERDTreeShowLineNumbers", 0) +call s:initVariable("g:NERDTreeSortDirs", 1) + +if !exists("g:NERDTreeSortOrder") + let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$'] +else + "if there isnt a * in the sort sequence then add one + if count(g:NERDTreeSortOrder, '*') < 1 + call add(g:NERDTreeSortOrder, '*') + endif +endif + +"we need to use this number many times for sorting... so we calculate it only +"once here +let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*') + +call s:initVariable("g:NERDTreeStatusline", "%{b:NERDTreeRoot.path.strForOS(0)}") +call s:initVariable("g:NERDTreeWinPos", "left") +call s:initVariable("g:NERDTreeWinSize", 31) + +let s:running_windows = has("win16") || has("win32") || has("win64") + +"init the shell commands that will be used to copy nodes, and remove dir trees +" +"Note: the space after the command is important +if s:running_windows + call s:initVariable("g:NERDTreeRemoveDirCmd", 'rmdir /s /q ') +else + call s:initVariable("g:NERDTreeRemoveDirCmd", 'rm -rf ') + call s:initVariable("g:NERDTreeCopyCmd", 'cp -r ') +endif + + +"SECTION: Init variable calls for key mappings {{{2 +call s:initVariable("g:NERDTreeMapActivateNode", "o") +call s:initVariable("g:NERDTreeMapChangeRoot", "C") +call s:initVariable("g:NERDTreeMapChdir", "cd") +call s:initVariable("g:NERDTreeMapCloseChildren", "X") +call s:initVariable("g:NERDTreeMapCloseDir", "x") +call s:initVariable("g:NERDTreeMapDeleteBookmark", "D") +call s:initVariable("g:NERDTreeMapExecute", "!") +call s:initVariable("g:NERDTreeMapFilesystemMenu", "m") +call s:initVariable("g:NERDTreeMapHelp", "?") +call s:initVariable("g:NERDTreeMapJumpFirstChild", "K") +call s:initVariable("g:NERDTreeMapJumpLastChild", "J") +call s:initVariable("g:NERDTreeMapJumpNextSibling", "") +call s:initVariable("g:NERDTreeMapJumpParent", "p") +call s:initVariable("g:NERDTreeMapJumpPrevSibling", "") +call s:initVariable("g:NERDTreeMapJumpRoot", "P") +call s:initVariable("g:NERDTreeMapOpenExpl", "e") +call s:initVariable("g:NERDTreeMapOpenInTab", "t") +call s:initVariable("g:NERDTreeMapOpenInTabSilent", "T") +call s:initVariable("g:NERDTreeMapOpenRecursively", "O") +call s:initVariable("g:NERDTreeMapOpenSplit", "i") +call s:initVariable("g:NERDTreeMapOpenVSplit", "s") +call s:initVariable("g:NERDTreeMapPreview", "g" . NERDTreeMapActivateNode) +call s:initVariable("g:NERDTreeMapPreviewSplit", "g" . NERDTreeMapOpenSplit) +call s:initVariable("g:NERDTreeMapPreviewVSplit", "g" . NERDTreeMapOpenVSplit) +call s:initVariable("g:NERDTreeMapQuit", "q") +call s:initVariable("g:NERDTreeMapRefresh", "r") +call s:initVariable("g:NERDTreeMapRefreshRoot", "R") +call s:initVariable("g:NERDTreeMapToggleBookmarks", "B") +call s:initVariable("g:NERDTreeMapToggleFiles", "F") +call s:initVariable("g:NERDTreeMapToggleFilters", "f") +call s:initVariable("g:NERDTreeMapToggleHidden", "I") +call s:initVariable("g:NERDTreeMapUpdir", "u") +call s:initVariable("g:NERDTreeMapUpdirKeepOpen", "U") + +"SECTION: Script level variable declaration{{{2 +let s:escape_chars = " \\`\|\"#%&,?()\*^<>" +let s:NERDTreeBufName = 'NERD_tree_' + +let s:tree_wid = 2 +let s:tree_markup_reg = '^[ `|]*[\-+~]' +let s:tree_up_dir_line = '.. (up a dir)' + +let s:os_slash = '/' +if s:running_windows + let s:os_slash = '\' +endif + +"the number to add to the nerd tree buffer name to make the buf name unique +let s:next_buffer_number = 1 + +" SECTION: Commands {{{1 +"============================================================ +"init the command that users start the nerd tree with +command! -n=? -complete=dir -bar NERDTree :call s:initNerdTree('') +command! -n=? -complete=dir -bar NERDTreeToggle :call s:toggle('') +command! -n=0 -bar NERDTreeClose :call s:closeTreeIfOpen() +command! -n=1 -complete=customlist,s:completeBookmarks -bar NERDTreeFromBookmark call s:initNerdTree('') +command! -n=0 -bar NERDTreeMirror call s:initNerdTreeMirror() +" SECTION: Auto commands {{{1 +"============================================================ +augroup NERDTree + "Save the cursor position whenever we close the nerd tree + exec "autocmd BufWinLeave *". s:NERDTreeBufName ." call saveScreenState()" + "cache bookmarks when vim loads + autocmd VimEnter * call s:Bookmark.CacheBookmarks(0) +augroup END + +if g:NERDTreeHijackNetrw + augroup NERDTreeHijackNetrw + autocmd VimEnter * silent! autocmd! FileExplorer + au BufEnter,VimEnter * call s:checkForBrowse(expand("")) + augroup END +endif + +"SECTION: Classes {{{1 +"============================================================ +"CLASS: Bookmark {{{2 +"============================================================ +let s:Bookmark = {} +" FUNCTION: Bookmark.AddBookmark(name, path) {{{3 +" Class method to add a new bookmark to the list, if a previous bookmark exists +" with the same name, just update the path for that bookmark +function! s:Bookmark.AddBookmark(name, path) + for i in s:Bookmark.Bookmarks() + if i.name ==# a:name + let i.path = a:path + return + endif + endfor + call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path)) + call s:Bookmark.Sort() +endfunction +" Function: Bookmark.Bookmarks() {{{3 +" Class method to get all bookmarks. Lazily initializes the bookmarks global +" variable +function! s:Bookmark.Bookmarks() + if !exists("g:NERDTreeBookmarks") + let g:NERDTreeBookmarks = [] + endif + return g:NERDTreeBookmarks +endfunction +" Function: Bookmark.BookmarkExistsFor(name) {{{3 +" class method that returns 1 if a bookmark with the given name is found, 0 +" otherwise +function! s:Bookmark.BookmarkExistsFor(name) + try + call s:Bookmark.BookmarkFor(a:name) + return 1 + catch /^NERDTree.BookmarkNotFoundError/ + return 0 + endtry +endfunction +" Function: Bookmark.BookmarkFor(name) {{{3 +" Class method to get the bookmark that has the given name. {} is return if no +" bookmark is found +function! s:Bookmark.BookmarkFor(name) + for i in s:Bookmark.Bookmarks() + if i.name ==# a:name + return i + endif + endfor + throw "NERDTree.BookmarkNotFoundError: no bookmark found for name: \"". a:name .'"' +endfunction +" Function: Bookmark.BookmarkNames() {{{3 +" Class method to return an array of all bookmark names +function! s:Bookmark.BookmarkNames() + let names = [] + for i in s:Bookmark.Bookmarks() + call add(names, i.name) + endfor + return names +endfunction +" FUNCTION: Bookmark.CacheBookmarks(silent) {{{3 +" Class method to read all bookmarks from the bookmarks file intialize +" bookmark objects for each one. +" +" Args: +" silent - dont echo an error msg if invalid bookmarks are found +function! s:Bookmark.CacheBookmarks(silent) + if filereadable(g:NERDTreeBookmarksFile) + let g:NERDTreeBookmarks = [] + let g:NERDTreeInvalidBookmarks = [] + let bookmarkStrings = readfile(g:NERDTreeBookmarksFile) + let invalidBookmarksFound = 0 + for i in bookmarkStrings + + "ignore blank lines + if i != '' + + let name = substitute(i, '^\(.\{-}\) .*$', '\1', '') + let path = substitute(i, '^.\{-} \(.*\)$', '\1', '') + + try + let bookmark = s:Bookmark.New(name, s:Path.New(path)) + call add(g:NERDTreeBookmarks, bookmark) + catch /^NERDTree.InvalidArgumentsError/ + call add(g:NERDTreeInvalidBookmarks, i) + let invalidBookmarksFound += 1 + endtry + endif + endfor + if invalidBookmarksFound + call s:Bookmark.Write() + if !a:silent + call s:echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.") + endif + endif + call s:Bookmark.Sort() + endif +endfunction +" FUNCTION: Bookmark.compareTo(otherbookmark) {{{3 +" Compare these two bookmarks for sorting purposes +function! s:Bookmark.compareTo(otherbookmark) + return a:otherbookmark.name < self.name +endfunction +" FUNCTION: Bookmark.ClearAll() {{{3 +" Class method to delete all bookmarks. +function! s:Bookmark.ClearAll() + for i in s:Bookmark.Bookmarks() + call i.delete() + endfor + call s:Bookmark.Write() +endfunction +" FUNCTION: Bookmark.delete() {{{3 +" Delete this bookmark. If the node for this bookmark is under the current +" root, then recache bookmarks for its Path object +function! s:Bookmark.delete() + let node = {} + try + let node = self.getNode(1) + catch /^NERDTree.BookmarkedNodeNotFoundError/ + endtry + call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self)) + if !empty(node) + call node.path.cacheDisplayString() + endif + call s:Bookmark.Write() +endfunction +" FUNCTION: Bookmark.getNode(searchFromAbsoluteRoot) {{{3 +" Gets the treenode for this bookmark +" +" Args: +" searchFromAbsoluteRoot: specifies whether we should search from the current +" tree root, or the highest cached node +function! s:Bookmark.getNode(searchFromAbsoluteRoot) + let searchRoot = a:searchFromAbsoluteRoot ? s:TreeDirNode.AbsoluteTreeRoot() : b:NERDTreeRoot + let targetNode = searchRoot.findNode(self.path) + if empty(targetNode) + throw "NERDTree.BookmarkedNodeNotFoundError: no node was found for bookmark: " . self.name + endif + return targetNode +endfunction +" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) {{{3 +" Class method that finds the bookmark with the given name and returns the +" treenode for it. +function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) + let bookmark = s:Bookmark.BookmarkFor(a:name) + return bookmark.getNode(a:searchFromAbsoluteRoot) +endfunction +" Function: Bookmark.InvalidBookmarks() {{{3 +" Class method to get all invalid bookmark strings read from the bookmarks +" file +function! s:Bookmark.InvalidBookmarks() + if !exists("g:NERDTreeInvalidBookmarks") + let g:NERDTreeInvalidBookmarks = [] + endif + return g:NERDTreeInvalidBookmarks +endfunction +" FUNCTION: Bookmark.mustExist() {{{3 +function! s:Bookmark.mustExist() + if !self.path.exists() + call s:Bookmark.CacheBookmarks(1) + throw "NERDTree.BookmarkPointsToInvalidLocationError: the bookmark \"". + \ self.name ."\" points to a non existing location: \"". self.path.strForOS(0) + endif +endfunction +" FUNCTION: Bookmark.New(name, path) {{{3 +" Create a new bookmark object with the given name and path object +function! s:Bookmark.New(name, path) + if a:name =~ ' ' + throw "NERDTree.IllegalBookmarkNameError: illegal name:" . a:name + endif + + let newBookmark = copy(self) + let newBookmark.name = a:name + let newBookmark.path = a:path + return newBookmark +endfunction +" Function: Bookmark.setPath(path) {{{3 +" makes this bookmark point to the given path +function! s:Bookmark.setPath(path) + let self.path = a:path +endfunction +" Function: Bookmark.Sort() {{{3 +" Class method that sorts all bookmarks +function! s:Bookmark.Sort() + let CompareFunc = function("s:compareBookmarks") + call sort(s:Bookmark.Bookmarks(), CompareFunc) +endfunction +" Function: Bookmark.str() {{{3 +" Get the string that should be rendered in the view for this bookmark +function! s:Bookmark.str() + let pathStrMaxLen = winwidth(s:getTreeWinNum()) - 4 - len(self.name) + if &nu + let pathStrMaxLen = pathStrMaxLen - &numberwidth + endif + + let pathStr = self.path.strForOS(0) + if len(pathStr) > pathStrMaxLen + let pathStr = '<' . strpart(pathStr, len(pathStr) - pathStrMaxLen) + endif + return '>' . self.name . ' ' . pathStr +endfunction +" FUNCTION: Bookmark.toRoot() {{{3 +" Make the node for this bookmark the new tree root +function! s:Bookmark.toRoot() + if self.validate() + try + let targetNode = self.getNode(1) + catch /^NERDTree.BookmarkedNodeNotFoundError/ + let targetNode = s:TreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path) + endtry + call targetNode.makeRoot() + call s:renderView() + call targetNode.putCursorHere(0, 0) + endif +endfunction +" FUNCTION: Bookmark.ToRoot(name) {{{3 +" Make the node for this bookmark the new tree root +function! s:Bookmark.ToRoot(name) + let bookmark = s:Bookmark.BookmarkFor(a:name) + call bookmark.toRoot() +endfunction + + +"FUNCTION: Bookmark.validate() {{{3 +function! s:Bookmark.validate() + if self.path.exists() + return 1 + else + call s:Bookmark.CacheBookmarks(1) + call s:renderView() + call s:echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.") + return 0 + endif +endfunction + +" Function: Bookmark.Write() {{{3 +" Class method to write all bookmarks to the bookmarks file +function! s:Bookmark.Write() + let bookmarkStrings = [] + for i in s:Bookmark.Bookmarks() + call add(bookmarkStrings, i.name . ' ' . i.path.strForOS(0)) + endfor + + "add a blank line before the invalid ones + call add(bookmarkStrings, "") + + for j in s:Bookmark.InvalidBookmarks() + call add(bookmarkStrings, j) + endfor + call writefile(bookmarkStrings, g:NERDTreeBookmarksFile) +endfunction +"CLASS: TreeFileNode {{{2 +"This class is the parent of the TreeDirNode class and constitures the +"'Component' part of the composite design pattern between the treenode +"classes. +"============================================================ +let s:TreeFileNode = {} +"FUNCTION: TreeFileNode.bookmark(name) {{{3 +"bookmark this node with a:name +function! s:TreeFileNode.bookmark(name) + try + let oldMarkedNode = s:Bookmark.GetNodeForName(a:name, 1) + call oldMarkedNode.path.cacheDisplayString() + catch /^NERDTree.BookmarkNotFoundError/ + endtry + + call s:Bookmark.AddBookmark(a:name, self.path) + call self.path.cacheDisplayString() + call s:Bookmark.Write() +endfunction +"FUNCTION: TreeFileNode.cacheParent() {{{3 +"initializes self.parent if it isnt already +function! s:TreeFileNode.cacheParent() + if empty(self.parent) + let parentPath = self.path.getParent() + if parentPath.equals(self.path) + throw "NERDTree.CannotCacheParentError: already at root" + endif + let self.parent = s:TreeFileNode.New(parentPath) + endif +endfunction +"FUNCTION: TreeFileNode.compareNodes {{{3 +"This is supposed to be a class level method but i cant figure out how to +"get func refs to work from a dict.. +" +"A class level method that compares two nodes +" +"Args: +"n1, n2: the 2 nodes to compare +function! s:compareNodes(n1, n2) + return a:n1.path.compareTo(a:n2.path) +endfunction + +"FUNCTION: TreeFileNode.clearBoomarks() {{{3 +function! s:TreeFileNode.clearBoomarks() + for i in s:Bookmark.Bookmarks() + if i.path.equals(self.path) + call i.delete() + end + endfor + call self.path.cacheDisplayString() +endfunction +"FUNCTION: TreeFileNode.copy(dest) {{{3 +function! s:TreeFileNode.copy(dest) + call self.path.copy(a:dest) + let newPath = s:Path.New(a:dest) + let parent = b:NERDTreeRoot.findNode(newPath.getParent()) + if !empty(parent) + call parent.refresh() + endif + return parent.findNode(newPath) +endfunction + +"FUNCTION: TreeFileNode.delete {{{3 +"Removes this node from the tree and calls the Delete method for its path obj +function! s:TreeFileNode.delete() + call self.path.delete() + call self.parent.removeChild(self) +endfunction + +"FUNCTION: TreeFileNode.renderToString {{{3 +"returns a string representation for this tree to be rendered in the view +function! s:TreeFileNode.renderToString() + return self._renderToString(0, 0, [], self.getChildCount() ==# 1) +endfunction + + +"Args: +"depth: the current depth in the tree for this call +"drawText: 1 if we should actually draw the line for this node (if 0 then the +"child nodes are rendered only) +"vertMap: a binary array that indicates whether a vertical bar should be draw +"for each depth in the tree +"isLastChild:true if this curNode is the last child of its parent +function! s:TreeFileNode._renderToString(depth, drawText, vertMap, isLastChild) + let output = "" + if a:drawText ==# 1 + + let treeParts = '' + + "get all the leading spaces and vertical tree parts for this line + if a:depth > 1 + for j in a:vertMap[0:-2] + if j ==# 1 + let treeParts = treeParts . '| ' + else + let treeParts = treeParts . ' ' + endif + endfor + endif + + "get the last vertical tree part for this line which will be different + "if this node is the last child of its parent + if a:isLastChild + let treeParts = treeParts . '`' + else + let treeParts = treeParts . '|' + endif + + + "smack the appropriate dir/file symbol on the line before the file/dir + "name itself + if self.path.isDirectory + if self.isOpen + let treeParts = treeParts . '~' + else + let treeParts = treeParts . '+' + endif + else + let treeParts = treeParts . '-' + endif + let line = treeParts . self.strDisplay() + + let output = output . line . "\n" + endif + + "if the node is an open dir, draw its children + if self.path.isDirectory ==# 1 && self.isOpen ==# 1 + + let childNodesToDraw = self.getVisibleChildren() + if len(childNodesToDraw) > 0 + + "draw all the nodes children except the last + let lastIndx = len(childNodesToDraw)-1 + if lastIndx > 0 + for i in childNodesToDraw[0:lastIndx-1] + let output = output . i._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 1), 0) + endfor + endif + + "draw the last child, indicating that it IS the last + let output = output . childNodesToDraw[lastIndx]._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 0), 1) + endif + endif + + return output +endfunction +"FUNCTION: TreeFileNode.equals(treenode) {{{3 +" +"Compares this treenode to the input treenode and returns 1 if they are the +"same node. +" +"Use this method instead of == because sometimes when the treenodes contain +"many children, vim seg faults when doing == +" +"Args: +"treenode: the other treenode to compare to +function! s:TreeFileNode.equals(treenode) + return self.path.str(1) ==# a:treenode.path.str(1) +endfunction + +"FUNCTION: TreeFileNode.findNode(path) {{{3 +"Returns self if this node.path.Equals the given path. +"Returns {} if not equal. +" +"Args: +"path: the path object to compare against +function! s:TreeFileNode.findNode(path) + if a:path.equals(self.path) + return self + endif + return {} +endfunction +"FUNCTION: TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) {{{3 +" +"Finds the next sibling for this node in the indicated direction. This sibling +"must be a directory and may/may not have children as specified. +" +"Args: +"direction: 0 if you want to find the previous sibling, 1 for the next sibling +" +"Return: +"a treenode object or {} if no appropriate sibling could be found +function! s:TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) + "if we have no parent then we can have no siblings + if self.parent != {} + let nextSibling = self.findSibling(a:direction) + + while nextSibling != {} + if nextSibling.path.isDirectory && nextSibling.hasVisibleChildren() && nextSibling.isOpen + return nextSibling + endif + let nextSibling = nextSibling.findSibling(a:direction) + endwhile + endif + + return {} +endfunction +"FUNCTION: TreeFileNode.findSibling(direction) {{{3 +" +"Finds the next sibling for this node in the indicated direction +" +"Args: +"direction: 0 if you want to find the previous sibling, 1 for the next sibling +" +"Return: +"a treenode object or {} if no sibling could be found +function! s:TreeFileNode.findSibling(direction) + "if we have no parent then we can have no siblings + if self.parent != {} + + "get the index of this node in its parents children + let siblingIndx = self.parent.getChildIndex(self.path) + + if siblingIndx != -1 + "move a long to the next potential sibling node + let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1 + + "keep moving along to the next sibling till we find one that is valid + let numSiblings = self.parent.getChildCount() + while siblingIndx >= 0 && siblingIndx < numSiblings + + "if the next node is not an ignored node (i.e. wont show up in the + "view) then return it + if self.parent.children[siblingIndx].path.ignore() ==# 0 + return self.parent.children[siblingIndx] + endif + + "go to next node + let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1 + endwhile + endif + endif + + return {} +endfunction + +"FUNCTION: TreeFileNode.getLineNum(){{{3 +"returns the line number this node is rendered on, or -1 if it isnt rendered +function! s:TreeFileNode.getLineNum() + "if the node is the root then return the root line no. + if self.isRoot() + return s:TreeFileNode.GetRootLineNum() + endif + + let totalLines = line("$") + + "the path components we have matched so far + let pathcomponents = [substitute(b:NERDTreeRoot.path.str(0), '/ *$', '', '')] + "the index of the component we are searching for + let curPathComponent = 1 + + let fullpath = self.path.str(0) + + + let lnum = s:TreeFileNode.GetRootLineNum() + while lnum > 0 + let lnum = lnum + 1 + "have we reached the bottom of the tree? + if lnum ==# totalLines+1 + return -1 + endif + + let curLine = getline(lnum) + + let indent = s:indentLevelFor(curLine) + if indent ==# curPathComponent + let curLine = s:stripMarkupFromLine(curLine, 1) + + let curPath = join(pathcomponents, '/') . '/' . curLine + if stridx(fullpath, curPath, 0) ==# 0 + if fullpath ==# curPath || strpart(fullpath, len(curPath)-1,1) ==# '/' + let curLine = substitute(curLine, '/ *$', '', '') + call add(pathcomponents, curLine) + let curPathComponent = curPathComponent + 1 + + if fullpath ==# curPath + return lnum + endif + endif + endif + endif + endwhile + return -1 +endfunction + +"FUNCTION: TreeFileNode.GetRootLineNum(){{{3 +"gets the line number of the root node +function! s:TreeFileNode.GetRootLineNum() + let rootLine = 1 + while getline(rootLine) !~ '^/' + let rootLine = rootLine + 1 + endwhile + return rootLine +endfunction + +"FUNCTION: TreeFileNode.GetSelected() {{{3 +"gets the treenode that the cursor is currently over +function! s:TreeFileNode.GetSelected() + try + let path = s:getPath(line(".")) + if path ==# {} + return {} + endif + return b:NERDTreeRoot.findNode(path) + catch /NERDTree/ + return {} + endtry +endfunction +"FUNCTION: TreeFileNode.isVisible() {{{3 +"returns 1 if this node should be visible according to the tree filters and +"hidden file filters (and their on/off status) +function! s:TreeFileNode.isVisible() + return !self.path.ignore() +endfunction +"FUNCTION: TreeFileNode.isRoot() {{{3 +"returns 1 if this node is b:NERDTreeRoot +function! s:TreeFileNode.isRoot() + if !s:treeExistsForBuf() + throw "NERDTree.NoTreeError: No tree exists for the current buffer" + endif + + return self.equals(b:NERDTreeRoot) +endfunction + +"FUNCTION: TreeFileNode.makeRoot() {{{3 +"Make this node the root of the tree +function! s:TreeFileNode.makeRoot() + if self.path.isDirectory + let b:NERDTreeRoot = self + else + call self.cacheParent() + let b:NERDTreeRoot = self.parent + endif + + call b:NERDTreeRoot.open() + + "change dir to the dir of the new root if instructed to + if g:NERDTreeChDirMode ==# 2 + exec "cd " . b:NERDTreeRoot.path.strForEditCmd() + endif +endfunction +"FUNCTION: TreeFileNode.New(path) {{{3 +"Returns a new TreeNode object with the given path and parent +" +"Args: +"path: a path object representing the full filesystem path to the file/dir that the node represents +function! s:TreeFileNode.New(path) + if a:path.isDirectory + return s:TreeDirNode.New(a:path) + else + let newTreeNode = {} + let newTreeNode = copy(self) + let newTreeNode.path = a:path + let newTreeNode.parent = {} + return newTreeNode + endif +endfunction + +"FUNCTION: TreeFileNode.open() {{{3 +"Open the file represented by the given node in the current window, splitting +"the window if needed +" +"ARGS: +"treenode: file node to open +function! s:TreeFileNode.open() + if b:NERDTreeType ==# "secondary" + exec 'edit ' . self.path.strForEditCmd() + return + endif + + "if the file is already open in this tab then just stick the cursor in it + let winnr = bufwinnr('^' . self.path.strForOS(0) . '$') + if winnr != -1 + call s:exec(winnr . "wincmd w") + + else + if !s:isWindowUsable(winnr("#")) && s:firstUsableWindow() ==# -1 + call self.openSplit() + else + try + if !s:isWindowUsable(winnr("#")) + call s:exec(s:firstUsableWindow() . "wincmd w") + else + call s:exec('wincmd p') + endif + exec ("edit " . self.path.strForEditCmd()) + catch /^Vim\%((\a\+)\)\=:E37/ + call s:putCursorInTreeWin() + throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self.path.str(0) ." is already open and modified." + catch /^Vim\%((\a\+)\)\=:/ + echo v:exception + endtry + endif + endif +endfunction +"FUNCTION: TreeFileNode.openSplit() {{{3 +"Open this node in a new window +function! s:TreeFileNode.openSplit() + + if b:NERDTreeType ==# "secondary" + exec "split " . self.path.strForEditCmd() + return + endif + + " Save the user's settings for splitbelow and splitright + let savesplitbelow=&splitbelow + let savesplitright=&splitright + + " 'there' will be set to a command to move from the split window + " back to the explorer window + " + " 'back' will be set to a command to move from the explorer window + " back to the newly split window + " + " 'right' and 'below' will be set to the settings needed for + " splitbelow and splitright IF the explorer is the only window. + " + let there= g:NERDTreeWinPos ==# "left" ? "wincmd h" : "wincmd l" + let back = g:NERDTreeWinPos ==# "left" ? "wincmd l" : "wincmd h" + let right= g:NERDTreeWinPos ==# "left" + let below=0 + + " Attempt to go to adjacent window + call s:exec(back) + + let onlyOneWin = (winnr("$") ==# 1) + + " If no adjacent window, set splitright and splitbelow appropriately + if onlyOneWin + let &splitright=right + let &splitbelow=below + else + " found adjacent window - invert split direction + let &splitright=!right + let &splitbelow=!below + endif + + let splitMode = onlyOneWin ? "vertical" : "" + + " Open the new window + try + exec(splitMode." sp " . self.path.strForEditCmd()) + catch /^Vim\%((\a\+)\)\=:E37/ + call s:putCursorInTreeWin() + throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self.path.str(0) ." is already open and modified." + catch /^Vim\%((\a\+)\)\=:/ + "do nothing + endtry + + "resize the tree window if no other window was open before + if onlyOneWin + let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize + call s:exec(there) + exec("silent ". splitMode ." resize ". size) + call s:exec('wincmd p') + endif + + " Restore splitmode settings + let &splitbelow=savesplitbelow + let &splitright=savesplitright +endfunction +"FUNCTION: TreeFileNode.openVSplit() {{{3 +"Open this node in a new vertical window +function! s:TreeFileNode.openVSplit() + if b:NERDTreeType ==# "secondary" + exec "vnew " . self.path.strForEditCmd() + return + endif + + let winwidth = winwidth(".") + if winnr("$")==#1 + let winwidth = g:NERDTreeWinSize + endif + + call s:exec("wincmd p") + exec "vnew " . self.path.strForEditCmd() + + "resize the nerd tree back to the original size + call s:putCursorInTreeWin() + exec("silent vertical resize ". winwidth) + call s:exec('wincmd p') +endfunction +"FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{3 +"Places the cursor on the line number this node is rendered on +" +"Args: +"isJump: 1 if this cursor movement should be counted as a jump by vim +"recurseUpward: try to put the cursor on the parent if the this node isnt +"visible +function! s:TreeFileNode.putCursorHere(isJump, recurseUpward) + let ln = self.getLineNum() + if ln != -1 + if a:isJump + mark ' + endif + call cursor(ln, col(".")) + else + if a:recurseUpward + let node = self + while node != {} && node.getLineNum() ==# -1 + let node = node.parent + call node.open() + endwhile + call s:renderView() + call node.putCursorHere(a:isJump, 0) + endif + endif +endfunction + +"FUNCTION: TreeFileNode.refresh() {{{3 +function! s:TreeFileNode.refresh() + call self.path.refresh() +endfunction +"FUNCTION: TreeFileNode.rename() {{{3 +"Calls the rename method for this nodes path obj +function! s:TreeFileNode.rename(newName) + let newName = substitute(a:newName, '\(\\\|\/\)$', '', '') + call self.path.rename(newName) + call self.parent.removeChild(self) + + let parentPath = self.path.getPathTrunk() + let newParent = b:NERDTreeRoot.findNode(parentPath) + + if newParent != {} + call newParent.createChild(self.path, 1) + call newParent.refresh() + endif +endfunction +"FUNCTION: TreeFileNode.strDisplay() {{{3 +" +"Returns a string that specifies how the node should be represented as a +"string +" +"Return: +"a string that can be used in the view to represent this node +function! s:TreeFileNode.strDisplay() + return self.path.strDisplay() +endfunction + +"CLASS: TreeDirNode {{{2 +"This class is a child of the TreeFileNode class and constitutes the +"'Composite' part of the composite design pattern between the treenode +"classes. +"============================================================ +let s:TreeDirNode = copy(s:TreeFileNode) +"FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{3 +"class method that returns the highest cached ancestor of the current root +function! s:TreeDirNode.AbsoluteTreeRoot() + let currentNode = b:NERDTreeRoot + while currentNode.parent != {} + let currentNode = currentNode.parent + endwhile + return currentNode +endfunction +"FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{3 +"Adds the given treenode to the list of children for this node +" +"Args: +"-treenode: the node to add +"-inOrder: 1 if the new node should be inserted in sorted order +function! s:TreeDirNode.addChild(treenode, inOrder) + call add(self.children, a:treenode) + let a:treenode.parent = self + + if a:inOrder + call self.sortChildren() + endif +endfunction + +"FUNCTION: TreeDirNode.close() {{{3 +"Closes this directory +function! s:TreeDirNode.close() + let self.isOpen = 0 +endfunction + +"FUNCTION: TreeDirNode.closeChildren() {{{3 +"Closes all the child dir nodes of this node +function! s:TreeDirNode.closeChildren() + for i in self.children + if i.path.isDirectory + call i.close() + call i.closeChildren() + endif + endfor +endfunction + +"FUNCTION: TreeDirNode.createChild(path, inOrder) {{{3 +"Instantiates a new child node for this node with the given path. The new +"nodes parent is set to this node. +" +"Args: +"path: a Path object that this node will represent/contain +"inOrder: 1 if the new node should be inserted in sorted order +" +"Returns: +"the newly created node +function! s:TreeDirNode.createChild(path, inOrder) + let newTreeNode = s:TreeFileNode.New(a:path) + call self.addChild(newTreeNode, a:inOrder) + return newTreeNode +endfunction + +"FUNCTION: TreeDirNode.findNode(path) {{{3 +"Will find one of the children (recursively) that has the given path +" +"Args: +"path: a path object +unlet s:TreeDirNode.findNode +function! s:TreeDirNode.findNode(path) + if a:path.equals(self.path) + return self + endif + if stridx(a:path.str(1), self.path.str(1), 0) ==# -1 + return {} + endif + + if self.path.isDirectory + for i in self.children + let retVal = i.findNode(a:path) + if retVal != {} + return retVal + endif + endfor + endif + return {} +endfunction +"FUNCTION: TreeDirNode.getChildCount() {{{3 +"Returns the number of children this node has +function! s:TreeDirNode.getChildCount() + return len(self.children) +endfunction + +"FUNCTION: TreeDirNode.getChild(path) {{{3 +"Returns child node of this node that has the given path or {} if no such node +"exists. +" +"This function doesnt not recurse into child dir nodes +" +"Args: +"path: a path object +function! s:TreeDirNode.getChild(path) + if stridx(a:path.str(1), self.path.str(1), 0) ==# -1 + return {} + endif + + let index = self.getChildIndex(a:path) + if index ==# -1 + return {} + else + return self.children[index] + endif + +endfunction + +"FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{3 +"returns the child at the given index +"Args: +"indx: the index to get the child from +"visible: 1 if only the visible children array should be used, 0 if all the +"children should be searched. +function! s:TreeDirNode.getChildByIndex(indx, visible) + let array_to_search = a:visible? self.getVisibleChildren() : self.children + if a:indx > len(array_to_search) + throw "NERDTree.InvalidArgumentsError: Index is out of bounds." + endif + return array_to_search[a:indx] +endfunction + +"FUNCTION: TreeDirNode.getChildIndex(path) {{{3 +"Returns the index of the child node of this node that has the given path or +"-1 if no such node exists. +" +"This function doesnt not recurse into child dir nodes +" +"Args: +"path: a path object +function! s:TreeDirNode.getChildIndex(path) + if stridx(a:path.str(1), self.path.str(1), 0) ==# -1 + return -1 + endif + + "do a binary search for the child + let a = 0 + let z = self.getChildCount() + while a < z + let mid = (a+z)/2 + let diff = a:path.compareTo(self.children[mid].path) + + if diff ==# -1 + let z = mid + elseif diff ==# 1 + let a = mid+1 + else + return mid + endif + endwhile + return -1 +endfunction + +"FUNCTION: TreeDirNode.GetSelected() {{{3 +"Returns the current node if it is a dir node, or else returns the current +"nodes parent +unlet s:TreeDirNode.GetSelected +function! s:TreeDirNode.GetSelected() + let currentDir = s:TreeFileNode.GetSelected() + if currentDir != {} && !currentDir.isRoot() + if currentDir.path.isDirectory ==# 0 + let currentDir = currentDir.parent + endif + endif + return currentDir +endfunction +"FUNCTION: TreeDirNode.getVisibleChildCount() {{{3 +"Returns the number of visible children this node has +function! s:TreeDirNode.getVisibleChildCount() + return len(self.getVisibleChildren()) +endfunction + +"FUNCTION: TreeDirNode.getVisibleChildren() {{{3 +"Returns a list of children to display for this node, in the correct order +" +"Return: +"an array of treenodes +function! s:TreeDirNode.getVisibleChildren() + let toReturn = [] + for i in self.children + if i.path.ignore() ==# 0 + call add(toReturn, i) + endif + endfor + return toReturn +endfunction + +"FUNCTION: TreeDirNode.hasVisibleChildren() {{{3 +"returns 1 if this node has any childre, 0 otherwise.. +function! s:TreeDirNode.hasVisibleChildren() + return self.getVisibleChildCount() != 0 +endfunction + +"FUNCTION: TreeDirNode._initChildren() {{{3 +"Removes all childen from this node and re-reads them +" +"Args: +"silent: 1 if the function should not echo any "please wait" messages for +"large directories +" +"Return: the number of child nodes read +function! s:TreeDirNode._initChildren(silent) + "remove all the current child nodes + let self.children = [] + + "get an array of all the files in the nodes dir + let dir = self.path + let filesStr = globpath(dir.strForGlob(), '*') . "\n" . globpath(dir.strForGlob(), '.*') + let files = split(filesStr, "\n") + + if !a:silent && len(files) > g:NERDTreeNotificationThreshold + call s:echo("Please wait, caching a large dir ...") + endif + + let invalidFilesFound = 0 + for i in files + + "filter out the .. and . directories + "Note: we must match .. AND ../ cos sometimes the globpath returns + "../ for path with strange chars (eg $) + if i !~ '\.\.\/\?$' && i !~ '\.\/\?$' + + "put the next file in a new node and attach it + try + let path = s:Path.New(i) + call self.createChild(path, 0) + catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ + let invalidFilesFound += 1 + endtry + endif + endfor + + call self.sortChildren() + + if !a:silent && len(files) > g:NERDTreeNotificationThreshold + call s:echo("Please wait, caching a large dir ... DONE (". self.getChildCount() ." nodes cached).") + endif + + if invalidFilesFound + call s:echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree") + endif + return self.getChildCount() +endfunction +"FUNCTION: TreeDirNode.New(path) {{{3 +"Returns a new TreeNode object with the given path and parent +" +"Args: +"path: a path object representing the full filesystem path to the file/dir that the node represents +unlet s:TreeDirNode.New +function! s:TreeDirNode.New(path) + if a:path.isDirectory != 1 + throw "NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object." + endif + + let newTreeNode = copy(self) + let newTreeNode.path = a:path + + let newTreeNode.isOpen = 0 + let newTreeNode.children = [] + + let newTreeNode.parent = {} + + return newTreeNode +endfunction +"FUNCTION: TreeDirNode.open() {{{3 +"Reads in all this nodes children +" +"Return: the number of child nodes read +unlet s:TreeDirNode.open +function! s:TreeDirNode.open() + let self.isOpen = 1 + if self.children ==# [] + return self._initChildren(0) + else + return 0 + endif +endfunction + +" FUNCTION: TreeDirNode.openExplorer() {{{3 +" opens an explorer window for this node in the previous window (could be a +" nerd tree or a netrw) +function! s:TreeDirNode.openExplorer() + let oldwin = winnr() + call s:exec('wincmd p') + if oldwin ==# winnr() || (&modified && s:bufInWindows(winbufnr(winnr())) < 2) + call s:exec('wincmd p') + call self.openSplit() + else + exec ("silent edit " . self.path.strForEditCmd()) + endif +endfunction +"FUNCTION: TreeDirNode.openRecursively() {{{3 +"Opens this treenode and all of its children whose paths arent 'ignored' +"because of the file filters. +" +"This method is actually a wrapper for the OpenRecursively2 method which does +"the work. +function! s:TreeDirNode.openRecursively() + call self._openRecursively2(1) +endfunction + +"FUNCTION: TreeDirNode._openRecursively2() {{{3 +"Opens this all children of this treenode recursively if either: +" *they arent filtered by file filters +" *a:forceOpen is 1 +" +"Args: +"forceOpen: 1 if this node should be opened regardless of file filters +function! s:TreeDirNode._openRecursively2(forceOpen) + if self.path.ignore() ==# 0 || a:forceOpen + let self.isOpen = 1 + if self.children ==# [] + call self._initChildren(1) + endif + + for i in self.children + if i.path.isDirectory ==# 1 + call i._openRecursively2(0) + endif + endfor + endif +endfunction + +"FUNCTION: TreeDirNode.refresh() {{{3 +unlet s:TreeDirNode.refresh +function! s:TreeDirNode.refresh() + call self.path.refresh() + + "if this node was ever opened, refresh its children + if self.isOpen || !empty(self.children) + "go thru all the files/dirs under this node + let newChildNodes = [] + let invalidFilesFound = 0 + let dir = self.path + let filesStr = globpath(dir.strForGlob(), '*') . "\n" . globpath(dir.strForGlob(), '.*') + let files = split(filesStr, "\n") + for i in files + if i !~ '\.\.$' && i !~ '\.$' + + try + "create a new path and see if it exists in this nodes children + let path = s:Path.New(i) + let newNode = self.getChild(path) + if newNode != {} + call newNode.refresh() + call add(newChildNodes, newNode) + + "the node doesnt exist so create it + else + let newNode = s:TreeFileNode.New(path) + let newNode.parent = self + call add(newChildNodes, newNode) + endif + + + catch /^NERDTree.InvalidArgumentsError/ + let invalidFilesFound = 1 + endtry + endif + endfor + + "swap this nodes children out for the children we just read/refreshed + let self.children = newChildNodes + call self.sortChildren() + + if invalidFilesFound + call s:echoWarning("some files could not be loaded into the NERD tree") + endif + endif +endfunction + +"FUNCTION: TreeDirNode.removeChild(treenode) {{{3 +" +"Removes the given treenode from this nodes set of children +" +"Args: +"treenode: the node to remove +" +"Throws a NERDTree.ChildNotFoundError if the given treenode is not found +function! s:TreeDirNode.removeChild(treenode) + for i in range(0, self.getChildCount()-1) + if self.children[i].equals(a:treenode) + call remove(self.children, i) + return + endif + endfor + + throw "NERDTree.ChildNotFoundError: child node was not found" +endfunction + +"FUNCTION: TreeDirNode.sortChildren() {{{3 +" +"Sorts the children of this node according to alphabetical order and the +"directory priority. +" +function! s:TreeDirNode.sortChildren() + let CompareFunc = function("s:compareNodes") + call sort(self.children, CompareFunc) +endfunction + +"FUNCTION: TreeDirNode.toggleOpen() {{{3 +"Opens this directory if it is closed and vice versa +function! s:TreeDirNode.toggleOpen() + if self.isOpen ==# 1 + call self.close() + else + call self.open() + endif +endfunction + +"FUNCTION: TreeDirNode.transplantChild(newNode) {{{3 +"Replaces the child of this with the given node (where the child node's full +"path matches a:newNode's fullpath). The search for the matching node is +"non-recursive +" +"Arg: +"newNode: the node to graft into the tree +function! s:TreeDirNode.transplantChild(newNode) + for i in range(0, self.getChildCount()-1) + if self.children[i].equals(a:newNode) + let self.children[i] = a:newNode + let a:newNode.parent = self + break + endif + endfor +endfunction +"============================================================ +"CLASS: Path {{{2 +"============================================================ +let s:Path = {} +"FUNCTION: Path.AbsolutePathFor(str) {{{3 +function! s:Path.AbsolutePathFor(str) + let prependCWD = 0 + if s:running_windows + let prependCWD = a:str !~ '^.:\(\\\|\/\)' + else + let prependCWD = a:str !~ '^/' + endif + + let toReturn = a:str + if prependCWD + let toReturn = getcwd() . s:os_slash . a:str + endif + + return toReturn +endfunction +"FUNCTION: Path.bookmarkNames() {{{3 +function! s:Path.bookmarkNames() + if !exists("self._bookmarkNames") + call self.cacheDisplayString() + endif + return self._bookmarkNames +endfunction +"FUNCTION: Path.cacheDisplayString() {{{3 +function! s:Path.cacheDisplayString() + let self.cachedDisplayString = self.getLastPathComponent(1) + + if self.isExecutable + let self.cachedDisplayString = self.cachedDisplayString . '*' + endif + + let self._bookmarkNames = [] + for i in s:Bookmark.Bookmarks() + if i.path.equals(self) + call add(self._bookmarkNames, i.name) + endif + endfor + if !empty(self._bookmarkNames) + let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}' + endif + + if self.isSymLink + let self.cachedDisplayString .= ' -> ' . self.symLinkDest + endif + + if self.isReadOnly + let self.cachedDisplayString .= ' [RO]' + endif +endfunction +"FUNCTION: Path.changeToDir() {{{3 +function! s:Path.changeToDir() + let dir = self.strForCd() + if self.isDirectory ==# 0 + let dir = self.getPathTrunk().strForCd() + endif + + try + execute "cd " . dir + call s:echo("CWD is now: " . getcwd()) + catch + throw "NERDTree.PathChangeError: cannot change CWD to " . dir + endtry +endfunction + +"FUNCTION: Path.compareTo() {{{3 +" +"Compares this Path to the given path and returns 0 if they are equal, -1 if +"this Path is "less than" the given path, or 1 if it is "greater". +" +"Args: +"path: the path object to compare this to +" +"Return: +"1, -1 or 0 +function! s:Path.compareTo(path) + let thisPath = self.getLastPathComponent(1) + let thatPath = a:path.getLastPathComponent(1) + + "if the paths are the same then clearly we return 0 + if thisPath ==# thatPath + return 0 + endif + + let thisSS = self.getSortOrderIndex() + let thatSS = a:path.getSortOrderIndex() + + "compare the sort sequences, if they are different then the return + "value is easy + if thisSS < thatSS + return -1 + elseif thisSS > thatSS + return 1 + else + "if the sort sequences are the same then compare the paths + "alphabetically + let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath >> +"FUNCTION: s:checkForBrowse(dir) {{{2 +"inits a secondary nerd tree in the current buffer if appropriate +function! s:checkForBrowse(dir) + if a:dir != '' && isdirectory(a:dir) + call s:initNerdTreeInPlace(a:dir) + endif +endfunction +"FUNCTION: s:compareBookmarks(first, second) {{{2 +"Compares two bookmarks +function! s:compareBookmarks(first, second) + return a:first.compareTo(a:second) +endfunction + +" FUNCTION: s:completeBookmarks(A,L,P) {{{2 +" completion function for the bookmark commands +function! s:completeBookmarks(A,L,P) + return filter(s:Bookmark.BookmarkNames(), 'v:val =~ "^' . a:A . '"') +endfunction +" FUNCTION: s:exec(cmd) {{{2 +" same as :exec cmd but eventignore=all is set for the duration +function! s:exec(cmd) + let old_ei = &ei + set ei=all + exec a:cmd + let &ei = old_ei +endfunction +"FUNCTION: s:initNerdTree(name) {{{2 +"Initialise the nerd tree for this tab. The tree will start in either the +"given directory, or the directory associated with the given bookmark +" +"Args: +"name: the name of a bookmark or a directory +function! s:initNerdTree(name) + let path = {} + if s:Bookmark.BookmarkExistsFor(a:name) + let path = s:Bookmark.BookmarkFor(a:name).path + else + let dir = a:name ==# '' ? getcwd() : a:name + + "hack to get an absolute path if a relative path is given + if dir =~ '^\.' + let dir = getcwd() . s:os_slash . dir + endif + let dir = resolve(dir) + + try + let path = s:Path.New(dir) + catch /^NERDTree.InvalidArgumentsError/ + call s:echo("No bookmark or directory found for: " . a:name) + return + endtry + endif + if !path.isDirectory + let path = path.getParent() + endif + + "if instructed to, then change the vim CWD to the dir the NERDTree is + "inited in + if g:NERDTreeChDirMode != 0 + exec 'cd ' . path.strForCd() + endif + + if s:treeExistsForTab() + if s:isTreeOpen() + call s:closeTree() + endif + unlet t:NERDTreeBufName + endif + + let newRoot = s:TreeDirNode.New(path) + call newRoot.open() + + call s:createTreeWin() + let b:treeShowHelp = 0 + let b:NERDTreeIgnoreEnabled = 1 + let b:NERDTreeShowFiles = g:NERDTreeShowFiles + let b:NERDTreeShowHidden = g:NERDTreeShowHidden + let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks + let b:NERDTreeRoot = newRoot + + let b:NERDTreeType = "primary" + + call s:renderView() + call b:NERDTreeRoot.putCursorHere(0, 0) +endfunction + +"FUNCTION: s:initNerdTreeInPlace(dir) {{{2 +function! s:initNerdTreeInPlace(dir) + try + let path = s:Path.New(a:dir) + catch /^NERDTree.InvalidArgumentsError/ + call s:echo("Invalid directory name:" . a:name) + return + endtry + + "we want the directory buffer to disappear when we do the :edit below + setlocal bufhidden=wipe + + let previousBuf = expand("#") + + "we need a unique name for each secondary tree buffer to ensure they are + "all independent + exec "silent edit " . s:nextBufferName() + + let b:NERDTreePreviousBuf = bufnr(previousBuf) + + let b:NERDTreeRoot = s:TreeDirNode.New(path) + call b:NERDTreeRoot.open() + + "throwaway buffer options + setlocal noswapfile + setlocal buftype=nofile + setlocal bufhidden=hide + setlocal nowrap + setlocal foldcolumn=0 + setlocal nobuflisted + setlocal nospell + if g:NERDTreeShowLineNumbers + setlocal nu + else + setlocal nonu + endif + + iabc + + if g:NERDTreeHighlightCursorline + setlocal cursorline + endif + + call s:setupStatusline() + + let b:treeShowHelp = 0 + let b:NERDTreeIgnoreEnabled = 1 + let b:NERDTreeShowFiles = g:NERDTreeShowFiles + let b:NERDTreeShowHidden = g:NERDTreeShowHidden + let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks + + let b:NERDTreeType = "secondary" + + call s:bindMappings() + setfiletype nerdtree + " syntax highlighting + if has("syntax") && exists("g:syntax_on") && !has("syntax_items") + call s:setupSyntaxHighlighting() + endif + + call s:renderView() +endfunction +" FUNCTION: s:initNerdTreeMirror() {{{2 +function! s:initNerdTreeMirror() + + "get the names off all the nerd tree buffers + let treeBufNames = [] + for i in range(1, tabpagenr("$")) + let nextName = s:tabpagevar(i, 'NERDTreeBufName') + if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName) + call add(treeBufNames, nextName) + endif + endfor + let treeBufNames = s:unique(treeBufNames) + + "map the option names (that the user will be prompted with) to the nerd + "tree buffer names + let options = {} + let i = 0 + while i < len(treeBufNames) + let bufName = treeBufNames[i] + let treeRoot = getbufvar(bufName, "NERDTreeRoot") + let options[i+1 . '. ' . treeRoot.path.strForOS(0) . ' (buf name: ' . bufName . ')'] = bufName + let i = i + 1 + endwhile + + "work out which tree to mirror, if there is more than 1 then ask the user + let bufferName = '' + if len(keys(options)) > 1 + let choices = ["Choose a tree to mirror"] + let choices = extend(choices, sort(keys(options))) + let choice = inputlist(choices) + if choice < 1 || choice > len(options) || choice ==# '' + return + endif + + let bufferName = options[keys(options)[choice-1]] + elseif len(keys(options)) ==# 1 + let bufferName = values(options)[0] + else + call s:echo("No trees to mirror") + return + endif + + if s:treeExistsForTab() && s:isTreeOpen() + call s:closeTree() + endif + + let t:NERDTreeBufName = bufferName + call s:createTreeWin() + exec 'buffer ' . bufferName + if !&hidden + call s:renderView() + endif +endfunction +" FUNCTION: s:nextBufferName() {{{2 +" returns the buffer name for the next nerd tree +function! s:nextBufferName() + let name = s:NERDTreeBufName . s:next_buffer_number + let s:next_buffer_number += 1 + return name +endfunction +" FUNCTION: s:tabpagevar(tabnr, var) {{{2 +function! s:tabpagevar(tabnr, var) + let currentTab = tabpagenr() + let old_ei = &ei + set ei=all + + exec "tabnext " . a:tabnr + let v = -1 + if exists('t:' . a:var) + exec 'let v = t:' . a:var + endif + exec "tabnext " . currentTab + + let &ei = old_ei + + return v +endfunction +" Function: s:treeExistsForBuffer() {{{2 +" Returns 1 if a nerd tree root exists in the current buffer +function! s:treeExistsForBuf() + return exists("b:NERDTreeRoot") +endfunction +" Function: s:treeExistsForTab() {{{2 +" Returns 1 if a nerd tree root exists in the current tab +function! s:treeExistsForTab() + return exists("t:NERDTreeBufName") +endfunction +" Function: s:unique(list) {{{2 +" returns a:list without duplicates +function! s:unique(list) + let uniqlist = [] + for elem in a:list + if index(uniqlist, elem) ==# -1 + let uniqlist += [elem] + endif + endfor + return uniqlist +endfunction +" SECTION: Public Functions {{{1 +"============================================================ +"Returns the node that the cursor is currently on. +" +"If the cursor is not in the NERDTree window, it is temporarily put there. +" +"If no NERD tree window exists for the current tab, a NERDTree.NoTreeForTab +"exception is thrown. +" +"If the cursor is not on a node then an empty dictionary {} is returned. +function! NERDTreeGetCurrentNode() + if !s:treeExistsForTab() || !s:isTreeOpen() + throw "NERDTree.NoTreeForTabError: there is no NERD tree open for the current tab" + endif + + let winnr = winnr() + if winnr != s:getTreeWinNum() + call s:putCursorInTreeWin() + endif + + let treenode = s:TreeFileNode.GetSelected() + + if winnr != winnr() + call s:exec('wincmd w') + endif + + return treenode +endfunction + +"Returns the path object for the current node. +" +"Subject to the same conditions as NERDTreeGetCurrentNode +function! NERDTreeGetCurrentPath() + let node = NERDTreeGetCurrentNode() + if node != {} + return node.path + else + return {} + endif +endfunction + +" SECTION: View Functions {{{1 +"============================================================ +"FUNCTION: s:centerView() {{{2 +"centers the nerd tree window around the cursor (provided the nerd tree +"options permit) +function! s:centerView() + if g:NERDTreeAutoCenter + let current_line = winline() + let lines_to_top = current_line + let lines_to_bottom = winheight(s:getTreeWinNum()) - current_line + if lines_to_top < g:NERDTreeAutoCenterThreshold || lines_to_bottom < g:NERDTreeAutoCenterThreshold + normal! zz + endif + endif +endfunction +"FUNCTION: s:closeTree() {{{2 +"Closes the NERD tree window +function! s:closeTree() + if !s:isTreeOpen() + throw "NERDTree.NoTreeFoundError: no NERDTree is open" + endif + + if winnr("$") != 1 + call s:exec(s:getTreeWinNum() . " wincmd w") + close + call s:exec("wincmd p") + else + :q + endif +endfunction + +"FUNCTION: s:closeTreeIfOpen() {{{2 +"Closes the NERD tree window if it is open +function! s:closeTreeIfOpen() + if s:isTreeOpen() + call s:closeTree() + endif +endfunction +"FUNCTION: s:closeTreeIfQuitOnOpen() {{{2 +"Closes the NERD tree window if the close on open option is set +function! s:closeTreeIfQuitOnOpen() + if g:NERDTreeQuitOnOpen + call s:closeTree() + endif +endfunction +"FUNCTION: s:createTreeWin() {{{2 +"Inits the NERD tree window. ie. opens it, sizes it, sets all the local +"options etc +function! s:createTreeWin() + "create the nerd tree window + let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright " + let splitSize = g:NERDTreeWinSize + + if !exists('t:NERDTreeBufName') + let t:NERDTreeBufName = s:nextBufferName() + silent! exec splitLocation . 'vertical ' . splitSize . ' new' + silent! exec "edit " . t:NERDTreeBufName + else + silent! exec splitLocation . 'vertical ' . splitSize . ' split' + silent! exec "buffer " . t:NERDTreeBufName + endif + + setlocal winfixwidth + + "throwaway buffer options + setlocal noswapfile + setlocal buftype=nofile + setlocal nowrap + setlocal foldcolumn=0 + setlocal nobuflisted + setlocal nospell + if g:NERDTreeShowLineNumbers + setlocal nu + else + setlocal nonu + endif + + iabc + + if g:NERDTreeHighlightCursorline + setlocal cursorline + endif + + call s:setupStatusline() + + call s:bindMappings() + setfiletype nerdtree + " syntax highlighting + if has("syntax") && exists("g:syntax_on") && !has("syntax_items") + call s:setupSyntaxHighlighting() + endif +endfunction + +"FUNCTION: s:dumpHelp {{{2 +"prints out the quick help +function! s:dumpHelp() + let old_h = @h + if b:treeShowHelp ==# 1 + let @h= "\" NERD tree (" . s:NERD_tree_version . ") quickhelp~\n" + let @h=@h."\" ============================\n" + let @h=@h."\" File node mappings~\n" + let @h=@h."\" ". (g:NERDTreeMouseMode ==# 3 ? "single" : "double") ."-click,\n" + let @h=@h."\" ,\n" + if b:NERDTreeType ==# "primary" + let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in prev window\n" + else + let @h=@h."\" ". g:NERDTreeMapActivateNode .": open in current window\n" + endif + if b:NERDTreeType ==# "primary" + let @h=@h."\" ". g:NERDTreeMapPreview .": preview\n" + endif + let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n" + let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" + let @h=@h."\" middle-click,\n" + let @h=@h."\" ". g:NERDTreeMapOpenSplit .": open split\n" + let @h=@h."\" ". g:NERDTreeMapPreviewSplit .": preview split\n" + let @h=@h."\" ". g:NERDTreeMapOpenVSplit .": open vsplit\n" + let @h=@h."\" ". g:NERDTreeMapPreviewVSplit .": preview vsplit\n" + let @h=@h."\" ". g:NERDTreeMapExecute.": Execute file\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Directory node mappings~\n" + let @h=@h."\" ". (g:NERDTreeMouseMode ==# 1 ? "double" : "single") ."-click,\n" + let @h=@h."\" ". g:NERDTreeMapActivateNode .": open & close node\n" + let @h=@h."\" ". g:NERDTreeMapOpenRecursively .": recursively open node\n" + let @h=@h."\" ". g:NERDTreeMapCloseDir .": close parent of node\n" + let @h=@h."\" ". g:NERDTreeMapCloseChildren .": close all child nodes of\n" + let @h=@h."\" current node recursively\n" + let @h=@h."\" middle-click,\n" + let @h=@h."\" ". g:NERDTreeMapOpenExpl.": explore selected dir\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Bookmark table mappings~\n" + let @h=@h."\" double-click,\n" + let @h=@h."\" ". g:NERDTreeMapActivateNode .": open bookmark\n" + let @h=@h."\" ". g:NERDTreeMapOpenInTab.": open in new tab\n" + let @h=@h."\" ". g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" + let @h=@h."\" ". g:NERDTreeMapDeleteBookmark .": delete bookmark\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Tree navigation mappings~\n" + let @h=@h."\" ". g:NERDTreeMapJumpRoot .": go to root\n" + let @h=@h."\" ". g:NERDTreeMapJumpParent .": go to parent\n" + let @h=@h."\" ". g:NERDTreeMapJumpFirstChild .": go to first child\n" + let @h=@h."\" ". g:NERDTreeMapJumpLastChild .": go to last child\n" + let @h=@h."\" ". g:NERDTreeMapJumpNextSibling .": go to next sibling\n" + let @h=@h."\" ". g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Filesystem mappings~\n" + let @h=@h."\" ". g:NERDTreeMapChangeRoot .": change tree root to the\n" + let @h=@h."\" selected dir\n" + let @h=@h."\" ". g:NERDTreeMapUpdir .": move tree root up a dir\n" + let @h=@h."\" ". g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n" + let @h=@h."\" but leave old root open\n" + let @h=@h."\" ". g:NERDTreeMapRefresh .": refresh cursor dir\n" + let @h=@h."\" ". g:NERDTreeMapRefreshRoot .": refresh current root\n" + let @h=@h."\" ". g:NERDTreeMapFilesystemMenu .": Show filesystem menu\n" + let @h=@h."\" ". g:NERDTreeMapChdir .":change the CWD to the\n" + let @h=@h."\" selected dir\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Tree filtering mappings~\n" + let @h=@h."\" ". g:NERDTreeMapToggleHidden .": hidden files (" . (b:NERDTreeShowHidden ? "on" : "off") . ")\n" + let @h=@h."\" ". g:NERDTreeMapToggleFilters .": file filters (" . (b:NERDTreeIgnoreEnabled ? "on" : "off") . ")\n" + let @h=@h."\" ". g:NERDTreeMapToggleFiles .": files (" . (b:NERDTreeShowFiles ? "on" : "off") . ")\n" + let @h=@h."\" ". g:NERDTreeMapToggleBookmarks .": bookmarks (" . (b:NERDTreeShowBookmarks ? "on" : "off") . ")\n" + + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Other mappings~\n" + let @h=@h."\" ". g:NERDTreeMapQuit .": Close the NERDTree window\n" + let @h=@h."\" ". g:NERDTreeMapHelp .": toggle help\n" + let @h=@h."\"\n\" ----------------------------\n" + let @h=@h."\" Bookmark commands~\n" + let @h=@h."\" :Bookmark \n" + let @h=@h."\" :BookmarkToRoot \n" + let @h=@h."\" :RevealBookmark \n" + let @h=@h."\" :OpenBookmark \n" + let @h=@h."\" :ClearBookmarks []\n" + let @h=@h."\" :ClearAllBookmarks\n" + else + let @h="\" Press ". g:NERDTreeMapHelp ." for help\n" + endif + + silent! put h + + let @h = old_h +endfunction +"FUNCTION: s:echo {{{2 +"A wrapper for :echo. Appends 'NERDTree:' on the front of all messages +" +"Args: +"msg: the message to echo +function! s:echo(msg) + redraw + echomsg "NERDTree: " . a:msg +endfunction +"FUNCTION: s:echoWarning {{{2 +"Wrapper for s:echo, sets the message type to warningmsg for this message +"Args: +"msg: the message to echo +function! s:echoWarning(msg) + echohl warningmsg + call s:echo(a:msg) + echohl normal +endfunction +"FUNCTION: s:echoError {{{2 +"Wrapper for s:echo, sets the message type to errormsg for this message +"Args: +"msg: the message to echo +function! s:echoError(msg) + echohl errormsg + call s:echo(a:msg) + echohl normal +endfunction +"FUNCTION: s:firstUsableWindow(){{{2 +"find the window number of the first normal window +function! s:firstUsableWindow() + let i = 1 + while i <= winnr("$") + let bnum = winbufnr(i) + if bnum != -1 && getbufvar(bnum, '&buftype') ==# '' + \ && !getwinvar(i, '&previewwindow') + \ && (!getbufvar(bnum, '&modified') || &hidden) + return i + endif + + let i += 1 + endwhile + return -1 +endfunction +"FUNCTION: s:getPath(ln) {{{2 +"Gets the full path to the node that is rendered on the given line number +" +"Args: +"ln: the line number to get the path for +" +"Return: +"A path if a node was selected, {} if nothing is selected. +"If the 'up a dir' line was selected then the path to the parent of the +"current root is returned +function! s:getPath(ln) + let line = getline(a:ln) + + "check to see if we have the root node + if line =~ '^\/' + return b:NERDTreeRoot.path + endif + + " in case called from outside the tree + if line !~ '^ *[|`]' || line =~ '^$' + return {} + endif + + if line ==# s:tree_up_dir_line + return b:NERDTreeRoot.path.getParent() + endif + + let indent = s:indentLevelFor(line) + + "remove the tree parts and the leading space + let curFile = s:stripMarkupFromLine(line, 0) + + let wasdir = 0 + if curFile =~ '/$' + let wasdir = 1 + let curFile = substitute(curFile, '/\?$', '/', "") + endif + + + let dir = "" + let lnum = a:ln + while lnum > 0 + let lnum = lnum - 1 + let curLine = getline(lnum) + let curLineStripped = s:stripMarkupFromLine(curLine, 1) + + "have we reached the top of the tree? + if curLine =~ '^/' + let dir = substitute (curLine, ' *$', "", "") . dir + break + endif + if curLineStripped =~ '/$' + let lpindent = s:indentLevelFor(curLine) + if lpindent < indent + let indent = indent - 1 + + let dir = substitute (curLineStripped,'^\\', "", "") . dir + continue + endif + endif + endwhile + let curFile = b:NERDTreeRoot.path.drive . dir . curFile + let toReturn = s:Path.New(curFile) + return toReturn +endfunction + +"FUNCTION: s:getSelectedBookmark() {{{2 +"returns the bookmark the cursor is over in the bookmarks table or {} +function! s:getSelectedBookmark() + let line = getline(".") + let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '') + if name != line + try + return s:Bookmark.BookmarkFor(name) + catch /^NERDTree.BookmarkNotFoundError/ + return {} + endtry + endif + return {} +endfunction + +"FUNCTION: s:getTreeWinNum() {{{2 +"gets the nerd tree window number for this tab +function! s:getTreeWinNum() + if exists("t:NERDTreeBufName") + return bufwinnr(t:NERDTreeBufName) + else + return -1 + endif +endfunction +"FUNCTION: s:indentLevelFor(line) {{{2 +function! s:indentLevelFor(line) + return match(a:line, '[^ \-+~`|]') / s:tree_wid +endfunction +"FUNCTION: s:isTreeOpen() {{{2 +function! s:isTreeOpen() + return s:getTreeWinNum() != -1 +endfunction +"FUNCTION: s:isWindowUsable(winnumber) {{{2 +"Returns 0 if opening a file from the tree in the given window requires it to +"be split, 1 otherwise +" +"Args: +"winnumber: the number of the window in question +function! s:isWindowUsable(winnumber) + "gotta split if theres only one window (i.e. the NERD tree) + if winnr("$") ==# 1 + return 0 + endif + + let oldwinnr = winnr() + call s:exec(a:winnumber . "wincmd p") + let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow') + let modified = &modified + call s:exec(oldwinnr . "wincmd p") + + "if its a special window e.g. quickfix or another explorer plugin then we + "have to split + if specialWindow + return 0 + endif + + if &hidden + return 1 + endif + + return !modified || s:bufInWindows(winbufnr(a:winnumber)) >= 2 +endfunction + +" FUNCTION: s:jumpToChild(direction) {{{2 +" Args: +" direction: 0 if going to first child, 1 if going to last +function! s:jumpToChild(direction) + let currentNode = s:TreeFileNode.GetSelected() + if currentNode ==# {} || currentNode.isRoot() + call s:echo("cannot jump to " . (a:direction ? "last" : "first") . " child") + return + end + let dirNode = currentNode.parent + let childNodes = dirNode.getVisibleChildren() + + let targetNode = childNodes[0] + if a:direction + let targetNode = childNodes[len(childNodes) - 1] + endif + + if targetNode.equals(currentNode) + let siblingDir = currentNode.parent.findOpenDirSiblingWithVisibleChildren(a:direction) + if siblingDir != {} + let indx = a:direction ? siblingDir.getVisibleChildCount()-1 : 0 + let targetNode = siblingDir.getChildByIndex(indx, 1) + endif + endif + + call targetNode.putCursorHere(1, 0) + + call s:centerView() +endfunction + + +"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{2 +"prints out the given msg and, if the user responds by pushing 'y' then the +"buffer with the given bufnum is deleted +" +"Args: +"bufnum: the buffer that may be deleted +"msg: a message that will be echoed to the user asking them if they wish to +" del the buffer +function! s:promptToDelBuffer(bufnum, msg) + echo a:msg + if nr2char(getchar()) ==# 'y' + exec "silent bdelete! " . a:bufnum + endif +endfunction + +"FUNCTION: s:putCursorOnBookmarkTable(){{{2 +"Places the cursor at the top of the bookmarks table +function! s:putCursorOnBookmarkTable() + if !b:NERDTreeShowBookmarks + throw "NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active" + endif + + let rootNodeLine = s:TreeFileNode.GetRootLineNum() + + let line = 1 + while getline(line) !~ '^>-\+Bookmarks-\+$' + let line = line + 1 + if line >= rootNodeLine + throw "NERDTree.BookmarkTableNotFoundError: didnt find the bookmarks table" + endif + endwhile + call cursor(line, 0) +endfunction + +"FUNCTION: s:putCursorInTreeWin(){{{2 +"Places the cursor in the nerd tree window +function! s:putCursorInTreeWin() + if !s:isTreeOpen() + throw "NERDTree.InvalidOperationError: cant put cursor in NERD tree window, no window exists" + endif + + call s:exec(s:getTreeWinNum() . "wincmd w") +endfunction + +"FUNCTION: s:renderBookmarks {{{2 +function! s:renderBookmarks() + + call setline(line(".")+1, ">----------Bookmarks----------") + call cursor(line(".")+1, col(".")) + + for i in s:Bookmark.Bookmarks() + call setline(line(".")+1, i.str()) + call cursor(line(".")+1, col(".")) + endfor + + call setline(line(".")+1, '') + call cursor(line(".")+1, col(".")) +endfunction +"FUNCTION: s:renderView {{{2 +"The entry function for rendering the tree +function! s:renderView() + setlocal modifiable + + "remember the top line of the buffer and the current line so we can + "restore the view exactly how it was + let curLine = line(".") + let curCol = col(".") + let topLine = line("w0") + + "delete all lines in the buffer (being careful not to clobber a register) + silent 1,$delete _ + + call s:dumpHelp() + + "delete the blank line before the help and add one after it + call setline(line(".")+1, "") + call cursor(line(".")+1, col(".")) + + if b:NERDTreeShowBookmarks + call s:renderBookmarks() + endif + + "add the 'up a dir' line + call setline(line(".")+1, s:tree_up_dir_line) + call cursor(line(".")+1, col(".")) + + "draw the header line + call setline(line(".")+1, b:NERDTreeRoot.path.str(0)) + call cursor(line(".")+1, col(".")) + + "draw the tree + let old_o = @o + let @o = b:NERDTreeRoot.renderToString() + silent put o + let @o = old_o + + "delete the blank line at the top of the buffer + silent 1,1delete _ + + "restore the view + let old_scrolloff=&scrolloff + let &scrolloff=0 + call cursor(topLine, 1) + normal! zt + call cursor(curLine, curCol) + let &scrolloff = old_scrolloff + + setlocal nomodifiable +endfunction + +"FUNCTION: s:renderViewSavingPosition {{{2 +"Renders the tree and ensures the cursor stays on the current node or the +"current nodes parent if it is no longer available upon re-rendering +function! s:renderViewSavingPosition() + let currentNode = s:TreeFileNode.GetSelected() + + "go up the tree till we find a node that will be visible or till we run + "out of nodes + while currentNode != {} && !currentNode.isVisible() && !currentNode.isRoot() + let currentNode = currentNode.parent + endwhile + + call s:renderView() + + if currentNode != {} + call currentNode.putCursorHere(0, 0) + endif +endfunction +"FUNCTION: s:restoreScreenState() {{{2 +" +"Sets the screen state back to what it was when s:saveScreenState was last +"called. +" +"Assumes the cursor is in the NERDTree window +function! s:restoreScreenState() + if !exists("b:NERDTreeOldTopLine") || !exists("b:NERDTreeOldPos") || !exists("b:NERDTreeOldWindowSize") + return + endif + exec("silent vertical resize ".b:NERDTreeOldWindowSize) + + let old_scrolloff=&scrolloff + let &scrolloff=0 + call cursor(b:NERDTreeOldTopLine, 0) + normal! zt + call setpos(".", b:NERDTreeOldPos) + let &scrolloff=old_scrolloff +endfunction + +"FUNCTION: s:saveScreenState() {{{2 +"Saves the current cursor position in the current buffer and the window +"scroll position +function! s:saveScreenState() + let win = winnr() + try + call s:putCursorInTreeWin() + let b:NERDTreeOldPos = getpos(".") + let b:NERDTreeOldTopLine = line("w0") + let b:NERDTreeOldWindowSize = winwidth("") + call s:exec(win . "wincmd w") + catch /^NERDTree.InvalidOperationError/ + endtry +endfunction + +"FUNCTION: s:setupStatusline() {{{2 +function! s:setupStatusline() + if g:NERDTreeStatusline != -1 + let &l:statusline = g:NERDTreeStatusline + endif +endfunction +"FUNCTION: s:setupSyntaxHighlighting() {{{2 +function! s:setupSyntaxHighlighting() + "treeFlags are syntax items that should be invisible, but give clues as to + "how things should be highlighted + syn match treeFlag #\~# + syn match treeFlag #\[RO\]# + + "highlighting for the .. (up dir) line at the top of the tree + execute "syn match treeUp #". s:tree_up_dir_line ."#" + + "highlighting for the ~/+ symbols for the directory nodes + syn match treeClosable #\~\<# + syn match treeClosable #\~\.# + syn match treeOpenable #+\<# + syn match treeOpenable #+\.#he=e-1 + + "highlighting for the tree structural parts + syn match treePart #|# + syn match treePart #`# + syn match treePartFile #[|`]-#hs=s+1 contains=treePart + + "quickhelp syntax elements + syn match treeHelpKey #" \{1,2\}[^ ]*:#hs=s+2,he=e-1 + syn match treeHelpKey #" \{1,2\}[^ ]*,#hs=s+2,he=e-1 + syn match treeHelpTitle #" .*\~#hs=s+2,he=e-1 contains=treeFlag + syn match treeToggleOn #".*(on)#hs=e-2,he=e-1 contains=treeHelpKey + syn match treeToggleOff #".*(off)#hs=e-3,he=e-1 contains=treeHelpKey + syn match treeHelpCommand #" :.\{-}\>#hs=s+3 + syn match treeHelp #^".*# contains=treeHelpKey,treeHelpTitle,treeFlag,treeToggleOff,treeToggleOn,treeHelpCommand + + "highlighting for readonly files + syn match treeRO #.*\[RO\]#hs=s+2 contains=treeFlag,treeBookmark,treePart,treePartFile + + "highlighting for sym links + syn match treeLink #[^-| `].* -> # contains=treeBookmark,treeOpenable,treeClosable,treeDirSlash + + "highlighing for directory nodes and file nodes + syn match treeDirSlash #/# + syn match treeDir #[^-| `].*/# contains=treeLink,treeDirSlash,treeOpenable,treeClosable + syn match treeExecFile #[|`]-.*\*\($\| \)# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark + syn match treeFile #|-.*# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark,treeExecFile + syn match treeFile #`-.*# contains=treeLink,treePart,treeRO,treePartFile,treeBookmark,treeExecFile + syn match treeCWD #^/.*$# + + "highlighting for bookmarks + syn match treeBookmark # {.*}#hs=s+1 + + "highlighting for the bookmarks table + syn match treeBookmarksLeader #^># + syn match treeBookmarksHeader #^>-\+Bookmarks-\+$# contains=treeBookmarksLeader + syn match treeBookmarkName #^>.\{-} #he=e-1 contains=treeBookmarksLeader + syn match treeBookmark #^>.*$# contains=treeBookmarksLeader,treeBookmarkName,treeBookmarksHeader + + if g:NERDChristmasTree + hi def link treePart Special + hi def link treePartFile Type + hi def link treeFile Normal + hi def link treeExecFile Title + hi def link treeDirSlash Identifier + hi def link treeClosable Type + else + hi def link treePart Normal + hi def link treePartFile Normal + hi def link treeFile Normal + hi def link treeClosable Title + endif + + hi def link treeBookmarksHeader statement + hi def link treeBookmarksLeader ignore + hi def link treeBookmarkName Identifier + hi def link treeBookmark normal + + hi def link treeHelp String + hi def link treeHelpKey Identifier + hi def link treeHelpCommand Identifier + hi def link treeHelpTitle Macro + hi def link treeToggleOn Question + hi def link treeToggleOff WarningMsg + + hi def link treeDir Directory + hi def link treeUp Directory + hi def link treeCWD Statement + hi def link treeLink Macro + hi def link treeOpenable Title + hi def link treeFlag ignore + hi def link treeRO WarningMsg + hi def link treeBookmark Statement + + hi def link NERDTreeCurrentNode Search +endfunction + +"FUNCTION: s:stripMarkupFromLine(line, removeLeadingSpaces){{{2 +"returns the given line with all the tree parts stripped off +" +"Args: +"line: the subject line +"removeLeadingSpaces: 1 if leading spaces are to be removed (leading spaces = +"any spaces before the actual text of the node) +function! s:stripMarkupFromLine(line, removeLeadingSpaces) + let line = a:line + "remove the tree parts and the leading space + let line = substitute (line, s:tree_markup_reg,"","") + + "strip off any read only flag + let line = substitute (line, ' \[RO\]', "","") + + "strip off any bookmark flags + let line = substitute (line, ' {[^}]*}', "","") + + "strip off any executable flags + let line = substitute (line, '*\ze\($\| \)', "","") + + let wasdir = 0 + if line =~ '/$' + let wasdir = 1 + endif + let line = substitute (line,' -> .*',"","") " remove link to + if wasdir ==# 1 + let line = substitute (line, '/\?$', '/', "") + endif + + if a:removeLeadingSpaces + let line = substitute (line, '^ *', '', '') + endif + + return line +endfunction + +"FUNCTION: s:toggle(dir) {{{2 +"Toggles the NERD tree. I.e the NERD tree is open, it is closed, if it is +"closed it is restored or initialized (if it doesnt exist) +" +"Args: +"dir: the full path for the root node (is only used if the NERD tree is being +"initialized. +function! s:toggle(dir) + if s:treeExistsForTab() + if !s:isTreeOpen() + call s:createTreeWin() + call s:restoreScreenState() + if !&hidden + call s:renderView() + endif + else + call s:closeTree() + endif + else + call s:initNerdTree(a:dir) + endif +endfunction +"SECTION: Interface bindings {{{1 +"============================================================ +"FUNCTION: s:activateNode(forceKeepWindowOpen) {{{2 +"If the current node is a file, open it in the previous window (or a new one +"if the previous is modified). If it is a directory then it is opened. +" +"args: +"forceKeepWindowOpen - dont close the window even if NERDTreeQuitOnOpen is set +function! s:activateNode(forceKeepWindowOpen) + if getline(".") ==# s:tree_up_dir_line + return s:upDir(0) + endif + + let treenode = s:TreeFileNode.GetSelected() + if treenode != {} + if treenode.path.isDirectory + call treenode.toggleOpen() + call s:renderView() + call treenode.putCursorHere(0, 0) + else + call treenode.open() + if !a:forceKeepWindowOpen + call s:closeTreeIfQuitOnOpen() + end + endif + else + let bookmark = s:getSelectedBookmark() + if !empty(bookmark) + if bookmark.path.isDirectory + call bookmark.toRoot() + else + if bookmark.validate() + let n = s:TreeFileNode.New(bookmark.path) + call n.open() + endif + endif + endif + endif +endfunction + +"FUNCTION: s:bindMappings() {{{2 +function! s:bindMappings() + " set up mappings and commands for this buffer + nnoremap :call handleMiddleMouse() + nnoremap :call checkForActivate() + nnoremap <2-leftmouse> :call activateNode(0) + + exec "nnoremap ". g:NERDTreeMapActivateNode . " :call activateNode(0)" + exec "nnoremap ". g:NERDTreeMapOpenSplit ." :call openEntrySplit(0,0)" + exec "nnoremap :call activateNode(0)" + + exec "nnoremap ". g:NERDTreeMapPreview ." :call previewNode(0)" + exec "nnoremap ". g:NERDTreeMapPreviewSplit ." :call previewNode(1)" + + exec "nnoremap ". g:NERDTreeMapOpenVSplit ." :call openEntrySplit(1,0)" + exec "nnoremap ". g:NERDTreeMapPreviewVSplit ." :call previewNode(2)" + + exec "nnoremap ". g:NERDTreeMapExecute ." :call executeNode()" + + exec "nnoremap ". g:NERDTreeMapOpenRecursively ." :call openNodeRecursively()" + + exec "nnoremap ". g:NERDTreeMapUpdirKeepOpen ." :call upDir(1)" + exec "nnoremap ". g:NERDTreeMapUpdir ." :call upDir(0)" + exec "nnoremap ". g:NERDTreeMapChangeRoot ." :call chRoot()" + + exec "nnoremap ". g:NERDTreeMapChdir ." :call chCwd()" + + exec "nnoremap ". g:NERDTreeMapQuit ." :call closeTreeWindow()" + + exec "nnoremap ". g:NERDTreeMapRefreshRoot ." :call refreshRoot()" + exec "nnoremap ". g:NERDTreeMapRefresh ." :call refreshCurrent()" + + exec "nnoremap ". g:NERDTreeMapHelp ." :call displayHelp()" + exec "nnoremap ". g:NERDTreeMapToggleHidden ." :call toggleShowHidden()" + exec "nnoremap ". g:NERDTreeMapToggleFilters ." :call toggleIgnoreFilter()" + exec "nnoremap ". g:NERDTreeMapToggleFiles ." :call toggleShowFiles()" + exec "nnoremap ". g:NERDTreeMapToggleBookmarks ." :call toggleShowBookmarks()" + + exec "nnoremap ". g:NERDTreeMapCloseDir ." :call closeCurrentDir()" + exec "nnoremap ". g:NERDTreeMapCloseChildren ." :call closeChildren()" + + exec "nnoremap ". g:NERDTreeMapFilesystemMenu ." :call showFileSystemMenu()" + + exec "nnoremap ". g:NERDTreeMapJumpParent ." :call jumpToParent()" + exec "nnoremap ". g:NERDTreeMapJumpNextSibling ." :call jumpToSibling(1)" + exec "nnoremap ". g:NERDTreeMapJumpPrevSibling ." :call jumpToSibling(0)" + exec "nnoremap ". g:NERDTreeMapJumpFirstChild ." :call jumpToFirstChild()" + exec "nnoremap ". g:NERDTreeMapJumpLastChild ." :call jumpToLastChild()" + exec "nnoremap ". g:NERDTreeMapJumpRoot ." :call jumpToRoot()" + + exec "nnoremap ". g:NERDTreeMapOpenInTab ." :call openInNewTab(0)" + exec "nnoremap ". g:NERDTreeMapOpenInTabSilent ." :call openInNewTab(1)" + + exec "nnoremap ". g:NERDTreeMapOpenExpl ." :call openExplorer()" + + exec "nnoremap ". g:NERDTreeMapDeleteBookmark ." :call deleteBookmark()" + + command! -buffer -nargs=1 Bookmark :call bookmarkNode('') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 RevealBookmark :call revealBookmark('') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=1 OpenBookmark :call openBookmark('') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=* ClearBookmarks call clearBookmarks('') + command! -buffer -complete=customlist,s:completeBookmarks -nargs=+ BookmarkToRoot call s:Bookmark.ToRoot('') + command! -buffer -nargs=0 ClearAllBookmarks call s:Bookmark.ClearAll() call renderView() + command! -buffer -nargs=0 ReadBookmarks call s:Bookmark.CacheBookmarks(0) call renderView() + command! -buffer -nargs=0 WriteBookmarks call s:Bookmark.Write() +endfunction + +" FUNCTION: s:bookmarkNode(name) {{{2 +" Associate the current node with the given name +function! s:bookmarkNode(name) + let currentNode = s:TreeFileNode.GetSelected() + if currentNode != {} + try + call currentNode.bookmark(a:name) + call s:renderView() + catch /^NERDTree.IllegalBookmarkNameError/ + call s:echo("bookmark names must not contain spaces") + endtry + else + call s:echo("select a node first") + endif +endfunction +"FUNCTION: s:checkForActivate() {{{2 +"Checks if the click should open the current node, if so then activate() is +"called (directories are automatically opened if the symbol beside them is +"clicked) +function! s:checkForActivate() + let currentNode = s:TreeFileNode.GetSelected() + if currentNode != {} + let startToCur = strpart(getline(line(".")), 0, col(".")) + let char = strpart(startToCur, strlen(startToCur)-1, 1) + + "if they clicked a dir, check if they clicked on the + or ~ sign + "beside it + if currentNode.path.isDirectory + if startToCur =~ s:tree_markup_reg . '$' && char =~ '[+~]' + call s:activateNode(0) + return + endif + endif + + if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3 + if char !~ s:tree_markup_reg && startToCur !~ '\/$' + call s:activateNode(0) + return + endif + endif + endif +endfunction + +" FUNCTION: s:chCwd() {{{2 +function! s:chCwd() + let treenode = s:TreeFileNode.GetSelected() + if treenode ==# {} + call s:echo("Select a node first") + return + endif + + try + call treenode.path.changeToDir() + catch /^NERDTree.PathChangeError/ + call s:echoWarning("could not change cwd") + endtry +endfunction + +" FUNCTION: s:chRoot() {{{2 +" changes the current root to the selected one +function! s:chRoot() + let treenode = s:TreeFileNode.GetSelected() + if treenode ==# {} + call s:echo("Select a node first") + return + endif + + call treenode.makeRoot() + call s:renderView() + call b:NERDTreeRoot.putCursorHere(0, 0) +endfunction + +" FUNCTION: s:clearBookmarks(bookmarks) {{{2 +function! s:clearBookmarks(bookmarks) + if a:bookmarks ==# '' + let currentNode = s:TreeFileNode.GetSelected() + if currentNode != {} + call currentNode.clearBoomarks() + endif + else + for name in split(a:bookmarks, ' ') + let bookmark = s:Bookmark.BookmarkFor(name) + call bookmark.delete() + endfor + endif + call s:renderView() +endfunction +" FUNCTION: s:closeChildren() {{{2 +" closes all childnodes of the current node +function! s:closeChildren() + let currentNode = s:TreeDirNode.GetSelected() + if currentNode ==# {} + call s:echo("Select a node first") + return + endif + + call currentNode.closeChildren() + call s:renderView() + call currentNode.putCursorHere(0, 0) +endfunction +" FUNCTION: s:closeCurrentDir() {{{2 +" closes the parent dir of the current node +function! s:closeCurrentDir() + let treenode = s:TreeFileNode.GetSelected() + if treenode ==# {} + call s:echo("Select a node first") + return + endif + + let parent = treenode.parent + if parent.isRoot() + call s:echo("cannot close tree root") + else + call treenode.parent.close() + call s:renderView() + call treenode.parent.putCursorHere(0, 0) + endif +endfunction +" FUNCTION: s:closeTreeWindow() {{{2 +" close the tree window +function! s:closeTreeWindow() + if b:NERDTreeType ==# "secondary" && b:NERDTreePreviousBuf != -1 + exec "buffer " . b:NERDTreePreviousBuf + else + if winnr("$") > 1 + wincmd c + else + call s:echo("Cannot close last window") + endif + endif +endfunction +" FUNCTION: s:copyNode() {{{2 +function! s:copyNode() + let currentNode = s:TreeFileNode.GetSelected() + if currentNode ==# {} + call s:echo("Put the cursor on a file node first") + return + endif + + let newNodePath = input("Copy the current node\n" . + \ "==========================================================\n" . + \ "Enter the new path to copy the node to: \n" . + \ "", currentNode.path.str(0)) + + if newNodePath != "" + "strip trailing slash + let newNodePath = substitute(newNodePath, '\/$', '', '') + + let confirmed = 1 + if currentNode.path.copyingWillOverwrite(newNodePath) + call s:echo("\nWarning: copying may overwrite files! Continue? (yN)") + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + if confirmed + try + let newNode = currentNode.copy(newNodePath) + call s:renderView() + call newNode.putCursorHere(0, 0) + catch /^NERDTree/ + call s:echoWarning("Could not copy node") + endtry + endif + else + call s:echo("Copy aborted.") + endif + redraw +endfunction + +" FUNCTION: s:deleteBookmark() {{{2 +" if the cursor is on a bookmark, prompt to delete +function! s:deleteBookmark() + let bookmark = s:getSelectedBookmark() + if bookmark ==# {} + call s:echo("Put the cursor on a bookmark") + return + endif + + echo "Are you sure you wish to delete the bookmark:\n\"" . bookmark.name . "\" (yN):" + + if nr2char(getchar()) ==# 'y' + try + call bookmark.delete() + call s:renderView() + redraw + catch /^NERDTree/ + call s:echoWarning("Could not remove bookmark") + endtry + else + call s:echo("delete aborted" ) + endif + +endfunction + +" FUNCTION: s:deleteNode() {{{2 +" if the current node is a file, pops up a dialog giving the user the option +" to delete it +function! s:deleteNode() + let currentNode = s:TreeFileNode.GetSelected() + if currentNode ==# {} + call s:echo("Put the cursor on a file node first") + return + endif + + let confirmed = 0 + + if currentNode.path.isDirectory + let choice =input("Delete the current node\n" . + \ "==========================================================\n" . + \ "STOP! To delete this entire directory, type 'yes'\n" . + \ "" . currentNode.path.strForOS(0) . ": ") + let confirmed = choice ==# 'yes' + else + echo "Delete the current node\n" . + \ "==========================================================\n". + \ "Are you sure you wish to delete the node:\n" . + \ "" . currentNode.path.strForOS(0) . " (yN):" + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + + if confirmed + try + call currentNode.delete() + call s:renderView() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + let bufnum = bufnr(currentNode.path.str(0)) + if buflisted(bufnum) + let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" + call s:promptToDelBuffer(bufnum, prompt) + endif + + redraw + catch /^NERDTree/ + call s:echoWarning("Could not remove node") + endtry + else + call s:echo("delete aborted" ) + endif + +endfunction + +" FUNCTION: s:displayHelp() {{{2 +" toggles the help display +function! s:displayHelp() + let b:treeShowHelp = b:treeShowHelp ? 0 : 1 + call s:renderView() + call s:centerView() +endfunction + +" FUNCTION: s:executeNode() {{{2 +function! s:executeNode() + let treenode = s:TreeFileNode.GetSelected() + if treenode ==# {} || treenode.path.isDirectory + call s:echo("Select an executable file node first" ) + else + echo "NERDTree executor\n" . + \ "==========================================================\n". + \ "Complete the command to execute (add arguments etc): \n\n" + let cmd = treenode.path.strForOS(1) + let cmd = input(':!', cmd . ' ') + + if cmd != '' + exec ':!' . cmd + else + call s:echo("command aborted") + endif + endif +endfunction + +" FUNCTION: s:handleMiddleMouse() {{{2 +function! s:handleMiddleMouse() + let curNode = s:TreeFileNode.GetSelected() + if curNode ==# {} + call s:echo("Put the cursor on a node first" ) + return + endif + + if curNode.path.isDirectory + call s:openExplorer() + else + call s:openEntrySplit(0,0) + endif +endfunction + + +" FUNCTION: s:insertNewNode() {{{2 +" Adds a new node to the filesystem and then into the tree +function! s:insertNewNode() + let curDirNode = s:TreeDirNode.GetSelected() + if curDirNode ==# {} + call s:echo("Put the cursor on a node first" ) + return + endif + + let newNodeName = input("Add a childnode\n". + \ "==========================================================\n". + \ "Enter the dir/file name to be created. Dirs end with a '/'\n" . + \ "", curDirNode.path.strForGlob() . s:os_slash) + + if newNodeName ==# '' + call s:echo("Node Creation Aborted.") + return + endif + + try + let newPath = s:Path.Create(newNodeName) + let parentNode = b:NERDTreeRoot.findNode(newPath.getPathTrunk()) + + let newTreeNode = s:TreeFileNode.New(newPath) + if parentNode.isOpen || !empty(parentNode.children) + call parentNode.addChild(newTreeNode, 1) + call s:renderView() + call newTreeNode.putCursorHere(1, 0) + endif + catch /^NERDTree/ + call s:echoWarning("Node Not Created.") + endtry +endfunction + +" FUNCTION: s:jumpToFirstChild() {{{2 +" wrapper for the jump to child method +function! s:jumpToFirstChild() + call s:jumpToChild(0) +endfunction + +" FUNCTION: s:jumpToLastChild() {{{2 +" wrapper for the jump to child method +function! s:jumpToLastChild() + call s:jumpToChild(1) +endfunction + +" FUNCTION: s:jumpToParent() {{{2 +" moves the cursor to the parent of the current node +function! s:jumpToParent() + let currentNode = s:TreeFileNode.GetSelected() + if !empty(currentNode) + if !empty(currentNode.parent) + call currentNode.parent.putCursorHere(1, 0) + call s:centerView() + else + call s:echo("cannot jump to parent") + endif + else + call s:echo("put the cursor on a node first") + endif +endfunction + +" FUNCTION: s:jumpToRoot() {{{2 +" moves the cursor to the root node +function! s:jumpToRoot() + call b:NERDTreeRoot.putCursorHere(1, 0) + call s:centerView() +endfunction + +" FUNCTION: s:jumpToSibling() {{{2 +" moves the cursor to the sibling of the current node in the given direction +" +" Args: +" forward: 1 if the cursor should move to the next sibling, 0 if it should +" move back to the previous sibling +function! s:jumpToSibling(forward) + let currentNode = s:TreeFileNode.GetSelected() + if !empty(currentNode) + let sibling = currentNode.findSibling(a:forward) + + if !empty(sibling) + call sibling.putCursorHere(1, 0) + call s:centerView() + endif + else + call s:echo("put the cursor on a node first") + endif +endfunction + +" FUNCTION: s:openBookmark(name) {{{2 +" put the cursor on the given bookmark and, if its a file, open it +function! s:openBookmark(name) + try + let targetNode = s:Bookmark.GetNodeForName(a:name, 0) + call targetNode.putCursorHere(0, 1) + redraw! + catch /^NERDTree.BookmarkedNodeNotFoundError/ + call s:echo("note - target node is not cached") + let bookmark = s:Bookmark.BookmarkFor(a:name) + let targetNode = s:TreeFileNode.New(bookmark.path) + endtry + if targetNode.path.isDirectory + call targetNode.openExplorer() + else + call targetNode.open() + endif +endfunction +" FUNCTION: s:openEntrySplit(vertical, forceKeepWindowOpen) {{{2 +"Opens the currently selected file from the explorer in a +"new window +" +"args: +"forceKeepWindowOpen - dont close the window even if NERDTreeQuitOnOpen is set +function! s:openEntrySplit(vertical, forceKeepWindowOpen) + let treenode = s:TreeFileNode.GetSelected() + if treenode != {} + if a:vertical + call treenode.openVSplit() + else + call treenode.openSplit() + endif + if !a:forceKeepWindowOpen + call s:closeTreeIfQuitOnOpen() + endif + else + call s:echo("select a node first") + endif +endfunction + +" FUNCTION: s:openExplorer() {{{2 +function! s:openExplorer() + let treenode = s:TreeDirNode.GetSelected() + if treenode != {} + call treenode.openExplorer() + else + call s:echo("select a node first") + endif +endfunction + +" FUNCTION: s:openInNewTab(stayCurrentTab) {{{2 +" Opens the selected node or bookmark in a new tab +" Args: +" stayCurrentTab: if 1 then vim will stay in the current tab, if 0 then vim +" will go to the tab where the new file is opened +function! s:openInNewTab(stayCurrentTab) + let currentTab = tabpagenr() + + let treenode = s:TreeFileNode.GetSelected() + if treenode != {} + if treenode.path.isDirectory + tabnew + call s:initNerdTree(treenode.path.strForOS(0)) + else + exec "tabedit " . treenode.path.strForEditCmd() + endif + else + let bookmark = s:getSelectedBookmark() + if bookmark != {} + if bookmark.path.isDirectory + tabnew + call s:initNerdTree(bookmark.name) + else + exec "tabedit " . bookmark.path.strForEditCmd() + endif + endif + endif + if a:stayCurrentTab + exec "tabnext " . currentTab + endif +endfunction + +" FUNCTION: s:openNodeRecursively() {{{2 +function! s:openNodeRecursively() + let treenode = s:TreeFileNode.GetSelected() + if treenode ==# {} || treenode.path.isDirectory ==# 0 + call s:echo("Select a directory node first" ) + else + call s:echo("Recursively opening node. Please wait...") + call treenode.openRecursively() + call s:renderView() + redraw + call s:echo("Recursively opening node. Please wait... DONE") + endif + +endfunction + +"FUNCTION: s:previewNode() {{{2 +"Args: +" openNewWin: if 0, use the previous window, if 1 open in new split, if 2 +" open in a vsplit +function! s:previewNode(openNewWin) + let currentBuf = bufnr("") + if a:openNewWin > 0 + call s:openEntrySplit(a:openNewWin ==# 2,1) + else + call s:activateNode(1) + end + call s:exec(bufwinnr(currentBuf) . "wincmd w") +endfunction + +" FUNCTION: s:revealBookmark(name) {{{2 +" put the cursor on the node associate with the given name +function! s:revealBookmark(name) + try + let targetNode = s:Bookmark.GetNodeForName(a:name, 0) + call targetNode.putCursorHere(0, 1) + catch /^NERDTree.BookmarkNotFoundError/ + call s:echo("Bookmark isnt cached under the current root") + endtry +endfunction +" FUNCTION: s:refreshRoot() {{{2 +" Reloads the current root. All nodes below this will be lost and the root dir +" will be reloaded. +function! s:refreshRoot() + call s:echo("Refreshing the root node. This could take a while...") + call b:NERDTreeRoot.refresh() + call s:renderView() + redraw + call s:echo("Refreshing the root node. This could take a while... DONE") +endfunction + +" FUNCTION: s:refreshCurrent() {{{2 +" refreshes the root for the current node +function! s:refreshCurrent() + let treenode = s:TreeDirNode.GetSelected() + if treenode ==# {} + call s:echo("Refresh failed. Select a node first") + return + endif + + call s:echo("Refreshing node. This could take a while...") + call treenode.refresh() + call s:renderView() + redraw + call s:echo("Refreshing node. This could take a while... DONE") +endfunction +" FUNCTION: s:renameCurrent() {{{2 +" allows the user to rename the current node +function! s:renameCurrent() + let curNode = s:TreeFileNode.GetSelected() + if curNode ==# {} + call s:echo("Put the cursor on a node first" ) + return + endif + + let newNodePath = input("Rename the current node\n" . + \ "==========================================================\n" . + \ "Enter the new path for the node: \n" . + \ "", curNode.path.strForOS(0)) + + if newNodePath ==# '' + call s:echo("Node Renaming Aborted.") + return + endif + + try + let bufnum = bufnr(curNode.path.str(0)) + + call curNode.rename(newNodePath) + call s:renderView() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + if bufnum != -1 + let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" + call s:promptToDelBuffer(bufnum, prompt) + endif + + call curNode.putCursorHere(1, 0) + + redraw + catch /^NERDTree/ + call s:echoWarning("Node Not Renamed.") + endtry +endfunction + +" FUNCTION: s:showFileSystemMenu() {{{2 +function! s:showFileSystemMenu() + let curNode = s:TreeFileNode.GetSelected() + if curNode ==# {} + call s:echo("Put the cursor on a node first" ) + return + endif + + + let prompt = "NERDTree Filesystem Menu\n" . + \ "==========================================================\n". + \ "Select the desired operation: \n" . + \ " (a)dd a childnode\n". + \ " (m)ove the current node\n". + \ " (d)elete the current node\n" + if s:Path.CopyingSupported() + let prompt = prompt . " (c)opy the current node\n\n" + else + let prompt = prompt . " \n" + endif + + echo prompt + + let choice = nr2char(getchar()) + + if choice ==? "a" + call s:insertNewNode() + elseif choice ==? "m" + call s:renameCurrent() + elseif choice ==? "d" + call s:deleteNode() + elseif choice ==? "c" && s:Path.CopyingSupported() + call s:copyNode() + endif +endfunction + +" FUNCTION: s:toggleIgnoreFilter() {{{2 +" toggles the use of the NERDTreeIgnore option +function! s:toggleIgnoreFilter() + let b:NERDTreeIgnoreEnabled = !b:NERDTreeIgnoreEnabled + call s:renderViewSavingPosition() + call s:centerView() +endfunction + +" FUNCTION: s:toggleShowBookmarks() {{{2 +" toggles the display of bookmarks +function! s:toggleShowBookmarks() + let b:NERDTreeShowBookmarks = !b:NERDTreeShowBookmarks + if b:NERDTreeShowBookmarks + call s:renderView() + call s:putCursorOnBookmarkTable() + else + call s:renderViewSavingPosition() + endif + call s:centerView() +endfunction +" FUNCTION: s:toggleShowFiles() {{{2 +" toggles the display of hidden files +function! s:toggleShowFiles() + let b:NERDTreeShowFiles = !b:NERDTreeShowFiles + call s:renderViewSavingPosition() + call s:centerView() +endfunction + +" FUNCTION: s:toggleShowHidden() {{{2 +" toggles the display of hidden files +function! s:toggleShowHidden() + let b:NERDTreeShowHidden = !b:NERDTreeShowHidden + call s:renderViewSavingPosition() + call s:centerView() +endfunction + +"FUNCTION: s:upDir(keepState) {{{2 +"moves the tree up a level +" +"Args: +"keepState: 1 if the current root should be left open when the tree is +"re-rendered +function! s:upDir(keepState) + let cwd = b:NERDTreeRoot.path.str(0) + if cwd ==# "/" || cwd =~ '^[^/]..$' + call s:echo("already at top dir") + else + if !a:keepState + call b:NERDTreeRoot.close() + endif + + let oldRoot = b:NERDTreeRoot + + if empty(b:NERDTreeRoot.parent) + let path = b:NERDTreeRoot.path.getPathTrunk() + let newRoot = s:TreeDirNode.New(path) + call newRoot.open() + call newRoot.transplantChild(b:NERDTreeRoot) + let b:NERDTreeRoot = newRoot + else + let b:NERDTreeRoot = b:NERDTreeRoot.parent + endif + + if g:NERDTreeChDirMode ==# 2 + exec 'cd ' . b:NERDTreeRoot.path.strForCd() + endif + + call s:renderView() + call oldRoot.putCursorHere(0, 0) + endif +endfunction + + +"reset &cpo back to users setting +let &cpo = s:old_cpo + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/plugin/a.vim b/plugin/a.vim new file mode 100644 index 0000000..637feb5 --- /dev/null +++ b/plugin/a.vim @@ -0,0 +1,840 @@ +" Copyright (c) 1998-2006 +" Michael Sharpe +" +" We grant permission to use, copy modify, distribute, and sell this +" software for any purpose without fee, provided that the above copyright +" notice and this text are not removed. We make no guarantee about the +" suitability of this software for any purpose and we are not liable +" for any damages resulting from its use. Further, we are under no +" obligation to maintain or extend this software. It is provided on an +" "as is" basis without any expressed or implied warranty. + +" Directory & regex enhancements added by Bindu Wavell who is well known on +" vim.sf.net +" +" Patch for spaces in files/directories from Nathan Stien (also reported by +" Soeren Sonnenburg) + +" Do not load a.vim if is has already been loaded. +if exists("loaded_alternateFile") + finish +endif +if (v:progname == "ex") + finish +endif +let loaded_alternateFile = 1 + +let alternateExtensionsDict = {} + +" setup the default set of alternate extensions. The user can override in thier +" .vimrc if the defaults are not suitable. To override in a .vimrc simply set a +" g:alternateExtensions_ variable to a comma separated list of alternates, +" where is the extension to map. +" E.g. let g:alternateExtensions_CPP = "inc,h,H,HPP,hpp" +" let g:alternateExtensions_{'aspx.cs'} = "aspx" + + +" This variable will be increased when an extension with greater number of dots +" is added by the AddAlternateExtensionMapping call. +let s:maxDotsInExtension = 1 + +" Function : AddAlternateExtensionMapping (PRIVATE) +" Purpose : simple helper function to add the default alternate extension +" mappings. +" Args : extension -- the extension to map +" alternates -- comma separated list of alternates extensions +" Returns : nothing +" Author : Michael Sharpe +function! AddAlternateExtensionMapping(extension, alternates) + " This code does not actually work for variables like foo{'a.b.c.d.e'} + "let varName = "g:alternateExtensions_" . a:extension + "if (!exists(varName)) + " let g:alternateExtensions_{a:extension} = a:alternates + "endif + + " This code handles extensions which contains a dot. exists() fails with + " such names. + "let v:errmsg = "" + " FIXME this line causes ex to return 1 instead of 0 for some reason?? + "silent! echo g:alternateExtensions_{a:extension} + "if (v:errmsg != "") + "let g:alternateExtensions_{a:extension} = a:alternates + "endif + + let g:alternateExtensionsDict[a:extension] = a:alternates + let dotsNumber = strlen(substitute(a:extension, "[^.]", "", "g")) + if s:maxDotsInExtension < dotsNumber + let s:maxDotsInExtension = dotsNumber + endif +endfunction + + +" Add all the default extensions +" Mappings for C and C++ +call AddAlternateExtensionMapping('h',"c,cpp,cxx,cc,CC") +call AddAlternateExtensionMapping('H',"C,CPP,CXX,CC") +call AddAlternateExtensionMapping('hpp',"cpp,c") +call AddAlternateExtensionMapping('HPP',"CPP,C") +call AddAlternateExtensionMapping('c',"h") +call AddAlternateExtensionMapping('C',"H") +call AddAlternateExtensionMapping('cpp',"h,hpp") +call AddAlternateExtensionMapping('CPP',"H,HPP") +call AddAlternateExtensionMapping('cc',"h") +call AddAlternateExtensionMapping('CC',"H,h") +call AddAlternateExtensionMapping('cxx',"h") +call AddAlternateExtensionMapping('CXX',"H") +" Mappings for PSL7 +call AddAlternateExtensionMapping('psl',"ph") +call AddAlternateExtensionMapping('ph',"psl") +" Mappings for ADA +call AddAlternateExtensionMapping('adb',"ads") +call AddAlternateExtensionMapping('ads',"adb") +" Mappings for lex and yacc files +call AddAlternateExtensionMapping('l',"y,yacc,ypp") +call AddAlternateExtensionMapping('lex',"yacc,y,ypp") +call AddAlternateExtensionMapping('lpp',"ypp,y,yacc") +call AddAlternateExtensionMapping('y',"l,lex,lpp") +call AddAlternateExtensionMapping('yacc',"lex,l,lpp") +call AddAlternateExtensionMapping('ypp',"lpp,l,lex") +" Mappings for OCaml +call AddAlternateExtensionMapping('ml',"mli") +call AddAlternateExtensionMapping('mli',"ml") +" ASP stuff +call AddAlternateExtensionMapping('aspx.cs', 'aspx') +call AddAlternateExtensionMapping('aspx.vb', 'aspx') +call AddAlternateExtensionMapping('aspx', 'aspx.cs,aspx.vb') + +" Setup default search path, unless the user has specified +" a path in their [._]vimrc. +if (!exists('g:alternateSearchPath')) + let g:alternateSearchPath = 'sfr:../source,sfr:../src,sfr:../include,sfr:../inc' +endif + +" If this variable is true then a.vim will not alternate to a file/buffer which +" does not exist. E.g while editing a.c and the :A will not swtich to a.h +" unless it exists. +if (!exists('g:alternateNoDefaultAlternate')) + " by default a.vim will alternate to a file which does not exist + let g:alternateNoDefaultAlternate = 0 +endif + +" If this variable is true then a.vim will convert the alternate filename to a +" filename relative to the current working directory. +" Feature by Nathan Huizinga +if (!exists('g:alternateRelativeFiles')) + " by default a.vim will not convert the filename to one relative to the + " current working directory + let g:alternateRelativeFiles = 0 +endif + + +" Function : GetNthItemFromList (PRIVATE) +" Purpose : Support reading items from a comma seperated list +" Used to iterate all the extensions in an extension spec +" Used to iterate all path prefixes +" Args : list -- the list (extension spec, file paths) to iterate +" n -- the extension to get +" Returns : the nth item (extension, path) from the list (extension +" spec), or "" for failure +" Author : Michael Sharpe +" History : Renamed from GetNthExtensionFromSpec to GetNthItemFromList +" to reflect a more generic use of this function. -- Bindu +function! GetNthItemFromList(list, n) + let itemStart = 0 + let itemEnd = -1 + let pos = 0 + let item = "" + let i = 0 + while (i != a:n) + let itemStart = itemEnd + 1 + let itemEnd = match(a:list, ",", itemStart) + let i = i + 1 + if (itemEnd == -1) + if (i == a:n) + let itemEnd = strlen(a:list) + endif + break + endif + endwhile + if (itemEnd != -1) + let item = strpart(a:list, itemStart, itemEnd - itemStart) + endif + return item +endfunction + +" Function : ExpandAlternatePath (PRIVATE) +" Purpose : Expand path info. A path with a prefix of "wdr:" will be +" treated as relative to the working directory (i.e. the +" directory where vim was started.) A path prefix of "abs:" will +" be treated as absolute. No prefix or "sfr:" will result in the +" path being treated as relative to the source file (see sfPath +" argument). +" +" A prefix of "reg:" will treat the pathSpec as a regular +" expression substitution that is applied to the source file +" path. The format is: +" +" reg: +" +" seperator character, we often use one of [/|%#] +" is what you are looking for +" is the output pattern +" can be g for global replace or empty +" +" EXAMPLE: 'reg:/inc/src/g/' will replace every instance +" of 'inc' with 'src' in the source file path. It is possible +" to use match variables so you could do something like: +" 'reg:|src/\([^/]*\)|inc/\1||' (see 'help :substitute', +" 'help pattern' and 'help sub-replace-special' for more details +" +" NOTE: a.vim uses ',' (comma) internally so DON'T use it +" in your regular expressions or other pathSpecs unless you update +" the rest of the a.vim code to use some other seperator. +" +" Args : pathSpec -- path component (or substitution patterns) +" sfPath -- source file path +" Returns : a path that can be used by AlternateFile() +" Author : Bindu Wavell +function! ExpandAlternatePath(pathSpec, sfPath) + let prfx = strpart(a:pathSpec, 0, 4) + if (prfx == "wdr:" || prfx == "abs:") + let path = strpart(a:pathSpec, 4) + elseif (prfx == "reg:") + let re = strpart(a:pathSpec, 4) + let sep = strpart(re, 0, 1) + let patend = match(re, sep, 1) + let pat = strpart(re, 1, patend - 1) + let subend = match(re, sep, patend + 1) + let sub = strpart(re, patend+1, subend - patend - 1) + let flag = strpart(re, strlen(re) - 2) + if (flag == sep) + let flag = '' + endif + let path = substitute(a:sfPath, pat, sub, flag) + "call confirm('PAT: [' . pat . '] SUB: [' . sub . ']') + "call confirm(a:sfPath . ' => ' . path) + else + let path = a:pathSpec + if (prfx == "sfr:") + let path = strpart(path, 4) + endif + let path = a:sfPath . "/" . path + endif + return path +endfunction + +" Function : FindFileInSearchPath (PRIVATE) +" Purpose : Searches for a file in the search path list +" Args : filename -- name of the file to search for +" pathList -- the path list to search +" relPathBase -- the path which relative paths are expanded from +" Returns : An expanded filename if found, the empty string otherwise +" Author : Michael Sharpe (feline@irendi.com) +" History : inline code written by Bindu Wavell originally +function! FindFileInSearchPath(fileName, pathList, relPathBase) + let filepath = "" + let m = 1 + let pathListLen = strlen(a:pathList) + if (pathListLen > 0) + while (1) + let pathSpec = GetNthItemFromList(a:pathList, m) + if (pathSpec != "") + let path = ExpandAlternatePath(pathSpec, a:relPathBase) + let fullname = path . "/" . a:fileName + let foundMatch = BufferOrFileExists(fullname) + if (foundMatch) + let filepath = fullname + break + endif + else + break + endif + let m = m + 1 + endwhile + endif + return filepath +endfunction + +" Function : FindFileInSearchPathEx (PRIVATE) +" Purpose : Searches for a file in the search path list +" Args : filename -- name of the file to search for +" pathList -- the path list to search +" relPathBase -- the path which relative paths are expanded from +" count -- find the count'th occurence of the file on the path +" Returns : An expanded filename if found, the empty string otherwise +" Author : Michael Sharpe (feline@irendi.com) +" History : Based on FindFileInSearchPath() but with extensions +function! FindFileInSearchPathEx(fileName, pathList, relPathBase, count) + let filepath = "" + let m = 1 + let spath = "" + let pathListLen = strlen(a:pathList) + if (pathListLen > 0) + while (1) + let pathSpec = GetNthItemFromList(a:pathList, m) + if (pathSpec != "") + let path = ExpandAlternatePath(pathSpec, a:relPathBase) + if (spath != "") + let spath = spath . ',' + endif + let spath = spath . path + else + break + endif + let m = m + 1 + endwhile + endif + + if (&path != "") + if (spath != "") + let spath = spath . ',' + endif + let spath = spath . &path + endif + + let filepath = findfile(a:fileName, spath, a:count) + return filepath +endfunction + +" Function : EnumerateFilesByExtension (PRIVATE) +" Purpose : enumerates all files by a particular list of alternate extensions. +" Args : path -- path of a file (not including the file) +" baseName -- base name of the file to be expanded +" extension -- extension whose alternates are to be enumerated +" Returns : comma separated list of files with extensions +" Author : Michael Sharpe +function! EnumerateFilesByExtension(path, baseName, extension) + let enumeration = "" + let extSpec = "" + let v:errmsg = "" + silent! echo g:alternateExtensions_{a:extension} + if (v:errmsg == "") + let extSpec = g:alternateExtensions_{a:extension} + endif + if (extSpec == "") + if (has_key(g:alternateExtensionsDict, a:extension)) + let extSpec = g:alternateExtensionsDict[a:extension] + endif + endif + if (extSpec != "") + let n = 1 + let done = 0 + while (!done) + let ext = GetNthItemFromList(extSpec, n) + if (ext != "") + if (a:path != "") + let newFilename = a:path . "/" . a:baseName . "." . ext + else + let newFilename = a:baseName . "." . ext + endif + if (enumeration == "") + let enumeration = newFilename + else + let enumeration = enumeration . "," . newFilename + endif + else + let done = 1 + endif + let n = n + 1 + endwhile + endif + return enumeration +endfunction + +" Function : EnumerateFilesByExtensionInPath (PRIVATE) +" Purpose : enumerates all files by expanding the path list and the extension +" list. +" Args : baseName -- base name of the file +" extension -- extension whose alternates are to be enumerated +" pathList -- the list of paths to enumerate +" relPath -- the path of the current file for expansion of relative +" paths in the path list. +" Returns : A comma separated list of paths with extensions +" Author : Michael Sharpe +function! EnumerateFilesByExtensionInPath(baseName, extension, pathList, relPathBase) + let enumeration = "" + let filepath = "" + let m = 1 + let pathListLen = strlen(a:pathList) + if (pathListLen > 0) + while (1) + let pathSpec = GetNthItemFromList(a:pathList, m) + if (pathSpec != "") + let path = ExpandAlternatePath(pathSpec, a:relPathBase) + let pe = EnumerateFilesByExtension(path, a:baseName, a:extension) + if (enumeration == "") + let enumeration = pe + else + let enumeration = enumeration . "," . pe + endif + else + break + endif + let m = m + 1 + endwhile + endif + return enumeration +endfunction + +" Function : DetermineExtension (PRIVATE) +" Purpose : Determines the extension of a filename based on the register +" alternate extension. This allow extension which contain dots to +" be considered. E.g. foo.aspx.cs to foo.aspx where an alternate +" exists for the aspx.cs extension. Note that this will only accept +" extensions which contain less than 5 dots. This is only +" implemented in this manner for simplicity...it is doubtful that +" this will be a restriction in non-contrived situations. +" Args : The path to the file to find the extension in +" Returns : The matched extension if any +" Author : Michael Sharpe (feline@irendi.com) +" History : idea from Tom-Erik Duestad +" Notes : there is some magic occuring here. The exists() function does not +" work well when the curly brace variable has dots in it. And why +" should it, dots are not valid in variable names. But the exists +" function is wierd too. Lets say foo_c does exist. Then +" exists("foo_c.e.f") will be true...even though the variable does +" not exist. However the curly brace variables do work when the +" variable has dots in it. E.g foo_{'c'} is different from +" foo_{'c.d.e'}...and foo_{'c'} is identical to foo_c and +" foo_{'c.d.e'} is identical to foo_c.d.e right? Yes in the current +" implementation of vim. To trick vim to test for existence of such +" variables echo the curly brace variable and look for an error +" message. +function! DetermineExtension(path) + let mods = ":t" + let i = 0 + while i <= s:maxDotsInExtension + let mods = mods . ":e" + let extension = fnamemodify(a:path, mods) + if (has_key(g:alternateExtensionsDict, extension)) + return extension + endif + let v:errmsg = "" + silent! echo g:alternateExtensions_{extension} + if (v:errmsg == "") + return extension + endif + let i = i + 1 + endwhile + return "" +endfunction + +" Function : AlternateFile (PUBLIC) +" Purpose : Opens a new buffer by looking at the extension of the current +" buffer and finding the corresponding file. E.g. foo.c <--> foo.h +" Args : accepts one argument. If present it used the argument as the new +" extension. +" Returns : nothing +" Author : Michael Sharpe +" History : + When an alternate can't be found in the same directory as the +" source file, a search path will be traversed looking for the +" alternates. +" + Moved some code into a separate function, minor optimization +" + rework to favor files in memory based on complete enumeration of +" all files extensions and paths +function! AlternateFile(splitWindow, ...) + let extension = DetermineExtension(expand("%:p")) + let baseName = substitute(expand("%:t"), "\." . extension . '$', "", "") + let currentPath = expand("%:p:h") + + if (a:0 != 0) + let newFullname = currentPath . "/" . baseName . "." . a:1 + call FindOrCreateBuffer(newFullname, a:splitWindow, 0) + else + let allfiles = "" + if (extension != "") + let allfiles1 = EnumerateFilesByExtension(currentPath, baseName, extension) + let allfiles2 = EnumerateFilesByExtensionInPath(baseName, extension, g:alternateSearchPath, currentPath) + + if (allfiles1 != "") + if (allfiles2 != "") + let allfiles = allfiles1 . ',' . allfiles2 + else + let allfiles = allfiles1 + endif + else + let allfiles = allfiles2 + endif + endif + + if (allfiles != "") + let bestFile = "" + let bestScore = 0 + let score = 0 + let n = 1 + + let onefile = GetNthItemFromList(allfiles, n) + let bestFile = onefile + while (onefile != "" && score < 2) + let score = BufferOrFileExists(onefile) + if (score > bestScore) + let bestScore = score + let bestFile = onefile + endif + let n = n + 1 + let onefile = GetNthItemFromList(allfiles, n) + endwhile + + if (bestScore == 0 && g:alternateNoDefaultAlternate == 1) + echo "No existing alternate available" + else + call FindOrCreateBuffer(bestFile, a:splitWindow, 1) + let b:AlternateAllFiles = allfiles + endif + else + echo "No alternate file/buffer available" + endif + endif +endfunction + +" Function : AlternateOpenFileUnderCursor (PUBLIC) +" Purpose : Opens file under the cursor +" Args : splitWindow -- indicates how to open the file +" Returns : Nothing +" Author : Michael Sharpe (feline@irendi.com) www.irendi.com +function! AlternateOpenFileUnderCursor(splitWindow,...) + let cursorFile = (a:0 > 0) ? a:1 : expand("") + let currentPath = expand("%:p:h") + let openCount = 1 + + let fileName = FindFileInSearchPathEx(cursorFile, g:alternateSearchPath, currentPath, openCount) + if (fileName != "") + call FindOrCreateBuffer(fileName, a:splitWindow, 1) + let b:openCount = openCount + let b:cursorFile = cursorFile + let b:currentPath = currentPath + else + echo "Can't find file" + endif +endfunction + +" Function : AlternateOpenNextFile (PUBLIC) +" Purpose : Opens the next file corresponding to the search which found the +" current file +" Args : bang -- indicates what to do if the current file has not been +" saved +" Returns : nothing +" Author : Michael Sharpe (feline@irendi.com) www.irendi.com +function! AlternateOpenNextFile(bang) + let cursorFile = "" + if (exists("b:cursorFile")) + let cursorFile = b:cursorFile + endif + + let currentPath = "" + if (exists("b:currentPath")) + let currentPath = b:currentPath + endif + + let openCount = 0 + if (exists("b:openCount")) + let openCount = b:openCount + 1 + endif + + if (cursorFile != "" && currentPath != "" && openCount != 0) + let fileName = FindFileInSearchPathEx(cursorFile, g:alternateSearchPath, currentPath, openCount) + if (fileName != "") + call FindOrCreateBuffer(fileName, "n".a:bang, 0) + let b:openCount = openCount + let b:cursorFile = cursorFile + let b:currentPath = currentPath + else + let fileName = FindFileInSearchPathEx(cursorFile, g:alternateSearchPath, currentPath, 1) + if (fileName != "") + call FindOrCreateBuffer(fileName, "n".a:bang, 0) + let b:openCount = 1 + let b:cursorFile = cursorFile + let b:currentPath = currentPath + else + echo "Can't find next file" + endif + endif + endif +endfunction + +comm! -nargs=? -bang IH call AlternateOpenFileUnderCursor("n", ) +comm! -nargs=? -bang IHS call AlternateOpenFileUnderCursor("h", ) +comm! -nargs=? -bang IHV call AlternateOpenFileUnderCursor("v", ) +comm! -nargs=? -bang IHT call AlternateOpenFileUnderCursor("t", ) +comm! -nargs=? -bang IHN call AlternateOpenNextFile("") +imap ih :IHS +nmap ih :IHS +imap is :IHS:A +nmap is :IHS:A +imap ihn :IHN +nmap ihn :IHN + +"function! PrintList(theList) +" let n = 1 +" let oneFile = GetNthItemFromList(a:theList, n) +" while (oneFile != "") +" let n = n + 1 +" let oneFile = GetNthItemFromList(a:theList, n) +" endwhile +"endfunction + +" Function : NextAlternate (PUBLIC) +" Purpose : Used to cycle through any other alternate file which existed on +" the search path. +" Args : bang (IN) - used to implement the AN vs AN! functionality +" Returns : nothing +" Author : Michael Sharpe +function! NextAlternate(bang) + if (exists('b:AlternateAllFiles')) + let currentFile = expand("%") + let n = 1 + let onefile = GetNthItemFromList(b:AlternateAllFiles, n) + while (onefile != "" && !EqualFilePaths(fnamemodify(onefile,":p"), fnamemodify(currentFile,":p"))) + let n = n + 1 + let onefile = GetNthItemFromList(b:AlternateAllFiles, n) + endwhile + + if (onefile != "") + let stop = n + let n = n + 1 + let foundAlternate = 0 + let nextAlternate = "" + while (n != stop) + let nextAlternate = GetNthItemFromList(b:AlternateAllFiles, n) + if (nextAlternate == "") + let n = 1 + continue + endif + let n = n + 1 + if (EqualFilePaths(fnamemodify(nextAlternate, ":p"), fnamemodify(currentFile, ":p"))) + continue + endif + if (filereadable(nextAlternate)) + " on cygwin filereadable("foo.H") returns true if "foo.h" exists + if (has("unix") && $WINDIR != "" && fnamemodify(nextAlternate, ":p") ==? fnamemodify(currentFile, ":p")) + continue + endif + let foundAlternate = 1 + break + endif + endwhile + if (foundAlternate == 1) + let s:AlternateAllFiles = b:AlternateAllFiles + "silent! execute ":e".a:bang." " . nextAlternate + call FindOrCreateBuffer(nextAlternate, "n".a:bang, 0) + let b:AlternateAllFiles = s:AlternateAllFiles + else + echo "Only this alternate file exists" + endif + else + echo "Could not find current file in alternates list" + endif + else + echo "No other alternate files exist" + endif +endfunction + +comm! -nargs=? -bang A call AlternateFile("n", ) +comm! -nargs=? -bang AS call AlternateFile("h", ) +comm! -nargs=? -bang AV call AlternateFile("v", ) +comm! -nargs=? -bang AT call AlternateFile("t", ) +comm! -nargs=? -bang AN call NextAlternate("") + +" Function : BufferOrFileExists (PRIVATE) +" Purpose : determines if a buffer or a readable file exists +" Args : fileName (IN) - name of the file to check +" Returns : 2 if it exists in memory, 1 if it exists, 0 otherwise +" Author : Michael Sharpe +" History : Updated code to handle buffernames using just the +" filename and not the path. +function! BufferOrFileExists(fileName) + let result = 0 + + let lastBuffer = bufnr("$") + let i = 1 + while i <= lastBuffer + if EqualFilePaths(expand("#".i.":p"), a:fileName) + let result = 2 + break + endif + let i = i + 1 + endwhile + + if (!result) + let bufName = fnamemodify(a:fileName,":t") + let memBufName = bufname(bufName) + if (memBufName != "") + let memBufBasename = fnamemodify(memBufName, ":t") + if (bufName == memBufBasename) + let result = 2 + endif + endif + + if (!result) + let result = bufexists(bufName) || bufexists(a:fileName) || filereadable(a:fileName) + endif + endif + + if (!result) + let result = filereadable(a:fileName) + endif + return result +endfunction + +" Function : FindOrCreateBuffer (PRIVATE) +" Purpose : searches the buffer list (:ls) for the specified filename. If +" found, checks the window list for the buffer. If the buffer is in +" an already open window, it switches to the window. If the buffer +" was not in a window, it switches to that buffer. If the buffer did +" not exist, it creates it. +" Args : filename (IN) -- the name of the file +" doSplit (IN) -- indicates whether the window should be split +" ("v", "h", "n", "v!", "h!", "n!", "t", "t!") +" findSimilar (IN) -- indicate weather existing buffers should be +" prefered +" Returns : nothing +" Author : Michael Sharpe +" History : + bufname() was not working very well with the possibly strange +" paths that can abound with the search path so updated this +" slightly. -- Bindu +" + updated window switching code to make it more efficient -- Bindu +" Allow ! to be applied to buffer/split/editing commands for more +" vim/vi like consistency +" + implemented fix from Matt Perry +function! FindOrCreateBuffer(fileName, doSplit, findSimilar) + " Check to see if the buffer is already open before re-opening it. + let FILENAME = escape(a:fileName, ' ') + let bufNr = -1 + let lastBuffer = bufnr("$") + let i = 1 + if (a:findSimilar) + while i <= lastBuffer + if EqualFilePaths(expand("#".i.":p"), a:fileName) + let bufNr = i + break + endif + let i = i + 1 + endwhile + + if (bufNr == -1) + let bufName = bufname(a:fileName) + let bufFilename = fnamemodify(a:fileName,":t") + + if (bufName == "") + let bufName = bufname(bufFilename) + endif + + if (bufName != "") + let tail = fnamemodify(bufName, ":t") + if (tail != bufFilename) + let bufName = "" + endif + endif + if (bufName != "") + let bufNr = bufnr(bufName) + let FILENAME = bufName + endif + endif + endif + + if (g:alternateRelativeFiles == 1) + let FILENAME = fnamemodify(FILENAME, ":p:.") + endif + + let splitType = a:doSplit[0] + let bang = a:doSplit[1] + if (bufNr == -1) + " Buffer did not exist....create it + let v:errmsg="" + if (splitType == "h") + silent! execute ":split".bang." " . FILENAME + elseif (splitType == "v") + silent! execute ":vsplit".bang." " . FILENAME + elseif (splitType == "t") + silent! execute ":tab split".bang." " . FILENAME + else + silent! execute ":e".bang." " . FILENAME + endif + if (v:errmsg != "") + echo v:errmsg + endif + else + + " Find the correct tab corresponding to the existing buffer + let tabNr = -1 + " iterate tab pages + for i in range(tabpagenr('$')) + " get the list of buffers in the tab + let tabList = tabpagebuflist(i + 1) + let idx = 0 + " iterate each buffer in the list + while idx < len(tabList) + " if it matches the buffer we are looking for... + if (tabList[idx] == bufNr) + " ... save the number + let tabNr = i + 1 + break + endif + let idx = idx + 1 + endwhile + if (tabNr != -1) + break + endif + endfor + " switch the the tab containing the buffer + if (tabNr != -1) + execute "tabn ".tabNr + endif + + " Buffer was already open......check to see if it is in a window + let bufWindow = bufwinnr(bufNr) + if (bufWindow == -1) + " Buffer was not in a window so open one + let v:errmsg="" + if (splitType == "h") + silent! execute ":sbuffer".bang." " . FILENAME + elseif (splitType == "v") + silent! execute ":vert sbuffer " . FILENAME + elseif (splitType == "t") + silent! execute ":tab sbuffer " . FILENAME + else + silent! execute ":buffer".bang." " . FILENAME + endif + if (v:errmsg != "") + echo v:errmsg + endif + else + " Buffer is already in a window so switch to the window + execute bufWindow."wincmd w" + if (bufWindow != winnr()) + " something wierd happened...open the buffer + let v:errmsg="" + if (splitType == "h") + silent! execute ":split".bang." " . FILENAME + elseif (splitType == "v") + silent! execute ":vsplit".bang." " . FILENAME + elseif (splitType == "t") + silent! execute ":tab split".bang." " . FILENAME + else + silent! execute ":e".bang." " . FILENAME + endif + if (v:errmsg != "") + echo v:errmsg + endif + endif + endif + endif +endfunction + +" Function : EqualFilePaths (PRIVATE) +" Purpose : Compares two paths. Do simple string comparison anywhere but on +" Windows. On Windows take into account that file paths could differ +" in usage of separators and the fact that case does not matter. +" "c:\WINDOWS" is the same path as "c:/windows". has("win32unix") Vim +" version does not count as one having Windows path rules. +" Args : path1 (IN) -- first path +" path2 (IN) -- second path +" Returns : 1 if path1 is equal to path2, 0 otherwise. +" Author : Ilya Bobir +function! EqualFilePaths(path1, path2) + if has("win16") || has("win32") || has("win64") || has("win95") + return substitute(a:path1, "\/", "\\", "g") ==? substitute(a:path2, "\/", "\\", "g") + else + return a:path1 == a:path2 + endif +endfunction diff --git a/plugin/c.vim b/plugin/c.vim new file mode 100644 index 0000000..4d64275 --- /dev/null +++ b/plugin/c.vim @@ -0,0 +1,3753 @@ +"################################################################################# +" +" Filename: c.vim +" +" Description: C/C++-IDE. Write programs by inserting complete statements, +" comments, idioms, code snippets, templates and comments. +" Compile, link and run one-file-programs without a makefile. +" See also help file csupport.txt . +" +" GVIM Version: 7.0+ +" +" Configuration: There are some personal details which should be configured +" (see the files README.csupport and csupport.txt). +" +" Author: Dr.-Ing. Fritz Mehner, FH Südwestfalen, 58644 Iserlohn, Germany +" Email: mehner@fh-swf.de +" +" Version: see variable g:C_Version below +" Created: 04.11.2000 +" License: Copyright (c) 2000-2011, Fritz Mehner +" This program is free software; you can redistribute it and/or +" modify it under the terms of the GNU General Public License as +" published by the Free Software Foundation, version 2 of the +" License. +" This program is distributed in the hope that it will be +" useful, but WITHOUT ANY WARRANTY; without even the implied +" warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +" PURPOSE. +" See the GNU General Public License version 2 for more details. +" Revision: $Id: c.vim,v 1.156 2011/12/27 21:05:07 mehner Exp $ +" +"------------------------------------------------------------------------------ +" +if v:version < 700 + echohl WarningMsg | echo 'The plugin c-support.vim needs Vim version >= 7 .'| echohl None + finish +endif +" +" Prevent duplicate loading: +" +if exists("g:C_Version") || &cp + finish +endif +let g:C_Version= "5.17" " version number of this script; do not change +" +"################################################################################# +" +" Global variables (with default values) which can be overridden. +" +" Platform specific items: {{{1 +" - root directory +" - characters that must be escaped for filenames +" +let s:MSWIN = has("win16") || has("win32") || has("win64") || has("win95") +let s:UNIX = has("unix") || has("macunix") || has("win32unix") +" +let s:installation = '*undefined*' +let s:C_GlobalTemplateFile = '' +let s:C_GlobalTemplateDir = '' +let s:C_LocalTemplateFile = '' +let s:C_LocalTemplateDir = '' +let s:C_FilenameEscChar = '' + +if s:MSWIN + " ========== MS Windows ====================================================== + " + " change '\' to '/' to avoid interpretation as escape character + if match( substitute( expand(""), '\', '/', 'g' ), + \ substitute( expand("$HOME"), '\', '/', 'g' ) ) == 0 + " + " USER INSTALLATION ASSUMED + let s:installation = 'local' + let s:plugin_dir = substitute( expand(':p:h:h'), '\', '/', 'g' ) + let s:C_LocalTemplateFile = s:plugin_dir.'/c-support/templates/Templates' + let s:C_LocalTemplateDir = fnamemodify( s:C_LocalTemplateFile, ":p:h" ).'/' + else + " + " SYSTEM WIDE INSTALLATION + let s:installation = 'system' + let s:plugin_dir = $VIM.'/vimfiles' + let s:C_GlobalTemplateDir = s:plugin_dir.'/c-support/templates' + let s:C_GlobalTemplateFile = s:C_GlobalTemplateDir.'/Templates' + let s:C_LocalTemplateFile = $HOME.'/vimfiles/c-support/templates/Templates' + let s:C_LocalTemplateDir = fnamemodify( s:C_LocalTemplateFile, ":p:h" ).'/' + endif + " + let s:C_FilenameEscChar = '' + let s:C_Display = '' + " +else + " ========== Linux/Unix ====================================================== + " + if match( expand(""), expand("$HOME") ) == 0 + " + " USER INSTALLATION ASSUMED + let s:installation = 'local' + let s:plugin_dir = expand(':p:h:h') + let s:C_LocalTemplateFile = s:plugin_dir.'/c-support/templates/Templates' + let s:C_LocalTemplateDir = fnamemodify( s:C_LocalTemplateFile, ":p:h" ).'/' + else + " + " SYSTEM WIDE INSTALLATION + let s:installation = 'system' + let s:plugin_dir = $VIM.'/vimfiles' + let s:C_GlobalTemplateDir = s:plugin_dir.'/c-support/templates' + let s:C_GlobalTemplateFile = s:C_GlobalTemplateDir.'/Templates' + let s:C_LocalTemplateFile = $HOME.'/.vim/c-support/templates/Templates' + let s:C_LocalTemplateDir = fnamemodify( s:C_LocalTemplateFile, ":p:h" ).'/' + endif + " + let s:C_FilenameEscChar = ' \%#[]' + let s:C_Display = $DISPLAY + " +endif +" +let s:C_CodeSnippets = s:plugin_dir.'/c-support/codesnippets/' +let s:C_IndentErrorLog = $HOME.'/.indent.errorlog' +" +" Use of dictionaries {{{1 +" Key word completion is enabled by the filetype plugin 'c.vim' +" g:C_Dictionary_File must be global +" +if !exists("g:C_Dictionary_File") + let g:C_Dictionary_File = s:plugin_dir.'/c-support/wordlists/c-c++-keywords.list,'. + \ s:plugin_dir.'/c-support/wordlists/k+r.list,'. + \ s:plugin_dir.'/c-support/wordlists/stl_index.list' +endif +" +" Modul global variables (with default values) which can be overridden. {{{1 +" +if s:MSWIN + let s:C_CCompiler = 'gcc.exe' " the C compiler + let s:C_CplusCompiler = 'g++.exe' " the C++ compiler + let s:C_ExeExtension = '.exe' " file extension for executables (leading point required) + let s:C_ObjExtension = '.obj' " file extension for objects (leading point required) + let s:C_Man = 'man.exe' " the manual program +else + let s:C_CCompiler = 'gcc' " the C compiler + let s:C_CplusCompiler = 'g++' " the C++ compiler + let s:C_ExeExtension = '' " file extension for executables (leading point required) + let s:C_ObjExtension = '.o' " file extension for objects (leading point required) + let s:C_Man = 'man' " the manual program +endif +let s:C_VimCompilerName = 'gcc' " the compiler name used by :compiler +" +let s:C_CExtension = 'c' " C file extension; everything else is C++ +let s:C_CFlags = '-Wall -g -O0 -c' " compiler flags: compile, don't optimize +let s:C_CodeCheckExeName = 'check' +let s:C_CodeCheckOptions = '-K13' +let s:C_LFlags = '-Wall -g -O0' " compiler flags: link , don't optimize +let s:C_Libs = '-lm' " libraries to use +let s:C_LineEndCommColDefault = 49 +let s:C_LoadMenus = 'yes' +let s:C_CreateMenusDelayed = 'no' +let s:C_MenuHeader = 'yes' +let s:C_OutputGvim = 'vim' +let s:C_Printheader = "%<%f%h%m%< %=%{strftime('%x %X')} Page %N" +let s:C_Root = '&C\/C\+\+.' " the name of the root menu of this plugin +let s:C_TypeOfH = 'cpp' +let s:C_Wrapper = s:plugin_dir.'/c-support/scripts/wrapper.sh' +let s:C_XtermDefaults = '-fa courier -fs 12 -geometry 80x24' +let s:C_GuiSnippetBrowser = 'gui' " gui / commandline +let s:C_GuiTemplateBrowser = 'gui' " gui / explorer / commandline +" +let s:C_TemplateOverriddenMsg = 'no' +let s:C_Ctrl_j = 'on' +" +let s:C_FormatDate = '%x' +let s:C_FormatTime = '%X' +let s:C_FormatYear = '%Y' +let s:C_SourceCodeExtensions = 'c cc cp cxx cpp CPP c++ C i ii' +" +"------------------------------------------------------------------------------ +" +" Look for global variables (if any), to override the defaults. +" +function! C_CheckGlobal ( name ) + if exists('g:'.a:name) + exe 'let s:'.a:name.' = g:'.a:name + endif +endfunction " ---------- end of function C_CheckGlobal ---------- +" +call C_CheckGlobal('C_CCompiler ') +call C_CheckGlobal('C_CExtension ') +call C_CheckGlobal('C_CFlags ') +call C_CheckGlobal('C_CodeCheckExeName ') +call C_CheckGlobal('C_CodeCheckOptions ') +call C_CheckGlobal('C_CodeSnippets ') +call C_CheckGlobal('C_CplusCompiler ') +call C_CheckGlobal('C_Ctrl_j ') +call C_CheckGlobal('C_ExeExtension ') +call C_CheckGlobal('C_FormatDate ') +call C_CheckGlobal('C_FormatTime ') +call C_CheckGlobal('C_FormatYear ') +call C_CheckGlobal('C_GlobalTemplateFile ') +call C_CheckGlobal('C_GuiSnippetBrowser ') +call C_CheckGlobal('C_GuiTemplateBrowser ') +call C_CheckGlobal('C_IndentErrorLog ') +call C_CheckGlobal('C_LFlags ') +call C_CheckGlobal('C_Libs ') +call C_CheckGlobal('C_LineEndCommColDefault') +call C_CheckGlobal('C_LoadMenus ') +call C_CheckGlobal('C_CreateMenusDelayed ') +call C_CheckGlobal('C_LocalTemplateFile ') +call C_CheckGlobal('C_Man ') +call C_CheckGlobal('C_MenuHeader ') +call C_CheckGlobal('C_ObjExtension ') +call C_CheckGlobal('C_OutputGvim ') +call C_CheckGlobal('C_Printheader ') +call C_CheckGlobal('C_Root ') +call C_CheckGlobal('C_SourceCodeExtensions ') +call C_CheckGlobal('C_TemplateOverriddenMsg') +call C_CheckGlobal('C_TypeOfH ') +call C_CheckGlobal('C_VimCompilerName ') +call C_CheckGlobal('C_XtermDefaults ') + +if exists('g:C_GlobalTemplateFile') && !empty(g:C_GlobalTemplateFile) + let s:C_GlobalTemplateDir = fnamemodify( s:C_GlobalTemplateFile, ":h" ) +endif +" +"----- some variables for internal use only ----------------------------------- +" +" +" set default geometry if not specified +" +if match( s:C_XtermDefaults, "-geometry\\s\\+\\d\\+x\\d\\+" ) < 0 + let s:C_XtermDefaults = s:C_XtermDefaults." -geometry 80x24" +endif +" +" escape the printheader +" +let s:C_Printheader = escape( s:C_Printheader, ' %' ) +" +let s:C_HlMessage = "" +" +" characters that must be escaped for filenames +" +let s:C_If0_Counter = 0 +let s:C_If0_Txt = "If0Label_" +" +let s:C_SplintIsExecutable = 0 +if executable( "splint" ) + let s:C_SplintIsExecutable = 1 +endif +" +let s:C_CodeCheckIsExecutable = 0 +if executable( s:C_CodeCheckExeName ) + let s:C_CodeCheckIsExecutable = 1 +endif +" +"------------------------------------------------------------------------------ +" Control variables (not user configurable) +"------------------------------------------------------------------------------ +let s:Attribute = { 'below':'', 'above':'', 'start':'', 'append':'', 'insert':'' } +let s:C_Attribute = {} +let s:C_ExpansionLimit = 10 +let s:C_FileVisited = [] +" +let s:C_MacroNameRegex = '\([a-zA-Z][a-zA-Z0-9_]*\)' +let s:C_MacroLineRegex = '^\s*|'.s:C_MacroNameRegex.'|\s*=\s*\(.*\)' +let s:C_MacroCommentRegex = '^\$' +let s:C_ExpansionRegex = '|?'.s:C_MacroNameRegex.'\(:\a\)\?|' +let s:C_NonExpansionRegex = '|'.s:C_MacroNameRegex.'\(:\a\)\?|' +" +let s:C_TemplateNameDelimiter = '-+_,\. ' +let s:C_TemplateLineRegex = '^==\s*\([a-zA-Z][0-9a-zA-Z'.s:C_TemplateNameDelimiter +let s:C_TemplateLineRegex .= ']\+\)\s*==\s*\([a-z]\+\s*==\)\?' +let s:C_TemplateIf = '^==\s*IF\s\+|STYLE|\s\+IS\s\+'.s:C_MacroNameRegex.'\s*==' +let s:C_TemplateEndif = '^==\s*ENDIF\s*==' +" +let s:C_Com1 = '/*' " C-style : comment start +let s:C_Com2 = '*/' " C-style : comment end +" +let s:C_ExpansionCounter = {} +let s:C_TJT = '[ 0-9a-zA-Z_]*' +let s:C_TemplateJumpTarget1 = '<+'.s:C_TJT.'+>\|{+'.s:C_TJT.'+}' +let s:C_TemplateJumpTarget2 = '<-'.s:C_TJT.'->\|{-'.s:C_TJT.'-}' +let s:C_Macro = {'|AUTHOR|' : 'first name surname', + \ '|AUTHORREF|' : '', + \ '|COMPANY|' : '', + \ '|COPYRIGHTHOLDER|': '', + \ '|EMAIL|' : '', + \ '|LICENSE|' : 'GNU General Public License', + \ '|ORGANIZATION|' : '', + \ '|PROJECT|' : '', + \ '|STYLE|' : '' + \ } +let s:C_MacroFlag = { ':l' : 'lowercase' , + \ ':u' : 'uppercase' , + \ ':c' : 'capitalize' , + \ ':L' : 'legalize name' , + \ } +let s:C_ActualStyle = 'default' +let s:C_ActualStyleLast = s:C_ActualStyle +let s:C_Template = { 'default' : {} } +let s:C_TemplatesLoaded = 'no' + +let s:C_ForTypes = [ + \ 'char' , + \ 'int' , + \ 'long' , + \ 'long int' , + \ 'long long' , + \ 'long long int' , + \ 'short' , + \ 'short int' , + \ 'size_t' , + \ 'unsigned' , + \ 'unsigned char' , + \ 'unsigned int' , + \ 'unsigned long' , + \ 'unsigned long int' , + \ 'unsigned long long' , + \ 'unsigned long long int', + \ 'unsigned short' , + \ 'unsigned short int' , + \ ] + +let s:C_ForTypes_Check_Order = [ + \ 'char' , + \ 'int' , + \ 'long long int' , + \ 'long long' , + \ 'long int' , + \ 'long' , + \ 'short int' , + \ 'short' , + \ 'size_t' , + \ 'unsigned short int' , + \ 'unsigned short' , + \ 'unsigned long long int', + \ 'unsigned long long' , + \ 'unsigned long int' , + \ 'unsigned long' , + \ 'unsigned int' , + \ 'unsigned char' , + \ 'unsigned' , + \ ] + +let s:MsgInsNotAvail = "insertion not available for a fold" +let s:MenuRun = s:C_Root.'&Run' + +"------------------------------------------------------------------------------ + +let s:C_SourceCodeExtensionsList = split( s:C_SourceCodeExtensions, '\s\+' ) + +"------------------------------------------------------------------------------ + +"------------------------------------------------------------------------------ +" C : C_InitMenus {{{1 +" Initialization of C support menus +"------------------------------------------------------------------------------ +" +function! C_InitMenus () +" +" the menu names +" + let MenuComments = s:C_Root.'&Comments' + let MenuStatements = s:C_Root.'&Statements' + let MenuIdioms = s:C_Root.'&Idioms' + let MenuPreprocessor = s:C_Root.'&Preprocessor' + let MenuSnippets = s:C_Root.'S&nippets' + let MenuCpp = s:C_Root.'C&++' + " + "=============================================================================================== + "----- Menu : C main menu entry ------------------------------------------- {{{2 + "=============================================================================================== + " + if s:C_MenuHeader == 'yes' + exe "amenu ".s:C_Root.'C\/C\+\+ :call C_MenuTitle()' + exe "amenu ".s:C_Root.'-Sep00- ' + exe "amenu ".MenuComments.'.&CommentsC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuComments.'.-Sep00- ' + exe "amenu ".MenuStatements.'.&StatementsC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuStatements.'.-Sep00- ' + exe "amenu ".MenuIdioms.'.&IdiomsC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuIdioms.'.-Sep00- ' + exe "amenu ".MenuPreprocessor.'.&PreprocessorC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuPreprocessor.'.-Sep00- ' + exe "amenu ".MenuPreprocessor.'.#include\ &Std\.Lib\.\\ps.Std\.Lib\.C\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuPreprocessor.'.#include\ &Std\.Lib\.\\ps.-Sep0- ' + exe "amenu ".MenuPreprocessor.'.#include\ C&99\\pc.C99C\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuPreprocessor.'.#include\ C&99\\pc.-Sep0- ' + exe "amenu ".MenuSnippets.'.S&nippetsC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuSnippets.'.-Sep00- ' + exe "amenu ".MenuCpp.'.C&\+\+C\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuCpp.'.-Sep00- ' + exe "amenu ".s:MenuRun.'.&RunC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".s:MenuRun.'.-Sep00- ' + endif + " + "=============================================================================================== + "----- Menu : C-Comments -------------------------------------------------- {{{2 + "=============================================================================================== + " + exe "amenu ".MenuComments.'.end-of-&line\ comment\\cl :call C_EndOfLineComment( )' + exe "vmenu ".MenuComments.'.end-of-&line\ comment\\cl :call C_EndOfLineComment( )' + + exe "amenu ".MenuComments.'.ad&just\ end-of-line\ com\.\\cj :call C_AdjustLineEndComm()' + exe "vmenu ".MenuComments.'.ad&just\ end-of-line\ com\.\\cj :call C_AdjustLineEndComm()' + + exe "amenu ".MenuComments.'.&set\ end-of-line\ com\.\ col\.\\cs :call C_GetLineEndCommCol()' + + exe "amenu ".MenuComments.'.-SEP10- :' + exe "amenu ".MenuComments.'.code\ ->\ comment\ \/&*\ *\/\\c* :call C_CodeToCommentC():nohlsearchj' + exe "vmenu ".MenuComments.'.code\ ->\ comment\ \/&*\ *\/\\c* :call C_CodeToCommentC():nohlsearchj' + exe "amenu ".MenuComments.'.code\ ->\ comment\ &\/\/\\cc :call C_CodeToCommentCpp():nohlsearchj' + exe "vmenu ".MenuComments.'.code\ ->\ comment\ &\/\/\\cc :call C_CodeToCommentCpp():nohlsearchj' + exe "amenu ".MenuComments.'.c&omment\ ->\ code\\co :call C_CommentToCode():nohlsearch' + exe "vmenu ".MenuComments.'.c&omment\ ->\ code\\co :call C_CommentToCode():nohlsearch' + + exe "amenu ".MenuComments.'.-SEP0- :' + exe "amenu ".MenuComments.'.&frame\ comment\\cfr :call C_InsertTemplate("comment.frame")' + exe "amenu ".MenuComments.'.f&unction\ description\\cfu :call C_InsertTemplate("comment.function")' + exe "amenu ".MenuComments.'.-SEP1- :' + exe "amenu ".MenuComments.'.&method\ description\\cme :call C_InsertTemplate("comment.method")' + exe "amenu ".MenuComments.'.cl&ass\ description\\ccl :call C_InsertTemplate("comment.class")' + exe "amenu ".MenuComments.'.-SEP2- :' + exe "amenu ".MenuComments.'.file\ description\ \(impl\.\)\\cfdi :call C_InsertTemplate("comment.file-description")' + exe "amenu ".MenuComments.'.file\ description\ \(header\)\\cfdh :call C_InsertTemplate("comment.file-description-header")' + exe "amenu ".MenuComments.'.-SEP3- :' + " + "----- Submenu : C-Comments : file sections ------------------------------------------------------------- + " + if s:C_MenuHeader == 'yes' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.file\ sectionsC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.-Sep0- ' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.H-file\ sectionsC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.-Sep0- ' + exe "amenu ".MenuComments.'.-SEP4- :' + exe "amenu ".MenuComments.'.&keyword\ comm\.\\ckc.keyw\.+comm\.C\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuComments.'.&keyword\ comm\.\\ckc.-Sep0- ' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.special\ comm\.C\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.-Sep0- ' + exe "amenu ".MenuComments.'.ta&gs\ (plugin).tags\ (plugin)C\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuComments.'.ta&gs\ (plugin).-Sep0- ' + endif + " + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.&Header\ File\ Includes :call C_InsertTemplate("comment.file-section-cpp-header-includes")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.Local\ &Macros :call C_InsertTemplate("comment.file-section-cpp-macros")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.Local\ &Type\ Def\. :call C_InsertTemplate("comment.file-section-cpp-typedefs")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.Local\ &Data\ Types :call C_InsertTemplate("comment.file-section-cpp-data-types")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.Local\ &Variables :call C_InsertTemplate("comment.file-section-cpp-local-variables")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.Local\ &Prototypes :call C_InsertTemplate("comment.file-section-cpp-prototypes")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.&Exp\.\ Function\ Def\. :call C_InsertTemplate("comment.file-section-cpp-function-defs-exported")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.&Local\ Function\ Def\. :call C_InsertTemplate("comment.file-section-cpp-function-defs-local")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.-SEP6- :' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.Local\ &Class\ Def\. :call C_InsertTemplate("comment.file-section-cpp-class-defs")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.E&xp\.\ Class\ Impl\. :call C_InsertTemplate("comment.file-section-cpp-class-implementations-exported")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.L&ocal\ Class\ Impl\. :call C_InsertTemplate("comment.file-section-cpp-class-implementations-local")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.-SEP7- :' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.&All\ sections,\ C :call C_Comment_C_SectionAll("c")' + exe "amenu ".MenuComments.'.&C\/C\+\+-file\ sections\\ccs.All\ §ions,\ C++ :call C_Comment_C_SectionAll("cpp")' + " + "----- Submenu : H-Comments : file sections ------------------------------------------------------------- + " + "' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.&Header\ File\ Includes :call C_InsertTemplate("comment.file-section-hpp-header-includes")' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.Exported\ &Macros :call C_InsertTemplate("comment.file-section-hpp-macros")' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.Exported\ &Type\ Def\. :call C_InsertTemplate("comment.file-section-hpp-exported-typedefs")' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.Exported\ &Data\ Types :call C_InsertTemplate("comment.file-section-hpp-exported-data-types")' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.Exported\ &Variables :call C_InsertTemplate("comment.file-section-hpp-exported-variables")' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.Exported\ &Funct\.\ Decl\. :call C_InsertTemplate("comment.file-section-hpp-exported-function-declarations")' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.-SEP4- :' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.E&xported\ Class\ Def\. :call C_InsertTemplate("comment.file-section-hpp-exported-class-defs")' + + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.-SEP5- :' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.&All\ sections,\ C :call C_Comment_H_SectionAll("c")' + exe "amenu ".MenuComments.'.&H-file\ sections\\chs.All\ §ions,\ C++ :call C_Comment_H_SectionAll("cpp")' + " + exe "amenu ".MenuComments.'.-SEP8- :' + " + "----- Submenu : C-Comments : keyword comments ---------------------------------------------------------- + " +" + exe "amenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:&BUG\: $:call C_InsertTemplate("comment.keyword-bug")' + exe "amenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:&COMPILER\: $:call C_InsertTemplate("comment.keyword-compiler")' + exe "amenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:&TODO\: $:call C_InsertTemplate("comment.keyword-todo")' + exe "amenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:&WARNING\: $:call C_InsertTemplate("comment.keyword-warning")' + exe "amenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:W&ORKAROUND\: $:call C_InsertTemplate("comment.keyword-workaround")' + exe "amenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:&new\ keyword\: $:call C_InsertTemplate("comment.keyword-keyword")' +" + exe "imenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:&BUG\: $:call C_InsertTemplate("comment.keyword-bug")' + exe "imenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:&COMPILER\: $:call C_InsertTemplate("comment.keyword-compiler")' + exe "imenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:&TODO\: $:call C_InsertTemplate("comment.keyword-todo")' + exe "imenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:&WARNING\: $:call C_InsertTemplate("comment.keyword-warning")' + exe "imenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:W&ORKAROUND\: $:call C_InsertTemplate("comment.keyword-workaround")' + exe "imenu ".MenuComments.'.&keyword\ comm\.\\ckc.\:&new\ keyword\: $:call C_InsertTemplate("comment.keyword-keyword")' + " + "----- Submenu : C-Comments : special comments ---------------------------------------------------------- + " + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.&EMPTY $:call C_InsertTemplate("comment.special-empty")' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.&FALL\ THROUGH $:call C_InsertTemplate("comment.special-fall-through") ' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.&IMPL\.\ TYPE\ CONV $:call C_InsertTemplate("comment.special-implicit-type-conversion") ' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.&NO\ RETURN $:call C_InsertTemplate("comment.special-no-return") ' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.NOT\ &REACHED $:call C_InsertTemplate("comment.special-not-reached") ' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.&TO\ BE\ IMPL\. $:call C_InsertTemplate("comment.special-remains-to-be-implemented")' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.-SEP81- :' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.constant\ type\ is\ &long\ (L) $:call C_InsertTemplate("comment.special-constant-type-is-long")' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.constant\ type\ is\ &unsigned\ (U) $:call C_InsertTemplate("comment.special-constant-type-is-unsigned")' + exe "amenu ".MenuComments.'.&special\ comm\.\\csc.constant\ type\ is\ unsigned\ l&ong\ (UL) $:call C_InsertTemplate("comment.special-constant-type-is-unsigned-long")' + " + exe "imenu ".MenuComments.'.&special\ comm\.\\csc.&EMPTY $:call C_InsertTemplate("comment.special-empty")' + exe "imenu ".MenuComments.'.&special\ comm\.\\csc.&FALL\ THROUGH $:call C_InsertTemplate("comment.special-fall-through") ' + exe "imenu ".MenuComments.'.&special\ comm\.\\csc.&IMPL\.\ TYPE\ CONV $:call C_InsertTemplate("comment.special-implicit-type-conversion") ' + exe "imenu ".MenuComments.'.&special\ comm\.\\csc.&NO\ RETURN $:call C_InsertTemplate("comment.special-no-return") ' + exe "imenu ".MenuComments.'.&special\ comm\.\\csc.NOT\ &REACHED $:call C_InsertTemplate("comment.special-not-reached") ' + exe "imenu ".MenuComments.'.&special\ comm\.\\csc.&TO\ BE\ IMPL\. $:call C_InsertTemplate("comment.special-remains-to-be-implemented")' + exe "imenu ".MenuComments.'.&special\ comm\.\\csc.-SEP81- :' + exe "imenu ".MenuComments.'.&special\ comm\.\\csc.constant\ type\ is\ &long\ (L) $:call C_InsertTemplate("comment.special-constant-type-is-long")' + exe "imenu ".MenuComments.'.&special\ comm\.\\csc.constant\ type\ is\ &unsigned\ (U) $:call C_InsertTemplate("comment.special-constant-type-is-unsigned")' + exe "imenu ".MenuComments.'.&special\ comm\.\\csc.constant\ type\ is\ unsigned\ l&ong\ (UL) $:call C_InsertTemplate("comment.special-constant-type-is-unsigned-long")' + " + "----- Submenu : C-Comments : Tags ---------------------------------------------------------- + " + " + exe "anoremenu ".MenuComments.'.ta&gs\ (plugin).&AUTHOR :call C_InsertMacroValue("AUTHOR")' + exe "anoremenu ".MenuComments.'.ta&gs\ (plugin).&AUTHORREF :call C_InsertMacroValue("AUTHORREF")' + exe "anoremenu ".MenuComments.'.ta&gs\ (plugin).&COMPANY :call C_InsertMacroValue("COMPANY")' + exe "anoremenu ".MenuComments.'.ta&gs\ (plugin).©RIGHTHOLDER :call C_InsertMacroValue("COPYRIGHTHOLDER")' + exe "anoremenu ".MenuComments.'.ta&gs\ (plugin).&EMAIL :call C_InsertMacroValue("EMAIL")' + exe "anoremenu ".MenuComments.'.ta&gs\ (plugin).&LICENSE :call C_InsertMacroValue("LICENSE")' + exe "anoremenu ".MenuComments.'.ta&gs\ (plugin).&ORGANIZATION :call C_InsertMacroValue("ORGANIZATION")' + exe "anoremenu ".MenuComments.'.ta&gs\ (plugin).&PROJECT :call C_InsertMacroValue("PROJECT")' + " + exe "inoremenu ".MenuComments.'.ta&gs\ (plugin).&AUTHOR :call C_InsertMacroValue("AUTHOR")a' + exe "inoremenu ".MenuComments.'.ta&gs\ (plugin).&AUTHORREF :call C_InsertMacroValue("AUTHORREF")a' + exe "inoremenu ".MenuComments.'.ta&gs\ (plugin).&COMPANY :call C_InsertMacroValue("COMPANY")a' + exe "inoremenu ".MenuComments.'.ta&gs\ (plugin).©RIGHTHOLDER :call C_InsertMacroValue("COPYRIGHTHOLDER")a' + exe "inoremenu ".MenuComments.'.ta&gs\ (plugin).&EMAIL :call C_InsertMacroValue("EMAIL")a' + exe "inoremenu ".MenuComments.'.ta&gs\ (plugin).&LICENSE :call C_InsertMacroValue("LICENSE")a' + exe "inoremenu ".MenuComments.'.ta&gs\ (plugin).&ORGANIZATION :call C_InsertMacroValue("ORGANIZATION")a' + exe "inoremenu ".MenuComments.'.ta&gs\ (plugin).&PROJECT :call C_InsertMacroValue("PROJECT")a' + " + exe "vnoremenu ".MenuComments.'.ta&gs\ (plugin).&AUTHOR s:call C_InsertMacroValue("AUTHOR")a' + exe "vnoremenu ".MenuComments.'.ta&gs\ (plugin).&AUTHORREF s:call C_InsertMacroValue("AUTHORREF")a' + exe "vnoremenu ".MenuComments.'.ta&gs\ (plugin).&COMPANY s:call C_InsertMacroValue("COMPANY")a' + exe "vnoremenu ".MenuComments.'.ta&gs\ (plugin).©RIGHTHOLDER s:call C_InsertMacroValue("COPYRIGHTHOLDER")a' + exe "vnoremenu ".MenuComments.'.ta&gs\ (plugin).&EMAIL s:call C_InsertMacroValue("EMAIL")a' + exe "vnoremenu ".MenuComments.'.ta&gs\ (plugin).&LICENSE s:call C_InsertMacroValue("LICENSE")a' + exe "vnoremenu ".MenuComments.'.ta&gs\ (plugin).&ORGANIZATION s:call C_InsertMacroValue("ORGANIZATION")a' + exe "vnoremenu ".MenuComments.'.ta&gs\ (plugin).&PROJECT s:call C_InsertMacroValue("PROJECT")a' + " + exe " menu ".MenuComments.'.&date\\cd :call C_InsertDateAndTime("d")' + exe "imenu ".MenuComments.'.&date\\cd :call C_InsertDateAndTime("d")a' + exe "vmenu ".MenuComments.'.&date\\cd s:call C_InsertDateAndTime("d")a' + exe " menu ".MenuComments.'.date\ &time\\ct :call C_InsertDateAndTime("dt")' + exe "imenu ".MenuComments.'.date\ &time\\ct :call C_InsertDateAndTime("dt")a' + exe "vmenu ".MenuComments.'.date\ &time\\ct s:call C_InsertDateAndTime("dt")a' + + exe "amenu ".MenuComments.'.-SEP12- :' + exe "amenu ".MenuComments.'.\/*\ &xxx\ *\/\ \ <->\ \ \/\/\ xxx\\cx :call C_CommentToggle()' + exe "vmenu ".MenuComments.'.\/*\ &xxx\ *\/\ \ <->\ \ \/\/\ xxx\\cx :call C_CommentToggle()' + " + "=============================================================================================== + "----- Menu : C-Statements------------------------------------------------- {{{2 + "=============================================================================================== + " + exe "amenu ".MenuStatements.'.&do\ \{\ \}\ while\\sd :call C_InsertTemplate("statements.do-while")' + exe "vmenu ".MenuStatements.'.&do\ \{\ \}\ while\\sd :call C_InsertTemplate("statements.do-while", "v")' + exe "imenu ".MenuStatements.'.&do\ \{\ \}\ while\\sd :call C_InsertTemplate("statements.do-while")' + " + exe "amenu ".MenuStatements.'.f&or\\sf :call C_InsertTemplate("statements.for")' + exe "imenu ".MenuStatements.'.f&or\\sf :call C_InsertTemplate("statements.for")' + " + exe "amenu ".MenuStatements.'.fo&r\ \{\ \}\\sfo :call C_InsertTemplate("statements.for-block")' + exe "vmenu ".MenuStatements.'.fo&r\ \{\ \}\\sfo :call C_InsertTemplate("statements.for-block", "v")' + exe "imenu ".MenuStatements.'.fo&r\ \{\ \}\\sfo :call C_InsertTemplate("statements.for-block")' + " + exe "amenu ".MenuStatements.'.&if\\si :call C_InsertTemplate("statements.if")' + exe "imenu ".MenuStatements.'.&if\\si :call C_InsertTemplate("statements.if")' + " + exe "amenu ".MenuStatements.'.i&f\ \{\ \}\\sif :call C_InsertTemplate("statements.if-block")' + exe "vmenu ".MenuStatements.'.i&f\ \{\ \}\\sif :call C_InsertTemplate("statements.if-block", "v")' + exe "imenu ".MenuStatements.'.i&f\ \{\ \}\\sif :call C_InsertTemplate("statements.if-block")' + + exe "amenu ".MenuStatements.'.if\ &else\\sie :call C_InsertTemplate("statements.if-else")' + exe "vmenu ".MenuStatements.'.if\ &else\\sie :call C_InsertTemplate("statements.if-else", "v")' + exe "imenu ".MenuStatements.'.if\ &else\\sie :call C_InsertTemplate("statements.if-else")' + " + exe "amenu ".MenuStatements.'.if\ \{\ \}\ e&lse\ \{\ \}\\sife :call C_InsertTemplate("statements.if-block-else")' + exe "vmenu ".MenuStatements.'.if\ \{\ \}\ e&lse\ \{\ \}\\sife :call C_InsertTemplate("statements.if-block-else", "v")' + exe "imenu ".MenuStatements.'.if\ \{\ \}\ e&lse\ \{\ \}\\sife :call C_InsertTemplate("statements.if-block-else")' + " + exe "amenu ".MenuStatements.'.&else\ \{\ \}\\se :call C_InsertTemplate("statements.else-block")' + exe "vmenu ".MenuStatements.'.&else\ \{\ \}\\se :call C_InsertTemplate("statements.else-block", "v")' + exe "imenu ".MenuStatements.'.&else\ \{\ \}\\se :call C_InsertTemplate("statements.else-block")' + " + exe "amenu ".MenuStatements.'.&while\\sw :call C_InsertTemplate("statements.while")' + exe "imenu ".MenuStatements.'.&while\\sw :call C_InsertTemplate("statements.while")' + " + exe "amenu ".MenuStatements.'.w&hile\ \{\ \}\\swh :call C_InsertTemplate("statements.while-block")' + exe "vmenu ".MenuStatements.'.w&hile\ \{\ \}\\swh :call C_InsertTemplate("statements.while-block", "v")' + exe "imenu ".MenuStatements.'.w&hile\ \{\ \}\\swh :call C_InsertTemplate("statements.while-block")' + " + exe "amenu ".MenuStatements.'.&switch\ \{\ \}\\ss :call C_InsertTemplate("statements.switch")' + exe "vmenu ".MenuStatements.'.&switch\ \{\ \}\\ss :call C_InsertTemplate("statements.switch", "v")' + exe "imenu ".MenuStatements.'.&switch\ \{\ \}\\ss :call C_InsertTemplate("statements.switch")' + " + exe "amenu ".MenuStatements.'.&case\ \.\.\.\ break\\sc :call C_InsertTemplate("statements.case")' + exe "imenu ".MenuStatements.'.&case\ \.\.\.\ break\\sc :call C_InsertTemplate("statements.case")' + " + " + exe "amenu ".MenuStatements.'.&\{\ \}\\sb :call C_InsertTemplate("statements.block")' + exe "vmenu ".MenuStatements.'.&\{\ \}\\sb :call C_InsertTemplate("statements.block", "v")' + exe "imenu ".MenuStatements.'.&\{\ \}\\sb :call C_InsertTemplate("statements.block")' + " + " + "=============================================================================================== + "----- Menu : C-Idioms ---------------------------------------------------- {{{2 + "=============================================================================================== + " + exe "amenu ".MenuIdioms.'.&function\\if :call C_InsertTemplate("idioms.function")' + exe "vmenu ".MenuIdioms.'.&function\\if :call C_InsertTemplate("idioms.function", "v")' + exe "imenu ".MenuIdioms.'.&function\\if :call C_InsertTemplate("idioms.function")' + exe "amenu ".MenuIdioms.'.s&tatic\ function\\isf :call C_InsertTemplate("idioms.function-static")' + exe "vmenu ".MenuIdioms.'.s&tatic\ function\\isf :call C_InsertTemplate("idioms.function-static", "v")' + exe "imenu ".MenuIdioms.'.s&tatic\ function\\isf :call C_InsertTemplate("idioms.function-static")' + exe "amenu ".MenuIdioms.'.&main\\im :call C_InsertTemplate("idioms.main")' + exe "vmenu ".MenuIdioms.'.&main\\im :call C_InsertTemplate("idioms.main", "v")' + exe "imenu ".MenuIdioms.'.&main\\im :call C_InsertTemplate("idioms.main")' + + exe "amenu ".MenuIdioms.'.-SEP1- :' + exe "amenu ".MenuIdioms.'.for(x=&0;\ x\\i0 :call C_CodeFor("up" )' + exe "vmenu ".MenuIdioms.'.for(x=&0;\ x\\i0 :call C_CodeFor("up" )' + exe "imenu ".MenuIdioms.'.for(x=&0;\ x\\i0 :call C_CodeFor("up" )i' + exe "amenu ".MenuIdioms.'.for(x=&n-1;\ x>=0;\ x\-=1)\\in :call C_CodeFor("down")' + exe "vmenu ".MenuIdioms.'.for(x=&n-1;\ x>=0;\ x\-=1)\\in :call C_CodeFor("down")' + exe "imenu ".MenuIdioms.'.for(x=&n-1;\ x>=0;\ x\-=1)\\in :call C_CodeFor("down")i' + + exe "amenu ".MenuIdioms.'.-SEP2- :' + exe "amenu ".MenuIdioms.'.&enum\\ie :call C_InsertTemplate("idioms.enum")' + exe "vmenu ".MenuIdioms.'.&enum\\ie :call C_InsertTemplate("idioms.enum" , "v")' + exe "imenu ".MenuIdioms.'.&enum\\ie :call C_InsertTemplate("idioms.enum" )' + exe "amenu ".MenuIdioms.'.&struct\\is :call C_InsertTemplate("idioms.struct")' + exe "vmenu ".MenuIdioms.'.&struct\\is :call C_InsertTemplate("idioms.struct", "v")' + exe "imenu ".MenuIdioms.'.&struct\\is :call C_InsertTemplate("idioms.struct")' + exe "amenu ".MenuIdioms.'.&union\\iu :call C_InsertTemplate("idioms.union")' + exe "vmenu ".MenuIdioms.'.&union\\iu :call C_InsertTemplate("idioms.union" , "v")' + exe "imenu ".MenuIdioms.'.&union\\iu :call C_InsertTemplate("idioms.union" )' + exe "amenu ".MenuIdioms.'.-SEP3- :' + " + exe "amenu ".MenuIdioms.'.&scanf\\isc :call C_InsertTemplate("idioms.scanf")' + exe "imenu ".MenuIdioms.'.&scanf\\isc :call C_InsertTemplate("idioms.scanf")' + exe "amenu ".MenuIdioms.'.&printf\\ip :call C_InsertTemplate("idioms.printf")' + exe "imenu ".MenuIdioms.'.&printf\\ip :call C_InsertTemplate("idioms.printf")' + " + exe "amenu ".MenuIdioms.'.-SEP4- :' + exe "amenu ".MenuIdioms.'.p=&calloc\(n,sizeof(type)\)\\ica :call C_InsertTemplate("idioms.calloc")' + exe "imenu ".MenuIdioms.'.p=&calloc\(n,sizeof(type)\)\\ica :call C_InsertTemplate("idioms.calloc")' + exe "amenu ".MenuIdioms.'.p=&malloc\(sizeof(type)\)\\ima :call C_InsertTemplate("idioms.malloc")' + exe "imenu ".MenuIdioms.'.p=&malloc\(sizeof(type)\)\\ima :call C_InsertTemplate("idioms.malloc")' + exe "amenu ".MenuIdioms.'.p=&realloc\(p,sizeof(type)\)\\ire :call C_InsertTemplate("idioms.realloc")' + exe "imenu ".MenuIdioms.'.p=&realloc\(p,sizeof(type)\)\\ire :call C_InsertTemplate("idioms.realloc")' + " + exe "anoremenu ".MenuIdioms.'.&sizeof(\ \)\\isi :call C_InsertTemplate("idioms.sizeof")' + exe "inoremenu ".MenuIdioms.'.&sizeof(\ \)\\isi :call C_InsertTemplate("idioms.sizeof")' + exe "vnoremenu ".MenuIdioms.'.&sizeof(\ \)\\isi :call C_InsertTemplate("idioms.sizeof", "v")' + " + exe "anoremenu ".MenuIdioms.'.&assert(\ \)\\ias :call C_InsertTemplate("idioms.assert")' + exe "inoremenu ".MenuIdioms.'.&assert(\ \)\\ias :call C_InsertTemplate("idioms.assert")' + exe "vnoremenu ".MenuIdioms.'.&assert(\ \)\\ias :call C_InsertTemplate("idioms.assert", "v")' + + exe "amenu ".MenuIdioms.'.-SEP5- :' + exe "amenu ".MenuIdioms.'.open\ &input\ file\\ii :call C_InsertTemplate("idioms.open-input-file")' + exe "imenu ".MenuIdioms.'.open\ &input\ file\\ii :call C_InsertTemplate("idioms.open-input-file")' + exe "vmenu ".MenuIdioms.'.open\ &input\ file\\ii :call C_InsertTemplate("idioms.open-input-file", "v")' + exe "amenu ".MenuIdioms.'.open\ &output\ file\\io :call C_InsertTemplate("idioms.open-output-file")' + exe "imenu ".MenuIdioms.'.open\ &output\ file\\io :call C_InsertTemplate("idioms.open-output-file")' + exe "vmenu ".MenuIdioms.'.open\ &output\ file\\io :call C_InsertTemplate("idioms.open-output-file", "v")' + " + exe "amenu ".MenuIdioms.'.fscanf\\ifs :call C_InsertTemplate("idioms.fscanf")' + exe "imenu ".MenuIdioms.'.fscanf\\ifs :call C_InsertTemplate("idioms.fscanf")' + exe "amenu ".MenuIdioms.'.fprintf\\ifp :call C_InsertTemplate("idioms.fprintf")' + exe "imenu ".MenuIdioms.'.fprintf\\ifp :call C_InsertTemplate("idioms.fprintf")' + " + "=============================================================================================== + "----- Menu : C-Preprocessor ---------------------------------------------- {{{2 + "=============================================================================================== + " + "----- Submenu : C-Idioms: standard library ------------------------------------------------------- + "' + call C_CIncludeMenus ( MenuPreprocessor.'.#include\ &Std\.Lib\.\\ps', s:C_StandardLibs ) + " + call C_CIncludeMenus ( MenuPreprocessor.'.#include\ C&99\\pc', s:C_C99Libs ) + " + exe "amenu ".MenuPreprocessor.'.-SEP2- :' + exe "anoremenu ".MenuPreprocessor.'.#include\ &\<\.\.\.\>\\p< :call C_InsertTemplate("preprocessor.include-global")' + exe "inoremenu ".MenuPreprocessor.'.#include\ &\<\.\.\.\>\\p< :call C_InsertTemplate("preprocessor.include-global")' + exe "anoremenu ".MenuPreprocessor.'.#include\ &\"\.\.\.\"\\p" :call C_InsertTemplate("preprocessor.include-local")' + exe "inoremenu ".MenuPreprocessor.'.#include\ &\"\.\.\.\"\\p" :call C_InsertTemplate("preprocessor.include-local")' + exe "amenu ".MenuPreprocessor.'.#&define\\pd :call C_InsertTemplate("preprocessor.define")' + exe "imenu ".MenuPreprocessor.'.#&define\\pd :call C_InsertTemplate("preprocessor.define")' + exe "amenu ".MenuPreprocessor.'.&#undef\\pu :call C_InsertTemplate("preprocessor.undefine")' + exe "imenu ".MenuPreprocessor.'.&#undef\\pu :call C_InsertTemplate("preprocessor.undefine")' + " + exe "amenu ".MenuPreprocessor.'.#&if\ #endif\\pif :call C_InsertTemplate("preprocessor.if-endif")' + exe "imenu ".MenuPreprocessor.'.#&if\ #endif\\pif :call C_InsertTemplate("preprocessor.if-endif")' + exe "vmenu ".MenuPreprocessor.'.#&if\ #endif\\pif :call C_InsertTemplate("preprocessor.if-endif", "v")' + exe "amenu ".MenuPreprocessor.'.#&if\ #else\ #endif\\pie :call C_InsertTemplate("preprocessor.if-else-endif")' + exe "imenu ".MenuPreprocessor.'.#&if\ #else\ #endif\\pie :call C_InsertTemplate("preprocessor.if-else-endif")' + exe "vmenu ".MenuPreprocessor.'.#&if\ #else\ #endif\\pie :call C_InsertTemplate("preprocessor.if-else-endif", "v")' + exe "amenu ".MenuPreprocessor.'.#i&fdef\ #else\ #endif\\pid :call C_InsertTemplate("preprocessor.ifdef-else-endif")' + exe "imenu ".MenuPreprocessor.'.#i&fdef\ #else\ #endif\\pid :call C_InsertTemplate("preprocessor.ifdef-else-endif")' + exe "vmenu ".MenuPreprocessor.'.#i&fdef\ #else\ #endif\\pid :call C_InsertTemplate("preprocessor.ifdef-else-endif", "v")' + exe "amenu ".MenuPreprocessor.'.#if&ndef\ #else\ #endif\\pin :call C_InsertTemplate("preprocessor.ifndef-else-endif")' + exe "imenu ".MenuPreprocessor.'.#if&ndef\ #else\ #endif\\pin :call C_InsertTemplate("preprocessor.ifndef-else-endif")' + exe "vmenu ".MenuPreprocessor.'.#if&ndef\ #else\ #endif\\pin :call C_InsertTemplate("preprocessor.ifndef-else-endif", "v")' + exe "amenu ".MenuPreprocessor.'.#ifnd&ef\ #def\ #endif\\pind :call C_InsertTemplate("preprocessor.ifndef-def-endif")' + exe "imenu ".MenuPreprocessor.'.#ifnd&ef\ #def\ #endif\\pind :call C_InsertTemplate("preprocessor.ifndef-def-endif")' + exe "vmenu ".MenuPreprocessor.'.#ifnd&ef\ #def\ #endif\\pind :call C_InsertTemplate("preprocessor.ifndef-def-endif", "v")' + + exe "amenu ".MenuPreprocessor.'.#if\ &0\ #endif\\pi0 :call C_PPIf0("a")2ji' + exe "imenu ".MenuPreprocessor.'.#if\ &0\ #endif\\pi0 :call C_PPIf0("a")2ji' + exe "vmenu ".MenuPreprocessor.'.#if\ &0\ #endif\\pi0 :call C_PPIf0("v")' + " + exe "amenu ".MenuPreprocessor.'.&remove\ #if\ 0\ #endif\\pr0 :call C_PPIf0Remove()' + exe "imenu ".MenuPreprocessor.'.&remove\ #if\ 0\ #endif\\pr0 :call C_PPIf0Remove()' + " + exe "amenu ".MenuPreprocessor.'.#err&or\\pe :call C_InsertTemplate("preprocessor.error")' + exe "imenu ".MenuPreprocessor.'.#err&or\\pe :call C_InsertTemplate("preprocessor.error")' + exe "amenu ".MenuPreprocessor.'.#&line\\pl :call C_InsertTemplate("preprocessor.line")' + exe "imenu ".MenuPreprocessor.'.#&line\\pl :call C_InsertTemplate("preprocessor.line")' + exe "amenu ".MenuPreprocessor.'.#&pragma\\pp :call C_InsertTemplate("preprocessor.pragma")' + exe "imenu ".MenuPreprocessor.'.#&pragma\\pp :call C_InsertTemplate("preprocessor.pragma")' + " + "=============================================================================================== + "----- Menu : Snippets ---------------------------------------------------- {{{2 + "=============================================================================================== + " + if !empty(s:C_CodeSnippets) + exe "amenu ".MenuSnippets.'.&read\ code\ snippet\\nr :call C_CodeSnippet("r")' + exe "imenu ".MenuSnippets.'.&read\ code\ snippet\\nr :call C_CodeSnippet("r")' + exe "amenu ".MenuSnippets.'.&write\ code\ snippet\\nw :call C_CodeSnippet("w")' + exe "vmenu ".MenuSnippets.'.&write\ code\ snippet\\nw :call C_CodeSnippet("wv")' + exe "imenu ".MenuSnippets.'.&write\ code\ snippet\\nw :call C_CodeSnippet("w")' + exe "amenu ".MenuSnippets.'.&edit\ code\ snippet\\ne :call C_CodeSnippet("e")' + exe "imenu ".MenuSnippets.'.&edit\ code\ snippet\\ne :call C_CodeSnippet("e")' + exe " menu ".MenuSnippets.'.-SEP1- :' + endif + exe " menu ".MenuSnippets.'.&pick\ up\ func\.\ prototype\\nf,\ \\np :call C_ProtoPick("function")' + exe "vmenu ".MenuSnippets.'.&pick\ up\ func\.\ prototype\\nf,\ \\np :call C_ProtoPick("function")' + exe "imenu ".MenuSnippets.'.&pick\ up\ func\.\ prototype\\nf,\ \\np :call C_ProtoPick("function")' + exe " menu ".MenuSnippets.'.&pick\ up\ method\ prototype\\nm :call C_ProtoPick("method")' + exe "vmenu ".MenuSnippets.'.&pick\ up\ method\ prototype\\nm :call C_ProtoPick("method")' + exe "imenu ".MenuSnippets.'.&pick\ up\ method\ prototype\\nm :call C_ProtoPick("method")' + exe " menu ".MenuSnippets.'.&insert\ prototype(s)\\ni :call C_ProtoInsert()' + exe "imenu ".MenuSnippets.'.&insert\ prototype(s)\\ni :call C_ProtoInsert()' + exe " menu ".MenuSnippets.'.&clear\ prototype(s)\\nc :call C_ProtoClear()' + exe "imenu ".MenuSnippets.'.&clear\ prototype(s)\\nc :call C_ProtoClear()' + exe " menu ".MenuSnippets.'.&show\ prototype(s)\\ns :call C_ProtoShow()' + exe "imenu ".MenuSnippets.'.&show\ prototype(s)\\ns :call C_ProtoShow()' + + exe " menu ".MenuSnippets.'.-SEP2- :' + exe "amenu ".MenuSnippets.'.edit\ &local\ templates\\ntl :call C_BrowseTemplateFiles("Local")' + exe "imenu ".MenuSnippets.'.edit\ &local\ templates\\ntl :call C_BrowseTemplateFiles("Local")' + if s:installation == 'system' + exe "amenu ".MenuSnippets.'.edit\ &global\ templates\\ntg :call C_BrowseTemplateFiles("Global")' + exe "imenu ".MenuSnippets.'.edit\ &global\ templates\\ntg :call C_BrowseTemplateFiles("Global")' + endif + exe "amenu ".MenuSnippets.'.reread\ &templates\\ntr :call C_RereadTemplates("yes")' + exe "imenu ".MenuSnippets.'.reread\ &templates\\ntr :call C_RereadTemplates("yes")' + exe "amenu ".MenuSnippets.'.switch\ template\ st&yle\\nts :CStyle' + exe "imenu ".MenuSnippets.'.switch\ template\ st&yle\\nts :CStyle' + " + "=============================================================================================== + "----- Menu : C++ --------------------------------------------------------- {{{2 + "=============================================================================================== + " + exe "anoremenu ".MenuCpp.'.c&in :call C_InsertTemplate("cpp.cin")' + exe "inoremenu ".MenuCpp.'.c&in :call C_InsertTemplate("cpp.cin")' + exe "anoremenu ".MenuCpp.'.c&out\\+co :call C_InsertTemplate("cpp.cout")' + exe "inoremenu ".MenuCpp.'.c&out\\+co :call C_InsertTemplate("cpp.cout")' + exe "anoremenu ".MenuCpp.'.<<\ &\"\"\\+" :call C_InsertTemplate("cpp.cout-operator")' + exe "inoremenu ".MenuCpp.'.<<\ &\"\"\\+" :call C_InsertTemplate("cpp.cout-operator")' + " + "----- Submenu : C++ : output manipulators ------------------------------------------------------- + " + if s:C_MenuHeader == 'yes' + exe "amenu ".MenuCpp.'.&output\ manipulators.output\ manip\.C\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuCpp.'.&output\ manipulators.-Sep0- ' + exe "amenu ".MenuCpp.'.ios\ flag&bits.ios\ flagsC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuCpp.'.ios\ flag&bits.-Sep0- ' + exe "amenu ".MenuCpp.'.&#include\ \\+ps.alg\.\.vecC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuCpp.'.&#include\ \\+ps.-Sep0- ' + exe "amenu ".MenuCpp.'.&#include\ \\+pc.cXC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuCpp.'.&#include\ \\+pc.-Sep0- ' + endif + " + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &boolalpha :call C_InsertTemplate("cpp.output-manipulator-boolalpha")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &dec :call C_InsertTemplate("cpp.output-manipulator-dec")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &endl :call C_InsertTemplate("cpp.output-manipulator-endl")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &fixed :call C_InsertTemplate("cpp.output-manipulator-fixed")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ fl&ush :call C_InsertTemplate("cpp.output-manipulator-flush")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &hex :call C_InsertTemplate("cpp.output-manipulator-hex")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &internal :call C_InsertTemplate("cpp.output-manipulator-internal")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &left :call C_InsertTemplate("cpp.output-manipulator-left")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &oct :call C_InsertTemplate("cpp.output-manipulator-oct")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &right :call C_InsertTemplate("cpp.output-manipulator-right")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ s&cientific :call C_InsertTemplate("cpp.output-manipulator-scientific")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &setbase\(\ \) :call C_InsertTemplate("cpp.output-manipulator-setbase")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ se&tfill\(\ \) :call C_InsertTemplate("cpp.output-manipulator-setfill")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ setiosfla&g\(\ \) :call C_InsertTemplate("cpp.output-manipulator-setiosflags")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ set&precision\(\ \) :call C_InsertTemplate("cpp.output-manipulator-setprecision")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ set&w\(\ \) :call C_InsertTemplate("cpp.output-manipulator-setw")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ showb&ase :call C_InsertTemplate("cpp.output-manipulator-showbase")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ showpoi&nt :call C_InsertTemplate("cpp.output-manipulator-showpoint")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ showpos\ \(&1\) :call C_InsertTemplate("cpp.output-manipulator-showpos")' + exe "anoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ uppercase\ \(&2\) :call C_InsertTemplate("cpp.output-manipulator-uppercase")' + " + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &boolalpha :call C_InsertTemplate("cpp.output-manipulator-boolalpha")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &dec :call C_InsertTemplate("cpp.output-manipulator-dec")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &endl :call C_InsertTemplate("cpp.output-manipulator-endl")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &fixed :call C_InsertTemplate("cpp.output-manipulator-fixed")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ fl&ush :call C_InsertTemplate("cpp.output-manipulator-flush")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &hex :call C_InsertTemplate("cpp.output-manipulator-hex")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &internal :call C_InsertTemplate("cpp.output-manipulator-internal")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &left :call C_InsertTemplate("cpp.output-manipulator-left")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &oct :call C_InsertTemplate("cpp.output-manipulator-oct")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &right :call C_InsertTemplate("cpp.output-manipulator-right")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ s&cientific :call C_InsertTemplate("cpp.output-manipulator-scientific")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ &setbase\(\ \) :call C_InsertTemplate("cpp.output-manipulator-setbase")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ se&tfill\(\ \) :call C_InsertTemplate("cpp.output-manipulator-setfill")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ setiosfla&g\(\ \) :call C_InsertTemplate("cpp.output-manipulator-setiosflags")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ set&precision\(\ \) :call C_InsertTemplate("cpp.output-manipulator-setprecision")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ set&w\(\ \) :call C_InsertTemplate("cpp.output-manipulator-setw")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ showb&ase :call C_InsertTemplate("cpp.output-manipulator-showbase")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ showpoi&nt :call C_InsertTemplate("cpp.output-manipulator-showpoint")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ showpos\ \(&1\) :call C_InsertTemplate("cpp.output-manipulator-showpos")' + exe "inoremenu ".MenuCpp.'.&output\ manipulators.\<\<\ uppercase\ \(&2\) :call C_InsertTemplate("cpp.output-manipulator-uppercase")' + " + "----- Submenu : C++ : ios flag bits ------------------------------------------------------------- + " + " + call C_CIosFlagMenus ( MenuCpp.'.ios\ flag&bits', s:Cpp_IosFlagBits ) + " + "----- Submenu : C++ library (algorithm - locale) ---------------------------------------------- + " + call C_CIncludeMenus ( MenuCpp.'.&#include\ \\+ps', s:Cpp_StandardLibs ) + " + "----- Submenu : C library (cassert - ctime) ------------------------------------------------- + " + call C_CIncludeMenus ( MenuCpp.'.&#include\ \\+pc', s:Cpp_CStandardLibs ) + " + "----- End Submenu : C library (cassert - ctime) --------------------------------------------- + " + exe "amenu ".MenuCpp.'.-SEP2- :' + + exe "amenu ".MenuCpp.'.&class\\+c :call C_InsertTemplate("cpp.class-definition")' + exe "imenu ".MenuCpp.'.&class\\+c :call C_InsertTemplate("cpp.class-definition")' + exe "amenu ".MenuCpp.'.class\ (w\.\ &new)\\+cn :call C_InsertTemplate("cpp.class-using-new-definition")' + exe "imenu ".MenuCpp.'.class\ (w\.\ &new)\\+cn :call C_InsertTemplate("cpp.class-using-new-definition")' + exe "amenu ".MenuCpp.'.&templ\.\ class\\+tc :call C_InsertTemplate("cpp.template-class-definition")' + exe "imenu ".MenuCpp.'.&templ\.\ class\\+tc :call C_InsertTemplate("cpp.template-class-definition")' + exe "amenu ".MenuCpp.'.templ\.\ class\ (w\.\ ne&w)\\+tcn :call C_InsertTemplate("cpp.template-class-using-new-definition")' + exe "imenu ".MenuCpp.'.templ\.\ class\ (w\.\ ne&w)\\+tcn :call C_InsertTemplate("cpp.template-class-using-new-definition")' + + " + "----- Submenu : C++ : IMPLEMENTATION ------------------------------------------------------- + " + if s:C_MenuHeader == 'yes' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.IMPLEMENT\.C\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.-Sep0- ' + endif + " + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.&class\\+ci :call C_InsertTemplate("cpp.class-implementation")' + exe "imenu ".MenuCpp.'.IM&PLEMENTATION.&class\\+ci :call C_InsertTemplate("cpp.class-implementation")' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.class\ (w\.\ &new)\\+cni :call C_InsertTemplate("cpp.class-using-new-implementation")' + exe "imenu ".MenuCpp.'.IM&PLEMENTATION.class\ (w\.\ &new)\\+cni :call C_InsertTemplate("cpp.class-using-new-implementation")' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.&method\\+mi :call C_InsertTemplate("cpp.method-implementation")' + exe "imenu ".MenuCpp.'.IM&PLEMENTATION.&method\\+mi :call C_InsertTemplate("cpp.method-implementation")' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.&accessor\\+ai :call C_InsertTemplate("cpp.accessor-implementation")' + exe "imenu ".MenuCpp.'.IM&PLEMENTATION.&accessor\\+ai :call C_InsertTemplate("cpp.accessor-implementation")' + " + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.-SEP21- :' + exe "imenu ".MenuCpp.'.IM&PLEMENTATION.&templ\.\ class\\+tci :call C_InsertTemplate("cpp.template-class-implementation")' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.&templ\.\ class\\+tci :call C_InsertTemplate("cpp.template-class-implementation")' + exe "imenu ".MenuCpp.'.IM&PLEMENTATION.templ\.\ class\ (w\.\ ne&w)\\+tcni :call C_InsertTemplate("cpp.template-class-using-new-implementation")' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.templ\.\ class\ (w\.\ ne&w)\\+tcni :call C_InsertTemplate("cpp.template-class-using-new-implementation")' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.templ\.\ mðod\\+tmi :call C_InsertTemplate("cpp.template-method-implementation")' + exe "imenu ".MenuCpp.'.IM&PLEMENTATION.templ\.\ mðod\\+tmi :call C_InsertTemplate("cpp.template-method-implementation")' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.templ\.\ a&ccessor\\+tai :call C_InsertTemplate("cpp.template-accessor-implementation")' + exe "imenu ".MenuCpp.'.IM&PLEMENTATION.templ\.\ a&ccessor\\+tai :call C_InsertTemplate("cpp.template-accessor-implementation")' + " + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.-SEP22- :' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.operator\ &<< :call C_InsertTemplate("cpp.operator-in")' + exe "imenu ".MenuCpp.'.IM&PLEMENTATION.operator\ &<< :call C_InsertTemplate("cpp.operator-in")' + exe "amenu ".MenuCpp.'.IM&PLEMENTATION.operator\ &>> :call C_InsertTemplate("cpp.operator-out")' + exe "imenu ".MenuCpp.'.IM&PLEMENTATION.operator\ &>> :call C_InsertTemplate("cpp.operator-out")' + " + "----- End Submenu : C++ : IMPLEMENTATION ------------------------------------------------------- + " + exe "amenu ".MenuCpp.'.-SEP31- :' + exe "amenu ".MenuCpp.'.templ\.\ &function\\+tf :call C_InsertTemplate("cpp.template-function")' + exe "imenu ".MenuCpp.'.templ\.\ &function\\+tf :call C_InsertTemplate("cpp.template-function")' + exe "amenu ".MenuCpp.'.&error\ class\\+ec :call C_InsertTemplate("cpp.error-class")' + exe "imenu ".MenuCpp.'.&error\ class\\+ec :call C_InsertTemplate("cpp.error-class")' + + exe "amenu ".MenuCpp.'.-SEP5- :' + exe "amenu ".MenuCpp.'.tr&y\ \.\.\ catch\\+tr :call C_InsertTemplate("cpp.try-catch")' + exe "imenu ".MenuCpp.'.tr&y\ \.\.\ catch\\+tr :call C_InsertTemplate("cpp.try-catch")' + exe "vmenu ".MenuCpp.'.tr&y\ \.\.\ catch\\+tr :call C_InsertTemplate("cpp.try-catch", "v")' + exe "amenu ".MenuCpp.'.catc&h\\+ca :call C_InsertTemplate("cpp.catch")' + exe "imenu ".MenuCpp.'.catc&h\\+ca :call C_InsertTemplate("cpp.catch")' + exe "vmenu ".MenuCpp.'.catc&h\\+ca :call C_InsertTemplate("cpp.catch", "v")' + + exe "amenu ".MenuCpp.'.catch\(&\.\.\.\)\\+c\. :call C_InsertTemplate("cpp.catch-points")' + exe "imenu ".MenuCpp.'.catch\(&\.\.\.\)\\+c\. :call C_InsertTemplate("cpp.catch-points")' + exe "vmenu ".MenuCpp.'.catch\(&\.\.\.\)\\+c\. :call C_InsertTemplate("cpp.catch-points", "v")' + + exe "amenu ".MenuCpp.'.-SEP6- :' + exe "amenu ".MenuCpp.'.open\ input\ file\ \ \(&4\) :call C_InsertTemplate("cpp.open-input-file")' + exe "imenu ".MenuCpp.'.open\ input\ file\ \ \(&4\) :call C_InsertTemplate("cpp.open-input-file")' + exe "vmenu ".MenuCpp.'.open\ input\ file\ \ \(&4\) :call C_InsertTemplate("cpp.open-input-file", "v")' + exe "amenu ".MenuCpp.'.open\ output\ file\ \(&5\) :call C_InsertTemplate("cpp.open-output-file")' + exe "imenu ".MenuCpp.'.open\ output\ file\ \(&5\) :call C_InsertTemplate("cpp.open-output-file")' + exe "vmenu ".MenuCpp.'.open\ output\ file\ \(&5\) :call C_InsertTemplate("cpp.open-output-file", "v")' + exe "amenu ".MenuCpp.'.-SEP7- :' + + exe "amenu ".MenuCpp.'.&using\ namespace\ std; :call C_InsertTemplate("cpp.namespace-std")' + exe "imenu ".MenuCpp.'.&using\ namespace\ std; :call C_InsertTemplate("cpp.namespace-std")' + exe "amenu ".MenuCpp.'.u&sing\ namespace\ ???; :call C_InsertTemplate("cpp.namespace")' + exe "imenu ".MenuCpp.'.u&sing\ namespace\ ???; :call C_InsertTemplate("cpp.namespace")' + + exe "amenu ".MenuCpp.'.names&pace\ ???\ \{\ \} :call C_InsertTemplate("cpp.namespace-block")' + exe "imenu ".MenuCpp.'.names&pace\ ???\ \{\ \} :call C_InsertTemplate("cpp.namespace-block")' + exe "vmenu ".MenuCpp.'.names&pace\ ???\ \{\ \} :call C_InsertTemplate("cpp.namespace-block", "v")' + exe "amenu ".MenuCpp.'.namespace\ &alias\ =\ ??? :call C_InsertTemplate("cpp.namespace-alias")' + exe "imenu ".MenuCpp.'.namespace\ &alias\ =\ ??? :call C_InsertTemplate("cpp.namespace-alias")' + + exe "amenu ".MenuCpp.'.-SEP8- :' + " + "----- Submenu : RTTI ---------------------------------------------------------------------------- + " + if s:C_MenuHeader == 'yes' + exe "amenu ".MenuCpp.'.&RTTI.RTTIC\/C\+\+ :call C_MenuTitle()' + exe "amenu ".MenuCpp.'.&RTTI.-Sep0- ' + endif + " + exe "anoremenu ".MenuCpp.'.&RTTI.&typeid :call C_InsertTemplate("cpp.rtti-typeid")' + exe "anoremenu ".MenuCpp.'.&RTTI.&static_cast :call C_InsertTemplate("cpp.rtti-static-cast")' + exe "anoremenu ".MenuCpp.'.&RTTI.&const_cast :call C_InsertTemplate("cpp.rtti-const-cast")' + exe "anoremenu ".MenuCpp.'.&RTTI.&reinterpret_cast :call C_InsertTemplate("cpp.rtti-reinterpret-cast")' + exe "anoremenu ".MenuCpp.'.&RTTI.&dynamic_cast :call C_InsertTemplate("cpp.rtti-dynamic-cast")' + " + exe "inoremenu ".MenuCpp.'.&RTTI.&typeid :call C_InsertTemplate("cpp.rtti-typeid")' + exe "inoremenu ".MenuCpp.'.&RTTI.&static_cast :call C_InsertTemplate("cpp.rtti-static-cast")' + exe "inoremenu ".MenuCpp.'.&RTTI.&const_cast :call C_InsertTemplate("cpp.rtti-const-cast")' + exe "inoremenu ".MenuCpp.'.&RTTI.&reinterpret_cast :call C_InsertTemplate("cpp.rtti-reinterpret-cast")' + exe "inoremenu ".MenuCpp.'.&RTTI.&dynamic_cast :call C_InsertTemplate("cpp.rtti-dynamic-cast")' + " + exe "vnoremenu ".MenuCpp.'.&RTTI.&typeid :call C_InsertTemplate("cpp.rtti-typeid", "v")' + exe "vnoremenu ".MenuCpp.'.&RTTI.&static_cast :call C_InsertTemplate("cpp.rtti-static-cast", "v")' + exe "vnoremenu ".MenuCpp.'.&RTTI.&const_cast :call C_InsertTemplate("cpp.rtti-const-cast", "v")' + exe "vnoremenu ".MenuCpp.'.&RTTI.&reinterpret_cast :call C_InsertTemplate("cpp.rtti-reinterpret-cast", "v")' + exe "vnoremenu ".MenuCpp.'.&RTTI.&dynamic_cast :call C_InsertTemplate("cpp.rtti-dynamic-cast", "v")' + " + "----- End Submenu : RTTI ------------------------------------------------------------------------ + " + exe "amenu ".MenuCpp.'.e&xtern\ \"C\"\ \{\ \} :call C_InsertTemplate("cpp.extern")' + exe "imenu ".MenuCpp.'.e&xtern\ \"C\"\ \{\ \} :call C_InsertTemplate("cpp.extern")' + exe "vmenu ".MenuCpp.'.e&xtern\ \"C\"\ \{\ \} :call C_InsertTemplate("cpp.extern", "v")' + " + "=============================================================================================== + "----- Menu : run ----- -------------------------------------------------- {{{2 + "=============================================================================================== + " + exe "amenu ".s:MenuRun.'.save\ and\ &compile\\rc\ \ \ :call C_Compile():call C_HlMessage()' + exe "imenu ".s:MenuRun.'.save\ and\ &compile\\rc\ \ \ :call C_Compile():call C_HlMessage()' + exe "amenu ".s:MenuRun.'.&link\\rl\ \ \ \ \ :call C_Link():call C_HlMessage()' + exe "imenu ".s:MenuRun.'.&link\\rl\ \ \ \ \ :call C_Link():call C_HlMessage()' + exe "amenu ".s:MenuRun.'.&run\\rr\ \ \ :call C_Run()' + exe "imenu ".s:MenuRun.'.&run\\rr\ \ \ :call C_Run()' + exe "amenu ".s:MenuRun.'.cmd\.\ line\ &arg\.\\ra\ \ \ :call C_Arguments()' + exe "imenu ".s:MenuRun.'.cmd\.\ line\ &arg\.\\ra\ \ \ :call C_Arguments()' + " + exe "amenu ".s:MenuRun.'.-SEP0- :' + exe "amenu ".s:MenuRun.'.&make\\rm :call C_Make()' + exe "imenu ".s:MenuRun.'.&make\\rm :call C_Make()' + exe "amenu ".s:MenuRun.'.&choose\ makefile\\rcm :call C_ChooseMakefile()' + exe "imenu ".s:MenuRun.'.&choose\ makefile\\rcm :call C_ChooseMakefile()' + exe "amenu ".s:MenuRun.'.executable\ to\ run\\rme :call C_MakeExeToRun()' + exe "imenu ".s:MenuRun.'.executable\ to\ run\\rme :call C_MakeExeToRun()' + exe "amenu ".s:MenuRun.'.&make\ clean\\rmc :call C_MakeClean()' + exe "imenu ".s:MenuRun.'.&make\ clean\\rmc :call C_MakeClean()' + exe "amenu ".s:MenuRun.'.cmd\.\ line\ ar&g\.\ for\ make\\rma :call C_MakeArguments()' + exe "imenu ".s:MenuRun.'.cmd\.\ line\ ar&g\.\ for\ make\\rma :call C_MakeArguments()' + " + exe "amenu ".s:MenuRun.'.-SEP1- :' + " + if s:C_SplintIsExecutable==1 + exe "amenu ".s:MenuRun.'.s&plint\\rp :call C_SplintCheck():call C_HlMessage()' + exe "imenu ".s:MenuRun.'.s&plint\\rp :call C_SplintCheck():call C_HlMessage()' + exe "amenu ".s:MenuRun.'.cmd\.\ line\ arg\.\ for\ spl&int\\rpa :call C_SplintArguments()' + exe "imenu ".s:MenuRun.'.cmd\.\ line\ arg\.\ for\ spl&int\\rpa :call C_SplintArguments()' + exe "amenu ".s:MenuRun.'.-SEP2- :' + endif + " + if s:C_CodeCheckIsExecutable==1 + exe "amenu ".s:MenuRun.'.CodeChec&k\\rk :call C_CodeCheck():call C_HlMessage()' + exe "imenu ".s:MenuRun.'.CodeChec&k\\rk :call C_CodeCheck():call C_HlMessage()' + exe "amenu ".s:MenuRun.'.cmd\.\ line\ arg\.\ for\ Cod&eCheck\\rka :call C_CodeCheckArguments()' + exe "imenu ".s:MenuRun.'.cmd\.\ line\ arg\.\ for\ Cod&eCheck\\rka :call C_CodeCheckArguments()' + exe "amenu ".s:MenuRun.'.-SEP3- :' + endif + " + exe "amenu ".s:MenuRun.'.in&dent\\rd :call C_Indent()' + exe "imenu ".s:MenuRun.'.in&dent\\rd :call C_Indent()' + if s:MSWIN + exe "amenu ".s:MenuRun.'.&hardcopy\ to\ printer\\rh :call C_Hardcopy()' + exe "imenu ".s:MenuRun.'.&hardcopy\ to\ printer\\rh :call C_Hardcopy()' + exe "vmenu ".s:MenuRun.'.&hardcopy\ to\ printer\\rh :call C_Hardcopy()' + else + exe "amenu ".s:MenuRun.'.&hardcopy\ to\ FILENAME\.ps\\rh :call C_Hardcopy()' + exe "imenu ".s:MenuRun.'.&hardcopy\ to\ FILENAME\.ps\\rh :call C_Hardcopy()' + exe "vmenu ".s:MenuRun.'.&hardcopy\ to\ FILENAME\.ps\\rh :call C_Hardcopy()' + endif + exe "imenu ".s:MenuRun.'.-SEP4- :' + + exe "amenu ".s:MenuRun.'.&settings\\rs :call C_Settings()' + exe "imenu ".s:MenuRun.'.&settings\\rs :call C_Settings()' + exe "imenu ".s:MenuRun.'.-SEP5- :' + + if !s:MSWIN + exe "amenu ".s:MenuRun.'.&xterm\ size\\rx :call C_XtermSize()' + exe "imenu ".s:MenuRun.'.&xterm\ size\\rx :call C_XtermSize()' + endif + if s:C_OutputGvim == "vim" + exe "amenu ".s:MenuRun.'.&output:\ VIM->buffer->xterm\\ro :call C_Toggle_Gvim_Xterm()' + exe "imenu ".s:MenuRun.'.&output:\ VIM->buffer->xterm\\ro :call C_Toggle_Gvim_Xterm()' + else + if s:C_OutputGvim == "buffer" + exe "amenu ".s:MenuRun.'.&output:\ BUFFER->xterm->vim\\ro :call C_Toggle_Gvim_Xterm()' + exe "imenu ".s:MenuRun.'.&output:\ BUFFER->xterm->vim\\ro :call C_Toggle_Gvim_Xterm()' + else + exe "amenu ".s:MenuRun.'.&output:\ XTERM->vim->buffer\\ro :call C_Toggle_Gvim_Xterm()' + exe "imenu ".s:MenuRun.'.&output:\ XTERM->vim->buffer\\ro :call C_Toggle_Gvim_Xterm()' + endif + endif + " + "=============================================================================================== + "----- Menu : help ------------------------------------------------------- {{{2 + "=============================================================================================== + " + exe " menu ".s:C_Root.'&help\ (C-Support)\\hp :call C_HelpCsupport()' + exe "imenu ".s:C_Root.'&help\ (C-Support)\\hp :call C_HelpCsupport()' + exe " menu ".s:C_Root.'show\ &manual\\hm :call C_Help("m")' + exe "imenu ".s:C_Root.'show\ &manual\\hm :call C_Help("m")' + +endfunction " ---------- end of function C_InitMenus ---------- +" +function! C_MenuTitle () + echohl WarningMsg | echo "This is a menu title." | echohl None +endfunction " ---------- end of function C_MenuTitle ---------- +" +"=============================================================================================== +"----- Menu Functions -------------------------------------------------------------------------- +"=============================================================================================== +" +let s:C_StandardLibs = [ + \ '&assert\.h' , '&ctype\.h' , '&errno\.h' , + \ '&float\.h' , '&limits\.h' , 'l&ocale\.h' , + \ '&math\.h' , 'set&jmp\.h' , 's&ignal\.h' , + \ 'stdar&g\.h' , 'st&ddef\.h' , '&stdio\.h' , + \ 'stdli&b\.h' , 'st&ring\.h' , '&time\.h' , + \ ] +" +let s:C_C99Libs = [ + \ '&complex\.h', '&fenv\.h', '&inttypes\.h', + \ 'is&o646\.h', '&stdbool\.h', 's&tdint\.h', + \ 'tg&math\.h', '&wchar\.h', 'wct&ype\.h', + \ ] +" +let s:Cpp_StandardLibs = [ + \ '&algorithm', '&bitset', '&complex', '&deque', + \ '&exception', '&fstream', 'f&unctional', 'iomani&p', + \ '&ios', 'iosf&wd', 'io&stream', 'istrea&m', + \ 'iterato&r', '&limits', 'lis&t', 'l&ocale', + \ '&map', 'memor&y', '&new', 'numeri&c', + \ '&ostream', '&queue', '&set', 'sst&ream', + \ 'st&ack', 'stde&xcept', 'stream&buf', 'str&ing', + \ '&typeinfo', '&utility', '&valarray', 'v&ector', + \ ] +" +let s:Cpp_CStandardLibs = [ + \ 'c&assert', 'c&ctype', 'c&errno', 'c&float', + \ 'c&limits', 'cl&ocale', 'c&math', 'cset&jmp', + \ 'cs&ignal', 'cstdar&g', 'cst&ddef', 'c&stdio', + \ 'cstdli&b', 'cst&ring', 'c&time', + \ ] + +let s:Cpp_IosFlagBits = [ + \ 'ios::&adjustfield', 'ios::bas&efield', 'ios::&boolalpha', + \ 'ios::&dec', 'ios::&fixed', 'ios::floa&tfield', + \ 'ios::&hex', 'ios::&internal', 'ios::&left', + \ 'ios::&oct', 'ios::&right', 'ios::s&cientific', + \ 'ios::sho&wbase', 'ios::showpoint\ \(&1\)', 'ios::show&pos', + \ 'ios::&skipws', 'ios::u&nitbuf', 'ios::&uppercase', + \ ] + +"------------------------------------------------------------------------------ +" C_CIncludeMenus: generate the C/C++-standard library menu entries {{{1 +"------------------------------------------------------------------------------ +function! C_CIncludeMenus ( menupath, liblist ) + for item in a:liblist + let replacement = substitute( item, '[&\\]*', '','g' ) + exe "anoremenu ".a:menupath.'.'.item.' i#include<'.replacement.'>' + exe "inoremenu ".a:menupath.'.'.item.' #include<'.replacement.'>' + endfor + return +endfunction " ---------- end of function C_CIncludeMenus ---------- + +"------------------------------------------------------------------------------ +" C_CIosFlagMenus: generate the C++ ios flags menu entries {{{1 +"------------------------------------------------------------------------------ +function! C_CIosFlagMenus ( menupath, flaglist ) + for item in a:flaglist + let replacement = substitute( item, '[^[:alpha:]:]', '','g' ) + exe " noremenu ".a:menupath.'.'.item.' i'.replacement + exe "inoremenu ".a:menupath.'.'.item.' '.replacement + endfor + return +endfunction " ---------- end of function C_CIosFlagMenus ---------- +" +"------------------------------------------------------------------------------ +" C_Input: Input after a highlighted prompt {{{1 +" 3. argument : optional completion +"------------------------------------------------------------------------------ +function! C_Input ( promp, text, ... ) + echohl Search " highlight prompt + call inputsave() " preserve typeahead + if a:0 == 0 || empty(a:1) + let retval =input( a:promp, a:text ) + else + let retval =input( a:promp, a:text, a:1 ) + endif + call inputrestore() " restore typeahead + echohl None " reset highlighting + let retval = substitute( retval, '^\s\+', "", "" ) " remove leading whitespaces + let retval = substitute( retval, '\s\+$', "", "" ) " remove trailing whitespaces + return retval +endfunction " ---------- end of function C_Input ---------- +" +"------------------------------------------------------------------------------ +" C_AdjustLineEndComm: adjust line-end comments {{{1 +"------------------------------------------------------------------------------ +" +" C comment or C++ comment: +let s:c_cppcomment= '\(\/\*.\{-}\*\/\|\/\/.*$\)' + +function! C_AdjustLineEndComm ( ) range + " + if !exists("b:C_LineEndCommentColumn") + let b:C_LineEndCommentColumn = s:C_LineEndCommColDefault + endif + + let save_cursor = getpos(".") + + let save_expandtab = &expandtab + exe ":set expandtab" + + let linenumber = a:firstline + exe ":".a:firstline + + while linenumber <= a:lastline + let line= getline(".") + + " line is not a pure comment but contains one + " + if match( line, '^\s*'.s:c_cppcomment ) < 0 && match( line, s:c_cppcomment ) > 0 + " + " disregard comments starting in a string + " + let idx1 = -1 + let idx2 = -1 + let commentstart= -2 + let commentend = 0 + while commentstart < idx2 && idx2 < commentend + let start = commentend + let idx2 = match( line, s:c_cppcomment, start ) + let commentstart= match ( line, '"[^"]\+"', start ) + let commentend = matchend( line, '"[^"]\+"', start ) + endwhile + " + " try to adjust the comment + " + let idx1 = 1 + match( line, '\s*'.s:c_cppcomment, start ) + let idx2 = 1 + idx2 + call setpos(".", [ 0, linenumber, idx1, 0 ] ) + let vpos1 = virtcol(".") + call setpos(".", [ 0, linenumber, idx2, 0 ] ) + let vpos2 = virtcol(".") + + if ! ( vpos2 == b:C_LineEndCommentColumn + \ || vpos1 > b:C_LineEndCommentColumn + \ || idx2 == 0 ) + + exe ":.,.retab" + " insert some spaces + if vpos2 < b:C_LineEndCommentColumn + let diff = b:C_LineEndCommentColumn-vpos2 + call setpos(".", [ 0, linenumber, vpos2, 0 ] ) + let @" = ' ' + exe "normal ".diff."P" + endif + + " remove some spaces + if vpos1 < b:C_LineEndCommentColumn && vpos2 > b:C_LineEndCommentColumn + let diff = vpos2 - b:C_LineEndCommentColumn + call setpos(".", [ 0, linenumber, b:C_LineEndCommentColumn, 0 ] ) + exe "normal ".diff."x" + endif + + endif + endif + let linenumber=linenumber+1 + normal j + endwhile + " + " restore tab expansion settings and cursor position + let &expandtab = save_expandtab + call setpos('.', save_cursor) + +endfunction " ---------- end of function C_AdjustLineEndComm ---------- +" +"------------------------------------------------------------------------------ +" C_GetLineEndCommCol: get line-end comment position {{{1 +"------------------------------------------------------------------------------ +function! C_GetLineEndCommCol () + let actcol = virtcol(".") + if actcol+1 == virtcol("$") + let b:C_LineEndCommentColumn = '' + while match( b:C_LineEndCommentColumn, '^\s*\d\+\s*$' ) < 0 + let b:C_LineEndCommentColumn = C_Input( 'start line-end comment at virtual column : ', actcol, '' ) + endwhile + else + let b:C_LineEndCommentColumn = virtcol(".") + endif + echomsg "line end comments will start at column ".b:C_LineEndCommentColumn +endfunction " ---------- end of function C_GetLineEndCommCol ---------- +" +"------------------------------------------------------------------------------ +" C_EndOfLineComment: single line-end comment {{{1 +"------------------------------------------------------------------------------ +function! C_EndOfLineComment ( ) range + if !exists("b:C_LineEndCommentColumn") + let b:C_LineEndCommentColumn = s:C_LineEndCommColDefault + endif + " ----- trim whitespaces ----- + exe a:firstline.','.a:lastline.'s/\s*$//' + + for line in range( a:lastline, a:firstline, -1 ) + let linelength = virtcol( [line, "$"] ) - 1 + let diff = 1 + if linelength < b:C_LineEndCommentColumn + let diff = b:C_LineEndCommentColumn -1 -linelength + endif + exe "normal ".diff."A " + call C_InsertTemplate('comment.end-of-line-comment') + if line > a:firstline + normal k + endif + endfor +endfunction " ---------- end of function C_EndOfLineComment ---------- +" +"------------------------------------------------------------------------------ +" C_Comment_C_SectionAll: Section Comments {{{1 +"------------------------------------------------------------------------------ +function! C_Comment_C_SectionAll ( type ) + + call C_InsertTemplate("comment.file-section-cpp-header-includes") + call C_InsertTemplate("comment.file-section-cpp-macros") + call C_InsertTemplate("comment.file-section-cpp-typedefs") + call C_InsertTemplate("comment.file-section-cpp-data-types") + if a:type=="cpp" + call C_InsertTemplate("comment.file-section-cpp-class-defs") + endif + call C_InsertTemplate("comment.file-section-cpp-local-variables") + call C_InsertTemplate("comment.file-section-cpp-prototypes") + call C_InsertTemplate("comment.file-section-cpp-function-defs-exported") + call C_InsertTemplate("comment.file-section-cpp-function-defs-local") + if a:type=="cpp" + call C_InsertTemplate("comment.file-section-cpp-class-implementations-exported") + call C_InsertTemplate("comment.file-section-cpp-class-implementations-local") + endif + +endfunction " ---------- end of function C_Comment_C_SectionAll ---------- +" +function! C_Comment_H_SectionAll ( type ) + + call C_InsertTemplate("comment.file-section-hpp-header-includes") + call C_InsertTemplate("comment.file-section-hpp-macros") + call C_InsertTemplate("comment.file-section-hpp-exported-typedefs") + call C_InsertTemplate("comment.file-section-hpp-exported-data-types") + if a:type=="cpp" + call C_InsertTemplate("comment.file-section-hpp-exported-class-defs") + endif + call C_InsertTemplate("comment.file-section-hpp-exported-variables") + call C_InsertTemplate("comment.file-section-hpp-exported-function-declarations") + +endfunction " ---------- end of function C_Comment_H_SectionAll ---------- +" +"---------------------------------------------------------------------- +" C_CodeToCommentC : Code -> Comment {{{1 +"---------------------------------------------------------------------- +function! C_CodeToCommentC ( ) range + silent exe ':'.a:firstline.','.a:lastline."s/^/ \* /" + silent exe ":".a:firstline."s'^ '\/'" + silent exe ":".a:lastline + silent put = ' */' +endfunction " ---------- end of function C_CodeToCommentC ---------- +" +"---------------------------------------------------------------------- +" C_CodeToCommentCpp : Code -> Comment {{{1 +"---------------------------------------------------------------------- +function! C_CodeToCommentCpp ( ) range + silent exe a:firstline.','.a:lastline.":s#^#//#" +endfunction " ---------- end of function C_CodeToCommentCpp ---------- +" +"---------------------------------------------------------------------- +" C_StartMultilineComment : Comment -> Code {{{1 +"---------------------------------------------------------------------- +let s:C_StartMultilineComment = '^\s*\/\*[\*! ]\=' + +function! C_RemoveCComment( start, end ) + + if a:end-a:start<1 + return 0 " lines removed + endif + " + " Is the C-comment complete ? Get length. + " + let check = getline( a:start ) =~ s:C_StartMultilineComment + let linenumber = a:start+1 + while linenumber < a:end && getline( linenumber ) !~ '^\s*\*\/' + let check = check && getline( linenumber ) =~ '^\s*\*[ ]\=' + let linenumber = linenumber+1 + endwhile + let check = check && getline( linenumber ) =~ '^\s*\*\/' + " + " remove a complete comment + " + if check + exe "silent :".a:start.' s/'.s:C_StartMultilineComment.'//' + let linenumber1 = a:start+1 + while linenumber1 < linenumber + exe "silent :".linenumber1.' s/^\s*\*[ ]\=//' + let linenumber1 = linenumber1+1 + endwhile + exe "silent :".linenumber1.' s/^\s*\*\///' + endif + + return linenumber-a:start+1 " lines removed +endfunction " ---------- end of function C_RemoveCComment ---------- +" +"---------------------------------------------------------------------- +" C_CommentToCode : Comment -> Code {{{1 +"---------------------------------------------------------------------- +function! C_CommentToCode( ) range + + let removed = 0 + " + let linenumber = a:firstline + while linenumber <= a:lastline + " Do we have a C++ comment ? + if getline( linenumber ) =~ '^\s*//' + exe "silent :".linenumber.' s#^\s*//##' + let removed = 1 + endif + " Do we have a C comment ? + if removed == 0 && getline( linenumber ) =~ s:C_StartMultilineComment + let removed = C_RemoveCComment( linenumber, a:lastline ) + endif + + if removed!=0 + let linenumber = linenumber+removed + let removed = 0 + else + let linenumber = linenumber+1 + endif + endwhile +endfunction " ---------- end of function C_CommentToCode ---------- +" +"---------------------------------------------------------------------- +" C_CommentCToCpp : C Comment -> C++ Comment {{{1 +" Changes the first comment in case of multiple C comments: +" xxxx; /* 1 */ /* 2 */ +" xxxx; // 1 // 2 +"---------------------------------------------------------------------- +function! C_CommentToggle () range + let LineEndCommentC = '\/\*\(.*\)\*\/' + let LineEndCommentCpp = '\/\/\(.*\)$' + " + for linenumber in range( a:firstline, a:lastline ) + let line = getline(linenumber) + " ---------- C => C++ ---------- + if match( line, LineEndCommentC ) >= 0 + let line = substitute( line, '\/\*\s*\(.\{-}\)\*\/', '\/\/ \1', '' ) + call setline( linenumber, line ) + continue + endif + " ---------- C++ => C ---------- + if match( line, LineEndCommentCpp ) >= 0 + let line = substitute( line, '\/\/\s*\(.*\)\s*$', '/* \1 */', '' ) + call setline( linenumber, line ) + endif + endfor +endfunction " ---------- end of function C_CommentToggle ---------- +" +"===================================================================================== +"----- Menu : Statements ----------------------------------------------------------- +"===================================================================================== +" +"------------------------------------------------------------------------------ +" C_PPIf0 : #if 0 .. #endif {{{1 +"------------------------------------------------------------------------------ +function! C_PPIf0 (mode) + " + let s:C_If0_Counter = 0 + let save_line = line(".") + let actual_line = 0 + " + " search for the maximum option number (if any) + " + normal gg + while actual_line < search( s:C_If0_Txt."\\d\\+" ) + let actual_line = line(".") + let actual_opt = matchstr( getline(actual_line), s:C_If0_Txt."\\d\\+" ) + let actual_opt = strpart( actual_opt, strlen(s:C_If0_Txt),strlen(actual_opt)-strlen(s:C_If0_Txt)) + if s:C_If0_Counter < actual_opt + let s:C_If0_Counter = actual_opt + endif + endwhile + let s:C_If0_Counter = s:C_If0_Counter+1 + silent exe ":".save_line + " + if a:mode=='a' + let zz= "\n#if 0 ".s:C_Com1." ----- #if 0 : ".s:C_If0_Txt.s:C_If0_Counter." ----- ".s:C_Com2."\n" + let zz= zz."\n#endif ".s:C_Com1." ----- #if 0 : ".s:C_If0_Txt.s:C_If0_Counter." ----- ".s:C_Com2."\n\n" + put =zz + normal 4k + endif + + if a:mode=='v' + let pos1 = line("'<") + let pos2 = line("'>") + let zz= "#endif ".s:C_Com1." ----- #if 0 : ".s:C_If0_Txt.s:C_If0_Counter." ----- ".s:C_Com2."\n\n" + exe ":".pos2."put =zz" + let zz= "\n#if 0 ".s:C_Com1." ----- #if 0 : ".s:C_If0_Txt.s:C_If0_Counter." ----- ".s:C_Com2."\n" + exe ":".pos1."put! =zz" + " + if &foldenable && foldclosed(".") + normal zv + endif + endif + +endfunction " ---------- end of function C_PPIf0 ---------- +" +"------------------------------------------------------------------------------ +" C_PPIf0Remove : remove #if 0 .. #endif {{{1 +"------------------------------------------------------------------------------ +function! C_PPIf0Remove () + " + " cursor on fold: open fold first + if &foldenable && foldclosed(".") + normal zv + endif + " + let frstline = searchpair( '^\s*#if\s\+0', '', '^\s*#endif\>.\+\.\+\=0 && match( l:snippetfile, '\.\(ni\|noindent\)$' ) < 0 + endif + endif + if line(".")==2 && getline(1)=~"^$" + silent exe ":1,1d" + endif + endif + " + " update current buffer / split window / edit snippet file + " + if a:mode == "e" + if has("browse") && s:C_GuiSnippetBrowser == 'gui' + let l:snippetfile = browse(0,"edit a code snippet",s:C_CodeSnippets,"") + else + let l:snippetfile=input("edit snippet ", s:C_CodeSnippets, "file" ) + endif + if !empty(l:snippetfile) + :execute "update! | split | edit ".l:snippetfile + endif + endif + " + " write whole buffer into snippet file + " + if a:mode == "w" || a:mode == "wv" + if has("browse") && s:C_GuiSnippetBrowser == 'gui' + let l:snippetfile = browse(0,"write a code snippet",s:C_CodeSnippets,"") + else + let l:snippetfile=input("write snippet ", s:C_CodeSnippets, "file" ) + endif + if !empty(l:snippetfile) + if filereadable(l:snippetfile) + if confirm("File ".l:snippetfile." exists ! Overwrite ? ", "&Cancel\n&No\n&Yes") != 3 + return + endif + endif + if a:mode == "w" + :execute ":write! ".l:snippetfile + else + :execute ":*write! ".l:snippetfile + endif + endif + endif + + else + echo "code snippet directory ".s:C_CodeSnippets." does not exist (please create it)" + endif +endfunction " ---------- end of function C_CodeSnippets ---------- +" +"------------------------------------------------------------------------------ +" C_help : builtin completion {{{1 +"------------------------------------------------------------------------------ +function! C_ForTypeComplete ( ArgLead, CmdLine, CursorPos ) + " + " show all types + if empty(a:ArgLead) + return s:C_ForTypes + endif + " + " show types beginning with a:ArgLead + let expansions = [] + for item in s:C_ForTypes + if match( item, '\<'.a:ArgLead.'\s*\w*' ) == 0 + call add( expansions, item ) + endif + endfor + return expansions +endfunction " ---------- end of function C_ForTypeComplete ---------- +" +"------------------------------------------------------------------------------ +" C_CodeFor : for (idiom) {{{1 +"------------------------------------------------------------------------------ +function! C_CodeFor( direction ) range + " + let updown = ( a:direction == 'up' ? 'INCR.' : 'DECR.' ) + let string = C_Input( '[TYPE (expand)] VARIABLE [START [END ['.updown.']]] : ', '', + \ 'customlist,C_ForTypeComplete' ) + if empty(string) + return + endif + " + let string = substitute( string, '\s\+', ' ', 'g' ) + let nextindex = -1 + let loopvar_type = '' + for item in s:C_ForTypes_Check_Order + let nextindex = matchend( string, '^'.item ) + if nextindex > 0 + let loopvar_type = item + let string = strpart( string, nextindex ) + endif + endfor + if !empty(loopvar_type) + let loopvar_type .= ' ' + if empty(string) + let string = C_Input( 'VARIABLE [START [END ['.updown.']]] : ', '' ) + if empty(string) + return + endif + endif + endif + let part = split( string ) + + if len( part ) > 4 + echohl WarningMsg | echomsg "for loop construction : to many arguments " | echohl None + return + endif + + let missing = 0 + while len(part) < 4 + let part = part + [''] + let missing = missing+1 + endwhile + + let [ loopvar, startval, endval, incval ] = part + + if empty(incval) + let incval = '1' + endif + + if a:direction == 'up' + if empty(endval) + let endval = 'n' + endif + if empty(startval) + let startval = '0' + endif + let zz= 'for ( '.loopvar_type.loopvar.' = '.startval.'; '.loopvar.' < '.endval.'; '.loopvar.' += '.incval." )" + else + if empty(endval) + let endval = '0' + endif + if empty(startval) + let startval = 'n-1' + endif + let zz= 'for ( '.loopvar_type.loopvar.' = '.startval.'; '.loopvar.' >= '.endval.'; '.loopvar.' -= '.incval." )" + endif + " + " use internal formatting to avoid conficts when using == below + let equalprg_save = &equalprg + set equalprg= + + " ----- normal mode ---------------- + if a:firstline == a:lastline + let zz = zz." {\n}" + put =zz + normal k + normal 2== + endif + " ----- visual mode ---------------- + if a:firstline < a:lastline + let zz = zz.' {' + let zz2= '}' + exe ":".a:lastline."put =zz2" + exe ":".a:firstline."put! =zz" + :exe 'normal ='.(a:lastline-a:firstline+2).'+' + endif + " + " restore formatter programm + let &equalprg = equalprg_save + " + " position the cursor + " + normal ^ + if missing == 1 + let match = search( '\<'.incval.'\>', 'W', line(".") ) + else + if missing == 2 + let match = search( '\<'.endval.'\>', 'W', line(".") ) + else + if missing == 3 + let match = search( '\<'.startval.'\>', 'W', line(".") ) + endif + endif + endif + " +endfunction " ---------- end of function C_CodeFor ---------- +" +"------------------------------------------------------------------------------ +" Handle prototypes {{{1 +"------------------------------------------------------------------------------ +" +let s:C_Prototype = [] +let s:C_PrototypeShow = [] +let s:C_PrototypeCounter = 0 +let s:C_CComment = '\/\*.\{-}\*\/\s*' " C comment with trailing whitespaces + " '.\{-}' any character, non-greedy +let s:C_CppComment = '\/\/.*$' " C++ comment +" +"------------------------------------------------------------------------------ +" C_ProtoPick: pick up a method prototype (normal/visual) {{{1 +" type : 'function', 'method' +"------------------------------------------------------------------------------ +function! C_ProtoPick( type ) range + " + " remove C/C++-comments, leading and trailing whitespaces, squeeze whitespaces + " + let prototyp = '' + for linenumber in range( a:firstline, a:lastline ) + let newline = getline(linenumber) + let newline = substitute( newline, s:C_CppComment, "", "" ) " remove C++ comment + let prototyp = prototyp." ".newline + endfor + " + let prototyp = substitute( prototyp, '^\s\+', "", "" ) " remove leading whitespaces + let prototyp = substitute( prototyp, s:C_CComment, "", "g" ) " remove (multiline) C comments + let prototyp = substitute( prototyp, '\s\+', " ", "g" ) " squeeze whitespaces + let prototyp = substitute( prototyp, '\s\+$', "", "" ) " remove trailing whitespaces + " + "------------------------------------------------------------------------------- + " prototype for methods + "------------------------------------------------------------------------------- + if a:type == 'method' + " + " remove template keyword + " + let prototyp = substitute( prototyp, '^template\s*<\s*class \w\+\s*>\s*', "", "" ) + " + let idx = stridx( prototyp, '(' ) " start of the parameter list + let head = strpart( prototyp, 0, idx ) + let parlist = strpart( prototyp, idx ) + " + " remove the scope resolution operator + " + let template_id = '\h\w*\s*<[^>]\+>' + let rgx2 = '\('.template_id.'\s*::\s*\)*\([~A-Za-z]\w*\|operator.\+\)\s*$' + let idx = match( head, rgx2 ) " start of the function name + let returntype = strpart( head, 0, idx ) + let fctname = strpart( head, idx ) + + let resret = matchstr( returntype, '\('.template_id.'\s*::\s*\)*'.template_id ) + let resret = substitute( resret, '\s\+', '', 'g' ) + + let resfct = matchstr( fctname , '\('.template_id.'\s*::\s*\)*'.template_id ) + let resfct = substitute( resfct, '\s\+', '', 'g' ) + + if !empty(resret) && match( resfct, resret.'$' ) >= 0 + "------------------------------------------------------------------------------- + " remove scope resolution from the return type (keep 'std::') + "------------------------------------------------------------------------------- + let returntype = substitute( returntype, '<\s*\w\+\s*>', '', 'g' ) + let returntype = substitute( returntype, '\', "", "g" ) + let fctname = substitute( fctname, '\ 1 + echon 's' + endif + " +endfunction " --------- end of function C_ProtoPick ---------- +" +"------------------------------------------------------------------------------ +" C_ProtoInsert : insert {{{1 +"------------------------------------------------------------------------------ +function! C_ProtoInsert () + " + " use internal formatting to avoid conficts when using == below + let equalprg_save = &equalprg + set equalprg= + " + if s:C_PrototypeCounter > 0 + for protytype in s:C_Prototype + put =protytype + endfor + let lines = s:C_PrototypeCounter - 1 + silent exe "normal =".lines."-" + call C_ProtoClear() + else + echo "currently no prototypes available" + endif + " + " restore formatter programm + let &equalprg = equalprg_save + " +endfunction " --------- end of function C_ProtoInsert ---------- +" +"------------------------------------------------------------------------------ +" C_ProtoClear : clear {{{1 +"------------------------------------------------------------------------------ +function! C_ProtoClear () + if s:C_PrototypeCounter > 0 + let s:C_Prototype = [] + let s:C_PrototypeShow = [] + if s:C_PrototypeCounter == 1 + echo s:C_PrototypeCounter.' prototype deleted' + else + echo s:C_PrototypeCounter.' prototypes deleted' + endif + let s:C_PrototypeCounter = 0 + else + echo "currently no prototypes available" + endif +endfunction " --------- end of function C_ProtoClear ---------- +" +"------------------------------------------------------------------------------ +" C_ProtoShow : show {{{1 +"------------------------------------------------------------------------------ +function! C_ProtoShow () + if s:C_PrototypeCounter > 0 + for protytype in s:C_PrototypeShow + echo protytype + endfor + else + echo "currently no prototypes available" + endif +endfunction " --------- end of function C_ProtoShow ---------- +" +"------------------------------------------------------------------------------ +" C_EscapeBlanks : C_EscapeBlanks {{{1 +"------------------------------------------------------------------------------ +function! C_EscapeBlanks (arg) + return substitute( a:arg, " ", "\\ ", "g" ) +endfunction " --------- end of function C_EscapeBlanks ---------- +" +"------------------------------------------------------------------------------ +" C_Compile : C_Compile {{{1 +"------------------------------------------------------------------------------ +" The standard make program 'make' called by vim is set to the C or C++ compiler +" and reset after the compilation (setlocal makeprg=... ). +" The errorfile created by the compiler will now be read by gvim and +" the commands cl, cp, cn, ... can be used. +"------------------------------------------------------------------------------ +let s:LastShellReturnCode = 0 " for compile / link / run only + +function! C_Compile () + + let s:C_HlMessage = "" + exe ":cclose" + let Sou = expand("%:p") " name of the file in the current buffer + let Obj = expand("%:p:r").s:C_ObjExtension " name of the object + let SouEsc= escape( Sou, s:C_FilenameEscChar ) + let ObjEsc= escape( Obj, s:C_FilenameEscChar ) + if s:MSWIN + let SouEsc = '"'.SouEsc.'"' + let ObjEsc = '"'.ObjEsc.'"' + endif + + " update : write source file if necessary + exe ":update" + + " compilation if object does not exist or object exists and is older then the source + if !filereadable(Obj) || (filereadable(Obj) && (getftime(Obj) < getftime(Sou))) + " &makeprg can be a string containing blanks + let makeprg_saved = '"'.&makeprg.'"' + if expand("%:e") == s:C_CExtension + exe "setlocal makeprg=".s:C_CCompiler + else + exe "setlocal makeprg=".s:C_CplusCompiler + endif + " + " COMPILATION + " + exe ":compiler ".s:C_VimCompilerName + let v:statusmsg = '' + let s:LastShellReturnCode = 0 + exe "make ".s:C_CFlags." ".SouEsc." -o ".ObjEsc + exe "setlocal makeprg=".makeprg_saved + if empty(v:statusmsg) + let s:C_HlMessage = "'".Obj."' : compilation successful" + endif + if v:shell_error != 0 + let s:LastShellReturnCode = v:shell_error + endif + " + " open error window if necessary + :redraw! + exe ":botright cwindow" + else + let s:C_HlMessage = " '".Obj."' is up to date " + endif + +endfunction " ---------- end of function C_Compile ---------- + +"=== FUNCTION ================================================================ +" NAME: C_CheckForMain +" DESCRIPTION: check if current buffer contains a main function +" PARAMETERS: +" RETURNS: 0 : no main function +"=============================================================================== +function! C_CheckForMain () + return search( '^\(\s*int\s\+\)\=\s*main', "cnw" ) +endfunction " ---------- end of function C_CheckForMain ---------- +" +"------------------------------------------------------------------------------ +" C_Link : C_Link {{{1 +"------------------------------------------------------------------------------ +" The standard make program which is used by gvim is set to the compiler +" (for linking) and reset after linking. +" +" calls: C_Compile +"------------------------------------------------------------------------------ +function! C_Link () + + call C_Compile() + :redraw! + if s:LastShellReturnCode != 0 + let s:LastShellReturnCode = 0 + return + endif + + let s:C_HlMessage = "" + let Sou = expand("%:p") " name of the file (full path) + let Obj = expand("%:p:r").s:C_ObjExtension " name of the object file + let Exe = expand("%:p:r").s:C_ExeExtension " name of the executable + let ObjEsc= escape( Obj, s:C_FilenameEscChar ) + let ExeEsc= escape( Exe, s:C_FilenameEscChar ) + if s:MSWIN + let ObjEsc = '"'.ObjEsc.'"' + let ExeEsc = '"'.ExeEsc.'"' + endif + + if C_CheckForMain() == 0 + let s:C_HlMessage = "no main function in '".Sou."'" + return + endif + + " no linkage if: + " executable exists + " object exists + " source exists + " executable newer then object + " object newer then source + + if filereadable(Exe) && + \ filereadable(Obj) && + \ filereadable(Sou) && + \ (getftime(Exe) >= getftime(Obj)) && + \ (getftime(Obj) >= getftime(Sou)) + let s:C_HlMessage = " '".Exe."' is up to date " + return + endif + + " linkage if: + " object exists + " source exists + " object newer then source + + if filereadable(Obj) && (getftime(Obj) >= getftime(Sou)) + let makeprg_saved='"'.&makeprg.'"' + if expand("%:e") == s:C_CExtension + exe "setlocal makeprg=".s:C_CCompiler + else + exe "setlocal makeprg=".s:C_CplusCompiler + endif + exe ":compiler ".s:C_VimCompilerName + let s:LastShellReturnCode = 0 + let v:statusmsg = '' + silent exe "make ".s:C_LFlags." -o ".ExeEsc." ".ObjEsc." ".s:C_Libs + if v:shell_error != 0 + let s:LastShellReturnCode = v:shell_error + endif + exe "setlocal makeprg=".makeprg_saved + " + if empty(v:statusmsg) + let s:C_HlMessage = "'".Exe."' : linking successful" + " open error window if necessary + :redraw! + exe ":botright cwindow" + else + exe ":botright copen" + endif + endif +endfunction " ---------- end of function C_Link ---------- +" +"------------------------------------------------------------------------------ +" C_Run : C_Run {{{1 +" calls: C_Link +"------------------------------------------------------------------------------ +" +let s:C_OutputBufferName = "C-Output" +let s:C_OutputBufferNumber = -1 +let s:C_RunMsg1 ="' does not exist or is not executable or object/source older then executable" +let s:C_RunMsg2 ="' does not exist or is not executable" +" +function! C_Run () +" + let s:C_HlMessage = "" + let Sou = expand("%:p") " name of the source file + let Obj = expand("%:p:r").s:C_ObjExtension " name of the object file + let Exe = expand("%:p:r").s:C_ExeExtension " name of the executable + let ExeEsc = escape( Exe, s:C_FilenameEscChar ) " name of the executable, escaped + let Quote = '' + if s:MSWIN + let Quote = '"' + endif + " + let l:arguments = exists("b:C_CmdLineArgs") ? b:C_CmdLineArgs : '' + " + let l:currentbuffer = bufname("%") + " + "============================================================================== + " run : run from the vim command line + "============================================================================== + if s:C_OutputGvim == "vim" + " + if s:C_MakeExecutableToRun !~ "^\s*$" + call C_HlMessage( "executable : '".s:C_MakeExecutableToRun."'" ) + exe '!'.Quote.s:C_MakeExecutableToRun.Quote.' '.l:arguments + else + + silent call C_Link() + if s:LastShellReturnCode == 0 + " clear the last linking message if any" + let s:C_HlMessage = "" + call C_HlMessage() + endif + " + if executable(Exe) && getftime(Exe) >= getftime(Obj) && getftime(Obj) >= getftime(Sou) + exe "!".Quote.ExeEsc.Quote." ".l:arguments + else + echomsg "file '".Exe.s:C_RunMsg1 + endif + endif + + endif + " + "============================================================================== + " run : redirect output to an output buffer + "============================================================================== + if s:C_OutputGvim == "buffer" + let l:currentbuffernr = bufnr("%") + " + if s:C_MakeExecutableToRun =~ "^\s*$" + call C_Link() + endif + if l:currentbuffer == bufname("%") + " + " + if bufloaded(s:C_OutputBufferName) != 0 && bufwinnr(s:C_OutputBufferNumber)!=-1 + exe bufwinnr(s:C_OutputBufferNumber) . "wincmd w" + " buffer number may have changed, e.g. after a 'save as' + if bufnr("%") != s:C_OutputBufferNumber + let s:C_OutputBufferNumber = bufnr(s:C_OutputBufferName) + exe ":bn ".s:C_OutputBufferNumber + endif + else + silent exe ":new ".s:C_OutputBufferName + let s:C_OutputBufferNumber=bufnr("%") + setlocal buftype=nofile + setlocal noswapfile + setlocal syntax=none + setlocal bufhidden=delete + setlocal tabstop=8 + endif + " + " run programm + " + setlocal modifiable + if s:C_MakeExecutableToRun !~ "^\s*$" + call C_HlMessage( "executable : '".s:C_MakeExecutableToRun."'" ) + exe '%!'.Quote.s:C_MakeExecutableToRun.Quote.' '.l:arguments + setlocal nomodifiable + " + if winheight(winnr()) >= line("$") + exe bufwinnr(l:currentbuffernr) . "wincmd w" + endif + else + " + if executable(Exe) && getftime(Exe) >= getftime(Obj) && getftime(Obj) >= getftime(Sou) + exe "%!".Quote.ExeEsc.Quote." ".l:arguments + setlocal nomodifiable + " + if winheight(winnr()) >= line("$") + exe bufwinnr(l:currentbuffernr) . "wincmd w" + endif + else + setlocal nomodifiable + :close + echomsg "file '".Exe.s:C_RunMsg1 + endif + endif + " + endif + endif + " + "============================================================================== + " run : run in a detached xterm (not available for MS Windows) + "============================================================================== + if s:C_OutputGvim == "xterm" + " + if s:C_MakeExecutableToRun !~ "^\s*$" + if s:MSWIN + exe '!'.Quote.s:C_MakeExecutableToRun.Quote.' '.l:arguments + else + silent exe '!xterm -title '.s:C_MakeExecutableToRun.' '.s:C_XtermDefaults.' -e '.s:C_Wrapper.' '.s:C_MakeExecutableToRun.' '.l:arguments.' &' + :redraw! + call C_HlMessage( "executable : '".s:C_MakeExecutableToRun."'" ) + endif + else + + silent call C_Link() + " + if executable(Exe) && getftime(Exe) >= getftime(Obj) && getftime(Obj) >= getftime(Sou) + if s:MSWIN + exe "!".Quote.ExeEsc.Quote." ".l:arguments + else + silent exe '!xterm -title '.ExeEsc.' '.s:C_XtermDefaults.' -e '.s:C_Wrapper.' '.ExeEsc.' '.l:arguments.' &' + :redraw! + endif + else + echomsg "file '".Exe.s:C_RunMsg1 + endif + endif + endif + +endfunction " ---------- end of function C_Run ---------- +" +"------------------------------------------------------------------------------ +" C_Arguments : Arguments for the executable {{{1 +"------------------------------------------------------------------------------ +function! C_Arguments () + let Exe = expand("%:r").s:C_ExeExtension + if empty(Exe) + redraw + echohl WarningMsg | echo "no file name " | echohl None + return + endif + let prompt = 'command line arguments for "'.Exe.'" : ' + if exists("b:C_CmdLineArgs") + let b:C_CmdLineArgs= C_Input( prompt, b:C_CmdLineArgs, 'file' ) + else + let b:C_CmdLineArgs= C_Input( prompt , "", 'file' ) + endif +endfunction " ---------- end of function C_Arguments ---------- +" +"---------------------------------------------------------------------- +" C_Toggle_Gvim_Xterm : change output destination {{{1 +"---------------------------------------------------------------------- +function! C_Toggle_Gvim_Xterm () + + if s:C_OutputGvim == "vim" + exe "aunmenu ".s:MenuRun.'.&output:\ VIM->buffer->xterm' + exe "amenu ".s:MenuRun.'.&output:\ BUFFER->xterm->vim\\ro :call C_Toggle_Gvim_Xterm()' + exe "imenu ".s:MenuRun.'.&output:\ BUFFER->xterm->vim\\ro :call C_Toggle_Gvim_Xterm()' + let s:C_OutputGvim = "buffer" + else + if s:C_OutputGvim == "buffer" + exe "aunmenu ".s:MenuRun.'.&output:\ BUFFER->xterm->vim' + if (!s:MSWIN) + exe "amenu ".s:MenuRun.'.&output:\ XTERM->vim->buffer\\ro :call C_Toggle_Gvim_Xterm()' + exe "imenu ".s:MenuRun.'.&output:\ XTERM->vim->buffer\\ro :call C_Toggle_Gvim_Xterm()' + else + exe "amenu ".s:MenuRun.'.&output:\ VIM->buffer->xterm\\ro :call C_Toggle_Gvim_Xterm()' + exe "imenu ".s:MenuRun.'.&output:\ VIM->buffer->xterm\\ro :call C_Toggle_Gvim_Xterm()' + endif + if (!s:MSWIN) && (!empty(s:C_Display)) + let s:C_OutputGvim = "xterm" + else + let s:C_OutputGvim = "vim" + endif + else + " ---------- output : xterm -> gvim + exe "aunmenu ".s:MenuRun.'.&output:\ XTERM->vim->buffer' + exe "amenu ".s:MenuRun.'.&output:\ VIM->buffer->xterm\\ro :call C_Toggle_Gvim_Xterm()' + exe "imenu ".s:MenuRun.'.&output:\ VIM->buffer->xterm\\ro :call C_Toggle_Gvim_Xterm()' + let s:C_OutputGvim = "vim" + endif + endif + echomsg "output destination is '".s:C_OutputGvim."'" + +endfunction " ---------- end of function C_Toggle_Gvim_Xterm ---------- +" +"------------------------------------------------------------------------------ +" C_XtermSize : xterm geometry {{{1 +"------------------------------------------------------------------------------ +function! C_XtermSize () + let regex = '-geometry\s\+\d\+x\d\+' + let geom = matchstr( s:C_XtermDefaults, regex ) + let geom = matchstr( geom, '\d\+x\d\+' ) + let geom = substitute( geom, 'x', ' ', "" ) + let answer= C_Input(" xterm size (COLUMNS LINES) : ", geom ) + while match(answer, '^\s*\d\+\s\+\d\+\s*$' ) < 0 + let answer= C_Input(" + xterm size (COLUMNS LINES) : ", geom ) + endwhile + let answer = substitute( answer, '\s\+', "x", "" ) " replace inner whitespaces + let s:C_XtermDefaults = substitute( s:C_XtermDefaults, regex, "-geometry ".answer , "" ) +endfunction " ---------- end of function C_XtermSize ---------- +" +"------------------------------------------------------------------------------ +" run make(1) {{{1 +"------------------------------------------------------------------------------ +let s:C_MakeCmdLineArgs = '' " command line arguments for Run-make; initially empty +let s:C_MakeExecutableToRun = '' +let s:C_Makefile = '' +" +"------------------------------------------------------------------------------ +" C_ChooseMakefile : choose a makefile {{{1 +"------------------------------------------------------------------------------ +function! C_ChooseMakefile () + let s:C_Makefile = '' + " the path will be escaped: + let s:C_Makefile = C_Input ( "choose a Makefile: ", getcwd(), "file" ) + if s:MSWIN + let s:C_Makefile = substitute( s:C_Makefile, '\\ ', ' ', 'g' ) + endif +endfunction " ---------- end of function C_ChooseMakefile ---------- +" +"------------------------------------------------------------------------------ +" C_Make : run make {{{1 +"------------------------------------------------------------------------------ +function! C_Make() + exe ":cclose" + " update : write source file if necessary + exe ":update" + " run make + if s:C_Makefile == '' + exe ":make ".s:C_MakeCmdLineArgs + else + exe ':lchdir '.fnamemodify( s:C_Makefile, ":p:h" ) + if s:MSWIN + exe ':make -f "'.s:C_Makefile.'" '.s:C_MakeCmdLineArgs + else + exe ':make -f '.s:C_Makefile.' '.s:C_MakeCmdLineArgs + endif + exe ":lchdir -" + endif + exe ":botright cwindow" + " +endfunction " ---------- end of function C_Make ---------- +" +"------------------------------------------------------------------------------ +" C_MakeClean : run 'make clean' {{{1 +"------------------------------------------------------------------------------ +function! C_MakeClean() + " run make clean + if s:C_Makefile == '' + exe ":make clean" + else + exe ':lchdir '.fnamemodify( s:C_Makefile, ":p:h" ) + if s:MSWIN + exe ':make -f "'.s:C_Makefile.'" clean' + else + exe ':make -f '.s:C_Makefile.' clean' + endif + exe ":lchdir -" + endif +endfunction " ---------- end of function C_MakeClean ---------- + +"------------------------------------------------------------------------------ +" C_MakeArguments : get make command line arguments {{{1 +"------------------------------------------------------------------------------ +function! C_MakeArguments () + let s:C_MakeCmdLineArgs= C_Input( 'make command line arguments : ', s:C_MakeCmdLineArgs, 'file' ) +endfunction " ---------- end of function C_MakeArguments ---------- + +"------------------------------------------------------------------------------ +" C_MakeExeToRun : choose executable to run {{{1 +"------------------------------------------------------------------------------ +function! C_MakeExeToRun () + let s:C_MakeExecutableToRun = C_Input( 'executable to run [tab compl.]: ', '', 'file' ) + if s:C_MakeExecutableToRun !~ "^\s*$" + if s:MSWIN + let s:C_MakeExecutableToRun = substitute(s:C_MakeExecutableToRun, '\\ ', ' ', 'g' ) + endif + let s:C_MakeExecutableToRun = escape( getcwd().'/', s:C_FilenameEscChar ).s:C_MakeExecutableToRun + endif +endfunction " ---------- end of function C_MakeExeToRun ---------- +" +"------------------------------------------------------------------------------ +" C_SplintArguments : splint command line arguments {{{1 +"------------------------------------------------------------------------------ +function! C_SplintArguments () + if s:C_SplintIsExecutable==0 + let s:C_HlMessage = ' Splint is not executable or not installed! ' + else + let prompt = 'Splint command line arguments for "'.expand("%").'" : ' + if exists("b:C_SplintCmdLineArgs") + let b:C_SplintCmdLineArgs= C_Input( prompt, b:C_SplintCmdLineArgs ) + else + let b:C_SplintCmdLineArgs= C_Input( prompt , "" ) + endif + endif +endfunction " ---------- end of function C_SplintArguments ---------- +" +"------------------------------------------------------------------------------ +" C_SplintCheck : run splint(1) {{{1 +"------------------------------------------------------------------------------ +function! C_SplintCheck () + if s:C_SplintIsExecutable==0 + let s:C_HlMessage = ' Splint is not executable or not installed! ' + return + endif + let l:currentbuffer=bufname("%") + if &filetype != "c" && &filetype != "cpp" + let s:C_HlMessage = ' "'.l:currentbuffer.'" seems not to be a C/C++ file ' + return + endif + let s:C_HlMessage = "" + exe ":cclose" + silent exe ":update" + let makeprg_saved='"'.&makeprg.'"' + " Windows seems to need this: + if s:MSWIN + :compiler splint + endif + :setlocal makeprg=splint + " + let l:arguments = exists("b:C_SplintCmdLineArgs") ? b:C_SplintCmdLineArgs : ' ' + silent exe "make ".l:arguments." ".escape(l:currentbuffer,s:C_FilenameEscChar) + exe "setlocal makeprg=".makeprg_saved + exe ":botright cwindow" + " + " message in case of success + " + if l:currentbuffer == bufname("%") + let s:C_HlMessage = " Splint --- no warnings for : ".l:currentbuffer + endif +endfunction " ---------- end of function C_SplintCheck ---------- +" +"------------------------------------------------------------------------------ +" C_CodeCheckArguments : CodeCheck command line arguments {{{1 +"------------------------------------------------------------------------------ +function! C_CodeCheckArguments () + if s:C_CodeCheckIsExecutable==0 + let s:C_HlMessage = ' CodeCheck is not executable or not installed! ' + else + let prompt = 'CodeCheck command line arguments for "'.expand("%").'" : ' + if exists("b:C_CodeCheckCmdLineArgs") + let b:C_CodeCheckCmdLineArgs= C_Input( prompt, b:C_CodeCheckCmdLineArgs ) + else + let b:C_CodeCheckCmdLineArgs= C_Input( prompt , s:C_CodeCheckOptions ) + endif + endif +endfunction " ---------- end of function C_CodeCheckArguments ---------- +" +"------------------------------------------------------------------------------ +" C_CodeCheck : run CodeCheck {{{1 +"------------------------------------------------------------------------------ +function! C_CodeCheck () + if s:C_CodeCheckIsExecutable==0 + let s:C_HlMessage = ' CodeCheck is not executable or not installed! ' + return + endif + let l:currentbuffer=bufname("%") + if &filetype != "c" && &filetype != "cpp" + let s:C_HlMessage = ' "'.l:currentbuffer.'" seems not to be a C/C++ file ' + return + endif + let s:C_HlMessage = "" + exe ":cclose" + silent exe ":update" + let makeprg_saved='"'.&makeprg.'"' + exe "setlocal makeprg=".s:C_CodeCheckExeName + " + " match the splint error messages (quickfix commands) + " ignore any lines that didn't match one of the patterns + " + :setlocal errorformat=%f(%l)%m + " + let l:arguments = exists("b:C_CodeCheckCmdLineArgs") ? b:C_CodeCheckCmdLineArgs : "" + if empty( l:arguments ) + let l:arguments = s:C_CodeCheckOptions + endif + exe ":make ".l:arguments." ".escape( l:currentbuffer, s:C_FilenameEscChar ) + exe ':setlocal errorformat=' + exe ":setlocal makeprg=".makeprg_saved + exe ":botright cwindow" + " + " message in case of success + " + if l:currentbuffer == bufname("%") + let s:C_HlMessage = " CodeCheck --- no warnings for : ".l:currentbuffer + endif +endfunction " ---------- end of function C_CodeCheck ---------- +" +"------------------------------------------------------------------------------ +" C_Indent : run indent(1) {{{1 +"------------------------------------------------------------------------------ +" +function! C_Indent ( ) + if !executable("indent") + echomsg 'indent is not executable or not installed!' + return + endif + let l:currentbuffer=expand("%:p") + if &filetype != "c" && &filetype != "cpp" + echomsg '"'.l:currentbuffer.'" seems not to be a C/C++ file ' + return + endif + if C_Input("indent whole file [y/n/Esc] : ", "y" ) != "y" + return + endif + :update + + exe ":cclose" + if s:MSWIN + silent exe ":%!indent " + else + silent exe ":%!indent 2> ".s:C_IndentErrorLog + redraw! + if getfsize( s:C_IndentErrorLog ) > 0 + exe ':edit! '.s:C_IndentErrorLog + let errorlogbuffer = bufnr("%") + exe ':%s/^indent: Standard input/indent: '.escape( l:currentbuffer, '/' ).'/' + setlocal errorformat=indent:\ %f:%l:%m + :cbuffer + exe ':bdelete! '.errorlogbuffer + exe ':botright cwindow' + else + echomsg 'File "'.l:currentbuffer.'" reformatted.' + endif + setlocal errorformat= + endif + +endfunction " ---------- end of function C_Indent ---------- +" +"------------------------------------------------------------------------------ +" C_HlMessage : indent message {{{1 +"------------------------------------------------------------------------------ +function! C_HlMessage ( ... ) + redraw! + echohl Search + if a:0 == 0 + echo s:C_HlMessage + else + echo a:1 + endif + echohl None +endfunction " ---------- end of function C_HlMessage ---------- +" +"------------------------------------------------------------------------------ +" C_Settings : settings {{{1 +"------------------------------------------------------------------------------ +function! C_Settings () + let txt = " C/C++-Support settings\n\n" + let txt = txt.' author : "'.s:C_Macro['|AUTHOR|']."\"\n" + let txt = txt.' authorref : "'.s:C_Macro['|AUTHORREF|']."\"\n" + let txt = txt.' company : "'.s:C_Macro['|COMPANY|']."\"\n" + let txt = txt.' copyright holder : "'.s:C_Macro['|COPYRIGHTHOLDER|']."\"\n" + let txt = txt.' email : "'.s:C_Macro['|EMAIL|']."\"\n" + let txt = txt.' licence : "'.s:C_Macro['|LICENSE|']."\"\n" + let txt = txt.' organization : "'.s:C_Macro['|ORGANIZATION|']."\"\n" + let txt = txt.' project : "'.s:C_Macro['|PROJECT|']."\"\n" + let txt = txt.' C / C++ compiler : '.s:C_CCompiler.' / '.s:C_CplusCompiler."\n" + let txt = txt.' C file extension : "'.s:C_CExtension.'" (everything else is C++)'."\n" + let txt = txt.' extension for objects : "'.s:C_ObjExtension."\"\n" + let txt = txt.'extension for executables : "'.s:C_ExeExtension."\"\n" + let txt = txt.' compiler flags : "'.s:C_CFlags."\"\n" + let txt = txt.' linker flags : "'.s:C_LFlags."\"\n" + let txt = txt.' libraries : "'.s:C_Libs."\"\n" + let txt = txt.' code snippet directory : "'.s:C_CodeSnippets."\"\n" + " ----- template files ------------------------ + let txt = txt.' template style : "'.s:C_ActualStyle."\"\n" + let txt = txt.' plugin installation : "'.s:installation."\"\n" + if s:installation == 'system' + let txt = txt.'global template directory : '.s:C_GlobalTemplateDir."\n" + if filereadable( s:C_LocalTemplateFile ) + let txt = txt.' local template directory : '.s:C_LocalTemplateDir."\n" + endif + else + let txt = txt.' local template directory : '.s:C_LocalTemplateDir."\n" + endif + if !s:MSWIN + let txt = txt.' xterm defaults : '.s:C_XtermDefaults."\n" + endif + " ----- dictionaries ------------------------ + if !empty(g:C_Dictionary_File) + let ausgabe= &dictionary + let ausgabe= substitute( ausgabe, ",", ",\n + ", "g" ) + let txt = txt." dictionary file(s) : ".ausgabe."\n" + endif + let txt = txt.' current output dest. : '.s:C_OutputGvim."\n" + " ----- splint ------------------------------ + if s:C_SplintIsExecutable==1 + if exists("b:C_SplintCmdLineArgs") + let ausgabe = b:C_SplintCmdLineArgs + else + let ausgabe = "" + endif + let txt = txt." splint options(s) : ".ausgabe."\n" + endif + " ----- code check -------------------------- + if s:C_CodeCheckIsExecutable==1 + if exists("b:C_CodeCheckCmdLineArgs") + let ausgabe = b:C_CodeCheckCmdLineArgs + else + let ausgabe = s:C_CodeCheckOptions + endif + let txt = txt."CodeCheck (TM) options(s) : ".ausgabe."\n" + endif + let txt = txt."\n" + let txt = txt."__________________________________________________________________________\n" + let txt = txt." C/C++-Support, Version ".g:C_Version." / Dr.-Ing. Fritz Mehner / mehner@fh-swf.de\n\n" + echo txt +endfunction " ---------- end of function C_Settings ---------- +" +"------------------------------------------------------------------------------ +" C_Hardcopy : hardcopy {{{1 +" MSWIN : a printer dialog is displayed +" other : print PostScript to file +"------------------------------------------------------------------------------ +function! C_Hardcopy () range + let outfile = expand("%") + if empty(outfile) + let s:C_HlMessage = 'Buffer has no name.' + call C_HlMessage() + endif + let outdir = getcwd() + if filewritable(outdir) != 2 + let outdir = $HOME + endif + if !s:MSWIN + let outdir = outdir.'/' + endif + let old_printheader=&printheader + exe ':set printheader='.s:C_Printheader + " ----- normal mode ---------------- + if a:firstline == a:lastline + silent exe 'hardcopy > '.outdir.outfile.'.ps' + if !s:MSWIN + echo 'file "'.outfile.'" printed to "'.outdir.outfile.'.ps"' + endif + endif + " ----- visual mode / range ---------------- + if a:firstline < a:lastline + silent exe a:firstline.','.a:lastline."hardcopy > ".outdir.outfile.".ps" + if !s:MSWIN + echo 'file "'.outfile.'" (lines '.a:firstline.'-'.a:lastline.') printed to "'.outdir.outfile.'.ps"' + endif + endif + exe ':set printheader='.escape( old_printheader, ' %' ) +endfunction " ---------- end of function C_Hardcopy ---------- +" +"------------------------------------------------------------------------------ +" C_HelpCsupport : help csupport {{{1 +"------------------------------------------------------------------------------ +function! C_HelpCsupport () + try + :help csupport + catch + exe ':helptags '.s:plugin_dir.'/doc' + :help csupport + endtry +endfunction " ---------- end of function C_HelpCsupport ---------- +" +"------------------------------------------------------------------------------ +" C_Help : lookup word under the cursor or ask {{{1 +"------------------------------------------------------------------------------ +" +let s:C_DocBufferName = "C_HELP" +let s:C_DocHelpBufferNumber = -1 +" +function! C_Help( type ) + + let cuc = getline(".")[col(".") - 1] " character under the cursor + let item = expand("") " word under the cursor + if empty(cuc) || empty(item) || match( item, cuc ) == -1 + let item=C_Input('name of the manual page : ', '' ) + endif + + if empty(item) + return + endif + "------------------------------------------------------------------------------ + " replace buffer content with bash help text + "------------------------------------------------------------------------------ + " + " jump to an already open bash help window or create one + " + if bufloaded(s:C_DocBufferName) != 0 && bufwinnr(s:C_DocHelpBufferNumber) != -1 + exe bufwinnr(s:C_DocHelpBufferNumber) . "wincmd w" + " buffer number may have changed, e.g. after a 'save as' + if bufnr("%") != s:C_DocHelpBufferNumber + let s:C_DocHelpBufferNumber=bufnr(s:C_OutputBufferName) + exe ":bn ".s:C_DocHelpBufferNumber + endif + else + exe ":new ".s:C_DocBufferName + let s:C_DocHelpBufferNumber=bufnr("%") + setlocal buftype=nofile + setlocal noswapfile + setlocal bufhidden=delete + setlocal filetype=sh " allows repeated use of + setlocal syntax=OFF + endif + setlocal modifiable + " + if a:type == 'm' + " + " Is there more than one manual ? + " + let manpages = system( s:C_Man.' -k '.item ) + if v:shell_error + echomsg "Shell command '".s:C_Man." -k ".item."' failed." + :close + return + endif + let catalogs = split( manpages, '\n', ) + let manual = {} + " + " Select manuals where the name exactly matches + " + for line in catalogs + if line =~ '^'.item.'\s\+(' + let itempart = split( line, '\s\+' ) + let catalog = itempart[1][1:-2] + if match( catalog, '.p$' ) == -1 + let manual[catalog] = catalog + endif + endif + endfor + " + " Build a selection list if there are more than one manual + " + let catalog = "" + if len(keys(manual)) > 1 + for key in keys(manual) + echo ' '.item.' '.key + endfor + let defaultcatalog = '' + if has_key( manual, '3' ) + let defaultcatalog = '3' + else + if has_key( manual, '2' ) + let defaultcatalog = '2' + endif + endif + let catalog = input( 'select manual section ( cancels) : ', defaultcatalog ) + if ! has_key( manual, catalog ) + :close + :redraw + echomsg "no appropriate manual section '".catalog."'" + return + endif + endif + + set filetype=man + silent exe ":%!".s:C_Man." ".catalog." ".item + + if s:MSWIN + call s:C_RemoveSpecialCharacters() + endif + endif + + setlocal nomodifiable +endfunction " ---------- end of function C_Help ---------- +" +"------------------------------------------------------------------------------ +" C_RemoveSpecialCharacters {{{1 +" remove in CYGWIN man(1) output +" remove _ in CYGWIN man(1) output +"------------------------------------------------------------------------------ +" +function! s:C_RemoveSpecialCharacters ( ) + let patternunderline = '_\%x08' + let patternbold = '\%x08.' + setlocal modifiable + if search(patternunderline) != 0 + silent exe ':%s/'.patternunderline.'//g' + endif + if search(patternbold) != 0 + silent exe ':%s/'.patternbold.'//g' + endif + setlocal nomodifiable + silent normal gg +endfunction " ---------- end of function s:C_RemoveSpecialCharacters ---------- + +"------------------------------------------------------------------------------ +" C_CreateMenusDelayed {{{1 +"------------------------------------------------------------------------------ +let s:C_MenusVisible = 'no' " state variable controlling the C-menus +" +function! C_CreateMenusDelayed () + if s:C_CreateMenusDelayed == 'yes' && s:C_MenusVisible == 'no' + call C_CreateGuiMenus() + endif +endfunction " ---------- end of function C_CreateMenusDelayed ---------- +" +"------------------------------------------------------------------------------ +" C_CreateGuiMenus {{{1 +"------------------------------------------------------------------------------ +function! C_CreateGuiMenus () + if s:C_MenusVisible == 'no' + aunmenu &Tools.Load\ C\ Support + amenu 40.1000 &Tools.-SEP100- : + amenu 40.1030 &Tools.Unload\ C\ Support :call C_RemoveGuiMenus() + call C_InitMenus() + let s:C_MenusVisible = 'yes' + endif +endfunction " ---------- end of function C_CreateGuiMenus ---------- + +"------------------------------------------------------------------------------ +" C_ToolMenu {{{1 +"------------------------------------------------------------------------------ +function! C_ToolMenu () + amenu 40.1000 &Tools.-SEP100- : + amenu 40.1030 &Tools.Load\ C\ Support :call C_CreateGuiMenus() + imenu 40.1030 &Tools.Load\ C\ Support :call C_CreateGuiMenus() +endfunction " ---------- end of function C_ToolMenu ---------- + +"------------------------------------------------------------------------------ +" C_RemoveGuiMenus {{{1 +"------------------------------------------------------------------------------ +function! C_RemoveGuiMenus () + if s:C_MenusVisible == 'yes' + exe "aunmenu ".s:C_Root + " + aunmenu &Tools.Unload\ C\ Support + call C_ToolMenu() + " + let s:C_MenusVisible = 'no' + endif +endfunction " ---------- end of function C_RemoveGuiMenus ---------- + +"------------------------------------------------------------------------------ +" C_RereadTemplates {{{1 +" rebuild commands and the menu from the (changed) template file +"------------------------------------------------------------------------------ +function! C_RereadTemplates ( msg ) + let s:style = 'default' + let s:C_Template = { 'default' : {} } + let s:C_FileVisited = [] + let messsage = '' + " + if s:installation == 'system' + "------------------------------------------------------------------------------- + " system installation + "------------------------------------------------------------------------------- + if filereadable( s:C_GlobalTemplateFile ) + call C_ReadTemplates( s:C_GlobalTemplateFile ) + else + echomsg "Global template file '".s:C_GlobalTemplateFile."' not readable." + return + endif + let messsage = "Templates read from '".s:C_GlobalTemplateFile."'" + " + if filereadable( s:C_LocalTemplateFile ) + call C_ReadTemplates( s:C_LocalTemplateFile ) + let messsage = messsage." and '".s:C_LocalTemplateFile."'" + if s:C_Macro['|AUTHOR|'] == 'YOUR NAME' + echomsg "Please set your personal details in file '".s:C_LocalTemplateFile."'." + endif + else + let template = [ '|AUTHOR| = YOUR NAME', + \ '|COPYRIGHT| = Copyright (c) |YEAR|, |AUTHOR|' + \ ] + if finddir( s:C_LocalTemplateDir ) == '' + " try to create a local template directory + if exists("*mkdir") + try + call mkdir( s:C_LocalTemplateDir, "p" ) + " write a default local template file + call writefile( template, s:C_LocalTemplateFile ) + catch /.*/ + endtry + endif + else + " write a default local template file + call writefile( template, s:C_LocalTemplateFile ) + endif + endif + " + else + "------------------------------------------------------------------------------- + " local installation + "------------------------------------------------------------------------------- + if filereadable( s:C_LocalTemplateFile ) + call C_ReadTemplates( s:C_LocalTemplateFile ) + let messsage = "Templates read from '".s:C_LocalTemplateFile."'" + else + echomsg "Local template file '".s:C_LocalTemplateFile."' not readable." + return + endif + " + endif + if a:msg == 'yes' + echomsg messsage.'.' + endif + +endfunction " ---------- end of function C_RereadTemplates ---------- +" +"------------------------------------------------------------------------------ +" C_BrowseTemplateFiles {{{1 +"------------------------------------------------------------------------------ +function! C_BrowseTemplateFiles ( type ) + let templatefile = eval( 's:C_'.a:type.'TemplateFile' ) + let templatedir = eval( 's:C_'.a:type.'TemplateDir' ) + if isdirectory( templatedir ) + if has("browse") && s:C_GuiTemplateBrowser == 'gui' + let l:templatefile = browse(0,"edit a template file", templatedir, "" ) + else + let l:templatefile = '' + if s:C_GuiTemplateBrowser == 'explorer' + exe ':Explore '.templatedir + endif + if s:C_GuiTemplateBrowser == 'commandline' + let l:templatefile = input("edit a template file", templatedir, "file" ) + endif + endif + if !empty(l:templatefile) + :execute "update! | split | edit ".l:templatefile + endif + else + echomsg "Template directory '".templatedir."' does not exist." + endif +endfunction " ---------- end of function C_BrowseTemplateFiles ---------- + +"------------------------------------------------------------------------------ +" C_ReadTemplates {{{1 +" read the template file(s), build the macro and the template dictionary +" +"------------------------------------------------------------------------------ +let s:style = 'default' +function! C_ReadTemplates ( templatefile ) + + if !filereadable( a:templatefile ) + echohl WarningMsg + echomsg "C/C++ template file '".a:templatefile."' does not exist or is not readable" + echohl None + return + endif + + let skipmacros = 0 + let s:C_FileVisited += [a:templatefile] + + "------------------------------------------------------------------------------ + " read template file, start with an empty template dictionary + "------------------------------------------------------------------------------ + + let item = '' + let skipline = 0 + for line in readfile( a:templatefile ) + " if not a comment : + if line !~ s:C_MacroCommentRegex + " + "------------------------------------------------------------------------------- + " IF |STYLE| IS ... + "------------------------------------------------------------------------------- + " + let string = matchlist( line, s:C_TemplateIf ) + if !empty(string) + if !has_key( s:C_Template, string[1] ) + " new s:style + let s:style = string[1] + let s:C_Template[s:style] = {} + continue + endif + endif + " + "------------------------------------------------------------------------------- + " ENDIF + "------------------------------------------------------------------------------- + " + let string = matchlist( line, s:C_TemplateEndif ) + if !empty(string) + let s:style = 'default' + continue + endif + " + " macros and file includes + " + let string = matchlist( line, s:C_MacroLineRegex ) + if !empty(string) && skipmacros == 0 + let key = '|'.string[1].'|' + let val = string[2] + let val = substitute( val, '\s\+$', '', '' ) + let val = substitute( val, "[\"\']$", '', '' ) + let val = substitute( val, "^[\"\']", '', '' ) + " + if key == '|includefile|' && count( s:C_FileVisited, val ) == 0 + let path = fnamemodify( a:templatefile, ":p:h" ) + call C_ReadTemplates( path.'/'.val ) " recursive call + else + let s:C_Macro[key] = escape( val, '&' ) + endif + continue " next line + endif + " + " template header + " + let name = matchstr( line, s:C_TemplateLineRegex ) + " + if !empty(name) + let part = split( name, '\s*==\s*') + let item = part[0] + if has_key( s:C_Template[s:style], item ) && s:C_TemplateOverriddenMsg == 'yes' + echomsg "existing C/C++ template '".item."' overwritten" + endif + let s:C_Template[s:style][item] = '' + let skipmacros = 1 + " + let s:C_Attribute[item] = 'below' + if has_key( s:Attribute, get( part, 1, 'NONE' ) ) + let s:C_Attribute[item] = part[1] + endif + else + if !empty(item) + let s:C_Template[s:style][item] .= line."\n" + endif + endif + endif + " + endfor " --------- read line --------- + + let s:C_ActualStyle = 'default' + if !empty( s:C_Macro['|STYLE|'] ) + let s:C_ActualStyle = s:C_Macro['|STYLE|'] + endif + let s:C_ActualStyleLast = s:C_ActualStyle + + call C_SetSmallCommentStyle() +endfunction " ---------- end of function C_ReadTemplates ---------- + +"------------------------------------------------------------------------------ +" C_Style{{{1 +" ex-command CStyle : callback function +"------------------------------------------------------------------------------ +function! C_Style ( style ) + let lstyle = substitute( a:style, '^\s\+', "", "" ) " remove leading whitespaces + let lstyle = substitute( lstyle, '\s\+$', "", "" ) " remove trailing whitespaces + if has_key( s:C_Template, lstyle ) + if len( s:C_Template[lstyle] ) == 0 + echomsg "style '".lstyle."' : no templates defined" + return + endif + let s:C_ActualStyleLast = s:C_ActualStyle + let s:C_ActualStyle = lstyle + if len( s:C_ActualStyle ) > 1 && s:C_ActualStyle != s:C_ActualStyleLast + echomsg "template style is '".lstyle."'" + endif + else + echomsg "style '".lstyle."' does not exist" + endif +endfunction " ---------- end of function C_Style ---------- + +"------------------------------------------------------------------------------ +" C_StyleList {{{1 +" ex-command CStyle +"------------------------------------------------------------------------------ +function! C_StyleList ( ArgLead, CmdLine, CursorPos ) + " show all types / types beginning with a:ArgLead + return filter( copy(keys( s:C_Template) ), 'v:val =~ "\\<'.a:ArgLead.'\\w*"' ) +endfunction " ---------- end of function C_StyleList ---------- + +"------------------------------------------------------------------------------ +" C_OpenFold {{{1 +" Open fold and go to the first or last line of this fold. +"------------------------------------------------------------------------------ +function! C_OpenFold ( mode ) + if foldclosed(".") >= 0 + " we are on a closed fold: get end position, open fold, jump to the + " last line of the previously closed fold + let foldstart = foldclosed(".") + let foldend = foldclosedend(".") + normal zv + if a:mode == 'below' + exe ":".foldend + endif + if a:mode == 'start' + exe ":".foldstart + endif + endif +endfunction " ---------- end of function C_OpenFold ---------- + +"------------------------------------------------------------------------------ +" C_InsertTemplate {{{1 +" insert a template from the template dictionary +" do macro expansion +"------------------------------------------------------------------------------ +function! C_InsertTemplate ( key, ... ) + + if s:C_TemplatesLoaded == 'no' + call C_RereadTemplates('no') + let s:C_TemplatesLoaded = 'yes' + endif + + if !has_key( s:C_Template[s:C_ActualStyle], a:key ) && + \ !has_key( s:C_Template['default'], a:key ) + echomsg "style '".a:key."' / template '".a:key + \ ."' not found. Please check your template file in '".s:C_GlobalTemplateDir."'" + return + endif + + if &foldenable + let foldmethod_save = &foldmethod + set foldmethod=manual + endif + "------------------------------------------------------------------------------ + " insert the user macros + "------------------------------------------------------------------------------ + + " use internal formatting to avoid conficts when using == below + " + let equalprg_save = &equalprg + set equalprg= + + let mode = s:C_Attribute[a:key] + + " remove and insert the complete macro + " + if a:0 == 0 + let val = C_ExpandUserMacros (a:key) + if empty(val) + return + endif + let val = C_ExpandSingleMacro( val, '', '' ) + + if mode == 'below' + call C_OpenFold('below') + let pos1 = line(".")+1 + put =val + let pos2 = line(".") + " proper indenting + exe ":".pos1 + let ins = pos2-pos1+1 + exe "normal ".ins."==" + " + elseif mode == 'above' + let pos1 = line(".") + put! =val + let pos2 = line(".") + " proper indenting + exe ":".pos1 + let ins = pos2-pos1+1 + exe "normal ".ins."==" + " + elseif mode == 'start' + normal gg + call C_OpenFold('start') + let pos1 = 1 + put! =val + let pos2 = line(".") + " proper indenting + exe ":".pos1 + let ins = pos2-pos1+1 + exe "normal ".ins."==" + " + elseif mode == 'append' + if &foldenable && foldclosed(".") >= 0 + echohl WarningMsg | echomsg s:MsgInsNotAvail | echohl None + exe "set foldmethod=".foldmethod_save + return + else + let pos1 = line(".") + put =val + let pos2 = line(".")-1 + exe ":".pos1 + :join! + endif + " + elseif mode == 'insert' + if &foldenable && foldclosed(".") >= 0 + echohl WarningMsg | echomsg s:MsgInsNotAvail | echohl None + exe "set foldmethod=".foldmethod_save + return + else + let val = substitute( val, '\n$', '', '' ) + let currentline = getline( "." ) + let pos1 = line(".") + let pos2 = pos1 + count( split(val,'\zs'), "\n" ) + " assign to the unnamed register "" : + exe 'normal! a'.val + " reformat only multiline inserts and previously empty lines + if pos2-pos1 > 0 || currentline =~ '' + exe ":".pos1 + let ins = pos2-pos1+1 + exe "normal ".ins."==" + endif + endif + " + endif + " + else + " + " ===== visual mode =============================== + " + if a:1 == 'v' + let val = C_ExpandUserMacros (a:key) + let val = C_ExpandSingleMacro( val, s:C_TemplateJumpTarget2, '' ) + if empty(val) + return + endif + + if match( val, '\s*\n' ) >= 0 + let part = split( val, '\s*\n' ) + else + let part = split( val, '' ) + endif + + if len(part) < 2 + let part = [ "" ] + part + echomsg 'SPLIT missing in template '.a:key + endif + " + " 'visual' and mode 'insert': + " + " part0 and part1 can consist of several lines + " + if mode == 'insert' + let pos1 = line(".") + let pos2 = pos1 + let string= @* + let replacement = part[0].string.part[1] + " remove trailing '\n' + let replacement = substitute( replacement, '\n$', '', '' ) + exe ':s/'.string.'/'.replacement.'/' + endif + " + " 'visual' and mode 'below': + " + " + " + " part0 and part1 can consist of several lines + " + if mode == 'below' + + :'put =part[1] + + let pos1 = line("'<") - len(split(part[0], '\n' )) + let pos2 = line("'>") + len(split(part[1], '\n' )) + "" echo part[0] part[1] pos1 pos2 + " " proper indenting + exe ":".pos1 + let ins = pos2-pos1+1 + exe "normal ".ins."==" + endif + " + endif " ---------- end visual mode + endif + + " restore formatter programm + let &equalprg = equalprg_save + + "------------------------------------------------------------------------------ + " position the cursor + "------------------------------------------------------------------------------ + exe ":".pos1 + let mtch = search( '\|{CURSOR}', 'c', pos2 ) + if mtch != 0 + let line = getline(mtch) + if line =~ '$\|{CURSOR}$' + call setline( mtch, substitute( line, '\|{CURSOR}', '', '' ) ) + if a:0 != 0 && a:1 == 'v' && getline(".") =~ '^\s*$' + normal J + else + if getpos(".")[2] < len(getline(".")) || mode == 'insert' + :startinsert + else + :startinsert! + endif + endif + else + call setline( mtch, substitute( line, '\|{CURSOR}', '', '' ) ) + :startinsert + endif + else + " to the end of the block; needed for repeated inserts + if mode == 'below' + exe ":".pos2 + endif + endif + + "------------------------------------------------------------------------------ + " marked words + "------------------------------------------------------------------------------ + " define a pattern to highlight + call C_HighlightJumpTargets () + + if &foldenable + " restore folding method + exe "set foldmethod=".foldmethod_save + normal zv + endif + +endfunction " ---------- end of function C_InsertTemplate ---------- + +"------------------------------------------------------------------------------ +" C_HighlightJumpTargets +"------------------------------------------------------------------------------ +function! C_HighlightJumpTargets () + if s:C_Ctrl_j == 'on' + exe 'match Search /'.s:C_TemplateJumpTarget1.'\|'.s:C_TemplateJumpTarget2.'/' + endif +endfunction " ---------- end of function C_HighlightJumpTargets ---------- + +"------------------------------------------------------------------------------ +" C_JumpCtrlJ {{{1 +"------------------------------------------------------------------------------ +function! C_JumpCtrlJ () + let match = search( s:C_TemplateJumpTarget1.'\|'.s:C_TemplateJumpTarget2, 'c' ) + if match > 0 + " remove the target + call setline( match, substitute( getline('.'), s:C_TemplateJumpTarget1.'\|'.s:C_TemplateJumpTarget2, '', '' ) ) + else + " try to jump behind parenthesis or strings in the current line + if match( getline(".")[col(".") - 1], "[\]})\"'`]" ) != 0 + call search( "[\]})\"'`]", '', line(".") ) + endif + normal l + endif + return '' +endfunction " ---------- end of function C_JumpCtrlJ ---------- + +"------------------------------------------------------------------------------ +" C_ExpandUserMacros {{{1 +"------------------------------------------------------------------------------ +function! C_ExpandUserMacros ( key ) + + if has_key( s:C_Template[s:C_ActualStyle], a:key ) + let template = s:C_Template[s:C_ActualStyle][ a:key ] + else + let template = s:C_Template['default'][ a:key ] + endif + let s:C_ExpansionCounter = {} " reset the expansion counter + + "------------------------------------------------------------------------------ + " renew the predefined macros and expand them + " can be replaced, with e.g. |?DATE| + "------------------------------------------------------------------------------ + let s:C_Macro['|BASENAME|'] = toupper(expand("%:t:r")) + let s:C_Macro['|DATE|'] = C_DateAndTime('d') + let s:C_Macro['|FILENAME|'] = expand("%:t") + let s:C_Macro['|PATH|'] = expand("%:p:h") + let s:C_Macro['|SUFFIX|'] = expand("%:e") + let s:C_Macro['|TIME|'] = C_DateAndTime('t') + let s:C_Macro['|YEAR|'] = C_DateAndTime('y') + + "------------------------------------------------------------------------------ + " delete jump targets if mapping for C-j is off + "------------------------------------------------------------------------------ + if s:C_Ctrl_j == 'off' + let template = substitute( template, s:C_TemplateJumpTarget1.'\|'.s:C_TemplateJumpTarget2, '', 'g' ) + endif + + "------------------------------------------------------------------------------ + " look for replacements + "------------------------------------------------------------------------------ + while match( template, s:C_ExpansionRegex ) != -1 + let macro = matchstr( template, s:C_ExpansionRegex ) + let replacement = substitute( macro, '?', '', '' ) + let template = substitute( template, macro, replacement, "g" ) + + let match = matchlist( macro, s:C_ExpansionRegex ) + + if !empty( match[1] ) + let macroname = '|'.match[1].'|' + " + " notify flag action, if any + let flagaction = '' + if has_key( s:C_MacroFlag, match[2] ) + let flagaction = ' (-> '.s:C_MacroFlag[ match[2] ].')' + endif + " + " ask for a replacement + if has_key( s:C_Macro, macroname ) + let name = C_Input( match[1].flagaction.' : ', C_ApplyFlag( s:C_Macro[macroname], match[2] ) ) + else + let name = C_Input( match[1].flagaction.' : ', '' ) + endif + if empty(name) + return "" + endif + " + " keep the modified name + let s:C_Macro[macroname] = C_ApplyFlag( name, match[2] ) + endif + endwhile + + "------------------------------------------------------------------------------ + " do the actual macro expansion + " loop over the macros found in the template + "------------------------------------------------------------------------------ + while match( template, s:C_NonExpansionRegex ) != -1 + + let macro = matchstr( template, s:C_NonExpansionRegex ) + let match = matchlist( macro, s:C_NonExpansionRegex ) + + if !empty( match[1] ) + let macroname = '|'.match[1].'|' + + if has_key( s:C_Macro, macroname ) + "------------------------------------------------------------------------------- + " check for recursion + "------------------------------------------------------------------------------- + if has_key( s:C_ExpansionCounter, macroname ) + let s:C_ExpansionCounter[macroname] += 1 + else + let s:C_ExpansionCounter[macroname] = 0 + endif + if s:C_ExpansionCounter[macroname] >= s:C_ExpansionLimit + echomsg " recursion terminated for recursive macro ".macroname + return template + endif + "------------------------------------------------------------------------------- + " replace + "------------------------------------------------------------------------------- + let replacement = C_ApplyFlag( s:C_Macro[macroname], match[2] ) + let replacement = escape( replacement, '&' ) + let template = substitute( template, macro, replacement, "g" ) + else + " + " macro not yet defined + let s:C_Macro['|'.match[1].'|'] = '' + endif + endif + + endwhile + + return template +endfunction " ---------- end of function C_ExpandUserMacros ---------- + +"------------------------------------------------------------------------------ +" C_ApplyFlag {{{1 +"------------------------------------------------------------------------------ +function! C_ApplyFlag ( val, flag ) + " + " l : lowercase + if a:flag == ':l' + return tolower(a:val) + endif + " + " u : uppercase + if a:flag == ':u' + return toupper(a:val) + endif + " + " c : capitalize + if a:flag == ':c' + return toupper(a:val[0]).a:val[1:] + endif + " + " L : legalized name + if a:flag == ':L' + return C_LegalizeName(a:val) + endif + " + " flag not valid + return a:val +endfunction " ---------- end of function C_ApplyFlag ---------- +" +"------------------------------------------------------------------------------ +" C_ExpandSingleMacro {{{1 +"------------------------------------------------------------------------------ +function! C_ExpandSingleMacro ( val, macroname, replacement ) + return substitute( a:val, escape(a:macroname, '$' ), a:replacement, "g" ) +endfunction " ---------- end of function C_ExpandSingleMacro ---------- + +"------------------------------------------------------------------------------ +" C_SetSmallCommentStyle {{{1 +"------------------------------------------------------------------------------ +function! C_SetSmallCommentStyle () + if has_key( s:C_Template, 'comment.end-of-line-comment' ) + if match( s:C_Template['comment.end-of-line-comment'], '^\s*/\*' ) != -1 + let s:C_Com1 = '/*' " C-style : comment start + let s:C_Com2 = '*/' " C-style : comment end + else + let s:C_Com1 = '//' " C++style : comment start + let s:C_Com2 = '' " C++style : comment end + endif + endif +endfunction " ---------- end of function C_SetSmallCommentStyle ---------- + +"------------------------------------------------------------------------------ +" C_InsertMacroValue {{{1 +"------------------------------------------------------------------------------ +function! C_InsertMacroValue ( key ) + if empty( s:C_Macro['|'.a:key.'|'] ) + echomsg 'the tag |'.a:key.'| is empty' + return + endif + " + if &foldenable && foldclosed(".") >= 0 + echohl WarningMsg | echomsg s:MsgInsNotAvail | echohl None + return + endif + if col(".") > 1 + exe 'normal! a'.s:C_Macro['|'.a:key.'|'] + else + exe 'normal! i'.s:C_Macro['|'.a:key.'|'] + endif +endfunction " ---------- end of function C_InsertMacroValue ---------- + +"------------------------------------------------------------------------------ +" insert date and time {{{1 +"------------------------------------------------------------------------------ +function! C_InsertDateAndTime ( format ) + if &foldenable && foldclosed(".") >= 0 + echohl WarningMsg | echomsg s:MsgInsNotAvail | echohl None + return "" + endif + if col(".") > 1 + exe 'normal a'.C_DateAndTime(a:format) + else + exe 'normal i'.C_DateAndTime(a:format) + endif +endfunction " ---------- end of function C_InsertDateAndTime ---------- + +"------------------------------------------------------------------------------ +" generate date and time {{{1 +"------------------------------------------------------------------------------ +function! C_DateAndTime ( format ) + if a:format == 'd' + return strftime( s:C_FormatDate ) + elseif a:format == 't' + return strftime( s:C_FormatTime ) + elseif a:format == 'dt' + return strftime( s:C_FormatDate ).' '.strftime( s:C_FormatTime ) + elseif a:format == 'y' + return strftime( s:C_FormatYear ) + endif +endfunction " ---------- end of function C_DateAndTime ---------- + +"------------------------------------------------------------------------------ +" check for header or implementation file {{{1 +"------------------------------------------------------------------------------ +function! C_InsertTemplateWrapper () + " prevent insertion for a file generated from a link error: + if isdirectory(expand('%:p:h')) + if index( s:C_SourceCodeExtensionsList, expand('%:e') ) >= 0 + call C_InsertTemplate("comment.file-description") + else + call C_InsertTemplate("comment.file-description-header") + endif + set modified + endif +endfunction " ---------- end of function C_InsertTemplateWrapper ---------- + +" +"------------------------------------------------------------------------------- +" Comment : C/C++ File Sections {{{1 +"------------------------------------------------------------------------------- +let s:CFileSection = { + \ "Header\ File\ Includes" : "file-section-cpp-header-includes" , + \ "Local\ Macros" : "file-section-cpp-macros" , + \ "Local\ Type\ Def\." : "file-section-cpp-typedefs" , + \ "Local\ Data\ Types" : "file-section-cpp-data-types" , + \ "Local\ Variables" : "file-section-cpp-local-variables" , + \ "Local\ Prototypes" : "file-section-cpp-prototypes" , + \ "Exp\.\ Function\ Def\." : "file-section-cpp-function-defs-exported" , + \ "Local\ Function\ Def\." : "file-section-cpp-function-defs-local" , + \ "Local\ Class\ Def\." : "file-section-cpp-class-defs" , + \ "Exp\.\ Class\ Impl\." : "file-section-cpp-class-implementations-exported", + \ "Local\ Class\ Impl\." : "file-section-cpp-class-implementations-local" , + \ "All\ sections,\ C" : "c", + \ "All\ sections,\ C++" : "cpp", + \ } + +function! C_CFileSectionList ( ArgLead, CmdLine, CursorPos ) + return filter( copy( sort(keys( s:CFileSection)) ), 'v:val =~ "\\<'.a:ArgLead.'\\w*"' ) +endfunction " ---------- end of function C_CFileSectionList ---------- + +function! C_CFileSectionListInsert ( arg ) + if has_key( s:CFileSection, a:arg ) + if s:CFileSection[a:arg] == 'c' || s:CFileSection[a:arg] == 'cpp' + call C_Comment_C_SectionAll( 'comment.'.s:CFileSection[a:arg] ) + return + endif + call C_InsertTemplate( 'comment.'.s:CFileSection[a:arg] ) + else + echomsg "entry '".a:arg."' does not exist" + endif +endfunction " ---------- end of function C_CFileSectionListInsert ---------- +" +"------------------------------------------------------------------------------- +" Comment : H File Sections {{{1 +"------------------------------------------------------------------------------- +let s:HFileSection = { + \ "Header\ File\ Includes" : "file-section-hpp-header-includes" , + \ "Exported\ Macros" : "file-section-hpp-macros" , + \ "Exported\ Type\ Def\." : "file-section-hpp-exported-typedefs" , + \ "Exported\ Data\ Types" : "file-section-hpp-exported-data-types" , + \ "Exported\ Variables" : "file-section-hpp-exported-variables" , + \ "Exported\ Funct\.\ Decl\." : "file-section-hpp-exported-function-declarations", + \ "Exported\ Class\ Def\." : "file-section-hpp-exported-class-defs" , + \ "All\ sections,\ C" : "c" , + \ "All\ sections,\ C++" : "cpp" , + \ } + +function! C_HFileSectionList ( ArgLead, CmdLine, CursorPos ) + return filter( copy( sort(keys( s:HFileSection)) ), 'v:val =~ "\\<'.a:ArgLead.'\\w*"' ) +endfunction " ---------- end of function C_HFileSectionList ---------- + +function! C_HFileSectionListInsert ( arg ) + if has_key( s:HFileSection, a:arg ) + if s:HFileSection[a:arg] == 'c' || s:HFileSection[a:arg] == 'cpp' + call C_Comment_C_SectionAll( 'comment.'.s:HFileSection[a:arg] ) + return + endif + call C_InsertTemplate( 'comment.'.s:HFileSection[a:arg] ) + else + echomsg "entry '".a:arg."' does not exist" + endif +endfunction " ---------- end of function C_HFileSectionListInsert ---------- +" +"------------------------------------------------------------------------------- +" Comment : Keyword Comments {{{1 +"------------------------------------------------------------------------------- +let s:KeywordComment = { + \ 'BUG' : 'keyword-bug', + \ 'COMPILER' : 'keyword-compiler', + \ 'TODO' : 'keyword-todo', + \ 'TRICKY' : 'keyword-tricky', + \ 'WARNING' : 'keyword-warning', + \ 'WORKAROUND' : 'keyword-workaround', + \ 'new\ keyword' : 'keyword-keyword', + \ } + +function! C_KeywordCommentList ( ArgLead, CmdLine, CursorPos ) + return filter( copy( sort(keys( s:KeywordComment)) ), 'v:val =~ "\\<'.a:ArgLead.'\\w*"' ) +endfunction " ---------- end of function C_KeywordCommentList ---------- + +function! C_KeywordCommentListInsert ( arg ) + if has_key( s:KeywordComment, a:arg ) + if s:KeywordComment[a:arg] == 'c' || s:KeywordComment[a:arg] == 'cpp' + call C_Comment_C_SectionAll( 'comment.'.s:KeywordComment[a:arg] ) + return + endif + call C_InsertTemplate( 'comment.'.s:KeywordComment[a:arg] ) + else + echomsg "entry '".a:arg."' does not exist" + endif +endfunction " ---------- end of function C_KeywordCommentListInsert ---------- +" +"------------------------------------------------------------------------------- +" Comment : Special Comments {{{1 +"------------------------------------------------------------------------------- +let s:SpecialComment = { + \ 'EMPTY' : 'special-empty' , + \ 'FALL\ THROUGH' : 'special-fall-through' , + \ 'IMPL\.\ TYPE\ CONV' : 'special-implicit-type-conversion")' , + \ 'NO\ RETURN' : 'special-no-return' , + \ 'NOT\ REACHED' : 'special-not-reached' , + \ 'TO\ BE\ IMPL\.' : 'special-remains-to-be-implemented' , + \ 'constant\ type\ is\ long\ (L)' : 'special-constant-type-is-long' , + \ 'constant\ type\ is\ unsigned\ (U)' : 'special-constant-type-is-unsigned' , + \ 'constant\ type\ is\ unsigned\ long\ (UL)' : 'special-constant-type-is-unsigned-long' , + \ } + +function! C_SpecialCommentList ( ArgLead, CmdLine, CursorPos ) + return filter( copy( sort(keys( s:SpecialComment)) ), 'v:val =~ "\\<'.a:ArgLead.'\\w*"' ) +endfunction " ---------- end of function C_SpecialCommentList ---------- + +function! C_SpecialCommentListInsert ( arg ) + if has_key( s:SpecialComment, a:arg ) + if s:SpecialComment[a:arg] == 'c' || s:SpecialComment[a:arg] == 'cpp' + call C_Comment_C_SectionAll( 'comment.'.s:SpecialComment[a:arg] ) + return + endif + call C_InsertTemplate( 'comment.'.s:SpecialComment[a:arg] ) + else + echomsg "entry '".a:arg."' does not exist" + endif +endfunction " ---------- end of function C_SpecialCommentListInsert ---------- + +"------------------------------------------------------------------------------- +" Standard Library Includes +"------------------------------------------------------------------------------- +function! C_CleanDirNameList ( list ) + let result = copy( a:list ) + let index = 0 + while index < len( result ) + let result[index] = substitute( result[index], '[&\\]', '', 'g' ) + let index = index + 1 + endwhile + return result +endfunction " ---------- end of function C_CleanDirNameList ---------- + +let s:C_StandardLibsClean = C_CleanDirNameList( s:C_StandardLibs ) +let s:C_C99LibsClean = C_CleanDirNameList( s:C_C99Libs ) +let s:Cpp_StandardLibsClean = C_CleanDirNameList( s:Cpp_StandardLibs ) +let s:Cpp_CStandardLibsClean = C_CleanDirNameList( s:Cpp_CStandardLibs ) + +"------------------------------------------------------------------------------- +" callback functions used in the filetype plugin ftplugin/c.vim +" callback functions +"------------------------------------------------------------------------------- + +function! C_IncludesInsert ( arg, List ) + if index( a:List, a:arg ) >= 0 + exe 'normal a#include <'.a:arg.'>' + else + echomsg "entry '".a:arg."' does not exist" + endif +endfunction " ---------- end of function C_IncludesInsert +" +function! C_StdLibraryIncludesInsert ( arg ) + call C_IncludesInsert ( a:arg, s:C_StandardLibsClean ) +endfunction " ---------- end of function C_StdLibraryIncludesInsert + +function! C_C99LibraryIncludesInsert ( arg ) + call C_IncludesInsert ( a:arg, s:C_C99LibsClean ) +endfunction " ---------- end of function C_C99LibraryIncludesInsert + +function! C_CppLibraryIncludesInsert ( arg ) + call C_IncludesInsert ( a:arg, s:Cpp_StandardLibsClean ) +endfunction " ---------- end of function C_CppLibraryIncludesInsert + +function! C_CppCLibraryIncludesInsert ( arg ) + call C_IncludesInsert ( a:arg, s:Cpp_CStandardLibsClean ) +endfunction " ---------- end of function C_CppCLibraryIncludesInsert + +"------------------------------------------------------------------------------- +" callback functions used in the filetype plugin ftplugin/c.vim +" custom completion +"------------------------------------------------------------------------------- + +function! C_IncludesList ( ArgLead, CmdLine, CursorPos, List ) + " show all libs + if empty(a:ArgLead) + return a:List + endif + " show libs beginning with a:ArgLead + let expansions = [] + for item in a:List + if match( item, '\<'.a:ArgLead.'\w*' ) == 0 + call add( expansions, item ) + endif + endfor + return expansions +endfunction " ---------- end of function C_IncludesList ---------- +" +function! C_StdLibraryIncludesList ( ArgLead, CmdLine, CursorPos ) + return C_IncludesList ( a:ArgLead, a:CmdLine, a:CursorPos, s:C_StandardLibsClean ) +endfunction " ---------- end of function C_StdLibraryIncludesList ---------- + +function! C_C99LibraryIncludesList ( ArgLead, CmdLine, CursorPos ) + return C_IncludesList ( a:ArgLead, a:CmdLine, a:CursorPos, s:C_C99LibsClean ) +endfunction " ---------- end of function C_C99LibraryIncludesList ---------- + +function! C_CppLibraryIncludesList ( ArgLead, CmdLine, CursorPos ) + return C_IncludesList ( a:ArgLead, a:CmdLine, a:CursorPos, s:Cpp_StandardLibsClean ) +endfunction " ---------- end of function C_CppLibraryIncludesList ---------- + +function! C_CppCLibraryIncludesList ( ArgLead, CmdLine, CursorPos ) + return C_IncludesList ( a:ArgLead, a:CmdLine, a:CursorPos, s:Cpp_CStandardLibsClean ) +endfunction " ---------- end of function C_CppCLibraryIncludesList ---------- + +"------------------------------------------------------------------------------ +" show / hide the c-support menus +" define key mappings (gVim only) +"------------------------------------------------------------------------------ +" +call C_ToolMenu() +" +if s:C_LoadMenus == 'yes' && s:C_CreateMenusDelayed == 'no' + call C_CreateGuiMenus() +endif +" +nmap lcs :call C_CreateGuiMenus() +nmap ucs :call C_RemoveGuiMenus() +" +"------------------------------------------------------------------------------ +" Automated header insertion +" Local settings for the quickfix window +" +" Vim always adds the {cmd} after existing autocommands, +" so that the autocommands execute in the order in which +" they were given. The order matters! +"------------------------------------------------------------------------------ + +if has("autocmd") + " + " *.h has filetype 'cpp' by default; this can be changed to 'c' : + " + if s:C_TypeOfH=='c' + autocmd BufNewFile,BufEnter *.h :set filetype=c + endif + " + " C/C++ source code files which should not be preprocessed. + " + autocmd BufNewFile,BufRead *.i :set filetype=c + autocmd BufNewFile,BufRead *.ii :set filetype=cpp + " + " + " DELAYED LOADING OF THE TEMPLATE DEFINITIONS + " + autocmd BufNewFile,BufRead * + \ if (&filetype=='cpp' || &filetype=='c') | + \ call C_CreateMenusDelayed() | + \ endif + " + " Automated header insertion (suffixes from the gcc manual) + " + if !exists( 'g:C_Styles' ) + "------------------------------------------------------------------------------- + " template styles are the default settings + "------------------------------------------------------------------------------- + autocmd BufNewFile * if &filetype =~ '^\(c\|cpp\)$' && expand("%:e") !~ 'ii\?' | + \ call C_InsertTemplateWrapper() | endif + " + else + "------------------------------------------------------------------------------- + " template styles are related to file extensions + "------------------------------------------------------------------------------- + for [ pattern, stl ] in items( g:C_Styles ) + exe "autocmd BufNewFile,BufRead,BufEnter ".pattern." call C_Style( '".stl."' )" + exe "autocmd BufNewFile ".pattern." call C_InsertTemplateWrapper()" + endfor + " + endif + " + " Wrap error descriptions in the quickfix window. + " + autocmd BufReadPost quickfix setlocal wrap | setlocal linebreak + " + exe 'autocmd BufRead *.'.join( s:C_SourceCodeExtensionsList, '\|*.' ) + \ .' call C_HighlightJumpTargets()' + " +endif " has("autocmd") +" +"===================================================================================== +" vim: tabstop=2 shiftwidth=2 foldmethod=marker diff --git a/plugin/minibufexpl.vim b/plugin/minibufexpl.vim new file mode 100644 index 0000000..87d2397 --- /dev/null +++ b/plugin/minibufexpl.vim @@ -0,0 +1,1840 @@ +" Mini Buffer Explorer +" +" HINT: Type zR if you don't know how to use folds +" +" Script Info and Documentation +"============================================================================= +" Copyright: Copyright (C) 2002 & 2003 Bindu Wavell +" 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, +" minibufexplorer.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 damamges +" resulting from the use of this software. +" +" Name Of File: minibufexpl.vim +" Description: Mini Buffer Explorer Vim Plugin +" Maintainer: Bindu Wavell +" URL: http://vim.sourceforge.net/scripts/script.php?script_id=159 +" Last Change: Sunday, June 21, 2004 +" Version: 6.3.2 +" Derived from Jeff Lanzarotta's bufexplorer.vim version 6.0.7 +" Jeff can be reached at (jefflanzarotta@yahoo.com) and the +" original plugin can be found at: +" http://lanzarotta.tripod.com/vim/plugin/6/bufexplorer.vim.zip +" +" Usage: Normally, this file should reside in the plugins +" directory and be automatically sourced. If not, you must +" manually source this file using ':source minibufexplorer.vim'. +" +" You may use the default keymappings of +" +" mbe - Opens MiniBufExplorer +" +" or you may want to add something like the following +" key mapping to your _vimrc/.vimrc file. +" +" map b :MiniBufExplorer +" +" However, in most cases you won't need any key-bindings at all. +" +" is usually backslash so type "\mbe" (quickly) to open +" the -MiniBufExplorer- window. +" +" Other keymappings include: mbc to close the Explorer +" window, mbu to force the Explorer to Update and +" mbt to toggle the Explorer window; it will open if +" closed or close if open. Each of these key bindings can be +" overridden (see the notes on mbe above.) +" +" You can map these additional commands as follows: +" +" map c :CMiniBufExplorer +" map u :UMiniBufExplorer +" map t :TMiniBufExplorer +" +" NOTE: you can change the key binding used in these mappings +" so that they fit with your configuration of vim. +" +" You can also call each of these features by typing the +" following in command mode: +" +" :MiniBufExplorer " Open and/or goto Explorer +" :CMiniBufExplorer " Close the Explorer if it's open +" :UMiniBufExplorer " Update Explorer without navigating +" :TMiniBufExplorer " Toggle the Explorer window open and +" closed. +" +" To control where the new split window goes relative to the +" current window, use the setting: +" +" let g:miniBufExplSplitBelow=0 " Put new window above +" " current or on the +" " left for vertical split +" let g:miniBufExplSplitBelow=1 " Put new window below +" " current or on the +" " right for vertical split +" +" The default for this is read from the &splitbelow VIM option. +" +" By default we are now (as of 6.0.2) forcing the -MiniBufExplorer- +" window to open up at the edge of the screen. You can turn this +" off by setting the following variable in your .vimrc: +" +" let g:miniBufExplSplitToEdge = 0 +" +" If you would like a vertical explorer you can assign the column +" width (in characters) you want for your explorer window with the +" following .vimrc variable (this was introduced in 6.3.0): +" +" let g:miniBufExplVSplit = 20 " column width in chars +" +" IN HORIZONTAL MODE: +" It is now (as of 6.1.1) possible to set a maximum height for +" the -MiniBufExplorer- window. You can set the max height by +" letting the following variable in your .vimrc: +" +" let g:miniBufExplMaxSize = +" +" setting this to 0 will mean the window gets as big as +" needed to fit all your buffers. +" +" NOTE: This was g:miniBufExplMaxHeight before 6.3.0; the old +" setting is backwards compatible if you don't use MaxSize. +" +" As of 6.2.2 it is possible to set a minimum height for the +" -MiniBufExplorer- window. You can set the min height by +" letting the following variable in your .vimrc: +" +" let g:miniBufExplMinSize = +" +" NOTE: This was g:miniBufExplMinHeight before 6.3.0; the old +" setting is backwards compatible if you don't use MinSize. +" +" IN VERTICAL MODE: (as of 6.3.0) +" By default the vertical explorer has a fixed width. If you put: +" +" let g:miniBufExplMaxSize = +" +" into your .vimrc then MBE will attempt to set the width of the +" MBE window to be as wide as your widest tab. The width will not +" exceed MaxSize even if you have wider tabs. +" +" Accepting the default value of 0 for this will give you a fixed +" width MBE window. +" +" You can specify a MinSize for the vertical explorer window by +" putting the following in your .vimrc: +" +" let g:miniBufExplMinSize = +" +" This will have no effect unless you also specivy MaxSize. +" +" By default we are now (as of 6.0.1) turning on the MoreThanOne +" option. This stops the -MiniBufExplorer- from opening +" automatically until more than one eligible buffer is available. +" You can turn this feature off by setting the following variable +" in your .vimrc: +" +" let g:miniBufExplorerMoreThanOne=1 +" +" (The following enhancement is as of 6.2.2) +" Setting this to 0 will cause the MBE window to be loaded even +" if no buffers are available. Setting it to 1 causes the MBE +" window to be loaded as soon as an eligible buffer is read. You +" can also set it to larger numbers. So if you set it to 4 for +" example the MBE window wouldn't auto-open until 4 eligibles +" buffers had been loaded. This is nice for folks that don't +" want an MBE window unless they are editing more than two or +" three buffers. +" +" To enable the optional mapping of Control + Vim Direction Keys +" [hjkl] to window movement commands, you can put the following into +" your .vimrc: +" +" let g:miniBufExplMapWindowNavVim = 1 +" +" To enable the optional mapping of Control + Arrow Keys to window +" movement commands, you can put the following into your .vimrc: +" +" let g:miniBufExplMapWindowNavArrows = 1 +" +" To enable the optional mapping of and to a +" function that will bring up the next or previous buffer in the +" current window, you can put the following into your .vimrc: +" +" let g:miniBufExplMapCTabSwitchBufs = 1 +" +" To enable the optional mapping of and to mappings +" that will move to the next and previous (respectively) window, you +" can put the following into your .vimrc: +" +" let g:miniBufExplMapCTabSwitchWindows = 1 +" +" +" NOTE: If you set the ...TabSwitchBufs AND ...TabSwitchWindows, +" ...TabSwitchBufs will be enabled and ...TabSwitchWindows +" will not. +" +" As of MBE 6.3.0, you can put the following into your .vimrc: +" +" let g:miniBufExplUseSingleClick = 1 +" +" If you would like to single click on tabs rather than double +" clicking on them to goto the selected buffer. +" +" NOTE: If you use the single click option in taglist.vim you may +" need to get an updated version that includes a patch I +" provided to allow both explorers to provide single click +" buffer selection. +" +" It is possible to customize the the highlighting for the tabs in +" the MBE by configuring the following highlighting groups: +" +" MBENormal - for buffers that have NOT CHANGED and +" are NOT VISIBLE. +" MBEChanged - for buffers that HAVE CHANGED and are +" NOT VISIBLE +" MBEVisibleNormal - buffers that have NOT CHANGED and are +" VISIBLE +" MBEVisibleChanged - buffers that have CHANGED and are VISIBLE +" +" You can either link to an existing highlighting group by +" adding a command like: +" +" hi link MBEVisibleChanged Error +" +" to your .vimrc or you can specify exact foreground and background +" colors using the following syntax: +" +" hi MBEChanged guibg=darkblue ctermbg=darkblue termbg=white +" +" NOTE: If you set a colorscheme in your .vimrc you should do it +" BEFORE updating the MBE highlighting groups. +" +" If you use other explorers like TagList you can (As of 6.2.8) put: +" +" let g:miniBufExplModSelTarget = 1 +" +" into your .vimrc in order to force MBE to try to place selected +" buffers into a window that does not have a nonmodifiable buffer. +" The upshot of this should be that if you go into MBE and select +" a buffer, the buffer should not show up in a window that is +" hosting an explorer. +" +" There is a VIM bug that can cause buffers to show up without +" their highlighting. The following setting will cause MBE to +" try and turn highlighting back on (introduced in 6.3.1): +" +" let g:miniBufExplForceSyntaxEnable = 1 +" +" MBE has had a basic debugging capability for quite some time. +" However, it has not been very friendly in the past. As of 6.0.8, +" you can put one of each of the following into your .vimrc: +" +" let g:miniBufExplorerDebugLevel = 0 " MBE serious errors output +" let g:miniBufExplorerDebugLevel = 4 " MBE all errors output +" let g:miniBufExplorerDebugLevel = 10 " MBE reports everything +" +" You can also set a DebugMode to cause output to be target as +" follows (default is mode 3): +" +" let g:miniBufExplorerDebugMode = 0 " Errors will show up in +" " a vim window +" let g:miniBufExplorerDebugMode = 1 " Uses VIM's echo function +" " to display on the screen +" let g:miniBufExplorerDebugMode = 2 " Writes to a file +" " MiniBufExplorer.DBG +" let g:miniBufExplorerDebugMode = 3 " Store output in global: +" " g:miniBufExplorerDebugOutput +" +" Or if you are able to start VIM, you might just perform these +" at a command prompt right before you do the operation that is +" failing. +" +" History: Moved to end of file +" +" Known Issues: When debugging is turned on and set to output to a window, there +" are some cases where the window is opened more than once, there +" are other cases where an old debug window can be lost. +" +" Several MBE commands can break the window history so [pnw] +" might not take you to the expected window. +" +" Todo: Add the ability to specify a regexp for eligible buffers +" allowing the ability to filter out certain buffers that +" you don't want to control from MBE +" +"============================================================================= +" }}} +" +" + +" Startup Check +" +" Has this plugin already been loaded? {{{ +" +if exists('loaded_minibufexplorer') + finish +endif +let loaded_minibufexplorer = 1 +" }}} + +" Mappings and Commands +" +" MBE Keyboard Mappings {{{ +" If we don't already have keyboard mappings for MBE then create them +" +if !hasmapto('MiniBufExplorer') + map mbe MiniBufExplorer +endif +if !hasmapto('CMiniBufExplorer') + map mbc CMiniBufExplorer +endif +if !hasmapto('UMiniBufExplorer') + map mbu UMiniBufExplorer +endif +if !hasmapto('TMiniBufExplorer') + map mbt TMiniBufExplorer +endif + +" }}} +" MBE