PageRenderTime 62ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/bundle/tagbar/autoload/tagbar.vim

https://bitbucket.org/jaju/vimrc
Vim Script | 1461 lines | 1135 code | 150 blank | 176 comment | 85 complexity | e82e4735c48801a274ac45256cd3c7bb MD5 | raw file
  1. " ============================================================================
  2. " File: tagbar.vim
  3. " Description: List the current file's tags in a sidebar, ordered by class etc
  4. " Author: Jan Larres <jan@majutsushi.net>
  5. " Licence: Vim licence
  6. " Website: http://majutsushi.github.com/tagbar/
  7. " Version: 2.3
  8. " Note: This plugin was heavily inspired by the 'Taglist' plugin by
  9. " Yegappan Lakshmanan and uses a small amount of code from it.
  10. "
  11. " Original taglist copyright notice:
  12. " Permission is hereby granted to use and distribute this code,
  13. " with or without modifications, provided that this copyright
  14. " notice is copied with it. Like anything else that's free,
  15. " taglist.vim is provided *as is* and comes with no warranty of
  16. " any kind, either expressed or implied. In no event will the
  17. " copyright holder be liable for any damamges resulting from the
  18. " use of this software.
  19. " ============================================================================
  20. scriptencoding utf-8
  21. " Initialization {{{1
  22. " Basic init {{{2
  23. if !exists('g:tagbar_ctags_bin')
  24. let g:tagbar_ctags_bin = '/usr/local/bin/ctags'
  25. else
  26. " reset 'wildignore' temporarily in case *.exe is included in it
  27. let wildignore_save = &wildignore
  28. set wildignore&
  29. let g:tagbar_ctags_bin = expand(g:tagbar_ctags_bin)
  30. let &wildignore = wildignore_save
  31. if !executable(g:tagbar_ctags_bin)
  32. echomsg 'Tagbar: Exuberant ctags not found in specified place,'
  33. \ 'skipping plugin'
  34. finish
  35. endif
  36. endif
  37. redir => s:ftype_out
  38. silent filetype
  39. redir END
  40. if s:ftype_out !~# 'detection:ON'
  41. echomsg 'Tagbar: Filetype detection is turned off, skipping plugin'
  42. unlet s:ftype_out
  43. finish
  44. endif
  45. unlet s:ftype_out
  46. let s:icon_closed = g:tagbar_iconchars[0]
  47. let s:icon_open = g:tagbar_iconchars[1]
  48. let s:type_init_done = 0
  49. let s:autocommands_done = 0
  50. let s:checked_ctags = 0
  51. let s:window_expanded = 0
  52. let s:access_symbols = {
  53. \ 'public' : '+',
  54. \ 'protected' : '#',
  55. \ 'private' : '-'
  56. \ }
  57. let g:loaded_tagbar = 1
  58. let s:last_highlight_tline = 0
  59. let s:debug = 0
  60. let s:debug_file = ''
  61. " s:Init() {{{2
  62. function! s:Init()
  63. if !s:type_init_done
  64. call s:InitTypes()
  65. endif
  66. if !s:checked_ctags
  67. if !s:CheckForExCtags()
  68. return
  69. endif
  70. endif
  71. endfunction
  72. " s:InitTypes() {{{2
  73. function! s:InitTypes()
  74. call s:LogDebugMessage('Initializing types')
  75. let s:known_types = {}
  76. " Ant {{{3
  77. let type_ant = {}
  78. let type_ant.ctagstype = 'ant'
  79. let type_ant.kinds = [
  80. \ {'short' : 'p', 'long' : 'projects', 'fold' : 0},
  81. \ {'short' : 't', 'long' : 'targets', 'fold' : 0}
  82. \ ]
  83. let s:known_types.ant = type_ant
  84. " Asm {{{3
  85. let type_asm = {}
  86. let type_asm.ctagstype = 'asm'
  87. let type_asm.kinds = [
  88. \ {'short' : 'm', 'long' : 'macros', 'fold' : 0},
  89. \ {'short' : 't', 'long' : 'types', 'fold' : 0},
  90. \ {'short' : 'd', 'long' : 'defines', 'fold' : 0},
  91. \ {'short' : 'l', 'long' : 'labels', 'fold' : 0}
  92. \ ]
  93. let s:known_types.asm = type_asm
  94. " ASP {{{3
  95. let type_aspvbs = {}
  96. let type_aspvbs.ctagstype = 'asp'
  97. let type_aspvbs.kinds = [
  98. \ {'short' : 'd', 'long' : 'constants', 'fold' : 0},
  99. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  100. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  101. \ {'short' : 's', 'long' : 'subroutines', 'fold' : 0},
  102. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}
  103. \ ]
  104. let s:known_types.aspvbs = type_aspvbs
  105. " Awk {{{3
  106. let type_awk = {}
  107. let type_awk.ctagstype = 'awk'
  108. let type_awk.kinds = [
  109. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}
  110. \ ]
  111. let s:known_types.awk = type_awk
  112. " Basic {{{3
  113. let type_basic = {}
  114. let type_basic.ctagstype = 'basic'
  115. let type_basic.kinds = [
  116. \ {'short' : 'c', 'long' : 'constants', 'fold' : 0},
  117. \ {'short' : 'g', 'long' : 'enumerations', 'fold' : 0},
  118. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  119. \ {'short' : 'l', 'long' : 'labels', 'fold' : 0},
  120. \ {'short' : 't', 'long' : 'types', 'fold' : 0},
  121. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}
  122. \ ]
  123. let s:known_types.basic = type_basic
  124. " BETA {{{3
  125. let type_beta = {}
  126. let type_beta.ctagstype = 'beta'
  127. let type_beta.kinds = [
  128. \ {'short' : 'f', 'long' : 'fragments', 'fold' : 0},
  129. \ {'short' : 's', 'long' : 'slots', 'fold' : 0},
  130. \ {'short' : 'v', 'long' : 'patterns', 'fold' : 0}
  131. \ ]
  132. let s:known_types.beta = type_beta
  133. " C {{{3
  134. let type_c = {}
  135. let type_c.ctagstype = 'c'
  136. let type_c.kinds = [
  137. \ {'short' : 'd', 'long' : 'macros', 'fold' : 1},
  138. \ {'short' : 'p', 'long' : 'prototypes', 'fold' : 1},
  139. \ {'short' : 'g', 'long' : 'enums', 'fold' : 0},
  140. \ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0},
  141. \ {'short' : 't', 'long' : 'typedefs', 'fold' : 0},
  142. \ {'short' : 's', 'long' : 'structs', 'fold' : 0},
  143. \ {'short' : 'u', 'long' : 'unions', 'fold' : 0},
  144. \ {'short' : 'm', 'long' : 'members', 'fold' : 0},
  145. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0},
  146. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}
  147. \ ]
  148. let type_c.sro = '::'
  149. let type_c.kind2scope = {
  150. \ 'g' : 'enum',
  151. \ 's' : 'struct',
  152. \ 'u' : 'union'
  153. \ }
  154. let type_c.scope2kind = {
  155. \ 'enum' : 'g',
  156. \ 'struct' : 's',
  157. \ 'union' : 'u'
  158. \ }
  159. let s:known_types.c = type_c
  160. " C++ {{{3
  161. let type_cpp = {}
  162. let type_cpp.ctagstype = 'c++'
  163. let type_cpp.kinds = [
  164. \ {'short' : 'd', 'long' : 'macros', 'fold' : 1},
  165. \ {'short' : 'p', 'long' : 'prototypes', 'fold' : 1},
  166. \ {'short' : 'g', 'long' : 'enums', 'fold' : 0},
  167. \ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0},
  168. \ {'short' : 't', 'long' : 'typedefs', 'fold' : 0},
  169. \ {'short' : 'n', 'long' : 'namespaces', 'fold' : 0},
  170. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  171. \ {'short' : 's', 'long' : 'structs', 'fold' : 0},
  172. \ {'short' : 'u', 'long' : 'unions', 'fold' : 0},
  173. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  174. \ {'short' : 'm', 'long' : 'members', 'fold' : 0},
  175. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}
  176. \ ]
  177. let type_cpp.sro = '::'
  178. let type_cpp.kind2scope = {
  179. \ 'g' : 'enum',
  180. \ 'n' : 'namespace',
  181. \ 'c' : 'class',
  182. \ 's' : 'struct',
  183. \ 'u' : 'union'
  184. \ }
  185. let type_cpp.scope2kind = {
  186. \ 'enum' : 'g',
  187. \ 'namespace' : 'n',
  188. \ 'class' : 'c',
  189. \ 'struct' : 's',
  190. \ 'union' : 'u'
  191. \ }
  192. let s:known_types.cpp = type_cpp
  193. " C# {{{3
  194. let type_cs = {}
  195. let type_cs.ctagstype = 'c#'
  196. let type_cs.kinds = [
  197. \ {'short' : 'd', 'long' : 'macros', 'fold' : 1},
  198. \ {'short' : 'f', 'long' : 'fields', 'fold' : 0},
  199. \ {'short' : 'g', 'long' : 'enums', 'fold' : 0},
  200. \ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0},
  201. \ {'short' : 't', 'long' : 'typedefs', 'fold' : 0},
  202. \ {'short' : 'n', 'long' : 'namespaces', 'fold' : 0},
  203. \ {'short' : 'i', 'long' : 'interfaces', 'fold' : 0},
  204. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  205. \ {'short' : 's', 'long' : 'structs', 'fold' : 0},
  206. \ {'short' : 'E', 'long' : 'events', 'fold' : 0},
  207. \ {'short' : 'm', 'long' : 'methods', 'fold' : 0},
  208. \ {'short' : 'p', 'long' : 'properties', 'fold' : 0}
  209. \ ]
  210. let type_cs.sro = '.'
  211. let type_cs.kind2scope = {
  212. \ 'n' : 'namespace',
  213. \ 'i' : 'interface',
  214. \ 'c' : 'class',
  215. \ 's' : 'struct',
  216. \ 'g' : 'enum'
  217. \ }
  218. let type_cs.scope2kind = {
  219. \ 'namespace' : 'n',
  220. \ 'interface' : 'i',
  221. \ 'class' : 'c',
  222. \ 'struct' : 's',
  223. \ 'enum' : 'g'
  224. \ }
  225. let s:known_types.cs = type_cs
  226. " COBOL {{{3
  227. let type_cobol = {}
  228. let type_cobol.ctagstype = 'cobol'
  229. let type_cobol.kinds = [
  230. \ {'short' : 'd', 'long' : 'data items', 'fold' : 0},
  231. \ {'short' : 'f', 'long' : 'file descriptions', 'fold' : 0},
  232. \ {'short' : 'g', 'long' : 'group items', 'fold' : 0},
  233. \ {'short' : 'p', 'long' : 'paragraphs', 'fold' : 0},
  234. \ {'short' : 'P', 'long' : 'program ids', 'fold' : 0},
  235. \ {'short' : 's', 'long' : 'sections', 'fold' : 0}
  236. \ ]
  237. let s:known_types.cobol = type_cobol
  238. " DOS Batch {{{3
  239. let type_dosbatch = {}
  240. let type_dosbatch.ctagstype = 'dosbatch'
  241. let type_dosbatch.kinds = [
  242. \ {'short' : 'l', 'long' : 'labels', 'fold' : 0},
  243. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}
  244. \ ]
  245. let s:known_types.dosbatch = type_dosbatch
  246. " Eiffel {{{3
  247. let type_eiffel = {}
  248. let type_eiffel.ctagstype = 'eiffel'
  249. let type_eiffel.kinds = [
  250. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  251. \ {'short' : 'f', 'long' : 'features', 'fold' : 0}
  252. \ ]
  253. let type_eiffel.sro = '.' " Not sure, is nesting even possible?
  254. let type_eiffel.kind2scope = {
  255. \ 'c' : 'class',
  256. \ 'f' : 'feature'
  257. \ }
  258. let type_eiffel.scope2kind = {
  259. \ 'class' : 'c',
  260. \ 'feature' : 'f'
  261. \ }
  262. let s:known_types.eiffel = type_eiffel
  263. " Erlang {{{3
  264. let type_erlang = {}
  265. let type_erlang.ctagstype = 'erlang'
  266. let type_erlang.kinds = [
  267. \ {'short' : 'm', 'long' : 'modules', 'fold' : 0},
  268. \ {'short' : 'd', 'long' : 'macro definitions', 'fold' : 0},
  269. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  270. \ {'short' : 'r', 'long' : 'record definitions', 'fold' : 0}
  271. \ ]
  272. let type_erlang.sro = '.' " Not sure, is nesting even possible?
  273. let type_erlang.kind2scope = {
  274. \ 'm' : 'module'
  275. \ }
  276. let type_erlang.scope2kind = {
  277. \ 'module' : 'm'
  278. \ }
  279. let s:known_types.erlang = type_erlang
  280. " Flex {{{3
  281. " Vim doesn't support Flex out of the box, this is based on rough
  282. " guesses and probably requires
  283. " http://www.vim.org/scripts/script.php?script_id=2909
  284. " Improvements welcome!
  285. let type_mxml = {}
  286. let type_mxml.ctagstype = 'flex'
  287. let type_mxml.kinds = [
  288. \ {'short' : 'v', 'long' : 'global variables', 'fold' : 0},
  289. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  290. \ {'short' : 'm', 'long' : 'methods', 'fold' : 0},
  291. \ {'short' : 'p', 'long' : 'properties', 'fold' : 0},
  292. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  293. \ {'short' : 'x', 'long' : 'mxtags', 'fold' : 0}
  294. \ ]
  295. let type_mxml.sro = '.'
  296. let type_mxml.kind2scope = {
  297. \ 'c' : 'class'
  298. \ }
  299. let type_mxml.scope2kind = {
  300. \ 'class' : 'c'
  301. \ }
  302. let s:known_types.mxml = type_mxml
  303. " Fortran {{{3
  304. let type_fortran = {}
  305. let type_fortran.ctagstype = 'fortran'
  306. let type_fortran.kinds = [
  307. \ {'short' : 'm', 'long' : 'modules', 'fold' : 0},
  308. \ {'short' : 'p', 'long' : 'programs', 'fold' : 0},
  309. \ {'short' : 'k', 'long' : 'components', 'fold' : 0},
  310. \ {'short' : 't', 'long' : 'derived types and structures', 'fold' : 0},
  311. \ {'short' : 'c', 'long' : 'common blocks', 'fold' : 0},
  312. \ {'short' : 'b', 'long' : 'block data', 'fold' : 0},
  313. \ {'short' : 'e', 'long' : 'entry points', 'fold' : 0},
  314. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  315. \ {'short' : 's', 'long' : 'subroutines', 'fold' : 0},
  316. \ {'short' : 'l', 'long' : 'labels', 'fold' : 0},
  317. \ {'short' : 'n', 'long' : 'namelists', 'fold' : 0},
  318. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}
  319. \ ]
  320. let type_fortran.sro = '.' " Not sure, is nesting even possible?
  321. let type_fortran.kind2scope = {
  322. \ 'm' : 'module',
  323. \ 'p' : 'program',
  324. \ 'f' : 'function',
  325. \ 's' : 'subroutine'
  326. \ }
  327. let type_fortran.scope2kind = {
  328. \ 'module' : 'm',
  329. \ 'program' : 'p',
  330. \ 'function' : 'f',
  331. \ 'subroutine' : 's'
  332. \ }
  333. let s:known_types.fortran = type_fortran
  334. " HTML {{{3
  335. let type_html = {}
  336. let type_html.ctagstype = 'html'
  337. let type_html.kinds = [
  338. \ {'short' : 'f', 'long' : 'JavaScript funtions', 'fold' : 0},
  339. \ {'short' : 'a', 'long' : 'named anchors', 'fold' : 0}
  340. \ ]
  341. let s:known_types.html = type_html
  342. " Java {{{3
  343. let type_java = {}
  344. let type_java.ctagstype = 'java'
  345. let type_java.kinds = [
  346. \ {'short' : 'p', 'long' : 'packages', 'fold' : 1},
  347. \ {'short' : 'f', 'long' : 'fields', 'fold' : 0},
  348. \ {'short' : 'g', 'long' : 'enum types', 'fold' : 0},
  349. \ {'short' : 'e', 'long' : 'enum constants', 'fold' : 0},
  350. \ {'short' : 'i', 'long' : 'interfaces', 'fold' : 0},
  351. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  352. \ {'short' : 'm', 'long' : 'methods', 'fold' : 0}
  353. \ ]
  354. let type_java.sro = '.'
  355. let type_java.kind2scope = {
  356. \ 'g' : 'enum',
  357. \ 'i' : 'interface',
  358. \ 'c' : 'class'
  359. \ }
  360. let type_java.scope2kind = {
  361. \ 'enum' : 'g',
  362. \ 'interface' : 'i',
  363. \ 'class' : 'c'
  364. \ }
  365. let s:known_types.java = type_java
  366. " JavaScript {{{3
  367. " JavaScript is weird -- it does have scopes, but ctags doesn't seem to
  368. " properly generate the information for them, instead it simply uses the
  369. " complete name. So ctags has to be fixed before I can do anything here.
  370. " Alternatively jsctags/doctorjs will be used if available.
  371. let type_javascript = {}
  372. let type_javascript.ctagstype = 'javascript'
  373. let jsctags = s:CheckFTCtags('jsctags', 'javascript')
  374. if jsctags != ''
  375. let type_javascript.kinds = [
  376. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0},
  377. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}
  378. \ ]
  379. let type_javascript.sro = '.'
  380. let type_javascript.kind2scope = {
  381. \ 'v' : 'namespace',
  382. \ 'f' : 'namespace'
  383. \ }
  384. let type_javascript.scope2kind = {
  385. \ 'namespace' : 'v'
  386. \ }
  387. let type_javascript.ctagsbin = jsctags
  388. let type_javascript.ctagsargs = '-f -'
  389. else
  390. let type_javascript.kinds = [
  391. \ {'short' : 'v', 'long' : 'global variables', 'fold' : 0},
  392. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  393. \ {'short' : 'p', 'long' : 'properties', 'fold' : 0},
  394. \ {'short' : 'm', 'long' : 'methods', 'fold' : 0},
  395. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}
  396. \ ]
  397. endif
  398. let s:known_types.javascript = type_javascript
  399. " Lisp {{{3
  400. let type_lisp = {}
  401. let type_lisp.ctagstype = 'lisp'
  402. let type_lisp.kinds = [
  403. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}
  404. \ ]
  405. let s:known_types.lisp = type_lisp
  406. " Lua {{{3
  407. let type_lua = {}
  408. let type_lua.ctagstype = 'lua'
  409. let type_lua.kinds = [
  410. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}
  411. \ ]
  412. let s:known_types.lua = type_lua
  413. " Make {{{3
  414. let type_make = {}
  415. let type_make.ctagstype = 'make'
  416. let type_make.kinds = [
  417. \ {'short' : 'm', 'long' : 'macros', 'fold' : 0}
  418. \ ]
  419. let s:known_types.make = type_make
  420. " Matlab {{{3
  421. let type_matlab = {}
  422. let type_matlab.ctagstype = 'matlab'
  423. let type_matlab.kinds = [
  424. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}
  425. \ ]
  426. let s:known_types.matlab = type_matlab
  427. " Ocaml {{{3
  428. let type_ocaml = {}
  429. let type_ocaml.ctagstype = 'ocaml'
  430. let type_ocaml.kinds = [
  431. \ {'short' : 'M', 'long' : 'modules or functors', 'fold' : 0},
  432. \ {'short' : 'v', 'long' : 'global variables', 'fold' : 0},
  433. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  434. \ {'short' : 'C', 'long' : 'constructors', 'fold' : 0},
  435. \ {'short' : 'm', 'long' : 'methods', 'fold' : 0},
  436. \ {'short' : 'e', 'long' : 'exceptions', 'fold' : 0},
  437. \ {'short' : 't', 'long' : 'type names', 'fold' : 0},
  438. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  439. \ {'short' : 'r', 'long' : 'structure fields', 'fold' : 0}
  440. \ ]
  441. let type_ocaml.sro = '.' " Not sure, is nesting even possible?
  442. let type_ocaml.kind2scope = {
  443. \ 'M' : 'Module',
  444. \ 'c' : 'class',
  445. \ 't' : 'type'
  446. \ }
  447. let type_ocaml.scope2kind = {
  448. \ 'Module' : 'M',
  449. \ 'class' : 'c',
  450. \ 'type' : 't'
  451. \ }
  452. let s:known_types.ocaml = type_ocaml
  453. " Pascal {{{3
  454. let type_pascal = {}
  455. let type_pascal.ctagstype = 'pascal'
  456. let type_pascal.kinds = [
  457. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  458. \ {'short' : 'p', 'long' : 'procedures', 'fold' : 0}
  459. \ ]
  460. let s:known_types.pascal = type_pascal
  461. " Perl {{{3
  462. let type_perl = {}
  463. let type_perl.ctagstype = 'perl'
  464. let type_perl.kinds = [
  465. \ {'short' : 'p', 'long' : 'packages', 'fold' : 1},
  466. \ {'short' : 'c', 'long' : 'constants', 'fold' : 0},
  467. \ {'short' : 'f', 'long' : 'formats', 'fold' : 0},
  468. \ {'short' : 'l', 'long' : 'labels', 'fold' : 0},
  469. \ {'short' : 's', 'long' : 'subroutines', 'fold' : 0}
  470. \ ]
  471. let s:known_types.perl = type_perl
  472. " PHP {{{3
  473. let type_php = {}
  474. let type_php.ctagstype = 'php'
  475. let type_php.kinds = [
  476. \ {'short' : 'i', 'long' : 'interfaces', 'fold' : 0},
  477. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  478. \ {'short' : 'd', 'long' : 'constant definitions', 'fold' : 0},
  479. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  480. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0},
  481. \ {'short' : 'j', 'long' : 'javascript functions', 'fold' : 0}
  482. \ ]
  483. let s:known_types.php = type_php
  484. " Python {{{3
  485. let type_python = {}
  486. let type_python.ctagstype = 'python'
  487. let type_python.kinds = [
  488. \ {'short' : 'i', 'long' : 'imports', 'fold' : 1},
  489. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  490. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  491. \ {'short' : 'm', 'long' : 'members', 'fold' : 0},
  492. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}
  493. \ ]
  494. let type_python.sro = '.'
  495. let type_python.kind2scope = {
  496. \ 'c' : 'class',
  497. \ 'f' : 'function',
  498. \ 'm' : 'function'
  499. \ }
  500. let type_python.scope2kind = {
  501. \ 'class' : 'c',
  502. \ 'function' : 'f'
  503. \ }
  504. let s:known_types.python = type_python
  505. " REXX {{{3
  506. let type_rexx = {}
  507. let type_rexx.ctagstype = 'rexx'
  508. let type_rexx.kinds = [
  509. \ {'short' : 's', 'long' : 'subroutines', 'fold' : 0}
  510. \ ]
  511. let s:known_types.rexx = type_rexx
  512. " Ruby {{{3
  513. let type_ruby = {}
  514. let type_ruby.ctagstype = 'ruby'
  515. let type_ruby.kinds = [
  516. \ {'short' : 'm', 'long' : 'modules', 'fold' : 0},
  517. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  518. \ {'short' : 'f', 'long' : 'methods', 'fold' : 0},
  519. \ {'short' : 'F', 'long' : 'singleton methods', 'fold' : 0}
  520. \ ]
  521. let type_ruby.sro = '.'
  522. let type_ruby.kind2scope = {
  523. \ 'c' : 'class',
  524. \ 'm' : 'class'
  525. \ }
  526. let type_ruby.scope2kind = {
  527. \ 'class' : 'c'
  528. \ }
  529. let s:known_types.ruby = type_ruby
  530. " Scheme {{{3
  531. let type_scheme = {}
  532. let type_scheme.ctagstype = 'scheme'
  533. let type_scheme.kinds = [
  534. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  535. \ {'short' : 's', 'long' : 'sets', 'fold' : 0}
  536. \ ]
  537. let s:known_types.scheme = type_scheme
  538. " Shell script {{{3
  539. let type_sh = {}
  540. let type_sh.ctagstype = 'sh'
  541. let type_sh.kinds = [
  542. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}
  543. \ ]
  544. let s:known_types.sh = type_sh
  545. let s:known_types.csh = type_sh
  546. let s:known_types.zsh = type_sh
  547. " SLang {{{3
  548. let type_slang = {}
  549. let type_slang.ctagstype = 'slang'
  550. let type_slang.kinds = [
  551. \ {'short' : 'n', 'long' : 'namespaces', 'fold' : 0},
  552. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0}
  553. \ ]
  554. let s:known_types.slang = type_slang
  555. " SML {{{3
  556. let type_sml = {}
  557. let type_sml.ctagstype = 'sml'
  558. let type_sml.kinds = [
  559. \ {'short' : 'e', 'long' : 'exception declarations', 'fold' : 0},
  560. \ {'short' : 'f', 'long' : 'function definitions', 'fold' : 0},
  561. \ {'short' : 'c', 'long' : 'functor definitions', 'fold' : 0},
  562. \ {'short' : 's', 'long' : 'signature declarations', 'fold' : 0},
  563. \ {'short' : 'r', 'long' : 'structure declarations', 'fold' : 0},
  564. \ {'short' : 't', 'long' : 'type definitions', 'fold' : 0},
  565. \ {'short' : 'v', 'long' : 'value bindings', 'fold' : 0}
  566. \ ]
  567. let s:known_types.sml = type_sml
  568. " SQL {{{3
  569. " The SQL ctags parser seems to be buggy for me, so this just uses the
  570. " normal kinds even though scopes should be available. Improvements
  571. " welcome!
  572. let type_sql = {}
  573. let type_sql.ctagstype = 'sql'
  574. let type_sql.kinds = [
  575. \ {'short' : 'P', 'long' : 'packages', 'fold' : 1},
  576. \ {'short' : 'c', 'long' : 'cursors', 'fold' : 0},
  577. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  578. \ {'short' : 'F', 'long' : 'record fields', 'fold' : 0},
  579. \ {'short' : 'L', 'long' : 'block label', 'fold' : 0},
  580. \ {'short' : 'p', 'long' : 'procedures', 'fold' : 0},
  581. \ {'short' : 's', 'long' : 'subtypes', 'fold' : 0},
  582. \ {'short' : 't', 'long' : 'tables', 'fold' : 0},
  583. \ {'short' : 'T', 'long' : 'triggers', 'fold' : 0},
  584. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0},
  585. \ {'short' : 'i', 'long' : 'indexes', 'fold' : 0},
  586. \ {'short' : 'e', 'long' : 'events', 'fold' : 0},
  587. \ {'short' : 'U', 'long' : 'publications', 'fold' : 0},
  588. \ {'short' : 'R', 'long' : 'services', 'fold' : 0},
  589. \ {'short' : 'D', 'long' : 'domains', 'fold' : 0},
  590. \ {'short' : 'V', 'long' : 'views', 'fold' : 0},
  591. \ {'short' : 'n', 'long' : 'synonyms', 'fold' : 0},
  592. \ {'short' : 'x', 'long' : 'MobiLink Table Scripts', 'fold' : 0},
  593. \ {'short' : 'y', 'long' : 'MobiLink Conn Scripts', 'fold' : 0}
  594. \ ]
  595. let s:known_types.sql = type_sql
  596. " Tcl {{{3
  597. let type_tcl = {}
  598. let type_tcl.ctagstype = 'tcl'
  599. let type_tcl.kinds = [
  600. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  601. \ {'short' : 'm', 'long' : 'methods', 'fold' : 0},
  602. \ {'short' : 'p', 'long' : 'procedures', 'fold' : 0}
  603. \ ]
  604. let s:known_types.tcl = type_tcl
  605. " LaTeX {{{3
  606. let type_tex = {}
  607. let type_tex.ctagstype = 'tex'
  608. let type_tex.kinds = [
  609. \ {'short' : 'p', 'long' : 'parts', 'fold' : 0},
  610. \ {'short' : 'c', 'long' : 'chapters', 'fold' : 0},
  611. \ {'short' : 's', 'long' : 'sections', 'fold' : 0},
  612. \ {'short' : 'u', 'long' : 'subsections', 'fold' : 0},
  613. \ {'short' : 'b', 'long' : 'subsubsections', 'fold' : 0},
  614. \ {'short' : 'P', 'long' : 'paragraphs', 'fold' : 0},
  615. \ {'short' : 'G', 'long' : 'subparagraphs', 'fold' : 0}
  616. \ ]
  617. let s:known_types.tex = type_tex
  618. " Vera {{{3
  619. " Why are variables 'virtual'?
  620. let type_vera = {}
  621. let type_vera.ctagstype = 'vera'
  622. let type_vera.kinds = [
  623. \ {'short' : 'd', 'long' : 'macros', 'fold' : 1},
  624. \ {'short' : 'g', 'long' : 'enums', 'fold' : 0},
  625. \ {'short' : 'T', 'long' : 'typedefs', 'fold' : 0},
  626. \ {'short' : 'c', 'long' : 'classes', 'fold' : 0},
  627. \ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0},
  628. \ {'short' : 'm', 'long' : 'members', 'fold' : 0},
  629. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  630. \ {'short' : 't', 'long' : 'tasks', 'fold' : 0},
  631. \ {'short' : 'v', 'long' : 'variables', 'fold' : 0},
  632. \ {'short' : 'p', 'long' : 'programs', 'fold' : 0}
  633. \ ]
  634. let type_vera.sro = '.' " Nesting doesn't seem to be possible
  635. let type_vera.kind2scope = {
  636. \ 'g' : 'enum',
  637. \ 'c' : 'class',
  638. \ 'v' : 'virtual'
  639. \ }
  640. let type_vera.scope2kind = {
  641. \ 'enum' : 'g',
  642. \ 'class' : 'c',
  643. \ 'virtual' : 'v'
  644. \ }
  645. let s:known_types.vera = type_vera
  646. " Verilog {{{3
  647. let type_verilog = {}
  648. let type_verilog.ctagstype = 'verilog'
  649. let type_verilog.kinds = [
  650. \ {'short' : 'c', 'long' : 'constants', 'fold' : 0},
  651. \ {'short' : 'e', 'long' : 'events', 'fold' : 0},
  652. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  653. \ {'short' : 'm', 'long' : 'modules', 'fold' : 0},
  654. \ {'short' : 'n', 'long' : 'net data types', 'fold' : 0},
  655. \ {'short' : 'p', 'long' : 'ports', 'fold' : 0},
  656. \ {'short' : 'r', 'long' : 'register data types', 'fold' : 0},
  657. \ {'short' : 't', 'long' : 'tasks', 'fold' : 0}
  658. \ ]
  659. let s:known_types.verilog = type_verilog
  660. " VHDL {{{3
  661. " The VHDL ctags parser unfortunately doesn't generate proper scopes
  662. let type_vhdl = {}
  663. let type_vhdl.ctagstype = 'vhdl'
  664. let type_vhdl.kinds = [
  665. \ {'short' : 'P', 'long' : 'packages', 'fold' : 1},
  666. \ {'short' : 'c', 'long' : 'constants', 'fold' : 0},
  667. \ {'short' : 't', 'long' : 'types', 'fold' : 0},
  668. \ {'short' : 'T', 'long' : 'subtypes', 'fold' : 0},
  669. \ {'short' : 'r', 'long' : 'records', 'fold' : 0},
  670. \ {'short' : 'e', 'long' : 'entities', 'fold' : 0},
  671. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  672. \ {'short' : 'p', 'long' : 'procedures', 'fold' : 0}
  673. \ ]
  674. let s:known_types.vhdl = type_vhdl
  675. " Vim {{{3
  676. let type_vim = {}
  677. let type_vim.ctagstype = 'vim'
  678. let type_vim.kinds = [
  679. \ {'short' : 'v', 'long' : 'variables', 'fold' : 1},
  680. \ {'short' : 'f', 'long' : 'functions', 'fold' : 0},
  681. \ {'short' : 'a', 'long' : 'autocommand groups', 'fold' : 1},
  682. \ {'short' : 'c', 'long' : 'commands', 'fold' : 0},
  683. \ {'short' : 'm', 'long' : 'maps', 'fold' : 1}
  684. \ ]
  685. let s:known_types.vim = type_vim
  686. " YACC {{{3
  687. let type_yacc = {}
  688. let type_yacc.ctagstype = 'yacc'
  689. let type_yacc.kinds = [
  690. \ {'short' : 'l', 'long' : 'labels', 'fold' : 0}
  691. \ ]
  692. let s:known_types.yacc = type_yacc
  693. " }}}3
  694. let user_defs = s:GetUserTypeDefs()
  695. for [key, value] in items(user_defs)
  696. if !has_key(s:known_types, key) ||
  697. \ (has_key(value, 'replace') && value.replace)
  698. let s:known_types[key] = value
  699. else
  700. call extend(s:known_types[key], value)
  701. endif
  702. endfor
  703. " Create a dictionary of the kind order for fast
  704. " access in sorting functions
  705. for type in values(s:known_types)
  706. let i = 0
  707. let type.kinddict = {}
  708. for kind in type.kinds
  709. let type.kinddict[kind.short] = i
  710. let i += 1
  711. endfor
  712. endfor
  713. let s:type_init_done = 1
  714. endfunction
  715. " s:GetUserTypeDefs() {{{2
  716. function! s:GetUserTypeDefs()
  717. call s:LogDebugMessage('Initializing user types')
  718. redir => defs
  719. silent execute 'let g:'
  720. redir END
  721. let deflist = split(defs, '\n')
  722. call map(deflist, 'substitute(v:val, ''^\S\+\zs.*'', "", "")')
  723. call filter(deflist, 'v:val =~ "^tagbar_type_"')
  724. let defdict = {}
  725. for defstr in deflist
  726. let type = substitute(defstr, '^tagbar_type_', '', '')
  727. execute 'let defdict["' . type . '"] = g:' . defstr
  728. endfor
  729. " If the user only specified one of kind2scope and scope2kind use it to
  730. " generate the other one
  731. " Also, transform the 'kind' definitions into dictionary format
  732. for def in values(defdict)
  733. if has_key(def, 'kinds')
  734. let kinds = def.kinds
  735. let def.kinds = []
  736. for kind in kinds
  737. let kindlist = split(kind, ':')
  738. let kinddict = {'short' : kindlist[0], 'long' : kindlist[1]}
  739. if len(kindlist) == 3
  740. let kinddict.fold = kindlist[2]
  741. else
  742. let kinddict.fold = 0
  743. endif
  744. call add(def.kinds, kinddict)
  745. endfor
  746. endif
  747. if has_key(def, 'kind2scope') && !has_key(def, 'scope2kind')
  748. let def.scope2kind = {}
  749. for [key, value] in items(def.kind2scope)
  750. let def.scope2kind[value] = key
  751. endfor
  752. elseif has_key(def, 'scope2kind') && !has_key(def, 'kind2scope')
  753. let def.kind2scope = {}
  754. for [key, value] in items(def.scope2kind)
  755. let def.kind2scope[value] = key
  756. endfor
  757. endif
  758. endfor
  759. return defdict
  760. endfunction
  761. " s:RestoreSession() {{{2
  762. " Properly restore Tagbar after a session got loaded
  763. function! s:RestoreSession()
  764. call s:LogDebugMessage('Restoring session')
  765. let tagbarwinnr = bufwinnr('__Tagbar__')
  766. if tagbarwinnr == -1
  767. " Tagbar wasn't open in the saved session, nothing to do
  768. return
  769. else
  770. let in_tagbar = 1
  771. if winnr() != tagbarwinnr
  772. execute tagbarwinnr . 'wincmd w'
  773. let in_tagbar = 0
  774. endif
  775. endif
  776. call s:Init()
  777. call s:InitWindow(g:tagbar_autoclose)
  778. " Leave the Tagbar window and come back so the update event gets triggered
  779. wincmd p
  780. execute tagbarwinnr . 'wincmd w'
  781. if !in_tagbar
  782. wincmd p
  783. endif
  784. endfunction
  785. " s:MapKeys() {{{2
  786. function! s:MapKeys()
  787. call s:LogDebugMessage('Mapping keys')
  788. nnoremap <script> <silent> <buffer> <2-LeftMouse>
  789. \ :call <SID>JumpToTag(0)<CR>
  790. nnoremap <script> <silent> <buffer> <LeftRelease>
  791. \ <LeftRelease>:call <SID>CheckMouseClick()<CR>
  792. inoremap <script> <silent> <buffer> <2-LeftMouse>
  793. \ <C-o>:call <SID>JumpToTag(0)<CR>
  794. inoremap <script> <silent> <buffer> <LeftRelease>
  795. \ <LeftRelease><C-o>:call <SID>CheckMouseClick()<CR>
  796. nnoremap <script> <silent> <buffer> <CR> :call <SID>JumpToTag(0)<CR>
  797. nnoremap <script> <silent> <buffer> p :call <SID>JumpToTag(1)<CR>
  798. nnoremap <script> <silent> <buffer> <Space> :call <SID>ShowPrototype()<CR>
  799. nnoremap <script> <silent> <buffer> + :call <SID>OpenFold()<CR>
  800. nnoremap <script> <silent> <buffer> <kPlus> :call <SID>OpenFold()<CR>
  801. nnoremap <script> <silent> <buffer> zo :call <SID>OpenFold()<CR>
  802. nnoremap <script> <silent> <buffer> - :call <SID>CloseFold()<CR>
  803. nnoremap <script> <silent> <buffer> <kMinus> :call <SID>CloseFold()<CR>
  804. nnoremap <script> <silent> <buffer> zc :call <SID>CloseFold()<CR>
  805. nnoremap <script> <silent> <buffer> o :call <SID>ToggleFold()<CR>
  806. nnoremap <script> <silent> <buffer> za :call <SID>ToggleFold()<CR>
  807. nnoremap <script> <silent> <buffer> * :call <SID>SetFoldLevel(99)<CR>
  808. nnoremap <script> <silent> <buffer> <kMultiply>
  809. \ :call <SID>SetFoldLevel(99)<CR>
  810. nnoremap <script> <silent> <buffer> zR :call <SID>SetFoldLevel(99)<CR>
  811. nnoremap <script> <silent> <buffer> = :call <SID>SetFoldLevel(0)<CR>
  812. nnoremap <script> <silent> <buffer> zM :call <SID>SetFoldLevel(0)<CR>
  813. nnoremap <script> <silent> <buffer> <C-N>
  814. \ :call <SID>GotoNextToplevelTag(1)<CR>
  815. nnoremap <script> <silent> <buffer> <C-P>
  816. \ :call <SID>GotoNextToplevelTag(-1)<CR>
  817. nnoremap <script> <silent> <buffer> s :call <SID>ToggleSort()<CR>
  818. nnoremap <script> <silent> <buffer> x :call <SID>ZoomWindow()<CR>
  819. nnoremap <script> <silent> <buffer> q :call <SID>CloseWindow()<CR>
  820. nnoremap <script> <silent> <buffer> <F1> :call <SID>ToggleHelp()<CR>
  821. endfunction
  822. " s:CreateAutocommands() {{{2
  823. function! s:CreateAutocommands()
  824. call s:LogDebugMessage('Creating autocommands')
  825. augroup TagbarAutoCmds
  826. autocmd!
  827. autocmd BufEnter __Tagbar__ nested call s:QuitIfOnlyWindow()
  828. autocmd BufUnload __Tagbar__ call s:CleanUp()
  829. autocmd CursorHold __Tagbar__ call s:ShowPrototype()
  830. autocmd BufWritePost *
  831. \ if line('$') < g:tagbar_updateonsave_maxlines |
  832. \ call s:AutoUpdate(fnamemodify(expand('<afile>'), ':p')) |
  833. \ endif
  834. autocmd BufEnter,CursorHold,FileType * call
  835. \ s:AutoUpdate(fnamemodify(expand('<afile>'), ':p'))
  836. autocmd BufDelete * call
  837. \ s:CleanupFileinfo(fnamemodify(expand('<afile>'), ':p'))
  838. augroup END
  839. let s:autocommands_done = 1
  840. endfunction
  841. " s:CheckForExCtags() {{{2
  842. " Test whether the ctags binary is actually Exuberant Ctags and not GNU ctags
  843. " (or something else)
  844. function! s:CheckForExCtags()
  845. call s:LogDebugMessage('Checking for Exuberant Ctags')
  846. let ctags_cmd = s:EscapeCtagsCmd(g:tagbar_ctags_bin, '--version')
  847. if ctags_cmd == ''
  848. return
  849. endif
  850. let ctags_output = s:ExecuteCtags(ctags_cmd)
  851. if v:shell_error || ctags_output !~# 'Exuberant Ctags'
  852. echoerr 'Tagbar: Ctags doesn''t seem to be Exuberant Ctags!'
  853. echomsg 'GNU ctags will NOT WORK.'
  854. \ 'Please download Exuberant Ctags from ctags.sourceforge.net'
  855. \ 'and install it in a directory in your $PATH'
  856. \ 'or set g:tagbar_ctags_bin.'
  857. echomsg 'Executed command: "' . ctags_cmd . '"'
  858. if !empty(ctags_output)
  859. echomsg 'Command output:'
  860. for line in split(ctags_output, '\n')
  861. echomsg line
  862. endfor
  863. endif
  864. return 0
  865. elseif !s:CheckExCtagsVersion(ctags_output)
  866. echoerr 'Tagbar: Exuberant Ctags is too old!'
  867. echomsg 'You need at least version 5.5 for Tagbar to work.'
  868. \ 'Please download a newer version from ctags.sourceforge.net.'
  869. echomsg 'Executed command: "' . ctags_cmd . '"'
  870. if !empty(ctags_output)
  871. echomsg 'Command output:'
  872. for line in split(ctags_output, '\n')
  873. echomsg line
  874. endfor
  875. endif
  876. return 0
  877. else
  878. let s:checked_ctags = 1
  879. return 1
  880. endif
  881. endfunction
  882. " s:CheckExCtagsVersion() {{{2
  883. function! s:CheckExCtagsVersion(output)
  884. call s:LogDebugMessage('Checking Exuberant Ctags version')
  885. if a:output =~ 'Exuberant Ctags Development'
  886. return 1
  887. endif
  888. let matchlist = matchlist(a:output, '\vExuberant Ctags (\d+)\.(\d+)')
  889. let major = matchlist[1]
  890. let minor = matchlist[2]
  891. return major >= 6 || (major == 5 && minor >= 5)
  892. endfunction
  893. " s:CheckFTCtags() {{{2
  894. function! s:CheckFTCtags(bin, ftype)
  895. if executable(a:bin)
  896. return a:bin
  897. endif
  898. if exists('g:tagbar_type_' . a:ftype)
  899. execute 'let userdef = ' . 'g:tagbar_type_' . a:ftype
  900. if has_key(userdef, 'ctagsbin')
  901. return userdef.ctagsbin
  902. else
  903. return ''
  904. endif
  905. endif
  906. return ''
  907. endfunction
  908. " Prototypes {{{1
  909. " Base tag {{{2
  910. let s:BaseTag = {}
  911. " s:BaseTag._init() {{{3
  912. function! s:BaseTag._init(name) dict
  913. let self.name = a:name
  914. let self.fields = {}
  915. let self.fields.line = 0
  916. let self.path = ''
  917. let self.fullpath = a:name
  918. let self.depth = 0
  919. let self.parent = {}
  920. let self.tline = -1
  921. let self.fileinfo = {}
  922. endfunction
  923. " s:BaseTag.isNormalTag() {{{3
  924. function! s:BaseTag.isNormalTag() dict
  925. return 0
  926. endfunction
  927. " s:BaseTag.isPseudoTag() {{{3
  928. function! s:BaseTag.isPseudoTag() dict
  929. return 0
  930. endfunction
  931. " s:BaseTag.isKindheader() {{{3
  932. function! s:BaseTag.isKindheader() dict
  933. return 0
  934. endfunction
  935. " s:BaseTag.getPrototype() {{{3
  936. function! s:BaseTag.getPrototype() dict
  937. return ''
  938. endfunction
  939. " s:BaseTag._getPrefix() {{{3
  940. function! s:BaseTag._getPrefix() dict
  941. let fileinfo = self.fileinfo
  942. if has_key(self, 'children') && !empty(self.children)
  943. if fileinfo.tagfolds[self.fields.kind][self.fullpath]
  944. let prefix = s:icon_closed
  945. else
  946. let prefix = s:icon_open
  947. endif
  948. else
  949. let prefix = ' '
  950. endif
  951. if has_key(self.fields, 'access')
  952. let prefix .= get(s:access_symbols, self.fields.access, ' ')
  953. else
  954. let prefix .= ' '
  955. endif
  956. return prefix
  957. endfunction
  958. " s:BaseTag.initFoldState() {{{3
  959. function! s:BaseTag.initFoldState() dict
  960. let fileinfo = self.fileinfo
  961. if s:known_files.has(fileinfo.fpath) &&
  962. \ has_key(fileinfo._tagfolds_old[self.fields.kind], self.fullpath)
  963. " The file has been updated and the tag was there before, so copy its
  964. " old fold state
  965. let fileinfo.tagfolds[self.fields.kind][self.fullpath] =
  966. \ fileinfo._tagfolds_old[self.fields.kind][self.fullpath]
  967. elseif self.depth >= fileinfo.foldlevel
  968. let fileinfo.tagfolds[self.fields.kind][self.fullpath] = 1
  969. else
  970. let fileinfo.tagfolds[self.fields.kind][self.fullpath] =
  971. \ fileinfo.kindfolds[self.fields.kind]
  972. endif
  973. endfunction
  974. " s:BaseTag.getClosedParentTline() {{{3
  975. function! s:BaseTag.getClosedParentTline() dict
  976. let tagline = self.tline
  977. let fileinfo = self.fileinfo
  978. let parent = self.parent
  979. while !empty(parent)
  980. if parent.isFolded()
  981. let tagline = parent.tline
  982. break
  983. endif
  984. let parent = parent.parent
  985. endwhile
  986. return tagline
  987. endfunction
  988. " s:BaseTag.isFoldable() {{{3
  989. function! s:BaseTag.isFoldable() dict
  990. return has_key(self, 'children') && !empty(self.children)
  991. endfunction
  992. " s:BaseTag.isFolded() {{{3
  993. function! s:BaseTag.isFolded() dict
  994. return self.fileinfo.tagfolds[self.fields.kind][self.fullpath]
  995. endfunction
  996. " s:BaseTag.openFold() {{{3
  997. function! s:BaseTag.openFold() dict
  998. if self.isFoldable()
  999. let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = 0
  1000. endif
  1001. endfunction
  1002. " s:BaseTag.closeFold() {{{3
  1003. function! s:BaseTag.closeFold() dict
  1004. let newline = line('.')
  1005. if !empty(self.parent) && self.parent.isKindheader()
  1006. " Tag is child of generic 'kind'
  1007. call self.parent.closeFold()
  1008. let newline = self.parent.tline
  1009. elseif self.isFoldable() && !self.isFolded()
  1010. " Tag is parent of a scope and is not folded
  1011. let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = 1
  1012. let newline = self.tline
  1013. elseif !empty(self.parent)
  1014. " Tag is normal child, so close parent
  1015. let parent = self.parent
  1016. let self.fileinfo.tagfolds[parent.fields.kind][parent.fullpath] = 1
  1017. let newline = parent.tline
  1018. endif
  1019. return newline
  1020. endfunction
  1021. " s:BaseTag.setFolded() {{{3
  1022. function! s:BaseTag.setFolded(folded) dict
  1023. let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = a:folded
  1024. endfunction
  1025. " s:BaseTag.openParents() {{{3
  1026. function! s:BaseTag.openParents() dict
  1027. let parent = self.parent
  1028. while !empty(parent)
  1029. call parent.openFold()
  1030. let parent = parent.parent
  1031. endwhile
  1032. endfunction
  1033. " Normal tag {{{2
  1034. let s:NormalTag = copy(s:BaseTag)
  1035. " s:NormalTag.New() {{{3
  1036. function! s:NormalTag.New(name) dict
  1037. let newobj = copy(self)
  1038. call newobj._init(a:name)
  1039. return newobj
  1040. endfunction
  1041. " s:NormalTag.isNormalTag() {{{3
  1042. function! s:NormalTag.isNormalTag() dict
  1043. return 1
  1044. endfunction
  1045. " s:NormalTag.str() {{{3
  1046. function! s:NormalTag.str() dict
  1047. let fileinfo = self.fileinfo
  1048. let typeinfo = s:known_types[fileinfo.ftype]
  1049. let suffix = get(self.fields, 'signature', '')
  1050. if has_key(self.fields, 'type')
  1051. let suffix .= ' : ' . self.fields.type
  1052. elseif has_key(typeinfo, 'kind2scope') &&
  1053. \ has_key(typeinfo.kind2scope, self.fields.kind)
  1054. let suffix .= ' : ' . typeinfo.kind2scope[self.fields.kind]
  1055. endif
  1056. return self._getPrefix() . self.name . suffix . "\n"
  1057. endfunction
  1058. " s:NormalTag.getPrototype() {{{3
  1059. function! s:NormalTag.getPrototype() dict
  1060. return self.prototype
  1061. endfunction
  1062. " Pseudo tag {{{2
  1063. let s:PseudoTag = copy(s:BaseTag)
  1064. " s:PseudoTag.New() {{{3
  1065. function! s:PseudoTag.New(name) dict
  1066. let newobj = copy(self)
  1067. call newobj._init(a:name)
  1068. return newobj
  1069. endfunction
  1070. " s:PseudoTag.isPseudoTag() {{{3
  1071. function! s:PseudoTag.isPseudoTag() dict
  1072. return 1
  1073. endfunction
  1074. " s:PseudoTag.str() {{{3
  1075. function! s:PseudoTag.str() dict
  1076. let fileinfo = self.fileinfo
  1077. let typeinfo = s:known_types[fileinfo.ftype]
  1078. let suffix = get(self.fields, 'signature', '')
  1079. if has_key(typeinfo.kind2scope, self.fields.kind)
  1080. let suffix .= ' : ' . typeinfo.kind2scope[self.fields.kind]
  1081. endif
  1082. return self._getPrefix() . self.name . '*' . suffix
  1083. endfunction
  1084. " Kind header {{{2
  1085. let s:KindheaderTag = copy(s:BaseTag)
  1086. " s:KindheaderTag.New() {{{3
  1087. function! s:KindheaderTag.New(name) dict
  1088. let newobj = copy(self)
  1089. call newobj._init(a:name)
  1090. return newobj
  1091. endfunction
  1092. " s:KindheaderTag.isKindheader() {{{3
  1093. function! s:KindheaderTag.isKindheader() dict
  1094. return 1
  1095. endfunction
  1096. " s:KindheaderTag.getPrototype() {{{3
  1097. function! s:KindheaderTag.getPrototype() dict
  1098. return self.name . ': ' .
  1099. \ self.numtags . ' ' . (self.numtags > 1 ? 'tags' : 'tag')
  1100. endfunction
  1101. " s:KindheaderTag.isFoldable() {{{3
  1102. function! s:KindheaderTag.isFoldable() dict
  1103. return 1
  1104. endfunction
  1105. " s:KindheaderTag.isFolded() {{{3
  1106. function! s:KindheaderTag.isFolded() dict
  1107. return self.fileinfo.kindfolds[self.short]
  1108. endfunction
  1109. " s:KindheaderTag.openFold() {{{3
  1110. function! s:KindheaderTag.openFold() dict
  1111. let self.fileinfo.kindfolds[self.short] = 0
  1112. endfunction
  1113. " s:KindheaderTag.closeFold() {{{3
  1114. function! s:KindheaderTag.closeFold() dict
  1115. let self.fileinfo.kindfolds[self.short] = 1
  1116. return line('.')
  1117. endfunction
  1118. " s:KindheaderTag.toggleFold() {{{3
  1119. function! s:KindheaderTag.toggleFold() dict
  1120. let fileinfo = s:known_files.getCurrent()
  1121. let fileinfo.kindfolds[self.short] = !fileinfo.kindfolds[self.short]
  1122. endfunction
  1123. " File info {{{2
  1124. let s:FileInfo = {}
  1125. " s:FileInfo.New() {{{3
  1126. function! s:FileInfo.New(fname, ftype) dict
  1127. let newobj = copy(self)
  1128. " The complete file path
  1129. let newobj.fpath = a:fname
  1130. " File modification time
  1131. let newobj.mtime = getftime(a:fname)
  1132. " The vim file type
  1133. let newobj.ftype = a:ftype
  1134. " List of the tags that are present in the file, sorted according to the
  1135. " value of 'g:tagbar_sort'
  1136. let newobj.tags = []
  1137. " Dictionary of the tags, indexed by line number in the file
  1138. let newobj.fline = {}
  1139. " Dictionary of the tags, indexed by line number in the tagbar
  1140. let newobj.tline = {}
  1141. " Dictionary of the folding state of 'kind's, indexed by short name
  1142. let newobj.kindfolds = {}
  1143. let typeinfo = s:known_types[a:ftype]
  1144. " copy the default fold state from the type info
  1145. for kind in typeinfo.kinds
  1146. let newobj.kindfolds[kind.short] =
  1147. \ g:tagbar_foldlevel == 0 ? 1 : kind.fold
  1148. endfor
  1149. " Dictionary of dictionaries of the folding state of individual tags,
  1150. " indexed by kind and full path
  1151. let newobj.tagfolds = {}
  1152. for kind in typeinfo.kinds
  1153. let newobj.tagfolds[kind.short] = {}
  1154. endfor
  1155. " The current foldlevel of the file
  1156. let newobj.foldlevel = g:tagbar_foldlevel
  1157. return newobj
  1158. endfunction
  1159. " s:FileInfo.reset() {{{3
  1160. " Reset stuff that gets regenerated while processing a file and save the old
  1161. " tag folds
  1162. function! s:FileInfo.reset() dict
  1163. let self.mtime = getftime(self.fpath)
  1164. let self.tags = []
  1165. let self.fline = {}
  1166. let self.tline = {}
  1167. let self._tagfolds_old = self.tagfolds
  1168. let self.tagfolds = {}
  1169. let typeinfo = s:known_types[self.ftype]
  1170. for kind in typeinfo.kinds
  1171. let self.tagfolds[kind.short] = {}
  1172. endfor
  1173. endfunction
  1174. " s:FileInfo.clearOldFolds() {{{3
  1175. function! s:FileInfo.clearOldFolds() dict
  1176. if exists('self._tagfolds_old')
  1177. unlet self._tagfolds_old
  1178. endif
  1179. endfunction
  1180. " s:FileInfo.sortTags() {{{3
  1181. function! s:FileInfo.sortTags() dict
  1182. if has_key(s:compare_typeinfo, 'sort')
  1183. if s:compare_typeinfo.sort
  1184. call s:SortTags(self.tags, 's:CompareByKind')
  1185. else
  1186. call s:SortTags(self.tags, 's:CompareByLine')
  1187. endif
  1188. elseif g:tagbar_sort
  1189. call s:SortTags(self.tags, 's:CompareByKind')
  1190. else
  1191. call s:SortTags(self.tags, 's:CompareByLine')
  1192. endif
  1193. endfunction
  1194. " s:FileInfo.openKindFold() {{{3
  1195. function! s:FileInfo.openKindFold(kind) dict
  1196. let self.kindfolds[a:kind.short] = 0
  1197. endfunction
  1198. " s:FileInfo.closeKindFold() {{{3
  1199. function! s:FileInfo.closeKindFold(kind) dict
  1200. let self.kindfolds[a:kind.short] = 1
  1201. endfunction
  1202. " Known files {{{2
  1203. let s:known_files = {
  1204. \ '_current' : {},
  1205. \ '_files' : {}
  1206. \ }
  1207. " s:known_files.getCurrent() {{{3
  1208. function! s:known_files.getCurrent() dict
  1209. return self._current
  1210. endfunction
  1211. " s:known_files.setCurrent() {{{3
  1212. function! s:known_files.setCurrent(fileinfo) dict
  1213. let self._current = a:fileinfo
  1214. endfunction
  1215. " s:known_files.get() {{{3
  1216. function! s:known_files.get(fname) dict
  1217. return get(self._files, a:fname, {})
  1218. endfunction
  1219. " s:known_files.put() {{{3
  1220. " Optional second argument is the filename
  1221. function! s:known_files.put(fileinfo, ...) dict
  1222. if a:0 == 1
  1223. let self._files[a:1] = a:fileinfo
  1224. else
  1225. let fname = a:fileinfo.fpath
  1226. let self._files[fname] = a:fileinfo
  1227. endif
  1228. endfunction
  1229. " s:known_files.has() {{{3
  1230. function! s:known_files.has(fname) dict
  1231. return has_key(self._files, a:fname)
  1232. endfunction
  1233. " s:known_files.rm() {{{3
  1234. function! s:known_files.rm(fname) dict
  1235. if s:known_files.has(a:fname)
  1236. call remove(self._files, a:fname)
  1237. endif
  1238. endfunction
  1239. " Window management {{{1
  1240. " s:ToggleWindow() {{{2
  1241. function! s:ToggleWindow()
  1242. let tagbarwinnr = bufwinnr("__Tagbar__")
  1243. if tagbarwinnr != -1
  1244. call s:CloseWindow()
  1245. return
  1246. endif
  1247. call s:OpenWindow('')
  1248. endfunction
  1249. " s:OpenWindow() {{{2
  1250. function! s:OpenWindow(flags)
  1251. let autofocus = a:flags =~# 'f'
  1252. let jump = a:flags =~# 'j'
  1253. let autoclose = a:flags =~# 'c'
  1254. " If the tagbar window is already open check jump flag
  1255. " Also set the autoclose flag if requested
  1256. let tagbarwinnr = bufwinnr('__Tagbar__')
  1257. if tagbarwinnr != -1
  1258. if winnr() != tagbarwinnr && jump
  1259. execute tagbarwinnr . 'wincmd w'
  1260. if autoclose
  1261. let w:autoclose = autoclose
  1262. endif
  1263. endif
  1264. return
  1265. endif
  1266. call s:Init()
  1267. " Expand the Vim window to accomodate for the Tagbar window if requested
  1268. if g:tagbar_expand && !s:window_expanded && has('gui_running')
  1269. let &columns += g:tagbar_width + 1
  1270. let s:window_expanded = 1
  1271. endif
  1272. let eventignore_save = &eventignore
  1273. set eventignore=all
  1274. let openpos = g:tagbar_left ? 'topleft vertical ' : 'botright vertical '
  1275. exe 'silent keepalt ' . openpos . g:tagbar_width . 'split ' . '__Tagbar__'
  1276. let &eventignore = eventignore_save
  1277. call s:InitWindow(autoclose)
  1278. wincmd p
  1279. " Jump back to the tagbar window if autoclose or autofocus is set. Can't
  1280. " just stay in it since it wouldn't trigger the update event
  1281. if g:tagbar_autoclose || autofocus || g:tagbar_autofocus
  1282. let tagbarwinnr = bufwinnr('__Tagbar__')
  1283. execute tagbarwinnr . 'wincmd w'
  1284. endif
  1285. endfunction
  1286. " s:InitWindow() {{{2
  1287. function! s:InitWindow(autoclose)
  1288. setlocal noreadonly " in case the "view" mode is used
  1289. setlocal buftype=nofile
  1290. setlocal bufhidden=hide
  1291. setlocal noswapfile
  1292. setlocal nobuflisted
  1293. setlocal nomodifiable
  1294. setlocal filetype=tagbar
  1295. setlocal nolist
  1296. setlocal nonumber
  1297. setlocal nowrap
  1298. setlocal winfixwidth
  1299. setlocal textwidth=0
  1300. setlocal nocursorline
  1301. setlocal nocursorcolumn
  1302. if exists('+relativenumber')
  1303. setlocal norelativenumber
  1304. endif
  1305. setlocal nofoldenable
  1306. setlocal foldcolumn=0
  1307. " Reset fold settings in case a plugin set them globally to something
  1308. " expensive. Apparently 'foldexpr' gets executed even if 'foldenable' is
  1309. " off, and then for every appended line (like with :put).
  1310. setlocal foldmethod&
  1311. setlocal fo