📄 utils.vim
字号:
endfunc" Get a tag item after a scope resolution and typedef resolutionfunction! 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 resultendfunc" Returns if the type info is valid" @return" - 1 if valid" - 0 otherwisefunction! 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 1endfunc" Get the string of the type infofunction! omni#cpp#utils#GetTypeInfoString(typeInfo) if a:typeInfo.type == 1 return a:typeInfo.value else return substitute(a:typeInfo.value.typeref, '^\w\+:', '', 'g') endifendfunc" A resolved type info starts with '::'" @return" - 1 if type info starts with '::'" - 0 otherwisefunction! s:IsTypeInfoResolved(szTypeInfo) return match(a:szTypeInfo, '^::')!=-1endfunc" 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') endifendfunc" @return" - the tag with the same scope" - {} otherwisefunction! 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 regexpfunction! 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 '' endifendfunc" 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 emptyfunction! 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 szResultendfunc" Get the preview window stringfunction! 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -