" ============================================================================ " File: tagbar.vim " Description: List the current file's tags in a sidebar, ordered by class etc " Maintainer: Jan Larres " Licence: Vim licence " Website: http://github.com/majutsushi/tagbar " Note: This plugin was heavily inspired by the 'Taglist' plugin by " Yegappan Lakshmanan and uses some small portions of code from " it. " ============================================================================ if &cp || exists('g:loaded_tagbar') finish endif " Initialization {{{1 if !exists('*system') echomsg 'Tagbar: No system() function available, skipping plugin' finish endif if !exists('g:tagbar_ctags_bin') if executable('ctags-exuberant') let g:tagbar_ctags_bin = 'ctags-exuberant' elseif executable('exctags') let g:tagbar_ctags_bin = 'exctags' elseif executable('ctags') let g:tagbar_ctags_bin = 'ctags' elseif executable('ctags.exe') let g:tagbar_ctags_bin = 'ctags.exe' elseif executable('tags') let g:tagbar_ctags_bin = 'tags' else echomsg 'Tagbar: Exuberant ctags not found, skipping plugin' finish endif endif let g:loaded_tagbar = 1 if !exists('g:tagbar_left') let g:tagbar_left = 0 endif if !exists('g:tagbar_width') let g:tagbar_width = 40 endif if !exists('g:tagbar_types') let g:tagbar_types = {} endif if !exists('g:tagbar_autoclose') let g:tagbar_autoclose = 0 endif if !exists('g:tagbar_sort') let g:tagbar_sort = 1 endif let s:type_init_done = 0 " s:InitTypes() {{{1 function! s:InitTypes() " Dictionary of the already processed files, indexed by file name with " complete path. " The entries are again dictionaries with the following fields: " - mtime: File modification time " - ftype: The vim file type " - tags: List of the tags that are present in the file, sorted " according to the value of 'g:tagbar_sort' " - fline: Dictionary of the tags, indexed by line number in the file " - tline: Dictionary of the tags, indexed by line number in the tagbar let s:known_files = {} let s:known_types = {} " Ant {{{2 let type_ant = {} let type_ant.ctagstype = 'ant' let type_ant.kinds = [ \ 'p:projects', \ 't:targets' \ ] let s:known_types.ant = type_ant " Asm {{{2 let type_asm = {} let type_asm.ctagstype = 'asm' let type_asm.kinds = [ \ 'm:macros', \ 't:types', \ 'd:defines', \ 'l:labels' \ ] let s:known_types.asm = type_asm " ASP {{{2 let type_aspvbs = {} let type_aspvbs.ctagstype = 'asp' let type_aspvbs.kinds = [ \ 'd:constants', \ 'c:classes', \ 'f:functions', \ 's:subroutines', \ 'v:variables' \ ] let s:known_types.aspvbs = type_aspvbs " Awk {{{2 let type_awk = {} let type_awk.ctagstype = 'awk' let type_awk.kinds = [ \ 'f:functions' \ ] let s:known_types.awk = type_awk " Basic {{{2 let type_basic = {} let type_basic.ctagstype = 'basic' let type_basic.kinds = [ \ 'c:constants', \ 'g:enumerations', \ 'f:functions', \ 'l:labels', \ 't:types', \ 'v:variables' \ ] let s:known_types.basic = type_basic " BETA {{{2 let type_beta = {} let type_beta.ctagstype = 'beta' let type_beta.kinds = [ \ 'f:fragments', \ 's:slots', \ 'v:patterns' \ ] let s:known_types.beta = type_beta " C {{{2 let type_c = {} let type_c.ctagstype = 'c' let type_c.scopes = ['enum', 'struct', 'union'] let type_c.sro = '::' let type_c.kinds = [ \ 'd:macros', \ 'p:prototypes', \ 'g:enums', \ 'e:enumerators', \ 't:typedefs', \ 's:structs', \ 'u:unions', \ 'm:members', \ 'v:variables', \ 'f:functions' \ ] let type_c.kind2scope = { \ 'g' : 'enum', \ 's' : 'struct', \ 'u' : 'union' \ } let type_c.scope2kind = { \ 'enum' : 'g', \ 'struct' : 's', \ 'union' : 'u' \ } let s:known_types.c = type_c " C++ {{{2 let type_cpp = {} let type_cpp.ctagstype = 'c++' let type_cpp.scopes = [ \ 'namespace', \ 'class', \ 'struct', \ 'enum', \ 'union' \ ] let type_cpp.sro = '::' let type_cpp.kinds = [ \ 'd:macros', \ 'p:prototypes', \ 'g:enums', \ 'e:enumerators', \ 't:typedefs', \ 'n:namespaces', \ 'c:classes', \ 's:structs', \ 'u:unions', \ 'f:functions', \ 'm:members', \ 'v:variables' \ ] let type_cpp.kind2scope = { \ 'g' : 'enum', \ 'n' : 'namespace', \ 'c' : 'class', \ 's' : 'struct', \ 'u' : 'union' \ } let type_cpp.scope2kind = { \ 'enum' : 'g', \ 'namespace' : 'n', \ 'class' : 'c', \ 'struct' : 's', \ 'union' : 'u' \ } let s:known_types.cpp = type_cpp " C# {{{2 let type_cs = {} let type_cs.ctagstype = 'c#' let type_cs.scopes = [ \ 'namespace', \ 'interface', \ 'class', \ 'struct', \ 'enum' \ ] let type_cs.sro = '.' let type_cs.kinds = [ \ 'd:macros', \ 'f:fields', \ 'g:enums', \ 'e:enumerators', \ 't:typedefs', \ 'n:namespaces', \ 'i:interfaces', \ 'c:classes', \ 's:structs', \ 'E:events', \ 'm:methods', \ 'p:properties' \ ] let type_cs.kind2scope = { \ 'n' : 'namespace', \ 'i' : 'interface', \ 'c' : 'class', \ 's' : 'struct', \ 'g' : 'enum' \ } let type_cs.scope2kind = { \ 'namespace' : 'n', \ 'interface' : 'i', \ 'class' : 'c', \ 'struct' : 's', \ 'enum' : 'g' \ } let s:known_types.cs = type_cs " COBOL {{{2 let type_cobol = {} let type_cobol.ctagstype = 'cobol' let type_cobol.kinds = [ \ 'd:data items', \ 'f:file descriptions', \ 'g:group items', \ 'p:paragraphs', \ 'P:program ids', \ 's:sections' \ ] let s:known_types.cobol = type_cobol " DOS Batch {{{2 let type_dosbatch = {} let type_dosbatch.ctagstype = 'dosbatch' let type_dosbatch.kinds = [ \ 'l:labels', \ 'v:variables' \ ] let s:known_types.dosbatch = type_dosbatch " Eiffel {{{2 let type_eiffel = {} let type_eiffel.ctagstype = 'eiffel' let type_eiffel.scopes = ['class', 'feature'] let type_eiffel.sro = '.' " Not sure, is nesting even possible? let type_eiffel.kinds = [ \ 'c:classes', \ 'f:features' \ ] let type_eiffel.kind2scope = { \ 'c' : 'class', \ 'f' : 'feature' \ } let type_eiffel.scope2kind = { \ 'class' : 'c', \ 'feature' : 'f' \ } let s:known_types.eiffel = type_eiffel " Java {{{2 let type_java = {} let type_java.ctagstype = 'java' let type_java.scopes = ['enum', 'interface', 'class'] let type_java.sro = '.' let type_java.kinds = [ \ 'p:packages', \ 'f:fields', \ 'g:enum types', \ 'e:enum constants', \ 'i:interfaces', \ 'c:classes', \ 'm:methods' \ ] let type_java.kind2scope = { \ 'g' : 'enum', \ 'i' : 'interface', \ 'c' : 'class' \ } let type_java.scope2kind = { \ 'enum' : 'g', \ 'interface' : 'i', \ 'class' : 'c' \ } let s:known_types.java = type_java " Python {{{2 let type_python = {} let type_python.ctagstype = 'python' let type_python.scopes = ['class', 'function'] let type_python.sro = '.' let type_python.kinds = [ \ 'i:imports', \ 'c:classes', \ 'f:functions', \ 'm:members', \ 'v:variables' \ ] let type_python.kind2scope = { \ 'c' : 'class', \ 'f' : 'function', \ 'm' : 'function' \ } let type_python.scope2kind = { \ 'class' : 'c', \ 'function' : 'f' \ } let s:known_types.python = type_python " }}}2 call extend(s:known_types, g:tagbar_types) " Create a dictionary of the kind order for fast " access in sorting functions for type in values(s:known_types) let i = 0 let type.kinddict = {} for kind in type.kinds let type.kinddict[kind[0]] = i let i += 1 endfor endfor let s:access_symbols = {} let s:access_symbols.public = '+' let s:access_symbols.protected = '#' let s:access_symbols.private = '-' let s:type_init_done = 1 endfunction " s:ToggleWindow() {{{1 function! s:ToggleWindow() let tagbarwinnr = bufwinnr("__Tagbar__") if tagbarwinnr != -1 call s:CloseWindow() return endif call s:OpenWindow() endfunction " s:OpenWindow() {{{1 function! s:OpenWindow() if !s:type_init_done call s:InitTypes() endif " If the tagbar window is already open jump to it let tagbarwinnr = bufwinnr('__Tagbar__') if tagbarwinnr != -1 && winnr() != tagbarwinnr execute tagbarwinnr . 'wincmd w' return endif let openpos = g:tagbar_left ? 'topleft vertical ' : 'botright vertical ' exe 'silent! keepalt ' . openpos . g:tagbar_width . 'split ' . '__Tagbar__' setlocal noreadonly " in case the "view" mode is used setlocal buftype=nofile setlocal bufhidden=hide setlocal noswapfile setlocal nobuflisted setlocal nomodifiable setlocal filetype=tagbar setlocal nolist setlocal nonumber setlocal nowrap setlocal winfixwidth if exists('+relativenumber') setlocal norelativenumber endif setlocal foldenable setlocal foldminlines=0 setlocal foldmethod=manual setlocal foldlevel=9999 setlocal foldcolumn=1 setlocal foldtext=v:folddashes.getline(v:foldstart) setlocal statusline=%!TagbarGenerateStatusline() " Variable for saving the current file for functions that are called from " the tagbar window let s:current_file = '' " Script-local variable needed since compare functions can't " take extra arguments let s:compare_typeinfo = {} let s:is_maximized = 0 let s:short_help = 1 syntax match Comment '^" .*' " Comments syntax match Identifier '^ [^: ]\+[^:]\+$' " Non-scoped kinds syntax match Title '[^:(* ]\+\ze\*\? :' " Scope names syntax match Type ': \zs.*' " Scope types syntax match SpecialKey '(.*)' " Signatures syntax match NonText '\*\ze :' " Pseudo-tag identifiers highlight default TagbarAccessPublic guifg=Green ctermfg=Green highlight default TagbarAccessProtected guifg=Blue ctermfg=Blue highlight default TagbarAccessPrivate guifg=Red ctermfg=Red syntax match TagbarAccessPublic '^\s*+\ze[^ ]' syntax match TagbarAccessProtected '^\s*#\ze[^ ]' syntax match TagbarAccessPrivate '^\s*-\ze[^ ]' if has('balloon_eval') setlocal balloonexpr=TagbarBalloonExpr() set ballooneval endif let cpoptions_save = &cpoptions set cpoptions&vim nnoremap