2 " Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
4 " Last Modified: Feb 10, 2003
8 " The "Tag List" plugin can be used to efficiently browse through your
9 " source files. The "Tag List" plugin provides the following features:
11 " 1. Opens a vertically/horizontally split Vim window with a list of tags
12 " (functions, classes, structures, variables, etc) defined in the current
14 " 2. Groups the tags by their type and displays them in a foldable tree.
15 " 3. Automatically updates the taglist window as you switch between
17 " 4. When a tag name is selected from the taglist window, positions the cursor
18 " at the definition of the tag in the source file
19 " 5. Automatically highlights the current tag name.
20 " 6. Can display the prototype of a tag from the taglist window.
21 " 7. Displays the scope of a tag.
22 " 8. Can optionally use the tag prototype instead of the tag name.
23 " 9. The tag list can be sorted either by name or by line number.
24 " 10. Supports the following language files: Assembly, ASP, Awk, C, C++,
25 " Cobol, Eiffel, Fortran, Java, Lisp, Lua, Make, Pascal, Perl, PHP,
26 " Python, Rexx, Ruby, Scheme, Shell, Slang, Sql, TCL, Verilog, Vim and
28 " 11. Runs in all the platforms where the exuberant ctags utility and Vim are
29 " supported (this includes MS-Windows and Unix based systems).
30 " 12. Runs in both console/terminal and GUI versions of Vim.
31 " 13. The ctags output for a file is cached to speed up displaying the taglist
33 " 14. Works with the winmanager plugin. Using the winmanager plugin, you can
34 " use multiple Vim plugins at the same time efficiently.
35 " 15. Can be easily extended to support new languages. Support for existing
36 " languages can be modified easily.
38 " To see the screenshots of the taglist plugin in different environments,
39 " visit the following page:
41 " http://www.geocities.com/yegappan/taglist/screenshots.html
43 " This plugin relies on the exuberant ctags utility to dynamically generate
44 " the tag listing. You can download the exuberant ctags utility from
46 " http://ctags.sourceforge.net.
48 " The exuberant ctags utility must be installed in your system to use this
49 " plugin. You should use exuberant ctags version 5.0 and above. This plugin
50 " doesn't use or create a tags file and there is no need to create a tags file
53 " This script relies on the Vim "filetype" detection mechanism to determine
54 " the type of the current file. To turn on filetype detection use
58 " This plugin will not work in 'compatible' mode. Make sure the 'compatible'
59 " option is not set. This plugin will not work if you run Vim in the
60 " restricted mode (using the -Z command-line argument). This plugin also
61 " assumes that the system() Vim function is supported.
65 " 1. Copy the taglist.vim script to the $HOME/.vim/plugin directory. Refer to
66 " ':help add-plugin', ':help add-global-plugin' and ':help runtimepath' for
67 " more details about Vim plugins.
68 " 2. Set the Tlist_Ctags_Cmd variable to point to the location of the
69 " exuberant ctags utility (not to the directory).
70 " 3. If you are running a terminal/console version of Vim and the terminal
71 " doesn't support changing the window width then set the Tlist_Inc_Winwidth
74 " 5. You can use the ":Tlist" command to open/close the taglist window.
78 " You can open the taglist window by using the ":Tlist" command. Invoking this
79 " command will toggle (open or close) the taglist window. You can map a key to
80 " invoke this command:
82 " nnoremap <silent> <F8> :Tlist<CR>
84 " Add the above mapping to your ~/.vimrc file. You can also open the taglist
85 " window on startup using the following command line:
89 " You can close the taglist window from the taglist window by pressing 'q' or
90 " using the Vim ":q" command. You can also use any of the Vim window commands
91 " to close the taglist window. Invoking the ":Tlist" command when the taglist
92 " window is opened, will close the taglist window.
94 " As you switch between source files, the taglist window will be automatically
95 " updated with the tag listing for the current source file. The tag names
96 " will grouped by their type (variable, function, class, etc). For tags with
97 " scope information (like class members, structures inside structures, etc),
98 " the scope information will be displayed in square brackets "[]" after the
101 " The tag names will be displayed as a foldable tree using the Vim folding
102 " support. You can collapse the tree using the '-' key or using the Vim zc
103 " fold command. You can open the tree using the '+' key or using the Vim zo
104 " fold command. You can open all the fold using the '*' key or using the Vim
105 " zR fold command You can also use the mouse to open/close the folds.
107 " You can select a tag either by pressing the <Enter> key or by double
108 " clicking the tag name using the mouse. You can configure the taglist plugin
109 " by setting the 'Tlist_Use_SingleClick' variable to jump to a tag on a single
112 " The script will automatically highlight the name of the current tag. The
113 " tag name will be highlighted after 'updatetime' milliseconds. The default
114 " value for this Vim option is 4 seconds. You can also use the ":TlistSync"
115 " command to force the highlighting of the current tag. You can map a key to
116 " invoke this command:
118 " nnoremap <silent> <F9> :TlistSync<CR>
120 " Add the above mapping to your ~/.vimrc file.
122 " If you place the cursor on a tag name in the "Tag List" window, then the tag
123 " prototype will be displayed at the Vim status line after 'updatetime'
124 " milliseconds. The default value for the 'updatetime' Vim option is 4
125 " seconds. You can also press the space bar to display the prototype of the
126 " tag under the cursor.
128 " By default, the tag list will be sorted by the order in which the tags
129 " appear in the file. You can sort the tags either by name or by order by
130 " pressing the "s" key in the taglist window.
132 " You can press the 'x' key in the taglist window to maximize the taglist
133 " window width/height. The window will be maximized to the maximum possible
134 " width/height without closing the other existing windows. You can again press
135 " 'x' to restore the taglist window to the default width/height.
137 " You can press the '?' key to display help information about using the
138 " taglist window. If you again press the '?' key, the help information will be
141 " The following table lists the description of the keys that you can use
142 " in the taglist window.
146 " <CR> Jump to the location where the tag under cursor is
148 " o Jump to the location where the tag under cursor is
149 " defined in a new window.
150 " <Space> Display the prototype of the tag under the cursor.
151 " u Update the tags listed in the taglist window
152 " s Change the sort order of the tags (by name or by order)
153 " x Zoom-in or Zoom-out the taglist window
157 " q Close the taglist window
161 " You can use the ":TlistShowPrototype" command to display the prototype of
162 " a function in the specified line number. For example,
164 " :TlistShowPrototype 50
166 " If the line number is not supplied, this command will display the prototype
167 " of the current function.
169 " You can also use the taglist plugin with the winmanager plugin. This will
170 " allow you to use the file explorer, buffer explorer and the taglist plugin
171 " at the same time in different windows. To use the taglist plugin with the
172 " winmanager plugin, set 'TagList' in the 'winManagerWindowLayout' variable.
173 " For example, to use the file explorer plugin and the taglist plugin at the
174 " same time, use the following setting:
176 " let winManagerWindowLayout = 'FileExplorer|TagList'
180 " By changing the following variables you can configure the behavior of this
181 " script. Set the following variables in your .vimrc file using the 'let'
184 " The script uses the Tlist_Ctags_Cmd variable to locate the ctags utility.
185 " By default, this is set to ctags. Set this variable to point to the location
186 " of the ctags utility in your system. Note that this variable should point to
187 " the fully qualified exuberant ctags location and NOT to the directory in
188 " which exuberant ctags is installed.
190 " let Tlist_Ctags_Cmd = 'd:\tools\ctags.exe'
191 " let Tlist_Ctags_Cmd = '/usr/local/bin/ctags'
193 " By default, the tag names will be listed in the order in which they are
194 " defined in the file. You can alphabetically sort the tag names by pressing
195 " the "s" key in the taglist window. You can also change the default order by
196 " setting the variable Tlist_Sort_Type to "name" or "order":
198 " let Tlist_Sort_Type = "name"
200 " Be default, the tag names will be listed in a vertically split window. If
201 " you prefer a horizontally split window, then set the
202 " 'Tlist_Use_Horiz_Window' variable to 1. If you are running MS-Windows
203 " version of Vim in a MS-DOS command window, then you should use a
204 " horizontally split window instead of a vertically split window. Also, if
205 " you are using an older version of xterm in a Unix system that doesn't
206 " support changing the xterm window width, you should use a horizontally split
209 " let Tlist_Use_Horiz_Window = 1
211 " By default, the vertically split taglist window will appear on the left hand
212 " side. If you prefer to open the window on the right hand side, you can set
213 " the Tlist_Use_Right_Window variable to one:
215 " let Tlist_Use_Right_Window = 1
217 " To automatically open the taglist window, when you start Vim, you can set
218 " the Tlist_Auto_Open variable to 1. By default, this variable is set to 0 and
219 " the taglist window will not be opened automatically on Vim startup.
221 " let Tlist_Auto_Open = 1
223 " By default, only the tag name will be displayed in the taglist window. If
224 " you like to see tag prototypes instead of names, set the
225 " Tlist_Display_Prototype variable to 1. By default, this variable is set to 0
226 " and only tag names will be displayed.
228 " let Tlist_Display_Prototype = 1
230 " The default width of the vertically split taglist window will be 30. This
231 " can be changed by modifying the Tlist_WinWidth variable:
233 " let Tlist_WinWidth = 20
235 " Note that the value of the 'winwidth' option setting determines the minimum
236 " width of the current window. If you set the 'Tlist_WinWidth' variable to a
237 " value less than that of the 'winwidth' option setting, then Vim will use the
238 " value of the 'winwidth' option.
240 " By default, when the width of the window is less than 100 and a new taglist
241 " window is opened vertically, then the window width will be increased by the
242 " value set in the Tlist_WinWidth variable to accommodate the new window. The
243 " value of this variable is used only if you are using a vertically split
244 " taglist window. If your terminal doesn't support changing the window width
245 " from Vim (older version of xterm running in a Unix system) or if you see any
246 " weird problems in the screen due to the change in the window width or if you
247 " prefer not to adjust the window width then set the 'Tlist_Inc_Winwidth'
248 " variable to 0. CAUTION: If you are using the MS-Windows version of Vim in a
249 " MS-DOS command window then you must set this variable to 0, otherwise the
250 " system may hang due to a Vim limitation (explained in :help win32-problems)
252 " let Tlist_Inc_Winwidth = 0
254 " By default, when you double click on the tag name using the left mouse
255 " button, the cursor will be positioned at the definition of the tag. You
256 " can set the Tlist_Use_SingleClick variable to one to jump to a tag when
257 " you single click on the tag name using the mouse. By default this variable
260 " let Tlist_Use_SingleClick = 1
262 " Due to a bug in Vim, if you set Tlist_Use_SingleClick to one and try to
263 " resize the taglist window using the mouse, then Vim will crash. The fix for
264 " this bug will be available in the next version of Vim. In the meantime,
265 " instead of resizing the taglist window using the mouse, you can use normal
266 " Vim window resizing commands to resize the taglist window.
268 " By default, the taglist window will contain text that display the name of
269 " the file, sort order information and the key to press to get help. Also,
270 " empty lines will be used to separate different groups of tags. If you
271 " don't need these information, you can set the Tlist_Compact_Format variable
272 " to one to get a compact display.
274 " let Tlist_Compact_Format = 1
278 " You can extend exuberant ctags to add support for new languages. For more
279 " information, visit the following page
281 " http://ctags.sourceforge.net/EXTENDING.html
283 " You can extend the taglist plugin to add support for new languages or modify
284 " the support for an already supported language by setting the following
285 " variables in the .vimrc file.
287 " To modify the support for an already supported language, you have to set the
288 " tlist_xxx_settings variable. Replace xxx with the Vim filetype name. To
289 " determine the filetype name used by Vim for a file, use the command
293 " The format of the value set in the tlist_xxx_settings variable is
295 " <language_name>;flag1:name1;flag2:name2;flag3:name3
297 " The different fields are separated by the ';' character. The first field
298 " 'language_name' is the name used by exuberant ctags. This name can be
299 " different from the file type name used by Vim. For example, for C++, the
300 " language name used by ctags is 'c++' but the filetype name used by Vim is
301 " 'cpp'. The remaining fields follow the format "flag:name". The sub-field
302 " 'flag' is the language specific flag used by exuberant ctags to generate the
303 " corresponding tags. For example, for the C language, to list only the
304 " functions, the 'f' flag should be used. For more information about the flags
305 " supported by exuberant ctags for a particular language, read the help text
306 " from the 'ctags --help' comand. The sub-field 'name' specifies the title
307 " text to use for displaying the tags of a particular type. For example,
308 " 'name' can be set to 'functions'.
310 " For example, to list only the classes and functions defined in a C++
311 " language file, add the following lines to your .vimrc file
313 " let tlist_cpp_settings = 'c++;c:class;f:function'
315 " In the above setting, 'cpp' is the Vim filetype name and 'c++' is the name
316 " used by the exuberant ctags tool. 'c' and 'f' are the flags passed to
317 " exuberant ctags to list classes and functions.
319 " For example, to display only functions defined in a C file and to use "My
320 " Functions" as the title for the function group, use
322 " let tlist_c_settings = 'c;f:My Functions'
324 " To add support for a new language, set the tlist_xxx_settings variable
325 " appropriately as described above.
327 " ****************** Do not modify after this line ************************
328 if exists('loaded_taglist') || &cp
333 " Location of the exuberant ctags tool
334 if !exists('Tlist_Ctags_Cmd')
335 let Tlist_Ctags_Cmd = 'ctags'
338 " Tag listing sort type - 'name' or 'order'
339 if !exists('Tlist_Sort_Type')
340 let Tlist_Sort_Type = 'order'
343 " Tag listing window split (horizontal/vertical) control
344 if !exists('Tlist_Use_Horiz_Window')
345 let Tlist_Use_Horiz_Window = 0
348 " Open the vertically split taglist window on the left or on the right side.
349 " This setting is relevant only if Tlist_Use_Horiz_Window is set to zero (i.e.
350 " only for vertically split windows)
351 if !exists('Tlist_Use_Right_Window')
352 let Tlist_Use_Right_Window = 0
355 " Increase Vim window width to display vertically split taglist window. For
356 " MS-Windows version of Vim running in a MS-DOS window, this must be set to 0
357 " otherwise the system may hang due to a Vim limitation.
358 if !exists('Tlist_Inc_Winwidth')
359 if (has('win16') || has('win95')) && !has('gui_running')
360 let Tlist_Inc_Winwidth = 0
362 let Tlist_Inc_Winwidth = 1
366 " Vertically split taglist window width setting
367 if !exists('Tlist_WinWidth')
368 let Tlist_WinWidth = 30
371 " Horizontally split taglist window height setting
372 if !exists('Tlist_WinHeight')
373 let Tlist_WinHeight = 10
376 " Automatically open the taglist window on Vim startup
377 if !exists('Tlist_Auto_Open')
378 let Tlist_Auto_Open = 0
381 " Display tag prototypes or tag names in the taglist window
382 if !exists('Tlist_Display_Prototype')
383 let Tlist_Display_Prototype = 0
386 " Use single left mouse click to jump to a tag. By default this is disabled.
387 " Only double click using the mouse will be processed.
388 if !exists('Tlist_Use_SingleClick')
389 let Tlist_Use_SingleClick = 0
392 " Control whether additional help is displayed as part of the taglist or not.
393 " Also, controls whether empty lines are used to separate the tag tree.
394 if !exists('Tlist_Compact_Format')
395 let Tlist_Compact_Format = 0
399 let s:tlist_def_asm_settings = 'asm;d:define;l:label;m:macro;t:type'
402 let s:tlist_def_aspperl_settings = 'asp;f:function;s:sub'
405 let s:tlist_def_aspvbs_settings = 'asp;f:function;s:sub'
408 let s:tlist_def_awk_settings = 'awk;f:function'
411 let s:tlist_def_beta_settings = 'beta;f:fragment;s:pattern;v:virtual'
414 let s:tlist_def_c_settings = 'c;d:macro;g:enum;s:struct;u:union;t:typedef;' .
415 \ 'v:variable;f:function'
418 let s:tlist_def_cpp_settings = 'c++;v:variable;d:macro;t:typedef;c:class;' .
419 \ 'g:enum;s:struct;u:union;f:function'
422 let s:tlist_def_cobol_settings = 'cobol;d:data;f:file;g:group;p:paragraph;' .
423 \ 'P:program;s:section'
426 let s:tlist_def_eiffel_settings = 'eiffel;c:class;f:feature'
429 let s:tlist_def_fortran_settings = 'fortran;p:program;b:block data;' .
430 \ 'c:common;e:entry;i:interface;k:type;l:label;m:module;' .
431 \ 'n:namelist;t:derived;v:variable;f:function;s:subroutine'
434 let s:tlist_def_java_settings = 'java;p:package;c:class;i:interface;' .
438 let s:tlist_def_lisp_settings = 'lisp;f:function'
441 let s:tlist_def_lua_settings = 'lua;f:function'
444 let s:tlist_def_make_settings = 'make;m:macro'
447 let s:tlist_def_pascal_settings = 'pascal;f:function;p:procedure'
450 let s:tlist_def_perl_settings = 'perl;p:package;s:subroutine'
453 let s:tlist_def_php_settings = 'php;c:class;f:function'
456 let s:tlist_def_python_settings = 'python;c:class;m:member;f:function'
459 let s:tlist_def_rexx_settings = 'rexx;s:subroutine'
462 let s:tlist_def_ruby_settings = 'ruby;c:class;f:method;F:function;' .
463 \ 'm:singleton method'
466 let s:tlist_def_scheme_settings = 'scheme;s:set;f:function'
469 let s:tlist_def_sh_settings = 'sh;f:function'
472 let s:tlist_def_csh_settings = 'sh;f:function'
475 let s:tlist_def_zsh_settings = 'sh;f:function'
478 let s:tlist_def_slang_settings = 'slang;n:namespace;f:function'
481 let s:tlist_def_sql_settings = 'sql;c:cursor;F:field;P:package;r:record;' .
482 \ 's:subtype;t:table;T:trigger;v:variable;f:function;p:procedure'
485 let s:tlist_def_tcl_settings = 'tcl;c:class;f:method;p:procedure'
488 let s:tlist_def_verilog_settings = 'verilog;m:module;P:parameter;r:reg;' .
489 \ 't:task;w:write;p:port;v:variable;f:function'
492 let s:tlist_def_vim_settings = 'vim;v:variable;f:function'
495 let s:tlist_def_yacc_settings = 'yacc;l:label'
497 " Initialize the taglist script local variables for the supported file types
499 let s:tlist_winsize_chgd = 0
500 let s:tlist_win_maximized = 0
501 let s:tlist_part_of_winmanager = 0
502 " Do not change the name of the taglist title variable. The winmanager plugin
503 " relies on this name to determine the title for the taglist plugin.
504 let TagList_title = "__Tag_List__"
506 function! s:Tlist_Show_Help()
507 if g:Tlist_Compact_Format == 1
508 " In compact display mode, do not display help
511 if exists("s:tlist_show_help") && s:tlist_show_help == 1
512 let s:tlist_show_help = 0
514 let s:tlist_show_help = 1
517 call s:Tlist_Open_Window()
519 call s:Tlist_Init_Window(b:tlist_bufnum)
521 " Update the taglist window
522 call s:Tlist_Explore_File(b:tlist_bufnum)
525 " An autocommand is used to refresh the taglist window when entering any
526 " buffer. We don't want to refresh the taglist window if we are entering the
527 " file window from one of the taglist functions. The 'Tlist_Skip_Refresh'
528 " variable is used to skip the refresh of the taglist window
529 let s:Tlist_Skip_Refresh = 0
531 function! s:Tlist_Warning_Msg(msg)
537 " Tlist_Skip_Buffer()
538 " Check whether tag listing is supported for the specified buffer.
539 function! s:Tlist_Skip_Buffer(bufnum)
540 " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help
541 if getbufvar(a:bufnum, '&buftype') != ''
545 let ftype = getbufvar(a:bufnum, '&filetype')
547 " Skip buffers with filetype not set
552 " Skip files which are not supported by exuberant ctags
553 " First check whether default settings for this filetype are available.
554 " If it is not available, then check whether user specified settings are
555 " available. If both are not available, then don't list the tags for this
557 let var = 's:tlist_def_' . ftype . '_settings'
559 let var = 'g:tlist_' . ftype . '_settings'
565 let filename = fnamemodify(bufname(a:bufnum), '%:p')
567 " Skip buffers with no names
572 " Skip files which are not readable or files which are not yet stored
574 if !filereadable(filename)
581 " Tlist_FileType_Init
582 " Initialize the ctags arguments and tag variable for the specified
584 function! s:Tlist_FileType_Init(ftype)
585 " If the user didn't specify any settings, then use the default
586 " ctags args. Otherwise, use the settings specified by the user
587 let var = 'g:tlist_' . a:ftype . '_settings'
589 " User specified ctags arguments
590 let settings = {var} . ';'
592 " Default ctags arguments
593 let var = 's:tlist_def_' . a:ftype . '_settings'
595 " No default settings for this file type. This filetype is
599 let settings = s:tlist_def_{a:ftype}_settings . ';'
602 let msg = 'Invalid ctags option setting - ' . settings
604 " Extract the file type to pass to ctags. This can be different from the
605 " file type detected by Vim
606 let pos = stridx(settings, ';')
608 call s:Tlist_Warning_Msg(msg)
611 let ctags_ftype = strpart(settings, 0, pos)
613 call s:Tlist_Warning_Msg(msg)
616 " Make sure a valid filetype is supplied. If the user didn't specify a
617 " valid filetype, then the ctags option settings may be treated as the
619 if ctags_ftype =~ ':'
620 call s:Tlist_Warning_Msg(msg)
624 " Remove the file type from settings
625 let settings = strpart(settings, pos + 1)
627 call s:Tlist_Warning_Msg(msg)
631 " Process all the specified ctags flags. The format is
632 " flag1:name1;flag2:name2;flag3:name3
637 let pos = stridx(settings, ':')
639 call s:Tlist_Warning_Msg(msg)
642 let flag = strpart(settings, 0, pos)
644 call s:Tlist_Warning_Msg(msg)
647 " Remove the flag from settings
648 let settings = strpart(settings, pos + 1)
650 " Extract the tag type name
651 let pos = stridx(settings, ';')
653 call s:Tlist_Warning_Msg(msg)
656 let name = strpart(settings, 0, pos)
658 call s:Tlist_Warning_Msg(msg)
661 let settings = strpart(settings, pos + 1)
665 let s:tlist_{a:ftype}_{cnt}_name = flag
666 let s:tlist_{a:ftype}_{cnt}_fullname = name
667 let ctags_flags = ctags_flags . flag
670 let s:tlist_{a:ftype}_ctags_args = '--language-force=' . ctags_ftype .
671 \ ' --' . ctags_ftype . '-types=' . ctags_flags
672 let s:tlist_{a:ftype}_count = cnt
673 let s:tlist_{a:ftype}_ctags_flags = ctags_flags
679 " Cleanup all the taglist window variables.
680 function! s:Tlist_Cleanup()
682 silent! syntax clear TagListTitle
686 if exists('b:tlist_ftype') && b:tlist_ftype != ''
687 let count_var_name = 's:tlist_' . b:tlist_ftype . '_count'
688 if exists(count_var_name)
689 let old_ftype = b:tlist_ftype
691 while i <= s:tlist_{old_ftype}_count
692 let ttype = s:tlist_{old_ftype}_{i}_name
694 let var_name = 'b:tlist_' . old_ftype . '_' . ttype . '_count'
696 let cnt = b:tlist_{old_ftype}_{ttype}_count
701 unlet! b:tlist_{old_ftype}_{ttype}_{j}
704 unlet! b:tlist_{old_ftype}_{ttype}_count
705 unlet! b:tlist_{old_ftype}_{ttype}_start
711 " Clean up all the variables containing the tags output
712 if exists('b:tlist_tag_count')
713 while b:tlist_tag_count > 0
714 unlet! b:tlist_tag_{b:tlist_tag_count}
715 let b:tlist_tag_count = b:tlist_tag_count - 1
719 unlet! b:tlist_bufnum
720 unlet! b:tlist_bufname
725 " Create a new taglist window. If it is already open, clear it
726 function! s:Tlist_Open_Window()
727 " If used with winmanager don't open windows. Winmanager will handle
728 " the window/buffer management
729 if s:tlist_part_of_winmanager
733 " Cleanup the taglist window listing, if the window is open
734 let winnum = bufwinnr(g:TagList_title)
736 " Jump to the existing window
738 exe winnum . 'wincmd w'
741 " Create a new window. If user prefers a horizontal window, then open
742 " a horizontally split window. Otherwise open a vertically split
744 if g:Tlist_Use_Horiz_Window == 1
745 " If a single window is used for all files, then open the tag
746 " listing window at the very bottom
747 let win_dir = 'botright'
748 " Horizontal window height
749 let win_size = g:Tlist_WinHeight
751 " Increase the window size, if needed, to accomodate the new
753 if g:Tlist_Inc_Winwidth == 1 &&
754 \ &columns < (80 + g:Tlist_WinWidth)
755 " one extra column is needed to include the vertical split
756 let &columns= &columns + (g:Tlist_WinWidth + 1)
757 let s:tlist_winsize_chgd = 1
759 let s:tlist_winsize_chgd = 0
762 " Open the window at the leftmost place
763 if g:Tlist_Use_Right_Window == 1
764 let win_dir = 'botright vertical'
766 let win_dir = 'topleft vertical'
768 let win_size = g:Tlist_WinWidth
771 " If the tag listing temporary buffer already exists, then reuse it.
772 " Otherwise create a new buffer
773 let bufnum = bufnr(g:TagList_title)
775 " Create a new buffer
776 let wcmd = g:TagList_title
778 " Edit the existing buffer
779 let wcmd = '+buffer' . bufnum
782 " Create the taglist window
783 exe 'silent! ' . win_dir . ' ' . win_size . 'split ' . wcmd
788 " Zoom (maximize/minimize) the taglist window
789 function! s:Tlist_Zoom_Window()
790 if s:tlist_win_maximized == 1
791 if g:Tlist_Use_Horiz_Window == 1
792 exe 'resize ' . g:Tlist_WinHeight
794 exe 'vert resize ' . g:Tlist_WinWidth
796 let s:tlist_win_maximized = 0
798 " Set the window size to the maximum possible without closing other
800 if g:Tlist_Use_Horiz_Window == 1
805 let s:tlist_win_maximized = 1
810 " Set the default options for the taglist window
811 function! s:Tlist_Init_Window(bufnum)
812 " Set report option to a huge value to prevent informations messages
813 " while deleting the lines
814 let old_report = &report
817 " Mark the buffer as modifiable
820 " Delete the contents of the buffer to the black-hole register
823 " Mark the buffer as not modifiable
824 setlocal nomodifiable
826 " Restore the report option
827 let &report = old_report
829 " Clean up all the old variables used for the last filetype
830 call <SID>Tlist_Cleanup()
832 let filename = fnamemodify(bufname(a:bufnum), ':p')
834 " Set the sort type. First time, use the global setting. After that use
835 " the previous setting
836 let b:tlist_sort_type = getbufvar(a:bufnum, 'tlist_sort_type')
837 if b:tlist_sort_type == ''
838 let b:tlist_sort_type = g:Tlist_Sort_Type
841 let b:tlist_tag_count = 0
842 let b:tlist_bufnum = a:bufnum
843 let b:tlist_bufname = fnamemodify(bufname(a:bufnum), ':p')
844 let b:tlist_ftype = getbufvar(a:bufnum, '&filetype')
846 " Mark the buffer as modifiable
849 if s:tlist_part_of_winmanager
850 " To handle a bug in the winmanager plugin, add a space at the
852 call setline('$', ' ')
855 if g:Tlist_Compact_Format == 0
856 if exists("s:tlist_show_help") && s:tlist_show_help == 1
857 call append(0, '" <enter> : Jump to tag definition')
858 call append(1, '" o : Jump to tag definition in new window')
859 call append(2, '" <space> : Display tag prototype')
860 call append(3, '" u : Update tag list')
861 call append(4, '" s : Select sort field')
862 call append(5, '" x : Zoom-out/Zoom-in taglist window')
863 call append(6, '" + : Open a fold')
864 call append(7, '" - : Close a fold')
865 call append(8, '" * : Open all folds')
866 call append(9, '" q : Close the taglist window')
867 call append(10, '" ? : Remove help text')
868 call append(11, '" Sorted by ' . b:tlist_sort_type)
869 call append(12, '"= ' . fnamemodify(filename, ':t') . ' (' .
870 \ fnamemodify(filename, ':p:h') . ')')
872 call append(0, '" Press ? to display help text')
873 call append(1, '" Sorted by ' . b:tlist_sort_type)
874 call append(2, '"= ' . fnamemodify(filename, ':t') . ' (' .
875 \ fnamemodify(filename, ':p:h') . ')')
879 " Mark the buffer as not modifiable
880 setlocal nomodifiable
882 " Highlight the comments
884 syntax match TagListComment '^" .*'
885 syntax match TagListSortBy '^" Sorted by .*'
886 syntax match TagListCurDir '^"= .*'
888 " Colors used to highlight the selected tag name
889 highlight clear TagName
890 if has('gui_running') || &t_Co > 2
891 highlight link TagName Search
893 highlight TagName term=reverse cterm=reverse
896 " Colors to highlight comments and titles
897 highlight clear TagListComment
898 highlight link TagListComment Comment
899 highlight clear TagListTitle
900 highlight link TagListTitle Title
901 highlight clear TagListSortBy
902 highlight link TagListSortBy String
903 highlight clear TagListCurDir
904 highlight link TagListCurDir Statement
907 " Folding related settings
910 setlocal foldmethod=manual
911 setlocal foldcolumn=2
912 setlocal foldtext=v:folddashes.getline(v:foldstart)
915 if !s:tlist_part_of_winmanager
916 " Mark buffer as scratch
917 silent! setlocal buftype=nofile
918 silent! setlocal bufhidden=delete
919 silent! setlocal noswapfile
920 " Due to a bug in Vim 6.0, the winbufnr() function fails for unlisted
921 " buffers. So if the taglist buffer is unlisted, multiple taglist
922 " windows will be opened. This bug is fixed in Vim 6.1 and above
924 silent! setlocal nobuflisted
928 silent! setlocal nowrap
930 " If the 'number' option is set in the source window, it will affect the
931 " taglist window. So forcefully disable 'number' option for the taglist
933 silent! setlocal nonumber
935 " Create buffer local mappings for jumping to the tags and sorting the list
936 nnoremap <buffer> <silent> <CR> :call <SID>Tlist_Jump_To_Tag(0)<CR>
937 nnoremap <buffer> <silent> o :call <SID>Tlist_Jump_To_Tag(1)<CR>
938 nnoremap <buffer> <silent> <2-LeftMouse> :call <SID>Tlist_Jump_To_Tag(0)<CR>
939 nnoremap <buffer> <silent> s :call <SID>Tlist_Change_Sort()<CR>
940 nnoremap <buffer> <silent> + :silent! foldopen<CR>
941 nnoremap <buffer> <silent> - :silent! foldclose<CR>
942 nnoremap <buffer> <silent> * :silent! %foldopen!<CR>
943 nnoremap <buffer> <silent> <kPlus> :silent! foldopen<CR>
944 nnoremap <buffer> <silent> <kMinus> :silent! foldclose<CR>
945 nnoremap <buffer> <silent> <kMultiply> :silent! %foldopen!<CR>
946 nnoremap <buffer> <silent> <Space> :call <SID>Tlist_Show_Tag_Prototype()<CR>
947 nnoremap <buffer> <silent> u :call <SID>Tlist_Update_Window()<CR>
948 nnoremap <buffer> <silent> x :call <SID>Tlist_Zoom_Window()<CR>
949 nnoremap <buffer> <silent> ? :call <SID>Tlist_Show_Help()<CR>
950 nnoremap <buffer> <silent> q :close<CR>
952 " Map single left mouse click if the user wants this functionality
953 if g:Tlist_Use_SingleClick == 1
954 nnoremap <silent> <LeftMouse> <LeftMouse>:if bufname("%") =~ "__Tag_List__"
955 \ <bar> call <SID>Tlist_Jump_To_Tag(0) <bar> endif <CR>
958 " Define the autocommand to highlight the current tag
959 augroup TagListAutoCmds
961 " Display the tag prototype for the tag under the cursor.
962 autocmd CursorHold __Tag_List__ call s:Tlist_Show_Tag_Prototype()
963 " Highlight the current tag
964 autocmd CursorHold * silent call <SID>Tlist_Highlight_Tag(bufnr('%'),
966 autocmd BufUnload __Tag_List__ call <SID>Tlist_Close_Window()
967 if !s:tlist_part_of_winmanager
968 " Adjust the Vim window width when taglist window is closed
969 " Auto refresh the taglisting window
970 autocmd BufEnter * call <SID>Tlist_Refresh_Window()
975 " Tlist_Close_Window()
976 " Close the taglist window and adjust the Vim window width
977 function! s:Tlist_Close_Window()
978 " Remove the autocommands for the taglist window
979 silent! autocmd! TagListAutoCmds
981 " Clear all the highlights
985 silent! syntax clear TagListTitle
988 " Remove the left mouse click mapping if it was setup initially
989 if g:Tlist_Use_SingleClick == 1
990 if hasmapto('<LeftMouse>')
995 if !s:tlist_part_of_winmanager
996 if g:Tlist_Use_Horiz_Window || g:Tlist_Inc_Winwidth == 0 ||
997 \ s:tlist_winsize_chgd == 0 ||
998 \ &columns < (80 + g:Tlist_WinWidth)
999 " No need to adjust window width if horizontally split tag listing
1000 " window or if columns is less than 101 or if the user chose not to
1001 " adjust the window width
1003 " Adjust the Vim window width
1004 let &columns= &columns - (g:Tlist_WinWidth + 1)
1009 " Tlist_Explore_File()
1010 " List the tags defined in the specified file in a Vim window
1011 function! s:Tlist_Explore_File(bufnum)
1012 " Get the filename and file type
1013 let filename = fnamemodify(bufname(a:bufnum), ':p')
1014 let ftype = getbufvar(a:bufnum, '&filetype')
1016 " Check for valid filename and valid filetype
1017 if filename == '' || !filereadable(filename) || ftype == ''
1021 " If the tag types for this filetype are not yet created, then create
1023 let var = 's:tlist_' . ftype . '_count'
1025 if s:Tlist_FileType_Init(ftype) == 0
1030 " If the cached ctags output exists for the specified buffer, then use it.
1031 " Otherwise run ctags to get the output
1032 let valid_cache = getbufvar(a:bufnum, 'tlist_valid_cache')
1033 if valid_cache != ''
1034 " Load the cached processed tags output from the buffer local
1036 let b:tlist_tag_count = getbufvar(a:bufnum, 'tlist_tag_count') + 0
1038 while i <= b:tlist_tag_count
1039 let var_name = 'tlist_tag_' . i
1040 let b:tlist_tag_{i} = getbufvar(a:bufnum, var_name)
1045 while i <= s:tlist_{ftype}_count
1046 let ttype = s:tlist_{ftype}_{i}_name
1047 let var_name = 'tlist_' . ttype . '_start'
1048 let b:tlist_{ftype}_{ttype}_start =
1049 \ getbufvar(a:bufnum, var_name) + 0
1050 let var_name = 'tlist_' . ttype . '_count'
1051 let cnt = getbufvar(a:bufnum, var_name) + 0
1052 let b:tlist_{ftype}_{ttype}_count = cnt
1053 let var_name = 'tlist_' . ttype
1054 let l:tlist_{ftype}_{ttype} = getbufvar(a:bufnum, var_name)
1057 let var_name = 'tlist_' . ttype . '_' . j
1058 let b:tlist_{ftype}_{ttype}_{j} = getbufvar(a:bufnum, var_name)
1064 " Exuberant ctags arguments to generate a tag list
1065 let ctags_args = ' -f - --format=2 --excmd=pattern --fields=nks '
1067 " Form the ctags argument depending on the sort type
1068 if b:tlist_sort_type == 'name'
1069 let ctags_args = ctags_args . ' --sort=yes '
1071 let ctags_args = ctags_args . ' --sort=no '
1074 " Add the filetype specific arguments
1075 let ctags_args = ctags_args . ' ' . s:tlist_{ftype}_ctags_args
1077 " Ctags command to produce output with regexp for locating the tags
1078 let ctags_cmd = g:Tlist_Ctags_Cmd . ctags_args
1079 let ctags_cmd = ctags_cmd . ' "' . filename . '"'
1081 " Run ctags and get the tag list
1082 let cmd_output = system(ctags_cmd)
1084 " Cache the ctags output with a buffer local variable
1085 call setbufvar(a:bufnum, 'tlist_valid_cache', 'Yes')
1086 call setbufvar(a:bufnum, 'tlist_sort_type', b:tlist_sort_type)
1089 if v:shell_error && cmd_output != ''
1090 call s:Tlist_Warning_Msg(cmd_output)
1094 " No tags for current file
1096 call s:Tlist_Warning_Msg('No tags found for ' . filename)
1100 " Initialize variables for the new filetype
1102 while i <= s:tlist_{ftype}_count
1103 let ttype = s:tlist_{ftype}_{i}_name
1104 let b:tlist_{ftype}_{ttype}_start = 0
1105 let b:tlist_{ftype}_{ttype}_count = 0
1106 let l:tlist_{ftype}_{ttype} = ''
1110 " Process the ctags output one line at a time. Separate the tag output
1111 " based on the tag type and store it in the tag type variable
1112 while cmd_output != ''
1113 " Extract one line at a time
1114 let one_line = strpart(cmd_output, 0, stridx(cmd_output, "\n"))
1115 " Remove the line from the tags output
1116 let cmd_output = strpart(cmd_output, stridx(cmd_output, "\n") + 1)
1119 " Line is not in proper tags format
1123 " Extract the tag type
1124 let ttype = s:Tlist_Extract_Tagtype(one_line)
1127 " Line is not in proper tags format
1131 " make sure the tag type is supported
1132 if s:tlist_{ftype}_ctags_flags !~# ttype
1136 " Extract the tag name
1137 if g:Tlist_Display_Prototype == 0
1138 let ttxt = ' ' . strpart(one_line, 0, stridx(one_line, "\t"))
1140 " Add the tag scope, if it is available. Tag scope is the last
1141 " field after the 'line:<num>\t' field
1142 let start = strridx(one_line, 'line:')
1143 let end = strridx(one_line, "\t")
1145 let tscope = strpart(one_line, end + 1)
1146 let tscope = strpart(tscope, stridx(tscope, ':') + 1)
1148 let ttxt = ttxt . ' [' . tscope . ']'
1152 let start = stridx(one_line, '/^') + 2
1153 let end = strridx(one_line, '/;"' . "\t")
1154 if one_line[end - 1] == '$'
1157 let ttxt = strpart(one_line, start, end - start)
1160 " Update the count of this tag type
1161 let cnt = b:tlist_{ftype}_{ttype}_count + 1
1162 let b:tlist_{ftype}_{ttype}_count = cnt
1164 " Add this tag to the tag type variable
1165 let l:tlist_{ftype}_{ttype} = l:tlist_{ftype}_{ttype} . ttxt . "\n"
1167 " Update the total tag count
1168 let b:tlist_tag_count = b:tlist_tag_count + 1
1169 let b:tlist_tag_{b:tlist_tag_count} = cnt . ':' . one_line
1171 let b:tlist_{ftype}_{ttype}_{cnt} = b:tlist_tag_count
1174 " Cache the processed tags output using buffer local variables
1175 call setbufvar(a:bufnum, 'tlist_tag_count', b:tlist_tag_count)
1177 while i <= b:tlist_tag_count
1178 let var_name = 'tlist_tag_' . i
1179 call setbufvar(a:bufnum, var_name, b:tlist_tag_{i})
1184 while i <= s:tlist_{ftype}_count
1185 let ttype = s:tlist_{ftype}_{i}_name
1186 let var_name = 'tlist_' . ttype . '_start'
1187 call setbufvar(a:bufnum, var_name, b:tlist_{ftype}_{ttype}_start)
1188 let cnt = b:tlist_{ftype}_{ttype}_count
1189 let var_name = 'tlist_' . ttype . '_count'
1190 call setbufvar(a:bufnum, var_name, cnt)
1191 let var_name = 'tlist_' . ttype
1192 call setbufvar(a:bufnum, var_name, l:tlist_{ftype}_{ttype})
1195 let var_name = 'tlist_' . ttype . '_' . j
1196 call setbufvar(a:bufnum, var_name, b:tlist_{ftype}_{ttype}_{j})
1203 " Set report option to a huge value to prevent informational messages
1204 " while adding lines to the taglist window
1205 let old_report = &report
1208 " Mark the buffer as modifiable
1211 " Add the tag names grouped by tag type to the buffer with a title
1213 while i <= s:tlist_{ftype}_count
1214 let ttype = s:tlist_{ftype}_{i}_name
1215 " Add the tag type only if there are tags for that type
1216 if l:tlist_{ftype}_{ttype} != ''
1217 if g:Tlist_Compact_Format == 0
1218 let b:tlist_{ftype}_{ttype}_start = line('.') + 1
1219 silent! put =s:tlist_{ftype}_{i}_fullname
1221 let b:tlist_{ftype}_{ttype}_start = line('.')
1222 silent! put! =s:tlist_{ftype}_{i}_fullname
1224 silent! put =l:tlist_{ftype}_{ttype}
1226 " create a fold for this tag type
1228 let fold_start = b:tlist_{ftype}_{ttype}_start
1229 let fold_end = fold_start + b:tlist_{ftype}_{ttype}_count
1230 exe fold_start . ',' . fold_end . 'fold'
1233 " Syntax highlight the tag type names
1235 exe 'syntax match TagListTitle /\%' .
1236 \ b:tlist_{ftype}_{ttype}_start . 'l.*/'
1238 " Separate the tag types with a empty line
1240 if g:Tlist_Compact_Format == 0
1247 if s:tlist_part_of_winmanager
1248 " To handle a bug in the winmanager plugin, add a space at the
1250 call setline('$', ' ')
1253 " Mark the buffer as not modifiable
1254 setlocal nomodifiable
1256 " Restore the report option
1257 let &report = old_report
1259 " Initially open all the folds
1264 " Goto the first line in the buffer
1270 " Tlist_Toggle_Window()
1271 " Open or close a taglist window
1272 function! s:Tlist_Toggle_Window(bufnum)
1273 let curline = line('.')
1275 " If taglist window is open then close it.
1276 let winnum = bufwinnr(g:TagList_title)
1278 if winnr() == winnum
1279 " Already in the taglist window. Close it and return
1282 " Goto the taglist window, close it and then come back to the
1284 let curbufnr = bufnr('%')
1285 exe winnum . 'wincmd w'
1287 " Need to jump back to the original window only if we are not
1288 " already in that window
1289 let winnum = bufwinnr(curbufnr)
1290 if winnr() != winnum
1291 exe winnum . 'wincmd w'
1297 let s:tlist_part_of_winmanager = 0
1299 " Open the taglist window
1300 call s:Tlist_Open_Window()
1302 " Initialize the taglist window
1303 call s:Tlist_Init_Window(a:bufnum)
1305 " List the tags defined in a file
1306 call s:Tlist_Explore_File(a:bufnum)
1308 " Highlight the current tag
1309 call s:Tlist_Highlight_Tag(a:bufnum, curline)
1311 " Go back to the original window
1312 let s:Tlist_Skip_Refresh = 1
1314 let s:Tlist_Skip_Refresh = 0
1317 " Tlist_Extract_Tagtype
1318 " Extract the tag type from the tag text
1319 function! s:Tlist_Extract_Tagtype(tag_txt)
1320 " The tag type is after the tag prototype field. The prototype field
1321 " ends with the /;"\t string. We add 4 at the end to skip the characters
1322 " in this special string..
1323 let start = strridx(a:tag_txt, '/;"' . "\t") + 4
1324 let end = strridx(a:tag_txt, 'line:') - 1
1325 let ttype = strpart(a:tag_txt, start, end - start)
1330 " Tlist_Extract_Tag_Prototype
1331 " Extract the tag protoype from the tag text
1332 function! s:Tlist_Extract_Tag_Prototype(tag_txt)
1333 let start = stridx(a:tag_txt, '/^') + 2
1334 let end = strridx(a:tag_txt, '/;"' . "\t")
1335 if a:tag_txt[end - 1] == '$'
1338 let tag_pat = strpart(a:tag_txt, start, end - start)
1340 " Remove all the leading space characters
1341 let tag_pat = matchstr(tag_pat, '^\s*\zs.*')
1346 " Tlist_Refresh_Window()
1347 " Refresh the taglist window
1348 function! s:Tlist_Refresh_Window()
1349 " We are entering the buffer from one of the taglist functions. So no need
1350 " to refresh the taglist window again
1351 if s:Tlist_Skip_Refresh == 1
1355 " If the buffer doesn't support tag listing, skip it
1356 if s:Tlist_Skip_Buffer(bufnr('%'))
1360 let filename = expand('%:p')
1362 let curline = line('.')
1364 " Make sure the taglist window is open. Otherwise, no need to refresh
1365 let winnum = bufwinnr(g:TagList_title)
1370 let bno = bufnr(g:TagList_title)
1372 let cur_bufnr = bufnr('%')
1374 " If the tag listing for the current window is already present, no need to
1376 if getbufvar(bno, 'tlist_bufnum') == cur_bufnr &&
1377 \ getbufvar(bno, 'tlist_bufname') == filename
1381 " Save the current window number
1382 let cur_winnr = winnr()
1384 call s:Tlist_Open_Window()
1386 call s:Tlist_Init_Window(cur_bufnr)
1388 " Update the taglist window
1389 call s:Tlist_Explore_File(cur_bufnr)
1391 " Highlight the current tag
1392 call s:Tlist_Highlight_Tag(cur_bufnr, curline)
1394 " Refresh the taglist window
1397 if !s:tlist_part_of_winmanager
1398 " Jump back to the original window
1399 exe cur_winnr . 'wincmd w'
1403 " Tlist_Change_Sort()
1404 " Change the sort order of the tag listing
1405 function! s:Tlist_Change_Sort()
1406 if !exists('b:tlist_bufnum') || !exists('b:tlist_ftype')
1410 let sort_type = getbufvar(b:tlist_bufnum, 'tlist_sort_type')
1412 " Toggle the sort order from 'name' to 'order' and vice versa
1413 if sort_type == 'name'
1414 call setbufvar(b:tlist_bufnum, 'tlist_sort_type', 'order')
1416 call setbufvar(b:tlist_bufnum, 'tlist_sort_type', 'name')
1419 " Save the current line for later restoration
1420 let curline = '\V\^' . getline('.') . '\$'
1422 " Clear out the cached taglist information
1423 call setbufvar(b:tlist_bufnum, 'tlist_valid_cache', '')
1425 call s:Tlist_Open_Window()
1427 call s:Tlist_Init_Window(b:tlist_bufnum)
1429 call s:Tlist_Explore_File(b:tlist_bufnum)
1431 " Go back to the tag line before the list is sorted
1432 call search(curline, 'w')
1435 " Tlist_Update_Window()
1436 " Update the window by regenerating the tag list
1437 function! s:Tlist_Update_Window()
1438 if !exists('b:tlist_bufnum') || !exists('b:tlist_ftype')
1442 " Save the current line for later restoration
1443 let curline = '\V\^' . getline('.') . '\$'
1445 " Clear out the cached taglist information
1446 call setbufvar(b:tlist_bufnum, 'tlist_valid_cache', '')
1448 call s:Tlist_Open_Window()
1450 call s:Tlist_Init_Window(b:tlist_bufnum)
1452 " Update the taglist window
1453 call s:Tlist_Explore_File(b:tlist_bufnum)
1455 " Go back to the tag line before the list is sorted
1456 call search(curline, 'w')
1459 " Tlist_Get_Tag_Linenr()
1460 " Return the tag line for the current line
1461 function! s:Tlist_Get_Tag_Linenr()
1462 if !exists('b:tlist_ftype')
1466 let lnum = line('.')
1467 let ftype = b:tlist_ftype
1469 " Determine to which tag type the current line number belongs to using the
1470 " tag type start line number and the number of tags in a tag type
1472 while i <= s:tlist_{ftype}_count
1473 let ttype = s:tlist_{ftype}_{i}_name
1474 let end = b:tlist_{ftype}_{ttype}_start + b:tlist_{ftype}_{ttype}_count
1475 if lnum >= b:tlist_{ftype}_{ttype}_start && lnum <= end
1481 " Current line doesn't belong to any of the displayed tag types
1482 if i > s:tlist_{ftype}_count
1486 " Compute the offset into the displayed tags for the tag type
1487 let offset = lnum - b:tlist_{ftype}_{ttype}_start
1492 " Get the corresponding tag line and return it
1493 return b:tlist_{ftype}_{ttype}_{offset}
1496 function! s:Tlist_Highlight_Tagline()
1497 " Clear previously selected name
1500 " Highlight the current selected name
1501 if g:Tlist_Display_Prototype == 0
1502 exe 'match TagName /\%' . line('.') . 'l\s\+\zs.*/'
1504 exe 'match TagName /\%' . line('.') . 'l.*/'
1508 " Tlist_Jump_To_Tag()
1509 " Jump to the location of the current tag
1510 function! s:Tlist_Jump_To_Tag(new_window)
1511 " Do not process comment lines and empty lines
1512 let curline = getline('.')
1513 if curline == '' || curline[0] == '"'
1517 " If inside a fold, then don't try to jump to the tag
1518 if foldclosed('.') != -1
1522 " Get the tag output for the current tag
1523 let lnum = s:Tlist_Get_Tag_Linenr()
1528 let mtxt = b:tlist_tag_{lnum}
1529 let start = stridx(mtxt, '/^') + 2
1530 let end = strridx(mtxt, '/;"' . "\t")
1531 if mtxt[end - 1] == '$'
1534 let tagpat = '\V\^' . strpart(mtxt, start, end - start) .
1535 \ (mtxt[end] == '$' ? '\$' : '')
1537 " Highlight the tagline
1538 call s:Tlist_Highlight_Tagline()
1540 let s:Tlist_Skip_Refresh = 1
1542 if s:tlist_part_of_winmanager
1543 call WinManagerFileEdit(bufname(b:tlist_bufnum), a:new_window)
1545 " Goto the window containing the file. If the window is not there, open a
1547 let winnum = bufwinnr(b:tlist_bufnum)
1549 if g:Tlist_Use_Horiz_Window == 1
1550 exe 'leftabove split #' . b:tlist_bufnum
1551 " Go to the taglist window to change the window size to the user
1554 exe 'resize ' . g:Tlist_WinHeight
1555 " Go back to the file window
1558 " Open the file in a window and skip refreshing the taglist window
1559 exe 'rightbelow vertical split #' . b:tlist_bufnum
1560 " Go to the taglist window to change the window size to the user
1563 exe 'vertical resize ' . g:Tlist_WinWidth
1564 " Go back to the file window
1568 exe winnum . 'wincmd w'
1570 " If the user asked to jump to the tag in a new window, then split the
1571 " existing window into two.
1579 silent call search(tagpat, 'w')
1581 " Bring the line to the middle of the window
1584 " If the line is inside a fold, open the fold
1586 if foldlevel('.') != 0
1591 let s:Tlist_Skip_Refresh = 0
1594 " Tlist_Show_Tag_Prototype()
1595 " Display the prototype of the tag under the cursor
1596 function! s:Tlist_Show_Tag_Prototype()
1597 " If we have already display prototype in the tag window, no need to
1598 " display it in the status line
1599 if g:Tlist_Display_Prototype == 1
1603 " Clear the previously displayed line
1606 " Do not process comment lines and empty lines
1607 let curline = getline('.')
1608 if curline == '' || curline[0] == '"'
1612 " If inside a fold, then don't display the prototype
1613 if foldclosed('.') != -1
1617 " Get the tag output line for the current tag
1618 let lnum = s:Tlist_Get_Tag_Linenr()
1623 let mtxt = b:tlist_tag_{lnum}
1625 " Get the tag search pattern and display it
1626 echo s:Tlist_Extract_Tag_Prototype(mtxt)
1629 " Tlist_Locate_Tag_Text
1630 " Locate the tag text given the line number in the source window
1631 function! s:Tlist_Locate_Tag_Text(sort_type, linenum)
1633 let right = b:tlist_tag_count
1635 if a:sort_type == 'order'
1636 " Tag list sorted by order, do a binary search comparing the line
1639 " If the current line is the less than the first tag, then no need to
1641 let txt = b:tlist_tag_1
1642 let start = strridx(txt, 'line:') + strlen('line:')
1643 let end = strridx(txt, "\t")
1645 let first_lnum = strpart(txt, start) + 0
1647 let first_lnum = strpart(txt, start, end - start) + 0
1650 if a:linenum < first_lnum
1655 let middle = (right + left + 1) / 2
1656 let txt = b:tlist_tag_{middle}
1658 let start = strridx(txt, 'line:') + strlen('line:')
1659 let end = strridx(txt, "\t")
1661 let middle_lnum = strpart(txt, start) + 0
1663 let middle_lnum = strpart(txt, start, end - start) + 0
1666 if middle_lnum == a:linenum
1671 if middle_lnum > a:linenum
1672 let right = middle - 1
1678 " sorted by name, brute force method (Dave Eggum)
1679 let closest_lnum = 0
1682 let txt = b:tlist_tag_{left}
1684 let start = strridx(txt, 'line:') + strlen('line:')
1685 let end = strridx(txt, "\t")
1687 let lnum = strpart(txt, start) + 0
1689 let lnum = strpart(txt, start, end - start) + 0
1692 if lnum < a:linenum && lnum > closest_lnum
1693 let closest_lnum = lnum
1694 let final_left = left
1695 elseif lnum == a:linenum
1696 let closest_lnum = lnum
1702 if closest_lnum == 0
1706 let left = final_left
1710 return b:tlist_tag_{left}
1713 " Tlist_Highlight_Tag()
1714 " Do a binary search in the array of tag names and pick a tag entry that
1715 " contains the current line and highlight it. The idea behind this function
1716 " is taken from the ctags.vim script available at the Vim online website.
1717 function! s:Tlist_Highlight_Tag(bufnum, curline)
1718 let filename = fnamemodify(bufname(a:bufnum), ':p')
1723 " Make sure the taglist window is present
1724 let winnum = bufwinnr(g:TagList_title)
1729 let bno = bufnr(g:TagList_title)
1731 " Make sure we have the tag listing for the current file
1732 if getbufvar(bno, 'tlist_bufnum') != a:bufnum
1736 " If there are no tags for this file, then no need to proceed further
1737 if getbufvar(bno, 'tlist_tag_count') == 0
1741 " If part of winmanager then disable winmanager autocommands
1742 if s:tlist_part_of_winmanager
1743 call WinManagerSuspendAUs()
1746 " Save the original window number
1747 let org_winnr = winnr()
1749 if org_winnr == winnum
1750 let in_taglist_window = 1
1752 let in_taglist_window = 0
1755 " Go to the taglist window
1756 if !in_taglist_window
1757 exe winnum . 'wincmd w'
1760 " Clear previously selected name
1763 let tag_txt = s:Tlist_Locate_Tag_Text(getbufvar(bno, 'tlist_sort_type'),
1766 if !in_taglist_window
1767 let s:Tlist_Skip_Refresh = 1
1768 exe org_winnr . 'wincmd w'
1769 let s:Tlist_Skip_Refresh = 0
1771 if s:tlist_part_of_winmanager
1772 call WinManagerResumeAUs()
1777 " Extract the tag type
1778 let ttype = s:Tlist_Extract_Tagtype(tag_txt)
1780 " Extract the tag offset
1781 let offset = strpart(tag_txt, 0, stridx(tag_txt, ':')) + 0
1783 " Compute the line number
1784 let lnum = b:tlist_{b:tlist_ftype}_{ttype}_start + offset
1786 " Goto the line containing the tag
1794 " Call winline() to make sure the target line is visible in the taglist
1795 " window. This is a side effect of calling winline(). Don't know of a
1796 " better way to achieve this.
1799 " Highlight the tag name
1800 call s:Tlist_Highlight_Tagline()
1802 " Go back to the original window
1803 if !in_taglist_window
1804 let s:Tlist_Skip_Refresh = 1
1805 exe org_winnr . 'wincmd w'
1806 let s:Tlist_Skip_Refresh = 0
1809 if s:tlist_part_of_winmanager
1810 call WinManagerResumeAUs()
1816 " Tlist_Get_Tag_Prototype_By_Line
1817 function! s:Tlist_Get_Tag_Prototype_By_Line(linenum)
1818 " Make sure the current file has a name
1819 let filename = fnamemodify(bufname("%"), ':p')
1824 let linenr = a:linenum
1826 " Default is the current line
1827 let linenr = line('.')
1830 " If there are no tags for this file, then no need to proceed further
1831 if !exists("b:tlist_tag_count") || b:tlist_tag_count == 0
1835 " Get the tag text using the line number
1836 let tag_txt = s:Tlist_Locate_Tag_Text(b:tlist_sort_type, linenr)
1841 " Extract the tag search pattern and return it
1842 return s:Tlist_Extract_Tag_Prototype(tag_txt)
1845 " Define tag listing autocommand to automatically open the taglist window on
1847 if g:Tlist_Auto_Open
1848 autocmd VimEnter * nested Tlist
1851 " Define the 'Tlist' and 'TlistSync' user commands to open/close taglist
1853 command! -nargs=0 Tlist call s:Tlist_Toggle_Window(bufnr('%'))
1854 command! -nargs=0 TlistSync call s:Tlist_Highlight_Tag(bufnr('%'), line('.'))
1855 command! -nargs=? TlistShowPrototype echo s:Tlist_Get_Tag_Prototype_By_Line(<q-args>)
1857 " Winmanager integration
1859 " Initialization required for integration with winmanager
1860 function! TagList_Start()
1861 let s:tlist_part_of_winmanager = 1
1863 if bufname('%') != '__Tag_List__'
1867 let bufnum = WinManagerGetLastEditedFile()
1869 " If the tags for the buffer is already listed, then no need to do
1871 if exists('b:tlist_bufnum') && bufnum == b:tlist_bufnum
1875 call s:Tlist_Init_Window(bufnum)
1877 " Open the taglist window
1878 call s:Tlist_Explore_File(bufnum)
1881 function! TagList_IsValid()
1885 function! TagList_WrapUp()