diff options
Diffstat (limited to 'vim/autoload/tagbar.vim')
| -rw-r--r-- | vim/autoload/tagbar.vim | 3099 |
1 files changed, 0 insertions, 3099 deletions
diff --git a/vim/autoload/tagbar.vim b/vim/autoload/tagbar.vim deleted file mode 100644 index 48ad320..0000000 --- a/vim/autoload/tagbar.vim +++ /dev/null @@ -1,3099 +0,0 @@ -" ============================================================================ -" File: tagbar.vim -" Description: List the current file's tags in a sidebar, ordered by class etc -" Author: Jan Larres <jan@majutsushi.net> -" Licence: Vim licence -" Website: http://majutsushi.github.com/tagbar/ -" Version: 2.3 -" Note: This plugin was heavily inspired by the 'Taglist' plugin by -" Yegappan Lakshmanan and uses a small amount of code from it. -" -" Original taglist copyright notice: -" Permission is hereby granted to use and distribute this code, -" with or without modifications, provided that this copyright -" notice is copied with it. Like anything else that's free, -" taglist.vim is provided *as is* and comes with no warranty of -" any kind, either expressed or implied. In no event will the -" copyright holder be liable for any damamges resulting from the -" use of this software. -" ============================================================================ - -scriptencoding utf-8 - -" Initialization {{{1 - -" Basic init {{{2 - -if !exists('g:tagbar_ctags_bin') - if executable('ctags-exuberant') - let g:tagbar_ctags_bin = 'ctags-exuberant' - elseif executable('exuberant-ctags') - let g:tagbar_ctags_bin = 'exuberant-ctags' - elseif executable('exctags') - let g:tagbar_ctags_bin = 'exctags' - elseif has('macunix') && executable('/usr/local/bin/ctags') - " Homebrew default location - let g:tagbar_ctags_bin = '/usr/local/bin/ctags' - elseif has('macunix') && executable('/opt/local/bin/ctags') - " Macports default location - let g:tagbar_ctags_bin = '/opt/local/bin/ctags' - 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 -else - " reset 'wildignore' temporarily in case *.exe is included in it - let wildignore_save = &wildignore - set wildignore& - - let g:tagbar_ctags_bin = expand(g:tagbar_ctags_bin) - - let &wildignore = wildignore_save - - if !executable(g:tagbar_ctags_bin) - echomsg 'Tagbar: Exuberant ctags not found in specified place,' - \ 'skipping plugin' - finish - endif -endif - -redir => s:ftype_out -silent filetype -redir END -if s:ftype_out !~# 'detection:ON' - echomsg 'Tagbar: Filetype detection is turned off, skipping plugin' - unlet s:ftype_out - finish -endif -unlet s:ftype_out - -let s:icon_closed = g:tagbar_iconchars[0] -let s:icon_open = g:tagbar_iconchars[1] - -let s:type_init_done = 0 -let s:autocommands_done = 0 -let s:checked_ctags = 0 -let s:window_expanded = 0 - -let s:access_symbols = { - \ 'public' : '+', - \ 'protected' : '#', - \ 'private' : '-' -\ } - -let g:loaded_tagbar = 1 - -let s:last_highlight_tline = 0 -let s:debug = 0 -let s:debug_file = '' - -" s:Init() {{{2 -function! s:Init() - if !s:type_init_done - call s:InitTypes() - endif - - if !s:checked_ctags - if !s:CheckForExCtags() - return - endif - endif -endfunction - -" s:InitTypes() {{{2 -function! s:InitTypes() - call s:LogDebugMessage('Initializing types') - - let s:known_types = {} - - " Ant {{{3 - let type_ant = {} - let type_ant.ctagstype = 'ant' - let type_ant.kinds = [ - \ {'short' : 'p', 'long' : 'projects', 'fold' : 0}, - \ {'short' : 't', 'long' : 'targets', 'fold' : 0} - \ ] - let s:known_types.ant = type_ant - " Asm {{{3 - let type_asm = {} - let type_asm.ctagstype = 'asm' - let type_asm.kinds = [ - \ {'short' : 'm', 'long' : 'macros', 'fold' : 0}, - \ {'short' : 't', 'long' : 'types', 'fold' : 0}, - \ {'short' : 'd', 'long' : 'defines', 'fold' : 0}, - \ {'short' : 'l', 'long' : 'labels', 'fold' : 0} - \ ] - let s:known_types.asm = type_asm - " ASP {{{3 - let type_aspvbs = {} - let type_aspvbs.ctagstype = 'asp' - let type_aspvbs.kinds = [ - \ {'short' : 'd', 'long' : 'constants', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 's', 'long' : 'subroutines', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0} - \ ] - let s:known_types.aspvbs = type_aspvbs - " Awk {{{3 - let type_awk = {} - let type_awk.ctagstype = 'awk' - let type_awk.kinds = [ - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} - \ ] - let s:known_types.awk = type_awk - " Basic {{{3 - let type_basic = {} - let type_basic.ctagstype = 'basic' - let type_basic.kinds = [ - \ {'short' : 'c', 'long' : 'constants', 'fold' : 0}, - \ {'short' : 'g', 'long' : 'enumerations', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'l', 'long' : 'labels', 'fold' : 0}, - \ {'short' : 't', 'long' : 'types', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0} - \ ] - let s:known_types.basic = type_basic - " BETA {{{3 - let type_beta = {} - let type_beta.ctagstype = 'beta' - let type_beta.kinds = [ - \ {'short' : 'f', 'long' : 'fragments', 'fold' : 0}, - \ {'short' : 's', 'long' : 'slots', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'patterns', 'fold' : 0} - \ ] - let s:known_types.beta = type_beta - " C {{{3 - let type_c = {} - let type_c.ctagstype = 'c' - let type_c.kinds = [ - \ {'short' : 'd', 'long' : 'macros', 'fold' : 1}, - \ {'short' : 'p', 'long' : 'prototypes', 'fold' : 1}, - \ {'short' : 'g', 'long' : 'enums', 'fold' : 0}, - \ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0}, - \ {'short' : 't', 'long' : 'typedefs', 'fold' : 0}, - \ {'short' : 's', 'long' : 'structs', 'fold' : 0}, - \ {'short' : 'u', 'long' : 'unions', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'members', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} - \ ] - let type_c.sro = '::' - 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++ {{{3 - let type_cpp = {} - let type_cpp.ctagstype = 'c++' - let type_cpp.kinds = [ - \ {'short' : 'd', 'long' : 'macros', 'fold' : 1}, - \ {'short' : 'p', 'long' : 'prototypes', 'fold' : 1}, - \ {'short' : 'g', 'long' : 'enums', 'fold' : 0}, - \ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0}, - \ {'short' : 't', 'long' : 'typedefs', 'fold' : 0}, - \ {'short' : 'n', 'long' : 'namespaces', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 's', 'long' : 'structs', 'fold' : 0}, - \ {'short' : 'u', 'long' : 'unions', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'members', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0} - \ ] - let type_cpp.sro = '::' - 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# {{{3 - let type_cs = {} - let type_cs.ctagstype = 'c#' - let type_cs.kinds = [ - \ {'short' : 'd', 'long' : 'macros', 'fold' : 1}, - \ {'short' : 'f', 'long' : 'fields', 'fold' : 0}, - \ {'short' : 'g', 'long' : 'enums', 'fold' : 0}, - \ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0}, - \ {'short' : 't', 'long' : 'typedefs', 'fold' : 0}, - \ {'short' : 'n', 'long' : 'namespaces', 'fold' : 0}, - \ {'short' : 'i', 'long' : 'interfaces', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 's', 'long' : 'structs', 'fold' : 0}, - \ {'short' : 'E', 'long' : 'events', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'methods', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'properties', 'fold' : 0} - \ ] - let type_cs.sro = '.' - 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 {{{3 - let type_cobol = {} - let type_cobol.ctagstype = 'cobol' - let type_cobol.kinds = [ - \ {'short' : 'd', 'long' : 'data items', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'file descriptions', 'fold' : 0}, - \ {'short' : 'g', 'long' : 'group items', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'paragraphs', 'fold' : 0}, - \ {'short' : 'P', 'long' : 'program ids', 'fold' : 0}, - \ {'short' : 's', 'long' : 'sections', 'fold' : 0} - \ ] - let s:known_types.cobol = type_cobol - " DOS Batch {{{3 - let type_dosbatch = {} - let type_dosbatch.ctagstype = 'dosbatch' - let type_dosbatch.kinds = [ - \ {'short' : 'l', 'long' : 'labels', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0} - \ ] - let s:known_types.dosbatch = type_dosbatch - " Eiffel {{{3 - let type_eiffel = {} - let type_eiffel.ctagstype = 'eiffel' - let type_eiffel.kinds = [ - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'features', 'fold' : 0} - \ ] - let type_eiffel.sro = '.' " Not sure, is nesting even possible? - let type_eiffel.kind2scope = { - \ 'c' : 'class', - \ 'f' : 'feature' - \ } - let type_eiffel.scope2kind = { - \ 'class' : 'c', - \ 'feature' : 'f' - \ } - let s:known_types.eiffel = type_eiffel - " Erlang {{{3 - let type_erlang = {} - let type_erlang.ctagstype = 'erlang' - let type_erlang.kinds = [ - \ {'short' : 'm', 'long' : 'modules', 'fold' : 0}, - \ {'short' : 'd', 'long' : 'macro definitions', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'r', 'long' : 'record definitions', 'fold' : 0} - \ ] - let type_erlang.sro = '.' " Not sure, is nesting even possible? - let type_erlang.kind2scope = { - \ 'm' : 'module' - \ } - let type_erlang.scope2kind = { - \ 'module' : 'm' - \ } - let s:known_types.erlang = type_erlang - " Flex {{{3 - " Vim doesn't support Flex out of the box, this is based on rough - " guesses and probably requires - " http://www.vim.org/scripts/script.php?script_id=2909 - " Improvements welcome! - let type_mxml = {} - let type_mxml.ctagstype = 'flex' - let type_mxml.kinds = [ - \ {'short' : 'v', 'long' : 'global variables', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'methods', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'properties', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'x', 'long' : 'mxtags', 'fold' : 0} - \ ] - let type_mxml.sro = '.' - let type_mxml.kind2scope = { - \ 'c' : 'class' - \ } - let type_mxml.scope2kind = { - \ 'class' : 'c' - \ } - let s:known_types.mxml = type_mxml - " Fortran {{{3 - let type_fortran = {} - let type_fortran.ctagstype = 'fortran' - let type_fortran.kinds = [ - \ {'short' : 'm', 'long' : 'modules', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'programs', 'fold' : 0}, - \ {'short' : 'k', 'long' : 'components', 'fold' : 0}, - \ {'short' : 't', 'long' : 'derived types and structures', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'common blocks', 'fold' : 0}, - \ {'short' : 'b', 'long' : 'block data', 'fold' : 0}, - \ {'short' : 'e', 'long' : 'entry points', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 's', 'long' : 'subroutines', 'fold' : 0}, - \ {'short' : 'l', 'long' : 'labels', 'fold' : 0}, - \ {'short' : 'n', 'long' : 'namelists', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0} - \ ] - let type_fortran.sro = '.' " Not sure, is nesting even possible? - let type_fortran.kind2scope = { - \ 'm' : 'module', - \ 'p' : 'program', - \ 'f' : 'function', - \ 's' : 'subroutine' - \ } - let type_fortran.scope2kind = { - \ 'module' : 'm', - \ 'program' : 'p', - \ 'function' : 'f', - \ 'subroutine' : 's' - \ } - let s:known_types.fortran = type_fortran - " HTML {{{3 - let type_html = {} - let type_html.ctagstype = 'html' - let type_html.kinds = [ - \ {'short' : 'f', 'long' : 'JavaScript funtions', 'fold' : 0}, - \ {'short' : 'a', 'long' : 'named anchors', 'fold' : 0} - \ ] - let s:known_types.html = type_html - " Java {{{3 - let type_java = {} - let type_java.ctagstype = 'java' - let type_java.kinds = [ - \ {'short' : 'p', 'long' : 'packages', 'fold' : 1}, - \ {'short' : 'f', 'long' : 'fields', 'fold' : 0}, - \ {'short' : 'g', 'long' : 'enum types', 'fold' : 0}, - \ {'short' : 'e', 'long' : 'enum constants', 'fold' : 0}, - \ {'short' : 'i', 'long' : 'interfaces', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'methods', 'fold' : 0} - \ ] - let type_java.sro = '.' - 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 - " JavaScript {{{3 - " JavaScript is weird -- it does have scopes, but ctags doesn't seem to - " properly generate the information for them, instead it simply uses the - " complete name. So ctags has to be fixed before I can do anything here. - " Alternatively jsctags/doctorjs will be used if available. - let type_javascript = {} - let type_javascript.ctagstype = 'javascript' - let jsctags = s:CheckFTCtags('jsctags', 'javascript') - if jsctags != '' - let type_javascript.kinds = [ - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} - \ ] - let type_javascript.sro = '.' - let type_javascript.kind2scope = { - \ 'v' : 'namespace', - \ 'f' : 'namespace' - \ } - let type_javascript.scope2kind = { - \ 'namespace' : 'v' - \ } - let type_javascript.ctagsbin = jsctags - let type_javascript.ctagsargs = '-f -' - else - let type_javascript.kinds = [ - \ {'short' : 'v', 'long' : 'global variables', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'properties', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'methods', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} - \ ] - endif - let s:known_types.javascript = type_javascript - " Lisp {{{3 - let type_lisp = {} - let type_lisp.ctagstype = 'lisp' - let type_lisp.kinds = [ - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} - \ ] - let s:known_types.lisp = type_lisp - " Lua {{{3 - let type_lua = {} - let type_lua.ctagstype = 'lua' - let type_lua.kinds = [ - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} - \ ] - let s:known_types.lua = type_lua - " Make {{{3 - let type_make = {} - let type_make.ctagstype = 'make' - let type_make.kinds = [ - \ {'short' : 'm', 'long' : 'macros', 'fold' : 0} - \ ] - let s:known_types.make = type_make - " Matlab {{{3 - let type_matlab = {} - let type_matlab.ctagstype = 'matlab' - let type_matlab.kinds = [ - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} - \ ] - let s:known_types.matlab = type_matlab - " Ocaml {{{3 - let type_ocaml = {} - let type_ocaml.ctagstype = 'ocaml' - let type_ocaml.kinds = [ - \ {'short' : 'M', 'long' : 'modules or functors', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'global variables', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'C', 'long' : 'constructors', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'methods', 'fold' : 0}, - \ {'short' : 'e', 'long' : 'exceptions', 'fold' : 0}, - \ {'short' : 't', 'long' : 'type names', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'r', 'long' : 'structure fields', 'fold' : 0} - \ ] - let type_ocaml.sro = '.' " Not sure, is nesting even possible? - let type_ocaml.kind2scope = { - \ 'M' : 'Module', - \ 'c' : 'class', - \ 't' : 'type' - \ } - let type_ocaml.scope2kind = { - \ 'Module' : 'M', - \ 'class' : 'c', - \ 'type' : 't' - \ } - let s:known_types.ocaml = type_ocaml - " Pascal {{{3 - let type_pascal = {} - let type_pascal.ctagstype = 'pascal' - let type_pascal.kinds = [ - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'procedures', 'fold' : 0} - \ ] - let s:known_types.pascal = type_pascal - " Perl {{{3 - let type_perl = {} - let type_perl.ctagstype = 'perl' - let type_perl.kinds = [ - \ {'short' : 'p', 'long' : 'packages', 'fold' : 1}, - \ {'short' : 'c', 'long' : 'constants', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'formats', 'fold' : 0}, - \ {'short' : 'l', 'long' : 'labels', 'fold' : 0}, - \ {'short' : 's', 'long' : 'subroutines', 'fold' : 0} - \ ] - let s:known_types.perl = type_perl - " PHP {{{3 - let type_php = {} - let type_php.ctagstype = 'php' - let type_php.kinds = [ - \ {'short' : 'i', 'long' : 'interfaces', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'd', 'long' : 'constant definitions', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}, - \ {'short' : 'j', 'long' : 'javascript functions', 'fold' : 0} - \ ] - let s:known_types.php = type_php - " Python {{{3 - let type_python = {} - let type_python.ctagstype = 'python' - let type_python.kinds = [ - \ {'short' : 'i', 'long' : 'imports', 'fold' : 1}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'members', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0} - \ ] - let type_python.sro = '.' - 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 - " REXX {{{3 - let type_rexx = {} - let type_rexx.ctagstype = 'rexx' - let type_rexx.kinds = [ - \ {'short' : 's', 'long' : 'subroutines', 'fold' : 0} - \ ] - let s:known_types.rexx = type_rexx - " Ruby {{{3 - let type_ruby = {} - let type_ruby.ctagstype = 'ruby' - let type_ruby.kinds = [ - \ {'short' : 'm', 'long' : 'modules', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'methods', 'fold' : 0}, - \ {'short' : 'F', 'long' : 'singleton methods', 'fold' : 0} - \ ] - let type_ruby.sro = '.' - let type_ruby.kind2scope = { - \ 'c' : 'class', - \ 'm' : 'class' - \ } - let type_ruby.scope2kind = { - \ 'class' : 'c' - \ } - let s:known_types.ruby = type_ruby - " Scheme {{{3 - let type_scheme = {} - let type_scheme.ctagstype = 'scheme' - let type_scheme.kinds = [ - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 's', 'long' : 'sets', 'fold' : 0} - \ ] - let s:known_types.scheme = type_scheme - " Shell script {{{3 - let type_sh = {} - let type_sh.ctagstype = 'sh' - let type_sh.kinds = [ - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} - \ ] - let s:known_types.sh = type_sh - let s:known_types.csh = type_sh - let s:known_types.zsh = type_sh - " SLang {{{3 - let type_slang = {} - let type_slang.ctagstype = 'slang' - let type_slang.kinds = [ - \ {'short' : 'n', 'long' : 'namespaces', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} - \ ] - let s:known_types.slang = type_slang - " SML {{{3 - let type_sml = {} - let type_sml.ctagstype = 'sml' - let type_sml.kinds = [ - \ {'short' : 'e', 'long' : 'exception declarations', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'function definitions', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'functor definitions', 'fold' : 0}, - \ {'short' : 's', 'long' : 'signature declarations', 'fold' : 0}, - \ {'short' : 'r', 'long' : 'structure declarations', 'fold' : 0}, - \ {'short' : 't', 'long' : 'type definitions', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'value bindings', 'fold' : 0} - \ ] - let s:known_types.sml = type_sml - " SQL {{{3 - " The SQL ctags parser seems to be buggy for me, so this just uses the - " normal kinds even though scopes should be available. Improvements - " welcome! - let type_sql = {} - let type_sql.ctagstype = 'sql' - let type_sql.kinds = [ - \ {'short' : 'P', 'long' : 'packages', 'fold' : 1}, - \ {'short' : 'c', 'long' : 'cursors', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'F', 'long' : 'record fields', 'fold' : 0}, - \ {'short' : 'L', 'long' : 'block label', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'procedures', 'fold' : 0}, - \ {'short' : 's', 'long' : 'subtypes', 'fold' : 0}, - \ {'short' : 't', 'long' : 'tables', 'fold' : 0}, - \ {'short' : 'T', 'long' : 'triggers', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}, - \ {'short' : 'i', 'long' : 'indexes', 'fold' : 0}, - \ {'short' : 'e', 'long' : 'events', 'fold' : 0}, - \ {'short' : 'U', 'long' : 'publications', 'fold' : 0}, - \ {'short' : 'R', 'long' : 'services', 'fold' : 0}, - \ {'short' : 'D', 'long' : 'domains', 'fold' : 0}, - \ {'short' : 'V', 'long' : 'views', 'fold' : 0}, - \ {'short' : 'n', 'long' : 'synonyms', 'fold' : 0}, - \ {'short' : 'x', 'long' : 'MobiLink Table Scripts', 'fold' : 0}, - \ {'short' : 'y', 'long' : 'MobiLink Conn Scripts', 'fold' : 0} - \ ] - let s:known_types.sql = type_sql - " Tcl {{{3 - let type_tcl = {} - let type_tcl.ctagstype = 'tcl' - let type_tcl.kinds = [ - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'methods', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'procedures', 'fold' : 0} - \ ] - let s:known_types.tcl = type_tcl - " LaTeX {{{3 - let type_tex = {} - let type_tex.ctagstype = 'tex' - let type_tex.kinds = [ - \ {'short' : 'p', 'long' : 'parts', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'chapters', 'fold' : 0}, - \ {'short' : 's', 'long' : 'sections', 'fold' : 0}, - \ {'short' : 'u', 'long' : 'subsections', 'fold' : 0}, - \ {'short' : 'b', 'long' : 'subsubsections', 'fold' : 0}, - \ {'short' : 'P', 'long' : 'paragraphs', 'fold' : 0}, - \ {'short' : 'G', 'long' : 'subparagraphs', 'fold' : 0} - \ ] - let s:known_types.tex = type_tex - " Vera {{{3 - " Why are variables 'virtual'? - let type_vera = {} - let type_vera.ctagstype = 'vera' - let type_vera.kinds = [ - \ {'short' : 'd', 'long' : 'macros', 'fold' : 1}, - \ {'short' : 'g', 'long' : 'enums', 'fold' : 0}, - \ {'short' : 'T', 'long' : 'typedefs', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'members', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 't', 'long' : 'tasks', 'fold' : 0}, - \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'programs', 'fold' : 0} - \ ] - let type_vera.sro = '.' " Nesting doesn't seem to be possible - let type_vera.kind2scope = { - \ 'g' : 'enum', - \ 'c' : 'class', - \ 'v' : 'virtual' - \ } - let type_vera.scope2kind = { - \ 'enum' : 'g', - \ 'class' : 'c', - \ 'virtual' : 'v' - \ } - let s:known_types.vera = type_vera - " Verilog {{{3 - let type_verilog = {} - let type_verilog.ctagstype = 'verilog' - let type_verilog.kinds = [ - \ {'short' : 'c', 'long' : 'constants', 'fold' : 0}, - \ {'short' : 'e', 'long' : 'events', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'modules', 'fold' : 0}, - \ {'short' : 'n', 'long' : 'net data types', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'ports', 'fold' : 0}, - \ {'short' : 'r', 'long' : 'register data types', 'fold' : 0}, - \ {'short' : 't', 'long' : 'tasks', 'fold' : 0} - \ ] - let s:known_types.verilog = type_verilog - " VHDL {{{3 - " The VHDL ctags parser unfortunately doesn't generate proper scopes - let type_vhdl = {} - let type_vhdl.ctagstype = 'vhdl' - let type_vhdl.kinds = [ - \ {'short' : 'P', 'long' : 'packages', 'fold' : 1}, - \ {'short' : 'c', 'long' : 'constants', 'fold' : 0}, - \ {'short' : 't', 'long' : 'types', 'fold' : 0}, - \ {'short' : 'T', 'long' : 'subtypes', 'fold' : 0}, - \ {'short' : 'r', 'long' : 'records', 'fold' : 0}, - \ {'short' : 'e', 'long' : 'entities', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'procedures', 'fold' : 0} - \ ] - let s:known_types.vhdl = type_vhdl - " Vim {{{3 - let type_vim = {} - let type_vim.ctagstype = 'vim' - let type_vim.kinds = [ - \ {'short' : 'v', 'long' : 'variables', 'fold' : 1}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}, - \ {'short' : 'a', 'long' : 'autocommand groups', 'fold' : 1}, - \ {'short' : 'c', 'long' : 'commands', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'maps', 'fold' : 1} - \ ] - let s:known_types.vim = type_vim - " YACC {{{3 - let type_yacc = {} - let type_yacc.ctagstype = 'yacc' - let type_yacc.kinds = [ - \ {'short' : 'l', 'long' : 'labels', 'fold' : 0} - \ ] - let s:known_types.yacc = type_yacc - " }}}3 - - let user_defs = s:GetUserTypeDefs() - for [key, value] in items(user_defs) - if !has_key(s:known_types, key) || - \ (has_key(value, 'replace') && value.replace) - let s:known_types[key] = value - else - call extend(s:known_types[key], value) - endif - endfor - - " 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.short] = i - let i += 1 - endfor - endfor - - let s:type_init_done = 1 -endfunction - -" s:GetUserTypeDefs() {{{2 -function! s:GetUserTypeDefs() - call s:LogDebugMessage('Initializing user types') - - redir => defs - silent execute 'let g:' - redir END - - let deflist = split(defs, '\n') - call map(deflist, 'substitute(v:val, ''^\S\+\zs.*'', "", "")') - call filter(deflist, 'v:val =~ "^tagbar_type_"') - - let defdict = {} - for defstr in deflist - let type = substitute(defstr, '^tagbar_type_', '', '') - execute 'let defdict["' . type . '"] = g:' . defstr - endfor - - " If the user only specified one of kind2scope and scope2kind use it to - " generate the other one - " Also, transform the 'kind' definitions into dictionary format - for def in values(defdict) - if has_key(def, 'kinds') - let kinds = def.kinds - let def.kinds = [] - for kind in kinds - let kindlist = split(kind, ':') - let kinddict = {'short' : kindlist[0], 'long' : kindlist[1]} - if len(kindlist) == 3 - let kinddict.fold = kindlist[2] - else - let kinddict.fold = 0 - endif - call add(def.kinds, kinddict) - endfor - endif - - if has_key(def, 'kind2scope') && !has_key(def, 'scope2kind') - let def.scope2kind = {} - for [key, value] in items(def.kind2scope) - let def.scope2kind[value] = key - endfor - elseif has_key(def, 'scope2kind') && !has_key(def, 'kind2scope') - let def.kind2scope = {} - for [key, value] in items(def.scope2kind) - let def.kind2scope[value] = key - endfor - endif - endfor - - return defdict -endfunction - -" s:RestoreSession() {{{2 -" Properly restore Tagbar after a session got loaded -function! s:RestoreSession() - call s:LogDebugMessage('Restoring session') - - let tagbarwinnr = bufwinnr('__Tagbar__') - if tagbarwinnr == -1 - " Tagbar wasn't open in the saved session, nothing to do - return - else - let in_tagbar = 1 - if winnr() != tagbarwinnr - execute tagbarwinnr . 'wincmd w' - let in_tagbar = 0 - endif - endif - - call s:Init() - - call s:InitWindow(g:tagbar_autoclose) - - " Leave the Tagbar window and come back so the update event gets triggered - wincmd p - execute tagbarwinnr . 'wincmd w' - - if !in_tagbar - wincmd p - endif -endfunction - -" s:MapKeys() {{{2 -function! s:MapKeys() - call s:LogDebugMessage('Mapping keys') - - nnoremap <script> <silent> <buffer> <2-LeftMouse> - \ :call <SID>JumpToTag(0)<CR> - nnoremap <script> <silent> <buffer> <LeftRelease> - \ <LeftRelease>:call <SID>CheckMouseClick()<CR> - - inoremap <script> <silent> <buffer> <2-LeftMouse> - \ <C-o>:call <SID>JumpToTag(0)<CR> - inoremap <script> <silent> <buffer> <LeftRelease> - \ <LeftRelease><C-o>:call <SID>CheckMouseClick()<CR> - - nnoremap <script> <silent> <buffer> <CR> :call <SID>JumpToTag(0)<CR> - nnoremap <script> <silent> <buffer> p :call <SID>JumpToTag(1)<CR> - nnoremap <script> <silent> <buffer> <Space> :call <SID>ShowPrototype()<CR> - - nnoremap <script> <silent> <buffer> + :call <SID>OpenFold()<CR> - nnoremap <script> <silent> <buffer> <kPlus> :call <SID>OpenFold()<CR> - nnoremap <script> <silent> <buffer> zo :call <SID>OpenFold()<CR> - nnoremap <script> <silent> <buffer> - :call <SID>CloseFold()<CR> - nnoremap <script> <silent> <buffer> <kMinus> :call <SID>CloseFold()<CR> - nnoremap <script> <silent> <buffer> zc :call <SID>CloseFold()<CR> - nnoremap <script> <silent> <buffer> o :call <SID>ToggleFold()<CR> - nnoremap <script> <silent> <buffer> za :call <SID>ToggleFold()<CR> - - nnoremap <script> <silent> <buffer> * :call <SID>SetFoldLevel(99)<CR> - nnoremap <script> <silent> <buffer> <kMultiply> - \ :call <SID>SetFoldLevel(99)<CR> - nnoremap <script> <silent> <buffer> zR :call <SID>SetFoldLevel(99)<CR> - nnoremap <script> <silent> <buffer> = :call <SID>SetFoldLevel(0)<CR> - nnoremap <script> <silent> <buffer> zM :call <SID>SetFoldLevel(0)<CR> - - nnoremap <script> <silent> <buffer> <C-N> - \ :call <SID>GotoNextToplevelTag(1)<CR> - nnoremap <script> <silent> <buffer> <C-P> - \ :call <SID>GotoNextToplevelTag(-1)<CR> - - nnoremap <script> <silent> <buffer> s :call <SID>ToggleSort()<CR> - nnoremap <script> <silent> <buffer> x :call <SID>ZoomWindow()<CR> - nnoremap <script> <silent> <buffer> q :call <SID>CloseWindow()<CR> - nnoremap <script> <silent> <buffer> <F1> :call <SID>ToggleHelp()<CR> -endfunction - -" s:CreateAutocommands() {{{2 -function! s:CreateAutocommands() - call s:LogDebugMessage('Creating autocommands') - - augroup TagbarAutoCmds - autocmd! - autocmd BufEnter __Tagbar__ nested call s:QuitIfOnlyWindow() - autocmd BufUnload __Tagbar__ call s:CleanUp() - autocmd CursorHold __Tagbar__ call s:ShowPrototype() - - autocmd BufWritePost * - \ if line('$') < g:tagbar_updateonsave_maxlines | - \ call s:AutoUpdate(fnamemodify(expand('<afile>'), ':p')) | - \ endif - autocmd BufEnter,CursorHold,FileType * call - \ s:AutoUpdate(fnamemodify(expand('<afile>'), ':p')) - autocmd BufDelete * call - \ s:CleanupFileinfo(fnamemodify(expand('<afile>'), ':p')) - augroup END - - let s:autocommands_done = 1 -endfunction - -" s:CheckForExCtags() {{{2 -" Test whether the ctags binary is actually Exuberant Ctags and not GNU ctags -" (or something else) -function! s:CheckForExCtags() - call s:LogDebugMessage('Checking for Exuberant Ctags') - - let ctags_cmd = s:EscapeCtagsCmd(g:tagbar_ctags_bin, '--version') - if ctags_cmd == '' - return - endif - - let ctags_output = s:ExecuteCtags(ctags_cmd) - - if v:shell_error || ctags_output !~# 'Exuberant Ctags' - echoerr 'Tagbar: Ctags doesn''t seem to be Exuberant Ctags!' - echomsg 'GNU ctags will NOT WORK.' - \ 'Please download Exuberant Ctags from ctags.sourceforge.net' - \ 'and install it in a directory in your $PATH' - \ 'or set g:tagbar_ctags_bin.' - echomsg 'Executed command: "' . ctags_cmd . '"' - if !empty(ctags_output) - echomsg 'Command output:' - for line in split(ctags_output, '\n') - echomsg line - endfor - endif - return 0 - elseif !s:CheckExCtagsVersion(ctags_output) - echoerr 'Tagbar: Exuberant Ctags is too old!' - echomsg 'You need at least version 5.5 for Tagbar to work.' - \ 'Please download a newer version from ctags.sourceforge.net.' - echomsg 'Executed command: "' . ctags_cmd . '"' - if !empty(ctags_output) - echomsg 'Command output:' - for line in split(ctags_output, '\n') - echomsg line - endfor - endif - return 0 - else - let s:checked_ctags = 1 - return 1 - endif -endfunction - -" s:CheckExCtagsVersion() {{{2 -function! s:CheckExCtagsVersion(output) - call s:LogDebugMessage('Checking Exuberant Ctags version') - - if a:output =~ 'Exuberant Ctags Development' - return 1 - endif - - let matchlist = matchlist(a:output, '\vExuberant Ctags (\d+)\.(\d+)') - let major = matchlist[1] - let minor = matchlist[2] - - return major >= 6 || (major == 5 && minor >= 5) -endfunction - -" s:CheckFTCtags() {{{2 -function! s:CheckFTCtags(bin, ftype) - if executable(a:bin) - return a:bin - endif - - if exists('g:tagbar_type_' . a:ftype) - execute 'let userdef = ' . 'g:tagbar_type_' . a:ftype - if has_key(userdef, 'ctagsbin') - return userdef.ctagsbin - else - return '' - endif - endif - - return '' -endfunction - -" Prototypes {{{1 -" Base tag {{{2 -let s:BaseTag = {} - -" s:BaseTag._init() {{{3 -function! s:BaseTag._init(name) dict - let self.name = a:name - let self.fields = {} - let self.fields.line = 0 - let self.path = '' - let self.fullpath = a:name - let self.depth = 0 - let self.parent = {} - let self.tline = -1 - let self.fileinfo = {} -endfunction - -" s:BaseTag.isNormalTag() {{{3 -function! s:BaseTag.isNormalTag() dict - return 0 -endfunction - -" s:BaseTag.isPseudoTag() {{{3 -function! s:BaseTag.isPseudoTag() dict - return 0 -endfunction - -" s:BaseTag.isKindheader() {{{3 -function! s:BaseTag.isKindheader() dict - return 0 -endfunction - -" s:BaseTag.getPrototype() {{{3 -function! s:BaseTag.getPrototype() dict - return '' -endfunction - -" s:BaseTag._getPrefix() {{{3 -function! s:BaseTag._getPrefix() dict - let fileinfo = self.fileinfo - - if has_key(self, 'children') && !empty(self.children) - if fileinfo.tagfolds[self.fields.kind][self.fullpath] - let prefix = s:icon_closed - else - let prefix = s:icon_open - endif - else - let prefix = ' ' - endif - if has_key(self.fields, 'access') - let prefix .= get(s:access_symbols, self.fields.access, ' ') - else - let prefix .= ' ' - endif - - return prefix -endfunction - -" s:BaseTag.initFoldState() {{{3 -function! s:BaseTag.initFoldState() dict - let fileinfo = self.fileinfo - - if s:known_files.has(fileinfo.fpath) && - \ has_key(fileinfo._tagfolds_old[self.fields.kind], self.fullpath) - " The file has been updated and the tag was there before, so copy its - " old fold state - let fileinfo.tagfolds[self.fields.kind][self.fullpath] = - \ fileinfo._tagfolds_old[self.fields.kind][self.fullpath] - elseif self.depth >= fileinfo.foldlevel - let fileinfo.tagfolds[self.fields.kind][self.fullpath] = 1 - else - let fileinfo.tagfolds[self.fields.kind][self.fullpath] = - \ fileinfo.kindfolds[self.fields.kind] - endif -endfunction - -" s:BaseTag.getClosedParentTline() {{{3 -function! s:BaseTag.getClosedParentTline() dict - let tagline = self.tline - let fileinfo = self.fileinfo - - let parent = self.parent - while !empty(parent) - if parent.isFolded() - let tagline = parent.tline - break - endif - let parent = parent.parent - endwhile - - return tagline -endfunction - -" s:BaseTag.isFoldable() {{{3 -function! s:BaseTag.isFoldable() dict - return has_key(self, 'children') && !empty(self.children) -endfunction - -" s:BaseTag.isFolded() {{{3 -function! s:BaseTag.isFolded() dict - return self.fileinfo.tagfolds[self.fields.kind][self.fullpath] -endfunction - -" s:BaseTag.openFold() {{{3 -function! s:BaseTag.openFold() dict - if self.isFoldable() - let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = 0 - endif -endfunction - -" s:BaseTag.closeFold() {{{3 -function! s:BaseTag.closeFold() dict - let newline = line('.') - - if !empty(self.parent) && self.parent.isKindheader() - " Tag is child of generic 'kind' - call self.parent.closeFold() - let newline = self.parent.tline - elseif self.isFoldable() && !self.isFolded() - " Tag is parent of a scope and is not folded - let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = 1 - let newline = self.tline - elseif !empty(self.parent) - " Tag is normal child, so close parent - let parent = self.parent - let self.fileinfo.tagfolds[parent.fields.kind][parent.fullpath] = 1 - let newline = parent.tline - endif - - return newline -endfunction - -" s:BaseTag.setFolded() {{{3 -function! s:BaseTag.setFolded(folded) dict - let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = a:folded -endfunction - -" s:BaseTag.openParents() {{{3 -function! s:BaseTag.openParents() dict - let parent = self.parent - - while !empty(parent) - call parent.openFold() - let parent = parent.parent - endwhile -endfunction - -" Normal tag {{{2 -let s:NormalTag = copy(s:BaseTag) - -" s:NormalTag.New() {{{3 -function! s:NormalTag.New(name) dict - let newobj = copy(self) - - call newobj._init(a:name) - - return newobj -endfunction - -" s:NormalTag.isNormalTag() {{{3 -function! s:NormalTag.isNormalTag() dict - return 1 -endfunction - -" s:NormalTag.str() {{{3 -function! s:NormalTag.str() dict - let fileinfo = self.fileinfo - let typeinfo = s:known_types[fileinfo.ftype] - - let suffix = get(self.fields, 'signature', '') - if has_key(self.fields, 'type') - let suffix .= ' : ' . self.fields.type - elseif has_key(typeinfo, 'kind2scope') && - \ has_key(typeinfo.kind2scope, self.fields.kind) - let suffix .= ' : ' . typeinfo.kind2scope[self.fields.kind] - endif - - return self._getPrefix() . self.name . suffix . "\n" -endfunction - -" s:NormalTag.getPrototype() {{{3 -function! s:NormalTag.getPrototype() dict - return self.prototype -endfunction - -" Pseudo tag {{{2 -let s:PseudoTag = copy(s:BaseTag) - -" s:PseudoTag.New() {{{3 -function! s:PseudoTag.New(name) dict - let newobj = copy(self) - - call newobj._init(a:name) - - return newobj -endfunction - -" s:PseudoTag.isPseudoTag() {{{3 -function! s:PseudoTag.isPseudoTag() dict - return 1 -endfunction - -" s:PseudoTag.str() {{{3 -function! s:PseudoTag.str() dict - let fileinfo = self.fileinfo - let typeinfo = s:known_types[fileinfo.ftype] - - let suffix = get(self.fields, 'signature', '') - if has_key(typeinfo.kind2scope, self.fields.kind) - let suffix .= ' : ' . typeinfo.kind2scope[self.fields.kind] - endif - - return self._getPrefix() . self.name . '*' . suffix -endfunction - -" Kind header {{{2 -let s:KindheaderTag = copy(s:BaseTag) - -" s:KindheaderTag.New() {{{3 -function! s:KindheaderTag.New(name) dict - let newobj = copy(self) - - call newobj._init(a:name) - - return newobj -endfunction - -" s:KindheaderTag.isKindheader() {{{3 -function! s:KindheaderTag.isKindheader() dict - return 1 -endfunction - -" s:KindheaderTag.getPrototype() {{{3 -function! s:KindheaderTag.getPrototype() dict - return self.name . ': ' . - \ self.numtags . ' ' . (self.numtags > 1 ? 'tags' : 'tag') -endfunction - -" s:KindheaderTag.isFoldable() {{{3 -function! s:KindheaderTag.isFoldable() dict - return 1 -endfunction - -" s:KindheaderTag.isFolded() {{{3 -function! s:KindheaderTag.isFolded() dict - return self.fileinfo.kindfolds[self.short] -endfunction - -" s:KindheaderTag.openFold() {{{3 -function! s:KindheaderTag.openFold() dict - let self.fileinfo.kindfolds[self.short] = 0 -endfunction - -" s:KindheaderTag.closeFold() {{{3 -function! s:KindheaderTag.closeFold() dict - let self.fileinfo.kindfolds[self.short] = 1 - return line('.') -endfunction - -" s:KindheaderTag.toggleFold() {{{3 -function! s:KindheaderTag.toggleFold() dict - let fileinfo = s:known_files.getCurrent() - - let fileinfo.kindfolds[self.short] = !fileinfo.kindfolds[self.short] -endfunction - -" File info {{{2 -let s:FileInfo = {} - -" s:FileInfo.New() {{{3 -function! s:FileInfo.New(fname, ftype) dict - let newobj = copy(self) - - " The complete file path - let newobj.fpath = a:fname - - " File modification time - let newobj.mtime = getftime(a:fname) - - " The vim file type - let newobj.ftype = a:ftype - - " List of the tags that are present in the file, sorted according to the - " value of 'g:tagbar_sort' - let newobj.tags = [] - - " Dictionary of the tags, indexed by line number in the file - let newobj.fline = {} - - " Dictionary of the tags, indexed by line number in the tagbar - let newobj.tline = {} - - " Dictionary of the folding state of 'kind's, indexed by short name - let newobj.kindfolds = {} - let typeinfo = s:known_types[a:ftype] - " copy the default fold state from the type info - for kind in typeinfo.kinds - let newobj.kindfolds[kind.short] = - \ g:tagbar_foldlevel == 0 ? 1 : kind.fold - endfor - - " Dictionary of dictionaries of the folding state of individual tags, - " indexed by kind and full path - let newobj.tagfolds = {} - for kind in typeinfo.kinds - let newobj.tagfolds[kind.short] = {} - endfor - - " The current foldlevel of the file - let newobj.foldlevel = g:tagbar_foldlevel - - return newobj -endfunction - -" s:FileInfo.reset() {{{3 -" Reset stuff that gets regenerated while processing a file and save the old -" tag folds -function! s:FileInfo.reset() dict - let self.mtime = getftime(self.fpath) - let self.tags = [] - let self.fline = {} - let self.tline = {} - - let self._tagfolds_old = self.tagfolds - let self.tagfolds = {} - - let typeinfo = s:known_types[self.ftype] - for kind in typeinfo.kinds - let self.tagfolds[kind.short] = {} - endfor -endfunction - -" s:FileInfo.clearOldFolds() {{{3 -function! s:FileInfo.clearOldFolds() dict - if exists('self._tagfolds_old') - unlet self._tagfolds_old - endif -endfunction - -" s:FileInfo.sortTags() {{{3 -function! s:FileInfo.sortTags() dict - if has_key(s:compare_typeinfo, 'sort') - if s:compare_typeinfo.sort - call s:SortTags(self.tags, 's:CompareByKind') - else - call s:SortTags(self.tags, 's:CompareByLine') - endif - elseif g:tagbar_sort - call s:SortTags(self.tags, 's:CompareByKind') - else - call s:SortTags(self.tags, 's:CompareByLine') - endif -endfunction - -" s:FileInfo.openKindFold() {{{3 -function! s:FileInfo.openKindFold(kind) dict - let self.kindfolds[a:kind.short] = 0 -endfunction - -" s:FileInfo.closeKindFold() {{{3 -function! s:FileInfo.closeKindFold(kind) dict - let self.kindfolds[a:kind.short] = 1 -endfunction - -" Known files {{{2 -let s:known_files = { - \ '_current' : {}, - \ '_files' : {} -\ } - -" s:known_files.getCurrent() {{{3 -function! s:known_files.getCurrent() dict - return self._current -endfunction - -" s:known_files.setCurrent() {{{3 -function! s:known_files.setCurrent(fileinfo) dict - let self._current = a:fileinfo -endfunction - -" s:known_files.get() {{{3 -function! s:known_files.get(fname) dict - return get(self._files, a:fname, {}) -endfunction - -" s:known_files.put() {{{3 -" Optional second argument is the filename -function! s:known_files.put(fileinfo, ...) dict - if a:0 == 1 - let self._files[a:1] = a:fileinfo - else - let fname = a:fileinfo.fpath - let self._files[fname] = a:fileinfo - endif -endfunction - -" s:known_files.has() {{{3 -function! s:known_files.has(fname) dict - return has_key(self._files, a:fname) -endfunction - -" s:known_files.rm() {{{3 -function! s:known_files.rm(fname) dict - if s:known_files.has(a:fname) - call remove(self._files, a:fname) - endif -endfunction - -" Window management {{{1 -" s:ToggleWindow() {{{2 -function! s:ToggleWindow() - let tagbarwinnr = bufwinnr("__Tagbar__") - if tagbarwinnr != -1 - call s:CloseWindow() - return - endif - - call s:OpenWindow('') -endfunction - -" s:OpenWindow() {{{2 -function! s:OpenWindow(flags) - let autofocus = a:flags =~# 'f' - let jump = a:flags =~# 'j' - let autoclose = a:flags =~# 'c' - - " If the tagbar window is already open check jump flag - " Also set the autoclose flag if requested - let tagbarwinnr = bufwinnr('__Tagbar__') - if tagbarwinnr != -1 - if winnr() != tagbarwinnr && jump - execute tagbarwinnr . 'wincmd w' - if autoclose - let w:autoclose = autoclose - endif - endif - return - endif - - call s:Init() - - " Expand the Vim window to accomodate for the Tagbar window if requested - if g:tagbar_expand && !s:window_expanded && has('gui_running') - let &columns += g:tagbar_width + 1 - let s:window_expanded = 1 - endif - - let eventignore_save = &eventignore - set eventignore=all - - let openpos = g:tagbar_left ? 'topleft vertical ' : 'botright vertical ' - exe 'silent keepalt ' . openpos . g:tagbar_width . 'split ' . '__Tagbar__' - - let &eventignore = eventignore_save - - call s:InitWindow(autoclose) - - wincmd p - - " Jump back to the tagbar window if autoclose or autofocus is set. Can't - " just stay in it since it wouldn't trigger the update event - if g:tagbar_autoclose || autofocus || g:tagbar_autofocus - let tagbarwinnr = bufwinnr('__Tagbar__') - execute tagbarwinnr . 'wincmd w' - endif -endfunction - -" s:InitWindow() {{{2 -function! s:InitWindow(autoclose) - 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 - setlocal textwidth=0 - setlocal nocursorline - setlocal nocursorcolumn - - if exists('+relativenumber') - setlocal norelativenumber - endif - - setlocal nofoldenable - setlocal foldcolumn=0 - " Reset fold settings in case a plugin set them globally to something - " expensive. Apparently 'foldexpr' gets executed even if 'foldenable' is - " off, and then for every appended line (like with :put). - setlocal foldmethod& - setlocal foldexpr& - - " Earlier versions have a bug in local, evaluated statuslines - if v:version > 701 || (v:version == 701 && has('patch097')) - setlocal statusline=%!TagbarGenerateStatusline() - else - setlocal statusline=Tagbar - endif - - " 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 - - let w:autoclose = a:autoclose - - if has('balloon_eval') - setlocal balloonexpr=TagbarBalloonExpr() - set ballooneval - endif - - let cpoptions_save = &cpoptions - set cpoptions&vim - - if !hasmapto('JumpToTag', 'n') - call s:MapKeys() - endif - - if !s:autocommands_done - call s:CreateAutocommands() - endif - - let &cpoptions = cpoptions_save -endfunction - -" s:CloseWindow() {{{2 -function! s:CloseWindow() - let tagbarwinnr = bufwinnr('__Tagbar__') - if tagbarwinnr == -1 - return - endif - - let tagbarbufnr = winbufnr(tagbarwinnr) - - if winnr() == tagbarwinnr - if winbufnr(2) != -1 - " Other windows are open, only close the tagbar one - close - wincmd p - endif - else - " Go to the tagbar window, close it and then come back to the - " original window - let curbufnr = bufnr('%') - execute tagbarwinnr . 'wincmd w' - close - " Need to jump back to the original window only if we are not - " already in that window - let winnum = bufwinnr(curbufnr) - if winnr() != winnum - exe winnum . 'wincmd w' - endif - endif - - " If the Vim window has been expanded, and Tagbar is not open in any other - " tabpages, shrink the window again - if s:window_expanded - let tablist = [] - for i in range(tabpagenr('$')) - call extend(tablist, tabpagebuflist(i + 1)) - endfor - - if index(tablist, tagbarbufnr) == -1 - let &columns -= g:tagbar_width + 1 - let s:window_expanded = 0 - endif - endif -endfunction - -" s:ZoomWindow() {{{2 -function! s:ZoomWindow() - if s:is_maximized - execute 'vert resize ' . g:tagbar_width - let s:is_maximized = 0 - else - vert resize - let s:is_maximized = 1 - endif -endfunction - -" Tag processing {{{1 -" s:ProcessFile() {{{2 -" Execute ctags and put the information into a 'FileInfo' object -function! s:ProcessFile(fname, ftype) - call s:LogDebugMessage('ProcessFile called on ' . a:fname) - - if !s:IsValidFile(a:fname, a:ftype) - call s:LogDebugMessage('Not a valid file, returning') - return - endif - - let ctags_output = s:ExecuteCtagsOnFile(a:fname, a:ftype) - - if ctags_output == -1 - call s:LogDebugMessage('Ctags error when processing file') - " put an empty entry into known_files so the error message is only - " shown once - call s:known_files.put({}, a:fname) - return - elseif ctags_output == '' - call s:LogDebugMessage('Ctags output empty') - return - endif - - " If the file has only been updated preserve the fold states, otherwise - " create a new entry - if s:known_files.has(a:fname) - let fileinfo = s:known_files.get(a:fname) - call fileinfo.reset() - else - let fileinfo = s:FileInfo.New(a:fname, a:ftype) - endif - - let typeinfo = s:known_types[a:ftype] - - " Parse the ctags output lines - call s:LogDebugMessage('Parsing ctags output') - let rawtaglist = split(ctags_output, '\n\+') - for line in rawtaglist - " skip comments - if line =~# '^!_TAG_' - continue - endif - - let parts = split(line, ';"') - if len(parts) == 2 " Is a valid tag line - let taginfo = s:ParseTagline(parts[0], parts[1], typeinfo, fileinfo) - let fileinfo.fline[taginfo.fields.line] = taginfo - call add(fileinfo.tags, taginfo) - endif - endfor - - " Process scoped tags - let processedtags = [] - if has_key(typeinfo, 'kind2scope') - call s:LogDebugMessage('Processing scoped tags') - - let scopedtags = [] - let is_scoped = 'has_key(typeinfo.kind2scope, v:val.fields.kind) || - \ has_key(v:val, "scope")' - let scopedtags += filter(copy(fileinfo.tags), is_scoped) - call filter(fileinfo.tags, '!(' . is_scoped . ')') - - call s:AddScopedTags(scopedtags, processedtags, {}, 0, - \ typeinfo, fileinfo) - - if !empty(scopedtags) - echoerr 'Tagbar: ''scopedtags'' not empty after processing,' - \ 'this should never happen!' - \ 'Please contact the script maintainer with an example.' - endif - endif - call s:LogDebugMessage('Number of top-level tags: ' . len(processedtags)) - - " Create a placeholder tag for the 'kind' header for folding purposes - for kind in typeinfo.kinds - - let curtags = filter(copy(fileinfo.tags), - \ 'v:val.fields.kind ==# kind.short') - call s:LogDebugMessage('Processing kind: ' . kind.short . - \ ', number of tags: ' . len(curtags)) - - if empty(curtags) - continue - endif - - let kindtag = s:KindheaderTag.New(kind.long) - let kindtag.short = kind.short - let kindtag.numtags = len(curtags) - let kindtag.fileinfo = fileinfo - - for tag in curtags - let tag.parent = kindtag - endfor - endfor - - if !empty(processedtags) - call extend(fileinfo.tags, processedtags) - endif - - " Clear old folding information from previous file version to prevent leaks - call fileinfo.clearOldFolds() - - " Sort the tags - let s:compare_typeinfo = typeinfo - call fileinfo.sortTags() - - call s:known_files.put(fileinfo) -endfunction - -" s:ExecuteCtagsOnFile() {{{2 -function! s:ExecuteCtagsOnFile(fname, ftype) - call s:LogDebugMessage('ExecuteCtagsOnFile called on ' . a:fname) - - let typeinfo = s:known_types[a:ftype] - - if has_key(typeinfo, 'ctagsargs') - let ctags_args = ' ' . typeinfo.ctagsargs . ' ' - else - let ctags_args = ' -f - ' - let ctags_args .= ' --format=2 ' - let ctags_args .= ' --excmd=pattern ' - let ctags_args .= ' --fields=nksSa ' - let ctags_args .= ' --extra= ' - let ctags_args .= ' --sort=yes ' - - " Include extra type definitions - if has_key(typeinfo, 'deffile') - let ctags_args .= ' --options=' . typeinfo.deffile . ' ' - endif - - let ctags_type = typeinfo.ctagstype - - let ctags_kinds = '' - for kind in typeinfo.kinds - let ctags_kinds .= kind.short - endfor - - let ctags_args .= ' --language-force=' . ctags_type . - \ ' --' . ctags_type . '-kinds=' . ctags_kinds . ' ' - endif - - if has_key(typeinfo, 'ctagsbin') - " reset 'wildignore' temporarily in case *.exe is included in it - let wildignore_save = &wildignore - set wildignore& - let ctags_bin = expand(typeinfo.ctagsbin) - let &wildignore = wildignore_save - else - let ctags_bin = g:tagbar_ctags_bin - endif - - let ctags_cmd = s:EscapeCtagsCmd(ctags_bin, ctags_args, a:fname) - if ctags_cmd == '' - return '' - endif - - let ctags_output = s:ExecuteCtags(ctags_cmd) - - if v:shell_error || ctags_output =~ 'Warning: cannot open source file' - echoerr 'Tagbar: Could not execute ctags for ' . a:fname . '!' - echomsg 'Executed command: "' . ctags_cmd . '"' - if !empty(ctags_output) - call s:LogDebugMessage('Command output:') - call s:LogDebugMessage(ctags_output) - echomsg 'Command output:' - for line in split(ctags_output, '\n') - echomsg line - endfor - endif - return -1 - endif - - call s:LogDebugMessage('Ctags executed successfully') - return ctags_output -endfunction - -" s:ParseTagline() {{{2 -" Structure of a tag line: -" tagname<TAB>filename<TAB>expattern;"fields -" fields: <TAB>name:value -" fields that are always present: kind, line -function! s:ParseTagline(part1, part2, typeinfo, fileinfo) - let basic_info = split(a:part1, '\t') - - let taginfo = s:NormalTag.New(basic_info[0]) - let taginfo.file = basic_info[1] - - " the pattern can contain tabs and thus may have been split up, so join - " the rest of the items together again - let pattern = join(basic_info[2:], "\t") - let start = 2 " skip the slash and the ^ - let end = strlen(pattern) - 1 - if pattern[end - 1] ==# '$' - let end -= 1 - let dollar = '\$' - else - let dollar = '' - endif - let pattern = strpart(pattern, start, end - start) - let taginfo.pattern = '\V\^\C' . pattern . dollar - let prototype = substitute(pattern, '^[[:space:]]\+', '', '') - let prototype = substitute(prototype, '[[:space:]]\+$', '', '') - let taginfo.prototype = prototype - - let fields = split(a:part2, '\t') - let taginfo.fields.kind = remove(fields, 0) - for field in fields - " can't use split() since the value can contain ':' - let delimit = stridx(field, ':') - let key = strpart(field, 0, delimit) - let val = strpart(field, delimit + 1) - if len(val) > 0 - let taginfo.fields[key] = val - endif - endfor - " Needed for jsctags - if has_key(taginfo.fields, 'lineno') - let taginfo.fields.line = taginfo.fields.lineno - endif - - " Make some information easier accessible - if has_key(a:typeinfo, 'scope2kind') - for scope in keys(a:typeinfo.scope2kind) - if has_key(taginfo.fields, scope) - let taginfo.scope = scope - let taginfo.path = taginfo.fields[scope] - - let taginfo.fullpath = taginfo.path . a:typeinfo.sro . - \ taginfo.name - break - endif - endfor - let taginfo.depth = len(split(taginfo.path, '\V' . a:typeinfo.sro)) - endif - - let taginfo.fileinfo = a:fileinfo - - " Needed for folding - try - call taginfo.initFoldState() - catch /^Vim(\a\+):E716:/ " 'Key not present in Dictionary' - " The tag has a 'kind' that doesn't exist in the type definition - echoerr 'Your ctags and Tagbar configurations are out of sync!' - \ 'Please read '':help tagbar-extend''.' - endtry - - return taginfo -endfunction - -" s:AddScopedTags() {{{2 -" Recursively process tags. Unfortunately there is a problem: not all tags in -" a hierarchy are actually there. For example, in C++ a class can be defined -" in a header file and implemented in a .cpp file (so the class itself doesn't -" appear in the .cpp file and thus doesn't generate a tag). Another example -" are anonymous structures like namespaces, structs, enums, and unions, that -" also don't get a tag themselves. These tags are thus called 'pseudo-tags' in -" Tagbar. Properly parsing them is quite tricky, so try not to think about it -" too much. -function! s:AddScopedTags(tags, processedtags, parent, depth, - \ typeinfo, fileinfo) - if !empty(a:parent) - let curpath = a:parent.fullpath - let pscope = a:typeinfo.kind2scope[a:parent.fields.kind] - else - let curpath = '' - let pscope = '' - endif - - let is_cur_tag = 'v:val.depth == a:depth' - - if !empty(curpath) - " Check whether the tag is either a direct child at the current depth - " or at least a proper grandchild with pseudo-tags in between. If it - " is a direct child also check for matching scope. - let is_cur_tag .= ' && - \ (v:val.path ==# curpath || - \ match(v:val.path, ''\V\^\C'' . curpath . a:typeinfo.sro) == 0) && - \ (v:val.path ==# curpath ? (v:val.scope ==# pscope) : 1)' - endif - - let curtags = filter(copy(a:tags), is_cur_tag) - - if !empty(curtags) - call filter(a:tags, '!(' . is_cur_tag . ')') - - let realtags = [] - let pseudotags = [] - - while !empty(curtags) - let tag = remove(curtags, 0) - - if tag.path != curpath - " tag is child of a pseudo-tag, so create a new pseudo-tag and - " add all its children to it - let pseudotag = s:ProcessPseudoTag(curtags, tag, a:parent, - \ a:typeinfo, a:fileinfo) - - call add(pseudotags, pseudotag) - else - call add(realtags, tag) - endif - endwhile - - " Recursively add the children of the tags on the current level - for tag in realtags - let tag.parent = a:parent - - if !has_key(a:typeinfo.kind2scope, tag.fields.kind) - continue - endif - - if !has_key(tag, 'children') - let tag.children = [] - endif - - call s:AddScopedTags(a:tags, tag.children, tag, a:depth + 1, - \ a:typeinfo, a:fileinfo) - endfor - call extend(a:processedtags, realtags) - - " Recursively add the children of the tags that are children of the - " pseudo-tags on the current level - for tag in pseudotags - call s:ProcessPseudoChildren(a:tags, tag, a:depth, a:typeinfo, - \ a:fileinfo) - endfor - call extend(a:processedtags, pseudotags) - endif - - " Now we have to check if there are any pseudo-tags at the current level - " so we have to check for real tags at a lower level, i.e. grandchildren - let is_grandchild = 'v:val.depth > a:depth' - - if !empty(curpath) - let is_grandchild .= - \ ' && match(v:val.path, ''\V\^\C'' . curpath . a:typeinfo.sro) == 0' - endif - - let grandchildren = filter(copy(a:tags), is_grandchild) - - if !empty(grandchildren) - call s:AddScopedTags(a:tags, a:processedtags, a:parent, a:depth + 1, - \ a:typeinfo, a:fileinfo) - endif -endfunction - -" s:ProcessPseudoTag() {{{2 -function! s:ProcessPseudoTag(curtags, tag, parent, typeinfo, fileinfo) - let curpath = !empty(a:parent) ? a:parent.fullpath : '' - - let pseudoname = substitute(a:tag.path, curpath, '', '') - let pseudoname = substitute(pseudoname, '\V\^' . a:typeinfo.sro, '', '') - let pseudotag = s:CreatePseudoTag(pseudoname, a:parent, a:tag.scope, - \ a:typeinfo, a:fileinfo) - let pseudotag.children = [a:tag] - - " get all the other (direct) children of the current pseudo-tag - let ispseudochild = 'v:val.path ==# a:tag.path && v:val.scope ==# a:tag.scope' - let pseudochildren = filter(copy(a:curtags), ispseudochild) - if !empty(pseudochildren) - call filter(a:curtags, '!(' . ispseudochild . ')') - call extend(pseudotag.children, pseudochildren) - endif - - return pseudotag -endfunction - -" s:ProcessPseudoChildren() {{{2 -function! s:ProcessPseudoChildren(tags, tag, depth, typeinfo, fileinfo) - for childtag in a:tag.children - let childtag.parent = a:tag - - if !has_key(a:typeinfo.kind2scope, childtag.fields.kind) - continue - endif - - if !has_key(childtag, 'children') - let childtag.children = [] - endif - - call s:AddScopedTags(a:tags, childtag.children, childtag, a:depth + 1, - \ a:typeinfo, a:fileinfo) - endfor - - let is_grandchild = 'v:val.depth > a:depth && - \ match(v:val.path, ''^\C'' . a:tag.fullpath) == 0' - let grandchildren = filter(copy(a:tags), is_grandchild) - if !empty(grandchildren) - call s:AddScopedTags(a:tags, a:tag.children, a:tag, a:depth + 1, - \ a:typeinfo, a:fileinfo) - endif -endfunction - -" s:CreatePseudoTag() {{{2 -function! s:CreatePseudoTag(name, parent, scope, typeinfo, fileinfo) - if !empty(a:parent) - let curpath = a:parent.fullpath - let pscope = a:typeinfo.kind2scope[a:parent.fields.kind] - else - let curpath = '' - let pscope = '' - endif - - let pseudotag = s:PseudoTag.New(a:name) - let pseudotag.fields.kind = a:typeinfo.scope2kind[a:scope] - - let parentscope = substitute(curpath, a:name . '$', '', '') - let parentscope = substitute(parentscope, - \ '\V\^' . a:typeinfo.sro . '\$', '', '') - - if pscope != '' - let pseudotag.fields[pscope] = parentscope - let pseudotag.scope = pscope - let pseudotag.path = parentscope - let pseudotag.fullpath = - \ pseudotag.path . a:typeinfo.sro . pseudotag.name - endif - let pseudotag.depth = len(split(pseudotag.path, '\V' . a:typeinfo.sro)) - - let pseudotag.parent = a:parent - - let pseudotag.fileinfo = a:fileinfo - - call pseudotag.initFoldState() - - return pseudotag -endfunction - -" Sorting {{{1 -" s:SortTags() {{{2 -function! s:SortTags(tags, comparemethod) - call sort(a:tags, a:comparemethod) - - for tag in a:tags - if has_key(tag, 'children') - call s:SortTags(tag.children, a:comparemethod) - endif - endfor -endfunction - -" s:CompareByKind() {{{2 -function! s:CompareByKind(tag1, tag2) - let typeinfo = s:compare_typeinfo - - if typeinfo.kinddict[a:tag1.fields.kind] <# - \ typeinfo.kinddict[a:tag2.fields.kind] - return -1 - elseif typeinfo.kinddict[a:tag1.fields.kind] ># - \ typeinfo.kinddict[a:tag2.fields.kind] - return 1 - else - " Ignore '~' prefix for C++ destructors to sort them directly under - " the constructors - if a:tag1.name[0] ==# '~' - let name1 = a:tag1.name[1:] - else - let name1 = a:tag1.name - endif - if a:tag2.name[0] ==# '~' - let name2 = a:tag2.name[1:] - else - let name2 = a:tag2.name - endif - - if name1 <=# name2 - return -1 - else - return 1 - endif - endif -endfunction - -" s:CompareByLine() {{{2 -function! s:CompareByLine(tag1, tag2) - return a:tag1.fields.line - a:tag2.fields.line -endfunction - -" s:ToggleSort() {{{2 -function! s:ToggleSort() - let fileinfo = s:known_files.getCurrent() - if empty(fileinfo) - return - endif - - let curline = line('.') - - match none - - let s:compare_typeinfo = s:known_types[fileinfo.ftype] - - if has_key(s:compare_typeinfo, 'sort') - let s:compare_typeinfo.sort = !s:compare_typeinfo.sort - else - let g:tagbar_sort = !g:tagbar_sort - endif - - call fileinfo.sortTags() - - call s:RenderContent() - - execute curline -endfunction - -" Display {{{1 -" s:RenderContent() {{{2 -function! s:RenderContent(...) - call s:LogDebugMessage('RenderContent called') - - if a:0 == 1 - let fileinfo = a:1 - else - let fileinfo = s:known_files.getCurrent() - endif - - if empty(fileinfo) - call s:LogDebugMessage('Empty fileinfo, returning') - return - endif - - let tagbarwinnr = bufwinnr('__Tagbar__') - - if &filetype == 'tagbar' - let in_tagbar = 1 - else - let in_tagbar = 0 - let prevwinnr = winnr() - execute tagbarwinnr . 'wincmd w' - endif - - if !empty(s:known_files.getCurrent()) && - \ fileinfo.fpath ==# s:known_files.getCurrent().fpath - " We're redisplaying the same file, so save the view - call s:LogDebugMessage('Redisplaying file' . fileinfo.fpath) - let saveline = line('.') - let savecol = col('.') - let topline = line('w0') - endif - - let lazyredraw_save = &lazyredraw - set lazyredraw - let eventignore_save = &eventignore - set eventignore=all - - setlocal modifiable - - silent %delete _ - - call s:PrintHelp() - - let typeinfo = s:known_types[fileinfo.ftype] - - " Print tags - call s:PrintKinds(typeinfo, fileinfo) - - " Delete empty lines at the end of the buffer - for linenr in range(line('$'), 1, -1) - if getline(linenr) =~ '^$' - execute 'silent ' . linenr . 'delete _' - else - break - endif - endfor - - setlocal nomodifiable - - if !empty(s:known_files.getCurrent()) && - \ fileinfo.fpath ==# s:known_files.getCurrent().fpath - let scrolloff_save = &scrolloff - set scrolloff=0 - - call cursor(topline, 1) - normal! zt - call cursor(saveline, savecol) - - let &scrolloff = scrolloff_save - else - " Make sure as much of the Tagbar content as possible is shown in the - " window by jumping to the top after drawing - execute 1 - call winline() - - " Invalidate highlight cache from old file - let s:last_highlight_tline = 0 - endif - - let &lazyredraw = lazyredraw_save - let &eventignore = eventignore_save - - if !in_tagbar - execute prevwinnr . 'wincmd w' - endif -endfunction - -" s:PrintKinds() {{{2 -function! s:PrintKinds(typeinfo, fileinfo) - call s:LogDebugMessage('PrintKinds called') - - let first_tag = 1 - - for kind in a:typeinfo.kinds - let curtags = filter(copy(a:fileinfo.tags), - \ 'v:val.fields.kind ==# kind.short') - call s:LogDebugMessage('Printing kind: ' . kind.short . - \ ', number of (top-level) tags: ' . len(curtags)) - - if empty(curtags) - continue - endif - - if has_key(a:typeinfo, 'kind2scope') && - \ has_key(a:typeinfo.kind2scope, kind.short) - " Scoped tags - for tag in curtags - if g:tagbar_compact && first_tag && s:short_help - silent 0put =tag.str() - else - silent put =tag.str() - endif - - " Save the current tagbar line in the tag for easy - " highlighting access - let curline = line('.') - let tag.tline = curline - let a:fileinfo.tline[curline] = tag - - " Print children - if tag.isFoldable() && !tag.isFolded() - for ckind in a:typeinfo.kinds - let childtags = filter(copy(tag.children), - \ 'v:val.fields.kind ==# ckind.short') - if len(childtags) > 0 - " Print 'kind' header of following children - if !has_key(a:typeinfo.kind2scope, ckind.short) - silent put =' [' . ckind.long . ']' - let a:fileinfo.tline[line('.')] = tag - endif - for childtag in childtags - call s:PrintTag(childtag, 1, - \ a:fileinfo, a:typeinfo) - endfor - endif - endfor - endif - - if !g:tagbar_compact - silent put _ - endif - - let first_tag = 0 - endfor - else - " Non-scoped tags - let kindtag = curtags[0].parent - - if kindtag.isFolded() - let foldmarker = s:icon_closed - else - let foldmarker = s:icon_open - endif - - if g:tagbar_compact && first_tag && s:short_help - silent 0put =foldmarker . ' ' . kind.long - else - silent put =foldmarker . ' ' . kind.long - endif - - let curline = line('.') - let kindtag.tline = curline - let a:fileinfo.tline[curline] = kindtag - - if !kindtag.isFolded() - for tag in curtags - let str = tag.str() - silent put =' ' . str - - " Save the current tagbar line in the tag for easy - " highlighting access - let curline = line('.') - let tag.tline = curline - let a:fileinfo.tline[curline] = tag - let tag.depth = 1 - endfor - endif - - if !g:tagbar_compact - silent put _ - endif - - let first_tag = 0 - endif - endfor -endfunction - -" s:PrintTag() {{{2 -function! s:PrintTag(tag, depth, fileinfo, typeinfo) - " Print tag indented according to depth - silent put =repeat(' ', a:depth * 2) . a:tag.str() - - " Save the current tagbar line in the tag for easy - " highlighting access - let curline = line('.') - let a:tag.tline = curline - let a:fileinfo.tline[curline] = a:tag - - " Recursively print children - if a:tag.isFoldable() && !a:tag.isFolded() - for ckind in a:typeinfo.kinds - let childtags = filter(copy(a:tag.children), - \ 'v:val.fields.kind ==# ckind.short') - if len(childtags) > 0 - " Print 'kind' header of following children - if !has_key(a:typeinfo.kind2scope, ckind.short) - silent put =' ' . repeat(' ', a:depth * 2) . - \ '[' . ckind.long . ']' - let a:fileinfo.tline[line('.')] = a:tag - endif - for childtag in childtags - call s:PrintTag(childtag, a:depth + 1, - \ a:fileinfo, a:typeinfo) - endfor - endif - endfor - endif -endfunction - -" s:PrintHelp() {{{2 -function! s:PrintHelp() - if !g:tagbar_compact && s:short_help - silent 0put ='\" Press <F1> for help' - silent put _ - elseif !s:short_help - silent 0put ='\" Tagbar keybindings' - silent put ='\"' - silent put ='\" --------- General ---------' - silent put ='\" <Enter> : Jump to tag definition' - silent put ='\" <Space> : Display tag prototype' - silent put ='\"' - silent put ='\" ---------- Folds ----------' - silent put ='\" +, zo : Open fold' - silent put ='\" -, zc : Close fold' - silent put ='\" o, za : Toggle fold' - silent put ='\" *, zR : Open all folds' - silent put ='\" =, zM : Close all folds' - silent put ='\"' - silent put ='\" ---------- Misc -----------' - silent put ='\" s : Toggle sort' - silent put ='\" x : Zoom window in/out' - silent put ='\" q : Close window' - silent put ='\" <F1> : Remove help' - silent put _ - endif -endfunction - -" s:RenderKeepView() {{{2 -" The gist of this function was taken from NERDTree by Martin Grenfell. -function! s:RenderKeepView(...) - if a:0 == 1 - let line = a:1 - else - let line = line('.') - endif - - let curcol = col('.') - let topline = line('w0') - - call s:RenderContent() - - let scrolloff_save = &scrolloff - set scrolloff=0 - - call cursor(topline, 1) - normal! zt - call cursor(line, curcol) - - let &scrolloff = scrolloff_save - - redraw -endfunction - -" User actions {{{1 -" s:HighlightTag() {{{2 -function! s:HighlightTag() - let tagline = 0 - - let tag = s:GetNearbyTag() - if !empty(tag) - let tagline = tag.tline - endif - - " Don't highlight the tag again if it's the same one as last time. - " This prevents the Tagbar window from jumping back after scrolling with - " the mouse. - if tagline == s:last_highlight_tline - return - else - let s:last_highlight_tline = tagline - endif - - let eventignore_save = &eventignore - set eventignore=all - - let tagbarwinnr = bufwinnr('__Tagbar__') - let prevwinnr = winnr() - execute tagbarwinnr . 'wincmd w' - - match none - - " No tag above cursor position so don't do anything - if tagline == 0 - execute prevwinnr . 'wincmd w' - let &eventignore = eventignore_save - redraw - return - endif - - if g:tagbar_autoshowtag - call s:OpenParents(tag) - endif - - " Check whether the tag is inside a closed fold and highlight the parent - " instead in that case - let tagline = tag.getClosedParentTline() - - " Go to the line containing the tag - execute tagline - - " Make sure the tag is visible in the window - call winline() - - let foldpat = '[' . s:icon_open . s:icon_closed . ' ]' - let pattern = '/^\%' . tagline . 'l\s*' . foldpat . '[-+# ]\zs[^( ]\+\ze/' - execute 'match TagbarHighlight ' . pattern - - execute prevwinnr . 'wincmd w' - - let &eventignore = eventignore_save - - redraw -endfunction - -" s:JumpToTag() {{{2 -function! s:JumpToTag(stay_in_tagbar) - let taginfo = s:GetTagInfo(line('.'), 1) - - let autoclose = w:autoclose - - if empty(taginfo) || has_key(taginfo, 'numtags') - return - endif - - let tagbarwinnr = winnr() - - let eventignore_save = &eventignore - set eventignore=all - - " This elaborate construct will try to switch to the correct - " buffer/window; if the buffer isn't currently shown in a window it will - " open it in the first window with a non-special buffer in it - wincmd p - let filebufnr = bufnr(taginfo.fileinfo.fpath) - if bufnr('%') != filebufnr - let filewinnr = bufwinnr(filebufnr) - if filewinnr != -1 - execute filewinnr . 'wincmd w' - else - for i in range(1, winnr('$')) - execute i . 'wincmd w' - if &buftype == '' - execute 'buffer ' . filebufnr - break - endif - endfor - endif - " To make ctrl-w_p work we switch between the Tagbar window and the - " correct window once - execute tagbarwinnr . 'wincmd w' - wincmd p - endif - - " Mark current position so it can be jumped back to - mark ' - - " Jump to the line where the tag is defined. Don't use the search pattern - " since it doesn't take the scope into account and thus can fail if tags - " with the same name are defined in different scopes (e.g. classes) - execute taginfo.fields.line - - " If the file has been changed but not saved, the tag may not be on the - " saved line anymore, so search for it in the vicinity of the saved line - if match(getline('.'), taginfo.pattern) == -1 - let interval = 1 - let forward = 1 - while search(taginfo.pattern, 'W' . forward ? '' : 'b') == 0 - if !forward - if interval > line('$') - break - else - let interval = interval * 2 - endif - endif - let forward = !forward - endwhile - endif - - " If the tag is on a different line after unsaved changes update the tag - " and file infos/objects - let curline = line('.') - if taginfo.fields.line != curline - let taginfo.fields.line = curline - let taginfo.fileinfo.fline[curline] = taginfo - endif - - " Center the tag in the window - normal! z. - - if foldclosed('.') != -1 - .foldopen! - endif - - redraw - - let &eventignore = eventignore_save - - if a:stay_in_tagbar - call s:HighlightTag() - execute tagbarwinnr . 'wincmd w' - elseif g:tagbar_autoclose || autoclose - call s:CloseWindow() - else - call s:HighlightTag() - endif -endfunction - -" s:ShowPrototype() {{{2 -function! s:ShowPrototype() - let taginfo = s:GetTagInfo(line('.'), 1) - - if empty(taginfo) - return - endif - - echo taginfo.getPrototype() -endfunction - -" s:ToggleHelp() {{{2 -function! s:ToggleHelp() - let s:short_help = !s:short_help - - " Prevent highlighting from being off after adding/removing the help text - match none - - call s:RenderContent() - - execute 1 - redraw -endfunction - -" s:GotoNextToplevelTag() {{{2 -function! s:GotoNextToplevelTag(direction) - let curlinenr = line('.') - let newlinenr = line('.') - - if a:direction == 1 - let range = range(line('.') + 1, line('$')) - else - let range = range(line('.') - 1, 1, -1) - endif - - for tmplinenr in range - let taginfo = s:GetTagInfo(tmplinenr, 0) - - if empty(taginfo) - continue - elseif empty(taginfo.parent) - let newlinenr = tmplinenr - break - endif - endfor - - if curlinenr != newlinenr - execute newlinenr - call winline() - endif - - redraw -endfunction - -" Folding {{{1 -" s:OpenFold() {{{2 -function! s:OpenFold() - let fileinfo = s:known_files.getCurrent() - if empty(fileinfo) - return - endif - - let curline = line('.') - - let tag = s:GetTagInfo(curline, 0) - if empty(tag) - return - endif - - call tag.openFold() - - call s:RenderKeepView() -endfunction - -" s:CloseFold() {{{2 -function! s:CloseFold() - let fileinfo = s:known_files.getCurrent() - if empty(fileinfo) - return - endif - - match none - - let curline = line('.') - - let curtag = s:GetTagInfo(curline, 0) - if empty(curtag) - return - endif - - let newline = curtag.closeFold() - - call s:RenderKeepView(newline) -endfunction - -" s:ToggleFold() {{{2 -function! s:ToggleFold() - let fileinfo = s:known_files.getCurrent() - if empty(fileinfo) - return - endif - - match none - - let curtag = s:GetTagInfo(line('.'), 0) - if empty(curtag) - return - endif - - let newline = line('.') - - if curtag.isKindheader() - call curtag.toggleFold() - elseif curtag.isFoldable() - if curtag.isFolded() - call curtag.openFold() - else - let newline = curtag.closeFold() - endif - else - let newline = curtag.closeFold() - endif - - call s:RenderKeepView(newline) -endfunction - -" s:SetFoldLevel() {{{2 -function! s:SetFoldLevel(level) - if a:level < 0 - echoerr 'Foldlevel can''t be negative' - return - endif - - let fileinfo = s:known_files.getCurrent() - if empty(fileinfo) - return - endif - - call s:SetFoldLevelRecursive(fileinfo, fileinfo.tags, a:level) - - let typeinfo = s:known_types[fileinfo.ftype] - - " Apply foldlevel to 'kind's - if a:level == 0 - for kind in typeinfo.kinds - call fileinfo.closeKindFold(kind) - endfor - else - for kind in typeinfo.kinds - call fileinfo.openKindFold(kind) - endfor - endif - - let fileinfo.foldlevel = a:level - - call s:RenderContent() -endfunction - -" s:SetFoldLevelRecursive() {{{2 -" Apply foldlevel to normal tags -function! s:SetFoldLevelRecursive(fileinfo, tags, level) - for tag in a:tags - if tag.depth >= a:level - call tag.setFolded(1) - else - call tag.setFolded(0) - endif - - if has_key(tag, 'children') - call s:SetFoldLevelRecursive(a:fileinfo, tag.children, a:level) - endif - endfor -endfunction - -" s:OpenParents() {{{2 -function! s:OpenParents(...) - let tagline = 0 - - if a:0 == 1 - let tag = a:1 - else - let tag = s:GetNearbyTag() - endif - - call tag.openParents() - - call s:RenderKeepView() -endfunction - -" Helper functions {{{1 -" s:CleanUp() {{{2 -function! s:CleanUp() - silent autocmd! TagbarAutoCmds - - unlet s:is_maximized - unlet s:compare_typeinfo - unlet s:short_help -endfunction - -" s:CleanupFileinfo() {{{2 -function! s:CleanupFileinfo(fname) - call s:known_files.rm(a:fname) -endfunction - -" s:QuitIfOnlyWindow() {{{2 -function! s:QuitIfOnlyWindow() - " Before quitting Vim, delete the tagbar buffer so that - " the '0 mark is correctly set to the previous buffer. - if winbufnr(2) == -1 - " Check if there is more than one tab page - if tabpagenr('$') == 1 - bdelete - quit - else - close - endif - endif -endfunction - -" s:AutoUpdate() {{{2 -function! s:AutoUpdate(fname) - call s:LogDebugMessage('AutoUpdate called on ' . a:fname) - - " Don't do anything if tagbar is not open or if we're in the tagbar window - let tagbarwinnr = bufwinnr('__Tagbar__') - if tagbarwinnr == -1 || &filetype == 'tagbar' - call s:LogDebugMessage('Tagbar window not open or in Tagbar window') - return - endif - - " Only consider the main filetype in cases like 'python.django' - let ftype = get(split(&filetype, '\.'), 0, '') - call s:LogDebugMessage('Vim filetype: ' . &filetype . - \ ', sanitized filetype: ' . ftype) - - " Don't do anything if the file isn't supported - if !s:IsValidFile(a:fname, ftype) - call s:LogDebugMessage('Not a valid file, stopping processing') - return - endif - - " Process the file if it's unknown or the information is outdated - " Also test for entries that exist but are empty, which will be the case - " if there was an error during the ctags execution - if s:known_files.has(a:fname) && !empty(s:known_files.get(a:fname)) - if s:known_files.get(a:fname).mtime != getftime(a:fname) - call s:LogDebugMessage('Filedata outdated, updating ' . a:fname) - call s:ProcessFile(a:fname, ftype) - endif - elseif !s:known_files.has(a:fname) - call s:LogDebugMessage('Unknown file, processing ' . a:fname) - call s:ProcessFile(a:fname, ftype) - endif - - let fileinfo = s:known_files.get(a:fname) - - " If we don't have an entry for the file by now something must have gone - " wrong, so don't change the tagbar content - if empty(fileinfo) - call s:LogDebugMessage('fileinfo empty after processing: ' . a:fname) - return - endif - - " Display the tagbar content - call s:RenderContent(fileinfo) - - " Call setCurrent after rendering so RenderContent can check whether the - " same file is redisplayed - if !empty(fileinfo) - call s:LogDebugMessage('Setting current file to ' . a:fname) - call s:known_files.setCurrent(fileinfo) - endif - - call s:HighlightTag() - call s:LogDebugMessage('AutoUpdate finished successfully') -endfunction - -" s:IsValidFile() {{{2 -function! s:IsValidFile(fname, ftype) - if a:fname == '' || a:ftype == '' - call s:LogDebugMessage('Empty filename or type') - return 0 - endif - - if !filereadable(a:fname) - call s:LogDebugMessage('File not readable') - return 0 - endif - - if !has_key(s:known_types, a:ftype) - call s:LogDebugMessage('Unsupported filetype: ' . a:ftype) - return 0 - endif - - return 1 -endfunction - -" s:EscapeCtagsCmd() {{{2 -" Assemble the ctags command line in a way that all problematic characters are -" properly escaped and converted to the system's encoding -" Optional third parameter is a file name to run ctags on -function! s:EscapeCtagsCmd(ctags_bin, args, ...) - call s:LogDebugMessage('EscapeCtagsCmd called') - call s:LogDebugMessage('ctags_bin: ' . a:ctags_bin) - call s:LogDebugMessage('ctags_args: ' . a:args) - - if exists('+shellslash') - let shellslash_save = &shellslash - set noshellslash - endif - - if a:0 == 1 - let fname = shellescape(a:1) - else - let fname = '' - endif - - let ctags_cmd = shellescape(a:ctags_bin) . ' ' . a:args . ' ' . fname - - if exists('+shellslash') - let &shellslash = shellslash_save - endif - - " Needed for cases where 'encoding' is different from the system's - " encoding - if g:tagbar_systemenc != &encoding - let ctags_cmd = iconv(ctags_cmd, &encoding, g:tagbar_systemenc) - elseif $LANG != '' - let ctags_cmd = iconv(ctags_cmd, &encoding, $LANG) - endif - - call s:LogDebugMessage('Escaped ctags command: ' . ctags_cmd) - - if ctags_cmd == '' - echoerr 'Tagbar: Encoding conversion failed!' - \ 'Please make sure your system is set up correctly' - \ 'and that Vim is compiled with the "iconv" feature.' - endif - - return ctags_cmd -endfunction - -" s:ExecuteCtags() {{{2 -" Execute ctags with necessary shell settings -" Partially based on the discussion at -" http://vim.1045645.n5.nabble.com/bad-default-shellxquote-in-Widows-td1208284.html -function! s:ExecuteCtags(ctags_cmd) - if exists('+shellslash') - let shellslash_save = &shellslash - set noshellslash - endif - - if &shell =~ 'cmd\.exe' - let shellxquote_save = &shellxquote - set shellxquote=\" - let shellcmdflag_save = &shellcmdflag - set shellcmdflag=/s\ /c - endif - - let ctags_output = system(a:ctags_cmd) - - if &shell =~ 'cmd\.exe' - let &shellxquote = shellxquote_save - let &shellcmdflag = shellcmdflag_save - endif - - if exists('+shellslash') - let &shellslash = shellslash_save - endif - - return ctags_output -endfunction - -" s:GetTagInfo() {{{2 -" Return the info dictionary of the tag on the specified line. If the line -" does not contain a valid tag (for example because it is empty or only -" contains a pseudo-tag) return an empty dictionary. -function! s:GetTagInfo(linenr, ignorepseudo) - let fileinfo = s:known_files.getCurrent() - - if empty(fileinfo) - return {} - endif - - " Don't do anything in empty and comment lines - let curline = getline(a:linenr) - if curline =~ '^\s*$' || curline[0] == '"' - return {} - endif - - " Check if there is a tag on the current line - if !has_key(fileinfo.tline, a:linenr) - return {} - endif - - let taginfo = fileinfo.tline[a:linenr] - - " Check if the current tag is not a pseudo-tag - if a:ignorepseudo && taginfo.isPseudoTag() - return {} - endif - - return taginfo -endfunction - -" s:GetNearbyTag() {{{2 -" Get the tag info for a file near the cursor in the current file -function! s:GetNearbyTag() - let fileinfo = s:known_files.getCurrent() - - let curline = line('.') - let tag = {} - - " If a tag appears in a file more than once (for example namespaces in - " C++) only one of them has a 'tline' entry and can thus be highlighted. - " The only way to solve this would be to go over the whole tag list again, - " making everything slower. Since this should be a rare occurence and - " highlighting isn't /that/ important ignore it for now. - for line in range(curline, 1, -1) - if has_key(fileinfo.fline, line) - let tag = fileinfo.fline[line] - break - endif - endfor - - return tag -endfunction - -" s:CheckMouseClick() {{{2 -function! s:CheckMouseClick() - let line = getline('.') - let curcol = col('.') - - if (match(line, s:icon_open . '[-+ ]') + 1) == curcol - call s:CloseFold() - elseif (match(line, s:icon_closed . '[-+ ]') + 1) == curcol - call s:OpenFold() - elseif g:tagbar_singleclick - call s:JumpToTag(0) - endif -endfunction - -" s:DetermineFiletype() {{{2 -function! s:DetectFiletype(bufnr) - " Filetype has already been detected for loaded buffers, but not - " necessarily for unloaded ones - let ftype = getbufvar(a:bufnr, '&filetype') - - if bufloaded(a:bufnr) - return ftype - endif - - if ftype != '' - return ftype - endif - - " Unloaded buffer with non-detected filetype, need to detect filetype - " manually - let bufname = bufname(a:bufnr) - - let eventignore_save = &eventignore - set eventignore=FileType - let filetype_save = &filetype - - exe 'doautocmd filetypedetect BufRead ' . bufname - let ftype = &filetype - - let &filetype = filetype_save - let &eventignore = eventignore_save - - return ftype -endfunction - - -" TagbarBalloonExpr() {{{2 -function! TagbarBalloonExpr() - let taginfo = s:GetTagInfo(v:beval_lnum, 1) - - if empty(taginfo) - return - endif - - return taginfo.getPrototype() -endfunction - -" TagbarGenerateStatusline() {{{2 -function! TagbarGenerateStatusline() - if g:tagbar_sort - let text = '[Name]' - else - let text = '[Order]' - endif - - if !empty(s:known_files.getCurrent()) - let filename = fnamemodify(s:known_files.getCurrent().fpath, ':t') - let text .= ' ' . filename - endif - - return text -endfunction - -" Debugging {{{1 -" s:StartDebug() {{{2 -function! s:StartDebug(filename) - if empty(a:filename) - let s:debug_file = 'tagbardebug.log' - else - let s:debug_file = a:filename - endif - - " Empty log file - exe 'redir! > ' . s:debug_file - redir END - - " Check whether the log file could be created - if !filewritable(s:debug_file) - echomsg 'Tagbar: Unable to create log file ' . s:debug_file - let s:debug_file = '' - return - endif - - let s:debug = 1 -endfunction - -" s:StopDebug() {{{2 -function! s:StopDebug() - let s:debug = 0 - let s:debug_file = '' -endfunction - -" s:LogDebugMessage() {{{2 -function! s:LogDebugMessage(msg) - if s:debug - exe 'redir >> ' . s:debug_file - silent echon strftime('%H:%M:%S') . ': ' . a:msg . "\n" - redir END - endif -endfunction - -" Autoload functions {{{1 -function! tagbar#ToggleWindow() - call s:ToggleWindow() -endfunction - -function! tagbar#OpenWindow(...) - let flags = a:0 > 0 ? a:1 : '' - call s:OpenWindow(flags) -endfunction - -function! tagbar#CloseWindow() - call s:CloseWindow() -endfunction - -function! tagbar#SetFoldLevel(...) - call s:SetFoldLevel(a:1) -endfunction - -function! tagbar#OpenParents() - call s:OpenParents() -endfunction - -function! tagbar#StartDebug(...) - let filename = a:0 > 0 ? a:1 : '' - call s:StartDebug(filename) -endfunction - -function! tagbar#StopDebug() - call s:StopDebug() -endfunction - -function! tagbar#RestoreSession() - call s:RestoreSession() -endfunction - -" Automatically open Tagbar if one of the open buffers contains a supported -" file -function! tagbar#autoopen() - call s:Init() - - for bufnr in range(1, bufnr('$')) - if buflisted(bufnr) - let ftype = s:DetectFiletype(bufnr) - if s:IsValidFile(bufname(bufnr), ftype) - call s:OpenWindow('') - return - endif - endif - endfor -endfunction - -" Modeline {{{1 -" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1 |