summaryrefslogtreecommitdiff
path: root/.vim/autoload/omni
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.vim/autoload/omni/common/debug.vim32
-rw-r--r--.vim/autoload/omni/common/utils.vim67
-rw-r--r--.vim/autoload/omni/cpp/complete.vim569
-rw-r--r--.vim/autoload/omni/cpp/includes.vim126
-rw-r--r--.vim/autoload/omni/cpp/items.vim660
-rw-r--r--.vim/autoload/omni/cpp/maycomplete.vim82
-rw-r--r--.vim/autoload/omni/cpp/namespaces.vim838
-rw-r--r--.vim/autoload/omni/cpp/settings.vim96
-rw-r--r--.vim/autoload/omni/cpp/tokenizer.vim93
-rw-r--r--.vim/autoload/omni/cpp/utils.vim587
10 files changed, 3150 insertions, 0 deletions
diff --git a/.vim/autoload/omni/common/debug.vim b/.vim/autoload/omni/common/debug.vim
new file mode 100644
index 0000000..eded649
--- /dev/null
+++ b/.vim/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/.vim/autoload/omni/common/utils.vim b/.vim/autoload/omni/common/utils.vim
new file mode 100644
index 0000000..c880ad2
--- /dev/null
+++ b/.vim/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/.vim/autoload/omni/cpp/complete.vim b/.vim/autoload/omni/cpp/complete.vim
new file mode 100644
index 0000000..a7e4edc
--- /dev/null
+++ b/.vim/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 <expr> <C-X><C-O> omni#cpp#maycomplete#Complete()
+ inoremap <expr> . omni#cpp#maycomplete#Dot()
+ inoremap <expr> > omni#cpp#maycomplete#Arrow()
+ inoremap <expr> : omni#cpp#maycomplete#Scope()
+endfunc
+
+" Find the start position of the completion
+function! s:FindStartPositionOfCompletion()
+ " Locate the start of the item, including ".", "->" and "[...]".
+ let line = getline('.')
+ let start = col('.') - 1
+
+ let lastword = -1
+ while start > 0
+ if line[start - 1] =~ '\w'
+ let start -= 1
+ elseif line[start - 1] =~ '\.'
+ " Searching for dot '.'
+ if lastword == -1
+ let lastword = start
+ endif
+ let start -= 1
+ elseif start > 1 && line[start - 2] == '-' && line[start - 1] == '>'
+ " Searching for '->'
+ if lastword == -1
+ let lastword = start
+ endif
+ let start -= 2
+ elseif start > 1 && line[start - 2] == ':' && line[start - 1] == ':'
+ " Searching for '::' for namespaces and class
+ if lastword == -1
+ let lastword = start
+ endif
+ let start -= 2
+ elseif line[start - 1] == ']'
+ " Skip over [...].
+ let n = 0
+ let start -= 1
+ while start > 0
+ let start -= 1
+ if line[start] == '['
+ if n == 0
+ break
+ endif
+ let n -= 1
+ elseif line[start] == ']' " nested []
+ let n += 1
+ endif
+ endwhile
+ else
+ break
+ endif
+ endwhile
+ if lastword==-1
+ " For completion on the current scope
+ let lastword = start
+ endif
+ return lastword
+endfunc
+
+" Returns if szKey1.szKey2 is in the cache
+" @return
+" - 0 = key not found
+" - 1 = szKey1.szKey2 found
+" - 2 = szKey1.[part of szKey2] found
+function! s:IsCached(cache, szKey1, szKey2)
+ " Searching key in the result cache
+ let szResultKey = a:szKey1 . a:szKey2
+ let result = [0, szResultKey]
+ if a:szKey2 != ''
+ let szKey = a:szKey2
+ while len(szKey)>0
+ if has_key(a:cache, a:szKey1 . szKey)
+ let result[1] = a:szKey1 . szKey
+ if szKey != a:szKey2
+ let result[0] = 2
+ else
+ let result[0] = 1
+ endif
+ break
+ endif
+ let szKey = szKey[:-2]
+ endwhile
+ else
+ if has_key(a:cache, szResultKey)
+ let result[0] = 1
+ endif
+ endif
+ return result
+endfunc
+
+" Extend a tag item to a popup item
+function! s:ExtendTagItemToPopupItem(tagItem, szTypeName)
+ let tagItem = a:tagItem
+
+ " Add the access
+ let szItemMenu = ''
+ let accessChar = {'public': '+','protected': '#','private': '-'}
+ if g:OmniCpp_ShowAccess
+ if has_key(tagItem, 'access') && has_key(accessChar, tagItem.access)
+ let szItemMenu = szItemMenu.accessChar[tagItem.access]
+ else
+ let szItemMenu = szItemMenu." "
+ endif
+ endif
+
+ " Formating optional menu string we extract the scope information
+ let szName = substitute(tagItem.name, '.*::', '', 'g')
+ let szItemWord = szName
+ let szAbbr = szName
+
+ if !g:OmniCpp_ShowScopeInAbbr
+ let szScopeOfTag = omni#cpp#utils#ExtractScope(tagItem)
+ let szItemMenu = szItemMenu.' '.szScopeOfTag[2:]
+ let szItemMenu = substitute(szItemMenu, '\s\+$', '', 'g')
+ else
+ let szAbbr = tagItem.name
+ endif
+ if g:OmniCpp_ShowAccess
+ let szItemMenu = substitute(szItemMenu, '^\s\+$', '', 'g')
+ else
+ let szItemMenu = substitute(szItemMenu, '\(^\s\+\)\|\(\s\+$\)', '', 'g')
+ endif
+
+ " Formating information for the preview window
+ if index(['f', 'p'], tagItem.kind[0])>=0
+ let szItemWord .= '('
+ if g:OmniCpp_ShowPrototypeInAbbr && has_key(tagItem, 'signature')
+ let szAbbr .= tagItem.signature
+ else
+ let szAbbr .= '('
+ endif
+ endif
+ let szItemInfo = ''
+ if s:hasPreviewWindow
+ let szItemInfo = omni#cpp#utils#GetPreviewWindowStringFromTagItem(tagItem)
+ endif
+
+ " If a function is a ctor we add a new key in the tagItem
+ if index(['f', 'p'], tagItem.kind[0])>=0
+ if match(szName, '^\~') < 0 && a:szTypeName =~ '\C\<'.szName.'$'
+ " It's a ctor
+ let tagItem['ctor'] = 1
+ elseif has_key(tagItem, 'access') && tagItem.access == 'friend'
+ " Friend function
+ let tagItem['friendfunc'] = 1
+ endif
+ endif
+
+ " Extending the tag item to a popup item
+ let tagItem['word'] = szItemWord
+ let tagItem['abbr'] = szAbbr
+ let tagItem['menu'] = szItemMenu
+ let tagItem['info'] = szItemInfo
+ let tagItem['dup'] = (s:hasPreviewWindow && index(['f', 'p', 'm'], tagItem.kind[0])>=0)
+ return tagItem
+endfunc
+
+" Get tag popup item list
+function! s:TagPopupList(szTypeName, szBase)
+ let result = []
+
+ " Searching key in the result cache
+ let cacheResult = s:IsCached(s:CACHE_TAG_POPUP_ITEMS, a:szTypeName, a:szBase)
+
+ " Building the tag query, we don't forget dtors when a:szBase==''
+ if a:szTypeName!=''
+ " Scope search
+ let szTagQuery = '^' . a:szTypeName . '::' . a:szBase . '\~\?\w\+$'
+ else
+ " Global search
+ let szTagQuery = '^' . a:szBase . '\w\+$'
+ endif
+
+ " If the result is already in the cache we return it
+ if cacheResult[0]
+ let result = s:CACHE_TAG_POPUP_ITEMS[ cacheResult[1] ]
+ if cacheResult[0] == 2
+ let result = filter(copy(result), 'v:val.name =~ szTagQuery' )
+ endif
+ return result
+ endif
+
+ try
+ " Getting tags
+ let result = omni#common#utils#TagList(szTagQuery)
+
+ " We extend tag items to popup items
+ call map(result, 's:ExtendTagItemToPopupItem(v:val, a:szTypeName)')
+
+ " We store the result in a cache
+ if cacheResult[1] != ''
+ let s:CACHE_TAG_POPUP_ITEMS[ cacheResult[1] ] = result
+ endif
+ catch /^TagList:UserInterrupt$/
+ endtry
+
+ return result
+endfunc
+
+" Find complete matches for a completion on the global scope
+function! s:SearchGlobalMembers(szBase)
+ if a:szBase != ''
+ let tagPopupList = s:TagPopupList('', a:szBase)
+ let tagPopupList = filter(copy(tagPopupList), g:omni#cpp#utils#szFilterGlobalScope)
+ call extend(s:popupItemResultList, tagPopupList)
+ endif
+endfunc
+
+" Search class, struct, union members
+" @param resolvedTagItem: a resolved tag item
+" @param szBase: string base
+" @return list of tag items extended to popup items
+function! s:SearchMembers(resolvedTagItem, szBase)
+ let result = []
+ if a:resolvedTagItem == {}
+ return result
+ endif
+
+ " Get type info without the starting '::'
+ let szTagName = omni#cpp#utils#ExtractTypeInfoFromTag(a:resolvedTagItem)[2:]
+
+ " Unnamed type case. A tag item representing an unnamed type is a variable
+ " ('v') a member ('m') or a typedef ('t')
+ if index(['v', 't', 'm'], a:resolvedTagItem.kind[0])>=0 && has_key(a:resolvedTagItem, 'typeref')
+ " We remove the 'struct:' or 'class:' etc...
+ let szTagName = substitute(a:resolvedTagItem.typeref, '^\w\+:', '', 'g')
+ endif
+
+ return copy(s:TagPopupList(szTagName, a:szBase))
+endfunc
+
+" Return if the tag env has changed
+function! s:HasTagEnvChanged()
+ if s:CACHE_TAG_ENV == &tags
+ return 0
+ else
+ let s:CACHE_TAG_ENV = &tags
+ return 1
+ endif
+endfunc
+
+" Return if a tag file has changed in tagfiles()
+function! s:HasATagFileOrTagEnvChanged()
+ if s:HasTagEnvChanged()
+ let s:CACHE_TAG_FILES = {}
+ return 1
+ endif
+
+ let result = 0
+ for tagFile in tagfiles()
+ if tagFile == ""
+ continue
+ endif
+
+ if has_key(s:CACHE_TAG_FILES, tagFile)
+ let currentFiletime = getftime(tagFile)
+ if currentFiletime > s:CACHE_TAG_FILES[tagFile]
+ " The file has changed, updating the cache
+ let s:CACHE_TAG_FILES[tagFile] = currentFiletime
+ let result = 1
+ endif
+ else
+ " We store the time of the file
+ let s:CACHE_TAG_FILES[tagFile] = getftime(tagFile)
+ let result = 1
+ endif
+ endfor
+ return result
+endfunc
+" Initialization
+call s:HasATagFileOrTagEnvChanged()
+
+" Filter same function signatures of base classes
+function! s:FilterOverloadedFunctions(tagPopupList)
+ let result = []
+ for tagPopupItem in a:tagPopupList
+ if has_key(tagPopupItem, 'kind') && index(['f', 'p'], tagPopupItem.kind[0])>=0 && has_key(tagPopupItem, 'signature')
+ if !has_key(s:CACHE_OVERLOADED_FUNCTIONS, tagPopupItem.word . tagPopupItem.signature)
+ let s:CACHE_OVERLOADED_FUNCTIONS[tagPopupItem.word . tagPopupItem.signature] = 1
+ call extend(result, [tagPopupItem])
+ endif
+ else
+ call extend(result, [tagPopupItem])
+ endif
+ endfor
+ return result
+endfunc
+
+" Access filter
+function! s:GetAccessFilter(szFilter, szAccessFilter)
+ let szFilter = a:szFilter
+ if g:OmniCpp_DisplayMode == 0
+ if a:szAccessFilter == 'public'
+ " We only get public members
+ let szFilter .= "&& v:val.access == 'public'"
+ elseif a:szAccessFilter == 'protected'
+ " We get public and protected members
+ let szFilter .= "&& v:val.access != 'private'"
+ endif
+ endif
+ return szFilter
+endfunc
+
+" Filter class members in the popup menu after a completion with -> or .
+function! s:FilterClassMembers(tagPopupList, szAccessFilter)
+ let szFilter = "(!has_key(v:val, 'friendfunc') && !has_key(v:val, 'ctor') && has_key(v:val, 'kind') && index(['m', 'p', 'f'], v:val.kind[0])>=0 && has_key(v:val, 'access'))"
+ call filter(a:tagPopupList, s:GetAccessFilter(szFilter, a:szAccessFilter))
+ call extend(s:popupItemResultList, s:FilterOverloadedFunctions(a:tagPopupList))
+endfunc
+
+" Filter class scope members in the popup menu after a completion with ::
+" We only display attribute and functions members that
+" have an access information. We also display nested
+" class, struct, union, and enums, typedefs
+function! s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
+ let szFilter = "!has_key(v:val, 'friendfunc') && has_key(v:val, 'kind') && (index(['m', 'p', 'f'], v:val.kind[0])>=0 && has_key(v:val, 'access'))"
+ let szFilter = s:GetAccessFilter(szFilter, a:szAccessFilter)
+ let szFilter .= "|| index(['c','e','g','s','t','u'], v:val.kind[0])>=0"
+ call filter(a:tagPopupList, szFilter)
+ call extend(s:popupItemResultList, s:FilterOverloadedFunctions(a:tagPopupList))
+endfunc
+
+" Filter static class members in the popup menu
+function! s:FilterStaticClassMembers(tagPopupList, szAccessFilter)
+ let szFilter = "!has_key(v:val, 'friendfunc') && has_key(v:val, 'kind') && (index(['m', 'p', 'f'], v:val.kind[0])>=0 && has_key(v:val, 'access') && match(v:val.cmd, '\\Cstatic')!=-1)"
+ let szFilter = s:GetAccessFilter(szFilter, a:szAccessFilter)
+ let szFilter = szFilter . "|| index(['c','e','g','n','s','t','u','v'], v:val.kind[0])>=0"
+ call filter(a:tagPopupList, szFilter)
+ call extend(s:popupItemResultList, s:FilterOverloadedFunctions(a:tagPopupList))
+endfunc
+
+" Filter scope members in the popup menu
+function! s:FilterNamespaceScopeMembers(tagPopupList)
+ call extend(s:popupItemResultList, a:tagPopupList)
+endfunc
+
+" Init data at the start of completion
+function! s:InitComplete()
+ " Reset the popup item list
+ let s:popupItemResultList = []
+ let s:CACHE_OVERLOADED_FUNCTIONS = {}
+
+ " Reset includes cache when the current working directory has changed
+ let szCurrentWorkingDir = getcwd()
+ if s:szCurrentWorkingDir != szCurrentWorkingDir
+ let s:szCurrentWorkingDir = szCurrentWorkingDir
+ let g:omni#cpp#includes#CACHE_INCLUDES = {}
+ let g:omni#cpp#includes#CACHE_FILE_TIME = {}
+ endif
+
+ " Has preview window ?
+ let s:hasPreviewWindow = match(&completeopt, 'preview')>=0
+
+ let bResetCache = 0
+
+ " Reset tag env or tag files dependent caches
+ if s:HasATagFileOrTagEnvChanged()
+ let bResetCache = 1
+ endif
+
+ if (s:OmniCpp_ShowScopeInAbbr != g:OmniCpp_ShowScopeInAbbr)
+ \|| (s:OmniCpp_ShowPrototypeInAbbr != g:OmniCpp_ShowPrototypeInAbbr)
+ \|| (s:OmniCpp_ShowAccess != g:OmniCpp_ShowAccess)
+
+ let s:OmniCpp_ShowScopeInAbbr = g:OmniCpp_ShowScopeInAbbr
+ let s:OmniCpp_ShowPrototypeInAbbr = g:OmniCpp_ShowPrototypeInAbbr
+ let s:OmniCpp_ShowAccess = g:OmniCpp_ShowAccess
+ let bResetCache = 1
+ endif
+
+ if s:hasPreviewWindow != s:hasPreviewWindowOld
+ let s:hasPreviewWindowOld = s:hasPreviewWindow
+ let bResetCache = 1
+ endif
+
+ if bResetCache
+ let g:omni#cpp#namespaces#CacheResolve = {}
+ let s:CACHE_TAG_POPUP_ITEMS = {}
+ let g:omni#cpp#utils#CACHE_TAG_INHERITS = {}
+ call garbagecollect()
+ endif
+
+ " Check for updates
+ for szIncludeName in keys(g:omni#cpp#includes#CACHE_INCLUDES)
+ let fTime = getftime(szIncludeName)
+ let bNeedUpdate = 0
+ if has_key(g:omni#cpp#includes#CACHE_FILE_TIME, szIncludeName)
+ if fTime != g:omni#cpp#includes#CACHE_FILE_TIME[szIncludeName]
+ let bNeedUpdate = 1
+ endif
+ else
+ let g:omni#cpp#includes#CACHE_FILE_TIME[szIncludeName] = fTime
+ let bNeedUpdate = 1
+ endif
+
+ if bNeedUpdate
+ " We have to update include list and namespace map of this file
+ call omni#cpp#includes#GetList(szIncludeName, 1)
+ call omni#cpp#namespaces#GetMapFromBuffer(szIncludeName, 1)
+ endif
+ endfor
+
+ let s:bDoNotComplete = 0
+endfunc
+
+
+" This function is used for the 'omnifunc' option.
+function! omni#cpp#complete#Main(findstart, base)
+ if a:findstart
+ "call omni#common#debug#Start()
+
+ call s:InitComplete()
+
+ " Note: if s:bMayComplete==1 g:omni#cpp#items#data is build by MayComplete functions
+ if !s:bMayComplete
+ " If the cursor is in a comment we go out
+ if omni#cpp#utils#IsCursorInCommentOrString()
+ " Returning -1 is not enough we have to set a variable to let
+ " the second call of omni#cpp#complete knows that the
+ " cursor was in a comment
+ " Why is there a second call when the first call returns -1 ?
+ let s:bDoNotComplete = 1
+ return -1
+ endif
+
+ " We get items here (whend a:findstart==1) because GetItemsToComplete()
+ " depends on the cursor position.
+ " When a:findstart==0 the cursor position is modified
+ let g:omni#cpp#items#data = omni#cpp#items#Get(omni#cpp#utils#TokenizeCurrentInstruction())
+ endif
+
+ " Get contexts stack
+ let s:contextStack = omni#cpp#namespaces#GetContexts()
+
+ " Reinit of may complete indicator
+ let s:bMayComplete = 0
+ return s:FindStartPositionOfCompletion()
+ endif
+
+ " If the cursor is in a comment we return an empty result
+ if s:bDoNotComplete
+ let s:bDoNotComplete = 0
+ return []
+ endif
+
+ if len(g:omni#cpp#items#data)==0
+ " A) CURRENT_SCOPE_COMPLETION_MODE
+
+ " 1) Displaying data of each context
+ let szAccessFilter = 'all'
+ for szCurrentContext in s:contextStack
+ if szCurrentContext == '::'
+ continue
+ endif
+
+ let resolvedTagItem = omni#cpp#utils#GetResolvedTagItem(s:contextStack, omni#cpp#utils#CreateTypeInfo(szCurrentContext))
+ if resolvedTagItem != {}
+ " We don't search base classes because bases classes are
+ " already in the context stack
+ let tagPopupList = s:SearchMembers(resolvedTagItem, a:base)
+ if index(['c','s'], resolvedTagItem.kind[0])>=0
+ " It's a class or struct
+ call s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
+ let szAccessFilter = 'protected'
+ else
+ " It's a namespace or union, we display all members
+ call s:FilterNamespaceScopeMembers(tagPopupList)
+ endif
+ endif
+ endfor
+
+ " 2) Displaying global scope members
+ if g:OmniCpp_GlobalScopeSearch
+ call s:SearchGlobalMembers(a:base)
+ endif
+ else
+ let typeInfo = omni#cpp#items#ResolveItemsTypeInfo(s:contextStack, g:omni#cpp#items#data)
+
+ if typeInfo != {}
+ if g:omni#cpp#items#data[-1].kind == 'itemScope'
+ " B) SCOPE_COMPLETION_MODE
+ if omni#cpp#utils#GetTypeInfoString(typeInfo)==''
+ call s:SearchGlobalMembers(a:base)
+ else
+ for resolvedTagItem in omni#cpp#utils#GetResolvedTags(s:contextStack, typeInfo)
+ let tagPopupList = s:SearchMembers(resolvedTagItem, a:base)
+ if index(['c','s'], resolvedTagItem.kind[0])>=0
+ let szTypeInfo = omni#cpp#utils#ExtractTypeInfoFromTag(resolvedTagItem)
+ if g:OmniCpp_DisplayMode==0
+ " We want to complete a class or struct
+ " If this class is a base class so we display all class members
+ if index(s:contextStack, szTypeInfo)<0
+ let szAccessFilter = 'public'
+ call s:FilterStaticClassMembers(tagPopupList, szAccessFilter)
+ else
+ let szAccessFilter = (s:contextStack[0] == szTypeInfo)? 'all' : 'protected'
+ call s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
+ endif
+ else
+ if index(s:contextStack, szTypeInfo)<0
+ let szAccessFilter = 'public'
+ else
+ let szAccessFilter = (s:contextStack[0] == szTypeInfo)? 'all' : 'protected'
+ endif
+ call s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
+ endif
+ else
+ " We want to complete a namespace
+ call s:FilterNamespaceScopeMembers(tagPopupList)
+ endif
+ endfor
+ endif
+ else
+ " C) CLASS_MEMBERS_COMPLETION_MODE
+ for resolvedTagItem in omni#cpp#utils#GetResolvedTags(s:contextStack, typeInfo)
+ let szTypeInfo = omni#cpp#utils#ExtractTypeInfoFromTag(resolvedTagItem)
+ if index(s:contextStack, szTypeInfo)<0
+ let szAccessFilter = 'public'
+ else
+ let szAccessFilter = (s:contextStack[0] == szTypeInfo)? 'all' : 'protected'
+ endif
+ call s:FilterClassMembers(s:SearchMembers(resolvedTagItem, a:base), szAccessFilter)
+ endfor
+ endif
+ endif
+ endif
+
+ "call omni#common#debug#End()
+
+ return s:popupItemResultList
+endfunc
diff --git a/.vim/autoload/omni/cpp/includes.vim b/.vim/autoload/omni/cpp/includes.vim
new file mode 100644
index 0000000..10a89bc
--- /dev/null
+++ b/.vim/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/.vim/autoload/omni/cpp/items.vim b/.vim/autoload/omni/cpp/items.vim
new file mode 100644
index 0000000..b943ad4
--- /dev/null
+++ b/.vim/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<MyClass*>(something)
+" @return type info string
+function! s:ResolveCppCast(tokens)
+ return omni#cpp#utils#ExtractTypeInfoFromTokens(s:ResolveCast(a:tokens, '<', '>'))
+endfunc
+
+" Resolve a cast.
+" Resolve a C cast
+" @param list of token. tokens must be a list that represents
+" a cast expression (C cast) the function does not control
+" if it's a cast or not
+" eg: (MyClass*)something
+" @return type info string
+function! s:ResolveCCast(tokens)
+ return omni#cpp#utils#ExtractTypeInfoFromTokens(s:ResolveCast(a:tokens, '(', ')'))
+endfunc
+
+" Resolve a cast.
+" Resolve a C cast
+" @param list of token. tokens must be a list that represents
+" a cast expression (C cast) the function does not control
+" if it's a cast or not
+" eg: (MyClass*)something
+" @return type tokens
+function! s:ResolveCast(tokens, startChar, endChar)
+ let tokens = omni#cpp#utils#BuildParenthesisGroups(a:tokens)
+
+ " We remove useless parenthesis eg: (((MyClass)))
+ let tokens = omni#cpp#utils#SimplifyParenthesis(tokens)
+
+ let countItem=0
+ let startIndex = -1
+ let endIndex = -1
+ let i = 0
+ for token in tokens
+ if startIndex==-1
+ if token.value==a:startChar
+ let countItem += 1
+ let startIndex = i
+ endif
+ else
+ if token.value==a:startChar
+ let countItem += 1
+ elseif token.value==a:endChar
+ let countItem -= 1
+ endif
+
+ if countItem==0
+ let endIndex = i
+ break
+ endif
+ endif
+ let i+=1
+ endfor
+
+ return tokens[startIndex+1 : endIndex-1]
+endfunc
+
+" Replacement for build-in function 'searchdecl'
+" It does not require that the upper-level bracket is in the first column.
+" Otherwise it should be equal to 'searchdecl(name, 0, 1)'
+" @param name: name of variable to find declaration for
+function! s:LocalSearchDecl(name)
+
+ if g:OmniCpp_LocalSearchDecl == 0
+ let bUserIgnoreCase = &ignorecase
+
+ " Forcing the noignorecase option
+ " avoid bug when, for example, if we have a declaration like this : "A a;"
+ set noignorecase
+
+ let result = searchdecl(a:name, 0, 1)
+
+ " Restoring user's setting
+ let &ignorecase = bUserIgnoreCase
+
+ return result
+ endif
+
+ let lastpos = getpos('.')
+ let winview = winsaveview()
+ let lastfoldenable = &foldenable
+ let &foldenable = 0
+
+ " We add \C (noignorecase) to
+ " avoid bug when, for example, if we have a declaration like this : "A a;"
+ let varname = "\\C\\<" . a:name . "\\>"
+
+ " Go to first blank line before begin of highest scope
+ normal 99[{
+ let scopepos = getpos('.')
+ while (line('.') > 1) && (len(split(getline('.'))) > 0)
+ call cursor(line('.')-1, 0)
+ endwhile
+
+ let declpos = [ 0, 0, 0, 0 ]
+ while search(varname, '', scopepos[1]) > 0
+ " Check if we are a string or a comment
+ if omni#cpp#utils#IsCursorInCommentOrString()
+ continue
+ endif
+
+ " Remember match
+ let declpos = getpos('.')
+ endwhile
+ if declpos[1] != 0
+ " We found a match
+ call winrestview(winview)
+ call setpos('.', declpos)
+ let &foldenable = lastfoldenable
+ return 0
+ endif
+
+ while search(varname, '', lastpos[1]) > 0
+ " Check if current scope is ending before variable
+ let old_cur = getpos('.')
+ normal ]}
+ let new_cur = getpos('.')
+ call setpos('.', old_cur)
+ if (new_cur[1] < lastpos[1]) || ((new_cur[1] == lastpos[1]) && (new_cur[2] < lastpos[2]))
+ continue
+ endif
+
+ " Check if we are a string or a comment
+ if omni#cpp#utils#IsCursorInCommentOrString()
+ continue
+ endif
+
+ " We found match
+ call winrestview(winview)
+ call setpos('.', old_cur)
+ let &foldenable = lastfoldenable
+ return 0
+ endwhile
+
+ " No match found.
+ call winrestview(winview)
+ let &foldenable = lastfoldenable
+ return 1
+endfunc
diff --git a/.vim/autoload/omni/cpp/maycomplete.vim b/.vim/autoload/omni/cpp/maycomplete.vim
new file mode 100644
index 0000000..610526b
--- /dev/null
+++ b/.vim/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 = "\<C-X>\<C-O>"
+
+ " 0 = don't select first item
+ " 1 = select first item (inserting it to the text, default vim behaviour)
+ " 2 = select first item (without inserting it to the text)
+ if g:OmniCpp_SelectFirstItem == 0
+ " We have to force the menuone option to avoid confusion when there is
+ " only one popup item
+ set completeopt-=menu
+ set completeopt+=menuone
+ let szOmniMapping .= "\<C-P>"
+ elseif g:OmniCpp_SelectFirstItem == 2
+ " We have to force the menuone option to avoid confusion when there is
+ " only one popup item
+ set completeopt-=menu
+ set completeopt+=menuone
+ let szOmniMapping .= "\<C-P>"
+ let szOmniMapping .= "\<C-R>=pumvisible() ? \"\\<down>\" : \"\"\<cr>"
+ endif
+ return szOmniMapping
+endfunc
+
+" May complete function for dot
+function! omni#cpp#maycomplete#Dot()
+ if s:CanUseOmnicompletion() && g:OmniCpp_MayCompleteDot
+ let g:omni#cpp#items#data = omni#cpp#items#Get(omni#cpp#utils#TokenizeCurrentInstruction('.'))
+ if len(g:omni#cpp#items#data)
+ let s:bMayComplete = 1
+ return '.' . omni#cpp#maycomplete#Complete()
+ endif
+ endif
+ return '.'
+endfunc
+" May complete function for arrow
+function! omni#cpp#maycomplete#Arrow()
+ if s:CanUseOmnicompletion() && g:OmniCpp_MayCompleteArrow
+ let index = col('.') - 2
+ if index >= 0
+ let char = getline('.')[index]
+ if char == '-'
+ let g:omni#cpp#items#data = omni#cpp#items#Get(omni#cpp#utils#TokenizeCurrentInstruction('>'))
+ if len(g:omni#cpp#items#data)
+ let s:bMayComplete = 1
+ return '>' . omni#cpp#maycomplete#Complete()
+ endif
+ endif
+ endif
+ endif
+ return '>'
+endfunc
+
+" May complete function for double points
+function! omni#cpp#maycomplete#Scope()
+ if s:CanUseOmnicompletion() && g:OmniCpp_MayCompleteScope
+ let index = col('.') - 2
+ if index >= 0
+ let char = getline('.')[index]
+ if char == ':'
+ let g:omni#cpp#items#data = omni#cpp#items#Get(omni#cpp#utils#TokenizeCurrentInstruction(':'))
+ if len(g:omni#cpp#items#data)
+ if len(g:omni#cpp#items#data[-1].tokens) && g:omni#cpp#items#data[-1].tokens[-1].value != '::'
+ let s:bMayComplete = 1
+ return ':' . omni#cpp#maycomplete#Complete()
+ endif
+ endif
+ endif
+ endif
+ endif
+ return ':'
+endfunc
diff --git a/.vim/autoload/omni/cpp/namespaces.vim b/.vim/autoload/omni/cpp/namespaces.vim
new file mode 100644
index 0000000..386b3f9
--- /dev/null
+++ b/.vim/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/.vim/autoload/omni/cpp/settings.vim b/.vim/autoload/omni/cpp/settings.vim
new file mode 100644
index 0000000..6683d3a
--- /dev/null
+++ b/.vim/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/.vim/autoload/omni/cpp/tokenizer.vim b/.vim/autoload/omni/cpp/tokenizer.vim
new file mode 100644
index 0000000..16e0be2
--- /dev/null
+++ b/.vim/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/.vim/autoload/omni/cpp/utils.vim b/.vim/autoload/omni/cpp/utils.vim
new file mode 100644
index 0000000..5d74d34
--- /dev/null
+++ b/.vim/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 && startCmt<endCmt
+ if startCmt>0
+ let result = result[ : startCmt-1 ] . result[ endCmt+2 : ]
+ else
+ " Case where '/*' is at the start of the line
+ let result = result[ endCmt+2 : ]
+ endif
+ let startCmt = match(result, '\/\*')
+ let endCmt = match(result, '\*\/')
+ endwhile
+ return result
+endfunc
+
+" Get a c++ code from current buffer from [lineStart, colStart] to
+" [lineEnd, colEnd] without c++ and c comments, without end of line
+" and with empty strings if any
+" @return a string
+function! omni#cpp#utils#GetCode(posStart, posEnd)
+ let posStart = a:posStart
+ let posEnd = a:posEnd
+ if a:posStart[0]>a:posEnd[0]
+ let posStart = a:posEnd
+ let posEnd = a:posStart
+ elseif a:posStart[0]==a:posEnd[0] && a:posStart[1]>a:posEnd[1]
+ let posStart = a:posEnd
+ let posEnd = a:posStart
+ endif
+
+ " Getting the lines
+ let lines = getline(posStart[0], posEnd[0])
+ let lenLines = len(lines)
+
+ " Formatting the result
+ let result = ''
+ if lenLines==1
+ let sStart = posStart[1]-1
+ let sEnd = posEnd[1]-1
+ let line = lines[0]
+ let lenLastLine = strlen(line)
+ let sEnd = (sEnd>lenLastLine)?lenLastLine : sEnd
+ if sStart >= 0
+ let result = omni#cpp#utils#GetCodeFromLine(line[ sStart : sEnd ])
+ endif
+ elseif lenLines>1
+ let sStart = posStart[1]-1
+ let sEnd = posEnd[1]-1
+ let lenLastLine = strlen(lines[-1])
+ let sEnd = (sEnd>lenLastLine)?lenLastLine : sEnd
+ if sStart >= 0
+ let lines[0] = lines[0][ sStart : ]
+ let lines[-1] = lines[-1][ : sEnd ]
+ for aLine in lines
+ let result = result . omni#cpp#utils#GetCodeFromLine(aLine)." "
+ endfor
+ let result = result[:-2]
+ endif
+ endif
+
+ " Now we have the entire code in one line and we can remove C comments
+ return s:RemoveCComments(result)
+endfunc
+
+" Extract the scope (context) of a tag item
+" eg: ::MyNamespace
+" @return a string of the scope. a scope from tag always starts with '::'
+function! omni#cpp#utils#ExtractScope(tagItem)
+ let listKindScope = ['class', 'struct', 'union', 'namespace', 'enum']
+ let szResult = '::'
+ for scope in listKindScope
+ if has_key(a:tagItem, scope)
+ let szResult = szResult . a:tagItem[scope]
+ break
+ endif
+ endfor
+ return szResult
+endfunc
+
+" Simplify scope string, remove consecutive '::' if any
+function! omni#cpp#utils#SimplifyScope(szScope)
+ let szResult = substitute(a:szScope, '\(::\)\+', '::', 'g')
+ if szResult=='::'
+ return szResult
+ else
+ return substitute(szResult, '::$', '', 'g')
+ endif
+endfunc
+
+" Check if the cursor is in comment
+function! omni#cpp#utils#IsCursorInCommentOrString()
+ return match(synIDattr(synID(line("."), col(".")-1, 1), "name"), '\C\<cComment\|\<cCppString\|\<cIncluded')>=0
+endfunc
+
+" Tokenize the current instruction until the cursor position.
+" @return list of tokens
+function! omni#cpp#utils#TokenizeCurrentInstruction(...)
+ let szAppendText = ''
+ if a:0>0
+ let szAppendText = a:1
+ endif
+
+ let startPos = searchpos('[;{}]\|\%^', 'bWn')
+ let curPos = getpos('.')[1:2]
+ " We don't want the character under the cursor
+ let column = curPos[1]-1
+ let curPos[1] = (column<1)?1:column
+ return omni#cpp#tokenizer#Tokenize(omni#cpp#utils#GetCode(startPos, curPos)[1:] . szAppendText)
+endfunc
+
+" Tokenize the current instruction until the word under the cursor.
+" @return list of tokens
+function! omni#cpp#utils#TokenizeCurrentInstructionUntilWord()
+ let startPos = searchpos('[;{}]\|\%^', 'bWn')
+
+ " Saving the current cursor pos
+ let originalPos = getpos('.')
+
+ " We go at the end of the word
+ execute 'normal gee'
+ let curPos = getpos('.')[1:2]
+
+ " Restoring the original cursor pos
+ call setpos('.', originalPos)
+
+ let szCode = omni#cpp#utils#GetCode(startPos, curPos)[1:]
+ return omni#cpp#tokenizer#Tokenize(szCode)
+endfunc
+
+" Build parenthesis groups
+" add a new key 'group' in the token
+" where value is the group number of the parenthesis
+" eg: (void*)(MyClass*)
+" group1 group0
+" if a parenthesis is unresolved the group id is -1
+" @return a copy of a:tokens with parenthesis group
+function! omni#cpp#utils#BuildParenthesisGroups(tokens)
+ let tokens = copy(a:tokens)
+ let kinds = {'(': '()', ')' : '()', '[' : '[]', ']' : '[]', '<' : '<>', '>' : '<>', '{': '{}', '}': '{}'}
+ let unresolved = {'()' : [], '[]': [], '<>' : [], '{}' : []}
+ let groupId = 0
+
+ " Note: we build paren group in a backward way
+ " because we can often have parenthesis unbalanced
+ " instruction
+ " eg: doSomething(_member.get()->
+ for token in reverse(tokens)
+ if index([')', ']', '>', '}'], token.value)>=0
+ let token['group'] = groupId
+ call extend(unresolved[kinds[token.value]], [token])
+ let groupId+=1
+ elseif index(['(', '[', '<', '{'], token.value)>=0
+ if len(unresolved[kinds[token.value]])
+ let tokenResolved = remove(unresolved[kinds[token.value]], -1)
+ let token['group'] = tokenResolved.group
+ else
+ let token['group'] = -1
+ endif
+ endif
+ endfor
+
+ return reverse(tokens)
+endfunc
+
+" Determine if tokens represent a C cast
+" @return
+" - itemCast
+" - itemCppCast
+" - itemVariable
+" - itemThis
+function! omni#cpp#utils#GetCastType(tokens)
+ " Note: a:tokens is not modified
+ let tokens = omni#cpp#utils#SimplifyParenthesis(omni#cpp#utils#BuildParenthesisGroups(a:tokens))
+
+ if tokens[0].value == '('
+ return 'itemCast'
+ elseif index(['static_cast', 'dynamic_cast', 'reinterpret_cast', 'const_cast'], tokens[0].value)>=0
+ return 'itemCppCast'
+ else
+ for token in tokens
+ if token.value=='this'
+ return 'itemThis'
+ endif
+ endfor
+ return 'itemVariable'
+ endif
+endfunc
+
+" Remove useless parenthesis
+function! omni#cpp#utils#SimplifyParenthesis(tokens)
+ "Note: a:tokens is not modified
+ let tokens = a:tokens
+ " We remove useless parenthesis eg: (((MyClass)))
+ if len(tokens)>2
+ while tokens[0].value=='(' && tokens[-1].value==')' && tokens[0].group==tokens[-1].group
+ let tokens = tokens[1:-2]
+ endwhile
+ endif
+ return tokens
+endfunc
+
+" Function create a type info
+function! omni#cpp#utils#CreateTypeInfo(param)
+ let type = type(a:param)
+ return {'type': type, 'value':a:param}
+endfunc
+
+" Extract type info from a tag item
+" eg: ::MyNamespace::MyClass
+function! omni#cpp#utils#ExtractTypeInfoFromTag(tagItem)
+ let szTypeInfo = omni#cpp#utils#ExtractScope(a:tagItem) . '::' . substitute(a:tagItem.name, '.*::', '', 'g')
+ return omni#cpp#utils#SimplifyScope(szTypeInfo)
+endfunc
+
+" Build a class inheritance list
+function! omni#cpp#utils#GetClassInheritanceList(namespaces, typeInfo)
+ let result = []
+ for tagItem in omni#cpp#utils#GetResolvedTags(a:namespaces, a:typeInfo)
+ call extend(result, [omni#cpp#utils#ExtractTypeInfoFromTag(tagItem)])
+ endfor
+ return result
+endfunc
+
+" Get class inheritance list where items in the list are tag items.
+" TODO: Verify inheritance order
+function! omni#cpp#utils#GetResolvedTags(namespaces, typeInfo)
+ let result = []
+ let tagItem = omni#cpp#utils#GetResolvedTagItem(a:namespaces, a:typeInfo)
+ if tagItem!={}
+ let szTypeInfo = omni#cpp#utils#ExtractTypeInfoFromTag(tagItem)
+ if has_key(g:omni#cpp#utils#CACHE_TAG_INHERITS, szTypeInfo)
+ let result = g:omni#cpp#utils#CACHE_TAG_INHERITS[szTypeInfo]
+ else
+ call extend(result, [tagItem])
+ if has_key(tagItem, 'inherits')
+ for baseClassTypeInfo in split(tagItem.inherits, ',')
+ let namespaces = [omni#cpp#utils#ExtractScope(tagItem), '::']
+ call extend(result, omni#cpp#utils#GetResolvedTags(namespaces, omni#cpp#utils#CreateTypeInfo(baseClassTypeInfo)))
+ endfor
+ endif
+ let g:omni#cpp#utils#CACHE_TAG_INHERITS[szTypeInfo] = result
+ endif
+ endif
+ return result
+endfunc
+
+" Get a tag item after a scope resolution and typedef resolution
+function! omni#cpp#utils#GetResolvedTagItem(namespaces, typeInfo)
+ let typeInfo = {}
+ if type(a:typeInfo) == 1
+ let typeInfo = omni#cpp#utils#CreateTypeInfo(a:typeInfo)
+ else
+ let typeInfo = a:typeInfo
+ endif
+
+ let result = {}
+ if !omni#cpp#utils#IsTypeInfoValid(typeInfo)
+ return result
+ endif
+
+ " Unnamed type case eg: '1::2'
+ if typeInfo.type == 4
+ " Here there is no typedef or namespace to resolve, the tagInfo.value is a tag item
+ " representing a variable ('v') a member ('m') or a typedef ('t') and the typename is
+ " always in global scope
+ return typeInfo.value
+ endif
+
+ " Named type case eg: 'MyNamespace::MyClass'
+ let szTypeInfo = omni#cpp#utils#GetTypeInfoString(typeInfo)
+
+ " Resolving namespace alias
+ " TODO: For the next release
+ "let szTypeInfo = omni#cpp#namespaces#ResolveAlias(g:omni#cpp#namespaces#CacheAlias, szTypeInfo)
+
+ if szTypeInfo=='::'
+ return result
+ endif
+
+ " We can only get members of class, struct, union and namespace
+ let szTagFilter = "index(['c', 's', 'u', 'n', 't'], v:val.kind[0])>=0"
+ let szTagQuery = szTypeInfo
+
+ if s:IsTypeInfoResolved(szTypeInfo)
+ " The type info is already resolved, we remove the starting '::'
+ let szTagQuery = substitute(szTypeInfo, '^::', '', 'g')
+ if len(split(szTagQuery, '::'))==1
+ " eg: ::MyClass
+ " Here we have to get tags that have no parent scope
+ " That's why we change the szTagFilter
+ let szTagFilter .= '&& ' . g:omni#cpp#utils#szFilterGlobalScope
+ let tagList = omni#common#utils#TagListNoThrow('^'.szTagQuery.'$')
+ call filter(tagList, szTagFilter)
+ if len(tagList)
+ let result = tagList[0]
+ endif
+ else
+ " eg: ::MyNamespace::MyClass
+ let tagList = omni#common#utils#TagListNoThrow('^'.szTagQuery.'$')
+ call filter(tagList, szTagFilter)
+
+ if len(tagList)
+ let result = tagList[0]
+ endif
+ endif
+ else
+ " The type is not resolved
+ let tagList = omni#common#utils#TagListNoThrow('^'.szTagQuery.'$')
+ call filter(tagList, szTagFilter)
+
+ if len(tagList)
+ " Resolving scope (namespace, nested class etc...)
+ let szScopeOfTypeInfo = s:ExtractScopeFromTypeInfo(szTypeInfo)
+ if s:IsTypeInfoResolved(szTypeInfo)
+ let result = s:GetTagOfSameScope(tagList, szScopeOfTypeInfo)
+ else
+ " For each namespace of the namespace list we try to get a tag
+ " that can be in the same scope
+ if g:OmniCpp_NamespaceSearch && &filetype != 'c'
+ for scope in a:namespaces
+ let szTmpScope = omni#cpp#utils#SimplifyScope(scope.'::'.szScopeOfTypeInfo)
+ let result = s:GetTagOfSameScope(tagList, szTmpScope)
+ if result!={}
+ break
+ endif
+ endfor
+ else
+ let szTmpScope = omni#cpp#utils#SimplifyScope('::'.szScopeOfTypeInfo)
+ let result = s:GetTagOfSameScope(tagList, szTmpScope)
+ endif
+ endif
+ endif
+ endif
+
+ if result!={}
+ " We have our tagItem but maybe it's a typedef or an unnamed type
+ if result.kind[0]=='t'
+ " Here we can have a typedef to another typedef, a class, struct, union etc
+ " but we can also have a typedef to an unnamed type, in that
+ " case the result contains a 'typeref' key
+ let namespaces = [omni#cpp#utils#ExtractScope(result), '::']
+ if has_key(result, 'typeref')
+ let result = omni#cpp#utils#GetResolvedTagItem(namespaces, omni#cpp#utils#CreateTypeInfo(result))
+ else
+ let szCmd = omni#cpp#utils#ExtractCmdFromTagItem(result)
+ let szCode = substitute(omni#cpp#utils#GetCodeFromLine(szCmd), '\C\<'.result.name.'\>.*', '', 'g')
+ let szTypeInfo = omni#cpp#utils#ExtractTypeInfoFromTokens(omni#cpp#tokenizer#Tokenize(szCode))
+ let result = omni#cpp#utils#GetResolvedTagItem(namespaces, omni#cpp#utils#CreateTypeInfo(szTypeInfo))
+ " TODO: Namespace resolution for result
+ endif
+ endif
+ endif
+
+ return result
+endfunc
+
+" Returns if the type info is valid
+" @return
+" - 1 if valid
+" - 0 otherwise
+function! omni#cpp#utils#IsTypeInfoValid(typeInfo)
+ if a:typeInfo=={}
+ return 0
+ else
+ if a:typeInfo.type == 1 && a:typeInfo.value==''
+ " String case
+ return 0
+ elseif a:typeInfo.type == 4 && a:typeInfo.value=={}
+ " Dictionary case
+ return 0
+ endif
+ endif
+ return 1
+endfunc
+
+" Get the string of the type info
+function! omni#cpp#utils#GetTypeInfoString(typeInfo)
+ if a:typeInfo.type == 1
+ return a:typeInfo.value
+ else
+ return substitute(a:typeInfo.value.typeref, '^\w\+:', '', 'g')
+ endif
+endfunc
+
+" A resolved type info starts with '::'
+" @return
+" - 1 if type info starts with '::'
+" - 0 otherwise
+function! s:IsTypeInfoResolved(szTypeInfo)
+ return match(a:szTypeInfo, '^::')!=-1
+endfunc
+
+" A returned type info's scope may not have the global namespace '::'
+" eg: '::NameSpace1::NameSpace2::MyClass' => '::NameSpace1::NameSpace2'
+" 'NameSpace1::NameSpace2::MyClass' => 'NameSpace1::NameSpace2'
+function! s:ExtractScopeFromTypeInfo(szTypeInfo)
+ let szScope = substitute(a:szTypeInfo, '\w\+$', '', 'g')
+ if szScope =='::'
+ return szScope
+ else
+ return substitute(szScope, '::$', '', 'g')
+ endif
+endfunc
+
+" @return
+" - the tag with the same scope
+" - {} otherwise
+function! s:GetTagOfSameScope(listTags, szScopeToMatch)
+ for tagItem in a:listTags
+ let szScopeOfTag = omni#cpp#utils#ExtractScope(tagItem)
+ if szScopeOfTag == a:szScopeToMatch
+ return tagItem
+ endif
+ endfor
+ return {}
+endfunc
+
+" Extract the cmd of a tag item without regexp
+function! omni#cpp#utils#ExtractCmdFromTagItem(tagItem)
+ let line = a:tagItem.cmd
+ let re = '\(\/\^\)\|\(\$\/\)'
+ if match(line, re)!=-1
+ let line = substitute(line, re, '', 'g')
+ return line
+ else
+ " TODO: the cmd is a line number
+ return ''
+ endif
+endfunc
+
+" Extract type from tokens.
+" eg: examples of tokens format
+" 'const MyClass&'
+" 'const map < int, int >&'
+" 'MyNs::MyClass'
+" '::MyClass**'
+" 'MyClass a, *b = NULL, c[1] = {};
+" 'hello(MyClass a, MyClass* b'
+" @return the type info string eg: ::std::map
+" can be empty
+function! omni#cpp#utils#ExtractTypeInfoFromTokens(tokens)
+ let szResult = ''
+ let state = 0
+
+ let tokens = omni#cpp#utils#BuildParenthesisGroups(a:tokens)
+
+ " If there is an unbalanced parenthesis we are in a parameter list
+ let bParameterList = 0
+ for token in tokens
+ if token.value == '(' && token.group==-1
+ let bParameterList = 1
+ break
+ endif
+ endfor
+
+ if bParameterList
+ let tokens = reverse(tokens)
+ let state = 0
+ let parenGroup = -1
+ for token in tokens
+ if state==0
+ if token.value=='>'
+ let parenGroup = token.group
+ let state=1
+ elseif token.kind == 'cppWord'
+ let szResult = token.value.szResult
+ let state=2
+ elseif index(['*', '&'], token.value)<0
+ break
+ endif
+ elseif state==1
+ if token.value=='<' && token.group==parenGroup
+ let state=0
+ endif
+ elseif state==2
+ if token.value=='::'
+ let szResult = token.value.szResult
+ let state=3
+ else
+ break
+ endif
+ elseif state==3
+ if token.kind == 'cppWord'
+ let szResult = token.value.szResult
+ let state=2
+ else
+ break
+ endif
+ endif
+ endfor
+ return szResult
+ endif
+
+ for token in tokens
+ if state==0
+ if token.value == '::'
+ let szResult .= token.value
+ let state = 1
+ elseif token.kind == 'cppWord'
+ let szResult .= token.value
+ let state = 2
+ " Maybe end of token
+ endif
+ elseif state==1
+ if token.kind == 'cppWord'
+ let szResult .= token.value
+ let state = 2
+ " Maybe end of token
+ else
+ break
+ endif
+ elseif state==2
+ if token.value == '::'
+ let szResult .= token.value
+ let state = 1
+ else
+ break
+ endif
+ endif
+ endfor
+ return szResult
+endfunc
+
+" Get the preview window string
+function! omni#cpp#utils#GetPreviewWindowStringFromTagItem(tagItem)
+ let szResult = ''
+
+ let szResult .= 'name: '.a:tagItem.name."\n"
+ for tagKey in keys(a:tagItem)
+ if index(['name', 'static'], tagKey)>=0
+ continue
+ endif
+ let szResult .= tagKey.': '.a:tagItem[tagKey]."\n"
+ endfor
+
+ return substitute(szResult, "\n$", '', 'g')
+endfunc