" ============================================================================ " File: tagbar.vim " Description: List the current file's tags in a sidebar, ordered by class etc " Author: Jan Larres " Licence: Vim licence " Website: https://preservim.github.io/tagbar " Version: 3.0.0 " 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 " If another plugin calls an autoloaded Tagbar function on startup before the " plugin/tagbar.vim file got loaded, load it explicitly if exists(':Tagbar') == 0 runtime plugin/tagbar.vim endif if exists(':Tagbar') == 0 echomsg 'Tagbar: Could not load plugin code, check your runtimepath!' finish endif " Basic init {{{2 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 g:tagbar#icon_closed = g:tagbar_iconchars[0] let g:tagbar#icon_open = g:tagbar_iconchars[1] let s:type_init_done = 0 let s:autocommands_done = 0 let s:statusline_in_use = 0 let s:init_done = 0 " 0: not checked yet; 1: checked and found; 2: checked and not found let s:checked_ctags = 0 let s:checked_ctags_types = 0 let s:ctags_is_uctags = 0 let s:new_window = 1 let s:is_maximized = 0 let s:winrestcmd = '' let s:short_help = 1 let s:nearby_disabled = 0 let s:paused = 0 let s:pwin_by_tagbar = 0 let s:buffer_seqno = 0 let s:vim_quitting = 0 let s:last_alt_bufnr = -1 let s:window_expanded = 0 let s:expand_bufnr = -1 let s:window_pos = { \ 'pre' : { 'x' : 0, 'y' : 0 }, \ 'post' : { 'x' : 0, 'y' : 0 } \} let s:delayed_update_files = [] let g:loaded_tagbar = 1 let s:last_highlight_tline = 0 let s:warnings = { \ 'type': [], \ 'encoding': 0 \ } let s:singular_types = { \ 'Classes': 'Class', \ 'Delegates': 'Delegate', \ 'Enumeration values': 'Enumeration value', \ 'Enumerations': 'Enumeration', \ 'Error codes': 'Error code', \ 'Error domains': 'Error domain', \ 'Fields': 'Field', \ 'Interfaces': 'Interface', \ 'JavaScript funtions': 'JavaScript function', \ 'Methods': 'Method', \ 'MobiLink Conn Scripts': 'MobiLink Conn Script', \ 'MobiLink Properties': 'MobiLink Property', \ 'MobiLink Table Scripts': 'MobiLink Table Script', \ 'Properties': 'Property', \ 'Signals': 'Signal', \ 'Structures': 'Structure', \ 'autocommand groups': 'autocommand group', \ 'block data': 'block data', \ 'block label': 'block label', \ 'chapters': 'chapter', \ 'classes': 'class', \ 'commands': 'command', \ 'common blocks': 'common block', \ 'components': 'component', \ 'constant definitions': 'constant definition', \ 'constants': 'constant', \ 'constructors': 'constructor', \ 'cursors': 'cursor', \ 'data items': 'data item', \ 'defines': 'define', \ 'derived types and structures': 'derived type and structure', \ 'domains': 'domain', \ 'entities': 'entity', \ 'entry points': 'entry point', \ 'embedded': 'embedded', \ 'enum constants': 'enum constant', \ 'enum types': 'enum type', \ 'enumerations': 'enumeration', \ 'enumerators': 'enumerator', \ 'enums': 'enum', \ 'events': 'event', \ 'exception declarations': 'exception declaration', \ 'exceptions': 'exception', \ 'features': 'feature', \ 'fields': 'field', \ 'file descriptions': 'file description', \ 'formats': 'format', \ 'fragments': 'fragment', \ 'function definitions': 'function definition', \ 'functions': 'function', \ 'functor definitions': 'functor definition', \ 'global variables': 'global variable', \ 'group items': 'group item', \ 'imports': 'import', \ 'includes': 'include', \ 'indexes': 'index', \ 'interfaces': 'interface', \ 'javascript functions': 'JavaScript function', \ 'labels': 'label', \ 'macro definitions': 'macro definition', \ 'macros': 'macro', \ 'maps': 'map', \ 'members': 'member', \ 'methods': 'method', \ 'modules or functors': 'module or function', \ 'modules': 'module', \ 'mxtags': 'mxtag', \ 'named anchors': 'named anchor', \ 'namelists': 'namelist', \ 'namespaces': 'namespace', \ 'net data types': 'net data type', \ 'packages': 'package', \ 'package': 'package', \ 'paragraphs': 'paragraph', \ 'parts': 'part', \ 'patterns': 'pattern', \ 'ports': 'port', \ 'procedures': 'procedure', \ 'program ids': 'program id', \ 'programs': 'program', \ 'projects': 'project', \ 'properties': 'property', \ 'prototypes': 'prototype', \ 'publications': 'publication', \ 'record definitions': 'record definition', \ 'record fields': 'record field', \ 'records': 'record', \ 'register data types': 'register data type', \ 'sections': 'section', \ 'services': 'services', \ 'sets': 'sets', \ 'signature declarations': 'signature declaration', \ 'singleton methods': 'singleton method', \ 'slots': 'slot', \ 'structs': 'struct', \ 'structure declarations': 'structure declaration', \ 'structure fields': 'structure field', \ 'subparagraphs': 'subparagraph', \ 'subroutines': 'subroutine', \ 'subsections': 'subsection', \ 'subsubsections': 'subsubsection', \ 'subtypes': 'subtype', \ 'synonyms': 'synonym', \ 'tables': 'table', \ 'targets': 'target', \ 'tasks': 'task', \ 'triggers': 'trigger', \ 'type definitions': 'type definition', \ 'type names': 'type name', \ 'typedefs': 'typedef', \ 'types': 'type', \ 'unions': 'union', \ 'value bindings': 'value binding', \ 'variables': 'variable', \ 'views': 'view', \ 'vimball filenames': 'vimball filename'} " s:Init() {{{2 function! s:Init(silent) abort if s:checked_ctags == 2 && a:silent return 0 elseif s:checked_ctags != 1 if !s:CheckForExCtags(a:silent) return 0 endif endif if !s:type_init_done call s:InitTypes() endif if !s:autocommands_done call s:CreateAutocommands() call s:AutoUpdate(fnamemodify(expand('%'), ':p'), 0) endif let s:init_done = 1 return 1 endfunction " s:InitTypes() {{{2 function! s:InitTypes() abort call tagbar#debug#log('Initializing types') let supported_types = s:GetSupportedFiletypes() if s:ctags_is_uctags let s:known_types = tagbar#types#uctags#init(supported_types) else let s:known_types = tagbar#types#ctags#init(supported_types) endif " Use dart_ctags if available let dart_ctags = s:CheckFTCtags('dart_ctags', 'dart') if dart_ctags !=# '' let supported_types['dart'] = 1 call tagbar#debug#log('Detected dart_ctags, overriding typedef') let type_dart = tagbar#prototypes#typeinfo#new() let type_dart.ctagstype = 'dart' let type_dart.kinds = [ \ {'short' : 'l', 'long' : 'library', 'fold' : 0, 'stl' : 0}, \ {'short' : 't', 'long' : 'export', 'fold' : 0, 'stl' : 0}, \ {'short' : 'i', 'long' : 'imports', 'fold' : 1, 'stl' : 0}, \ {'short' : 'D', 'long' : 'dart', 'fold' : 0, 'stl' : 0}, \ {'short' : 'U', 'long' : 'pub', 'fold' : 0, 'stl' : 0}, \ {'short' : 'L', 'long' : 'local', 'fold' : 0, 'stl' : 0}, \ {'short' : 'P', 'long' : 'part', 'fold' : 0, 'stl' : 0}, \ {'short' : 'p', 'long' : 'part of', 'fold' : 0, 'stl' : 0}, \ {'short' : 'C', 'long' : 'consts', 'fold' : 0, 'stl' : 0}, \ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0}, \ {'short' : 'F', 'long' : 'functions', 'fold' : 0, 'stl' : 0}, \ {'short' : 'E', 'long' : 'enums', 'fold' : 0, 'stl' : 0}, \ {'short' : 'e', 'long' : 'constants', 'fold' : 0, 'stl' : 0}, \ {'short' : 'x', 'long' : 'mixins', 'fold' : 0, 'stl' : 0}, \ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 0}, \ {'short' : 'd', 'long' : 'extends', 'fold' : 0, 'stl' : 0}, \ {'short' : 'w', 'long' : 'with', 'fold' : 0, 'stl' : 0}, \ {'short' : 'z', 'long' : 'implements', 'fold' : 0, 'stl' : 0}, \ {'short' : 'r', 'long' : 'constructors', 'fold' : 0, 'stl' : 0}, \ {'short' : 'a', 'long' : 'abstract functions', 'fold' : 0, 'stl' : 0}, \ {'short' : 'f', 'long' : 'fields', 'fold' : 0, 'stl' : 0}, \ {'short' : 'm', 'long' : 'methods', 'fold' : 0, 'stl' : 0}, \ {'short' : 'M', 'long' : 'static methods', 'fold' : 0, 'stl' : 0}, \ {'short' : 'g', 'long' : 'getters', 'fold' : 0, 'stl' : 0}, \ {'short' : 's', 'long' : 'setters', 'fold' : 0, 'stl' : 0}, \ {'short' : 'o', 'long' : 'operators', 'fold' : 0, 'stl' : 0}, \ ] let type_dart.sro = ':' let type_dart.kind2scope = { \ 'c' : 'class', \ 'E' : 'enum', \ 'x' : 'mixin', \ 'i' : 'directive' \ } let type_dart.scope2kind = { \ 'class' : 'c', \ 'enum' : 'E', \ 'mixin' : 'x', \ 'directive' : 'i' \ } let type_dart.ctagsbin = dart_ctags let type_dart.ctagsargs = '-l' let type_dart.ftype = 'dart' call type_dart.createKinddict() let s:known_types.dart = type_dart endif " Use jsctags/doctorjs if available let jsctags = s:CheckFTCtags('jsctags', 'javascript') if jsctags !=# '' call tagbar#debug#log('Detected jsctags, overriding typedef') let type_javascript = tagbar#prototypes#typeinfo#new() let type_javascript.ctagstype = 'javascript' let type_javascript.kinds = [ \ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0}, \ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1} \ ] let type_javascript.sro = '.' let type_javascript.kind2scope = { \ 'v' : 'namespace', \ 'f' : 'namespace' \ } let type_javascript.scope2kind = { \ 'namespace' : 'f' \ } let type_javascript.ctagsbin = jsctags let type_javascript.ctagsargs = '-f -' let type_javascript.ftype = 'javascript' call type_javascript.createKinddict() let s:known_types.javascript = type_javascript endif " Use gotags if available let gotags = s:CheckFTCtags('gotags', 'go') if gotags !=# '' call tagbar#debug#log('Detected gotags, overriding typedef') let type_go = tagbar#prototypes#typeinfo#new() let type_go.ctagstype = 'go' let type_go.kinds = [ \ {'short' : 'p', 'long' : 'package', 'fold' : 0, 'stl' : 0}, \ {'short' : 'i', 'long' : 'imports', 'fold' : 1, 'stl' : 0}, \ {'short' : 'c', 'long' : 'constants', 'fold' : 0, 'stl' : 0}, \ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0}, \ {'short' : 't', 'long' : 'types', 'fold' : 0, 'stl' : 0}, \ {'short' : 'n', 'long' : 'intefaces', 'fold' : 0, 'stl' : 0}, \ {'short' : 'w', 'long' : 'fields', 'fold' : 0, 'stl' : 0}, \ {'short' : 'e', 'long' : 'embedded', 'fold' : 0, 'stl' : 0}, \ {'short' : 'm', 'long' : 'methods', 'fold' : 0, 'stl' : 0}, \ {'short' : 'r', 'long' : 'constructors', 'fold' : 0, 'stl' : 0}, \ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 0}, \ ] let type_go.sro = '.' let type_go.kind2scope = { \ 't' : 'ctype', \ 'n' : 'ntype' \ } let type_go.scope2kind = { \ 'ctype' : 't', \ 'ntype' : 'n' \ } let type_go.ctagsbin = gotags let type_go.ctagsargs = '-sort -silent' let type_go.ftype = 'go' call type_go.createKinddict() let s:known_types.go = type_go endif call s:LoadUserTypeDefs() " Add an 'unknown' kind to the types for pseudotags that we can't " determine the correct kind for since they don't have any children that " are not pseudotags and that therefore don't provide scope information for typeinfo in values(s:known_types) if has_key(typeinfo, 'kind2scope') let unknown_kind = \ {'short' : '?', 'long' : 'unknown', 'fold' : 0, 'stl' : 1} " Check for existence first since some types exist under more than " one name if index(typeinfo.kinds, unknown_kind) == -1 call add(typeinfo.kinds, unknown_kind) endif let typeinfo.kind2scope['?'] = 'unknown' endif endfor let s:type_init_done = 1 endfunction " s:LoadUserTypeDefs() {{{2 function! s:LoadUserTypeDefs(...) abort if a:0 > 0 let type = a:1 let defdict = {} let defdict[type] = g:tagbar_type_{type} else let defdict = tagbar#getusertypes() endif let transformed = {} for [type, def] in items(defdict) let transformed[type] = s:TransformUserTypeDef(def) let transformed[type].ftype = type endfor for [key, value] in items(transformed) call tagbar#debug#log("Initializing user type '" . key . "'") if !has_key(s:known_types, key) || get(value, 'replace', 0) let s:known_types[key] = tagbar#prototypes#typeinfo#new(value) else call extend(s:known_types[key], value) endif call s:known_types[key].createKinddict() endfor endfunction " s:TransformUserTypeDef() {{{2 " Transform the user definitions into the internal format function! s:TransformUserTypeDef(def) abort let newdef = copy(a:def) if has_key(a:def, 'kinds') let newdef.kinds = [] let kinds = a:def.kinds for kind in kinds let kindlist = split(kind, ':') let kinddict = {'short' : kindlist[0], 'long' : kindlist[1]} let kinddict.fold = get(kindlist, 2, 0) let kinddict.stl = get(kindlist, 3, 1) call add(newdef.kinds, kinddict) endfor endif " If the user only specified one of kind2scope and scope2kind then use it " to generate the respective other if has_key(a:def, 'kind2scope') && !has_key(a:def, 'scope2kind') let newdef.scope2kind = {} for [key, value] in items(a:def.kind2scope) let newdef.scope2kind[value] = key endfor elseif has_key(a:def, 'scope2kind') && !has_key(a:def, 'kind2scope') let newdef.kind2scope = {} for [key, value] in items(a:def.scope2kind) let newdef.kind2scope[value] = key endfor endif return newdef endfunction " s:RestoreSession() {{{2 " Properly restore Tagbar after a session got loaded function! s:RestoreSession() abort if s:init_done call tagbar#debug#log('Tagbar already initialized; not restoring session') return endif call tagbar#debug#log('Restoring session') let curfile = fnamemodify(bufname('%'), ':p') let tagbarwinnr = bufwinnr(s:TagbarBufName()) if tagbarwinnr == -1 " Tagbar wasn't open in the saved session, nothing to do return endif let in_tagbar = 1 if winnr() != tagbarwinnr call s:goto_win(tagbarwinnr, 1) let in_tagbar = 0 endif let s:last_autofocus = 0 call s:Init(0) call s:InitWindow(g:tagbar_autoclose) call s:AutoUpdate(curfile, 0) if !in_tagbar call s:goto_win('p') endif endfunction " s:MapKeys() {{{2 function! s:MapKeys() abort call tagbar#debug#log('Mapping keys') nnoremap