2 " Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
4 " Last Modified: September 21, 2007
5 " Copyright: Copyright (C) 2002-2007 Yegappan Lakshmanan
6 " Permission is hereby granted to use and distribute this code,
7 " with or without modifications, provided that this copyright
8 " notice is copied with it. Like anything else that's free,
9 " taglist.vim is provided *as is* and comes with no warranty of any
10 " kind, either expressed or implied. In no event will the copyright
11 " holder be liable for any damamges resulting from the use of this
14 " The "Tag List" plugin is a source code browser plugin for Vim and provides
15 " an overview of the structure of the programming language files and allows
16 " you to efficiently browse through source code files for different
17 " programming languages. You can visit the taglist plugin home page for more
20 " http://vim-taglist.sourceforge.net
22 " You can subscribe to the taglist mailing list to post your questions
23 " or suggestions for improvement or to report bugs. Visit the following
24 " page for subscribing to the mailing list:
26 " http://groups.yahoo.com/group/taglist/
28 " For more information about using this plugin, after installing the
29 " taglist plugin, use the ":help taglist" command.
33 " 1. Download the taglist.zip file and unzip the files to the $HOME/.vim
34 " or the $HOME/vimfiles or the $VIM/vimfiles directory. This should
35 " unzip the following two files (the directory structure should be
38 " plugin/taglist.vim - main taglist plugin file
39 " doc/taglist.txt - documentation (help) file
41 " Refer to the 'add-plugin', 'add-global-plugin' and 'runtimepath'
42 " Vim help pages for more details about installing Vim plugins.
43 " 2. Change to the $HOME/.vim/doc or $HOME/vimfiles/doc or
44 " $VIM/vimfiles/doc directory, start Vim and run the ":helptags ."
45 " command to process the taglist help file.
46 " 3. If the exuberant ctags utility is not present in your PATH, then set the
47 " Tlist_Ctags_Cmd variable to point to the location of the exuberant ctags
48 " utility (not to the directory) in the .vimrc file.
49 " 4. If you are running a terminal/console version of Vim and the
50 " terminal doesn't support changing the window width then set the
51 " 'Tlist_Inc_Winwidth' variable to 0 in the .vimrc file.
53 " 6. You can now use the ":TlistToggle" command to open/close the taglist
54 " window. You can use the ":help taglist" command to get more
55 " information about using the taglist plugin.
57 " ****************** Do not modify after this line ************************
59 " Line continuation used here
63 if !exists('loaded_taglist')
64 " First time loading the taglist plugin
66 " To speed up the loading of Vim, the taglist plugin uses autoload
67 " mechanism to load the taglist functions.
68 " Only define the configuration variables, user commands and some
69 " auto-commands and finish sourcing the file
71 " The taglist plugin requires the built-in Vim system() function. If this
72 " function is not available, then don't load the plugin.
74 echomsg 'Taglist: Vim system() built-in function is not available. ' .
75 \ 'Plugin is not loaded.'
76 let loaded_taglist = 'no'
81 " Location of the exuberant ctags tool
82 if !exists('Tlist_Ctags_Cmd')
83 if executable('exuberant-ctags')
84 " On Debian Linux, exuberant ctags is installed
86 let Tlist_Ctags_Cmd = 'exuberant-ctags'
87 elseif executable('exctags')
88 " On Free-BSD, exuberant ctags is installed as exctags
89 let Tlist_Ctags_Cmd = 'exctags'
90 elseif executable('ctags')
91 let Tlist_Ctags_Cmd = 'ctags'
92 elseif executable('ctags.exe')
93 let Tlist_Ctags_Cmd = 'ctags.exe'
94 elseif executable('tags')
95 let Tlist_Ctags_Cmd = 'tags'
97 echomsg 'Taglist: Exuberant ctags (http://ctags.sf.net) ' .
98 \ 'not found in PATH. Plugin is not loaded.'
99 " Skip loading the plugin
100 let loaded_taglist = 'no'
101 let &cpo = s:cpo_save
107 " Automatically open the taglist window on Vim startup
108 if !exists('Tlist_Auto_Open')
109 let Tlist_Auto_Open = 0
112 " When the taglist window is toggle opened, move the cursor to the
114 if !exists('Tlist_GainFocus_On_ToggleOpen')
115 let Tlist_GainFocus_On_ToggleOpen = 0
118 " Process files even when the taglist window is not open
119 if !exists('Tlist_Process_File_Always')
120 let Tlist_Process_File_Always = 0
123 if !exists('Tlist_Show_Menu')
124 let Tlist_Show_Menu = 0
127 " Tag listing sort type - 'name' or 'order'
128 if !exists('Tlist_Sort_Type')
129 let Tlist_Sort_Type = 'order'
132 " Tag listing window split (horizontal/vertical) control
133 if !exists('Tlist_Use_Horiz_Window')
134 let Tlist_Use_Horiz_Window = 0
137 " Open the vertically split taglist window on the left or on the right
138 " side. This setting is relevant only if Tlist_Use_Horiz_Window is set to
139 " zero (i.e. only for vertically split windows)
140 if !exists('Tlist_Use_Right_Window')
141 let Tlist_Use_Right_Window = 0
144 " Increase Vim window width to display vertically split taglist window.
145 " For MS-Windows version of Vim running in a MS-DOS window, this must be
146 " set to 0 otherwise the system may hang due to a Vim limitation.
147 if !exists('Tlist_Inc_Winwidth')
148 if (has('win16') || has('win95')) && !has('gui_running')
149 let Tlist_Inc_Winwidth = 0
151 let Tlist_Inc_Winwidth = 1
155 " Vertically split taglist window width setting
156 if !exists('Tlist_WinWidth')
157 let Tlist_WinWidth = 30
160 " Horizontally split taglist window height setting
161 if !exists('Tlist_WinHeight')
162 let Tlist_WinHeight = 10
165 " Display tag prototypes or tag names in the taglist window
166 if !exists('Tlist_Display_Prototype')
167 let Tlist_Display_Prototype = 0
170 " Display tag scopes in the taglist window
171 if !exists('Tlist_Display_Tag_Scope')
172 let Tlist_Display_Tag_Scope = 1
175 " Use single left mouse click to jump to a tag. By default this is disabled.
176 " Only double click using the mouse will be processed.
177 if !exists('Tlist_Use_SingleClick')
178 let Tlist_Use_SingleClick = 0
181 " Control whether additional help is displayed as part of the taglist or
182 " not. Also, controls whether empty lines are used to separate the tag
184 if !exists('Tlist_Compact_Format')
185 let Tlist_Compact_Format = 0
188 " Exit Vim if only the taglist window is currently open. By default, this is
190 if !exists('Tlist_Exit_OnlyWindow')
191 let Tlist_Exit_OnlyWindow = 0
194 " Automatically close the folds for the non-active files in the taglist
196 if !exists('Tlist_File_Fold_Auto_Close')
197 let Tlist_File_Fold_Auto_Close = 0
200 " Close the taglist window when a tag is selected
201 if !exists('Tlist_Close_On_Select')
202 let Tlist_Close_On_Select = 0
205 " Automatically update the taglist window to display tags for newly
207 if !exists('Tlist_Auto_Update')
208 let Tlist_Auto_Update = 1
211 " Automatically highlight the current tag
212 if !exists('Tlist_Auto_Highlight_Tag')
213 let Tlist_Auto_Highlight_Tag = 1
216 " Automatically highlight the current tag on entering a buffer
217 if !exists('Tlist_Highlight_Tag_On_BufEnter')
218 let Tlist_Highlight_Tag_On_BufEnter = 1
221 " Enable fold column to display the folding for the tag tree
222 if !exists('Tlist_Enable_Fold_Column')
223 let Tlist_Enable_Fold_Column = 1
226 " Display the tags for only one file in the taglist window
227 if !exists('Tlist_Show_One_File')
228 let Tlist_Show_One_File = 0
231 if !exists('Tlist_Max_Submenu_Items')
232 let Tlist_Max_Submenu_Items = 20
235 if !exists('Tlist_Max_Tag_Length')
236 let Tlist_Max_Tag_Length = 10
239 " Do not change the name of the taglist title variable. The winmanager
240 " plugin relies on this name to determine the title for the taglist
242 let TagList_title = "__Tag_List__"
244 " Taglist debug messages
247 " Define the taglist autocommand to automatically open the taglist window
250 autocmd VimEnter * nested call s:Tlist_Window_Check_Auto_Open()
253 " Refresh the taglist
254 if g:Tlist_Process_File_Always
255 autocmd BufEnter * call s:Tlist_Refresh()
259 autocmd GUIEnter * call s:Tlist_Menu_Init()
262 " When the taglist buffer is created when loading a Vim session file,
263 " the taglist buffer needs to be initialized. The BufFilePost event
264 " is used to handle this case.
265 autocmd BufFilePost __Tag_List__ call s:Tlist_Vim_Session_Load()
267 " Define the user commands to manage the taglist window
268 command! -nargs=0 -bar TlistToggle call s:Tlist_Window_Toggle()
269 command! -nargs=0 -bar TlistOpen call s:Tlist_Window_Open()
270 " For backwards compatiblity define the Tlist command
271 command! -nargs=0 -bar Tlist TlistToggle
272 command! -nargs=+ -complete=file TlistAddFiles
273 \ call s:Tlist_Add_Files(<f-args>)
274 command! -nargs=+ -complete=dir TlistAddFilesRecursive
275 \ call s:Tlist_Add_Files_Recursive(<f-args>)
276 command! -nargs=0 -bar TlistClose call s:Tlist_Window_Close()
277 command! -nargs=0 -bar TlistUpdate call s:Tlist_Update_Current_File()
278 command! -nargs=0 -bar TlistHighlightTag call s:Tlist_Window_Highlight_Tag(
279 \ fnamemodify(bufname('%'), ':p'), line('.'), 2, 1)
280 " For backwards compatiblity define the TlistSync command
281 command! -nargs=0 -bar TlistSync TlistHighlightTag
282 command! -nargs=* -complete=buffer TlistShowPrototype
283 \ echo Tlist_Get_Tag_Prototype_By_Line(<f-args>)
284 command! -nargs=* -complete=buffer TlistShowTag
285 \ echo Tlist_Get_Tagname_By_Line(<f-args>)
286 command! -nargs=* -complete=file TlistSessionLoad
287 \ call s:Tlist_Session_Load(<q-args>)
288 command! -nargs=* -complete=file TlistSessionSave
289 \ call s:Tlist_Session_Save(<q-args>)
290 command! -bar TlistLock let Tlist_Auto_Update=0
291 command! -bar TlistUnlock let Tlist_Auto_Update=1
293 " Commands for enabling/disabling debug and to display debug messages
294 command! -nargs=? -complete=file -bar TlistDebug
295 \ call s:Tlist_Debug_Enable(<q-args>)
296 command! -nargs=0 -bar TlistUndebug call s:Tlist_Debug_Disable()
297 command! -nargs=0 -bar TlistMessages call s:Tlist_Debug_Show()
299 " Define autocommands to autoload the taglist plugin when needed.
301 " Trick to get the current script ID
303 let s:tlist_sid = substitute(maparg('<SID>xx'), '<SNR>\(\d\+_\)xx$',
307 exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_* source ' .
308 \ escape(expand('<sfile>'), ' ')
309 exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Window_* source ' .
310 \ escape(expand('<sfile>'), ' ')
311 exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Menu_* source ' .
312 \ escape(expand('<sfile>'), ' ')
313 exe 'autocmd FuncUndefined Tlist_* source ' .
314 \ escape(expand('<sfile>'), ' ')
315 exe 'autocmd FuncUndefined TagList_* source ' .
316 \ escape(expand('<sfile>'), ' ')
318 let loaded_taglist = 'fast_load_done'
320 if g:Tlist_Show_Menu && has('gui_running')
321 call s:Tlist_Menu_Init()
325 let &cpo = s:cpo_save
329 if !exists('s:tlist_sid')
330 " Two or more versions of taglist plugin are installed. Don't
331 " load this version of the plugin.
337 if loaded_taglist != 'fast_load_done'
339 let &cpo = s:cpo_save
343 " Taglist plugin functionality is available
344 let loaded_taglist = 'available'
346 "------------------- end of user configurable options --------------------
348 " Default language specific settings for supported file types and tag types
350 " Variable name format:
352 " s:tlist_def_{vim_ftype}_settings
354 " vim_ftype - Filetype detected by Vim
358 " <ctags_ftype>;<flag>:<name>;<flag>:<name>;...
360 " ctags_ftype - File type supported by exuberant ctags
361 " flag - Flag supported by exuberant ctags to generate a tag type
362 " name - Name of the tag type used in the taglist window to display the
367 let s:tlist_def_asm_settings = 'asm;d:define;l:label;m:macro;t:type'
370 let s:tlist_def_aspperl_settings = 'asp;f:function;s:sub;v:variable'
373 let s:tlist_def_aspvbs_settings = 'asp;f:function;s:sub;v:variable'
376 let s:tlist_def_awk_settings = 'awk;f:function'
379 let s:tlist_def_beta_settings = 'beta;f:fragment;s:slot;v:pattern'
382 let s:tlist_def_c_settings = 'c;d:macro;g:enum;s:struct;u:union;t:typedef;' .
383 \ 'v:variable;f:function'
386 let s:tlist_def_cpp_settings = 'c++;n:namespace;v:variable;d:macro;t:typedef;' .
387 \ 'c:class;g:enum;s:struct;u:union;f:function'
390 let s:tlist_def_cs_settings = 'c#;d:macro;t:typedef;n:namespace;c:class;' .
391 \ 'E:event;g:enum;s:struct;i:interface;' .
392 \ 'p:properties;m:method'
395 let s:tlist_def_cobol_settings = 'cobol;d:data;f:file;g:group;p:paragraph;' .
396 \ 'P:program;s:section'
399 let s:tlist_def_eiffel_settings = 'eiffel;c:class;f:feature'
402 let s:tlist_def_erlang_settings = 'erlang;d:macro;r:record;m:module;f:function'
404 " expect (same as tcl) language
405 let s:tlist_def_expect_settings = 'tcl;c:class;f:method;p:procedure'
408 let s:tlist_def_fortran_settings = 'fortran;p:program;b:block data;' .
409 \ 'c:common;e:entry;i:interface;k:type;l:label;m:module;' .
410 \ 'n:namelist;t:derived;v:variable;f:function;s:subroutine'
413 let s:tlist_def_html_settings = 'html;a:anchor;f:javascript function'
416 let s:tlist_def_java_settings = 'java;p:package;c:class;i:interface;' .
419 " javascript language
420 let s:tlist_def_javascript_settings = 'javascript;f:function'
423 let s:tlist_def_lisp_settings = 'lisp;f:function'
426 let s:tlist_def_lua_settings = 'lua;f:function'
429 let s:tlist_def_make_settings = 'make;m:macro'
432 let s:tlist_def_pascal_settings = 'pascal;f:function;p:procedure'
435 let s:tlist_def_perl_settings = 'perl;c:constant;l:label;p:package;s:subroutine'
438 let s:tlist_def_php_settings = 'php;c:class;d:constant;v:variable;f:function'
441 let s:tlist_def_python_settings = 'python;c:class;m:member;f:function'
444 let s:tlist_def_rexx_settings = 'rexx;s:subroutine'
447 let s:tlist_def_ruby_settings = 'ruby;c:class;f:method;F:function;' .
448 \ 'm:singleton method'
451 let s:tlist_def_scheme_settings = 'scheme;s:set;f:function'
454 let s:tlist_def_sh_settings = 'sh;f:function'
457 let s:tlist_def_csh_settings = 'sh;f:function'
460 let s:tlist_def_zsh_settings = 'sh;f:function'
463 let s:tlist_def_slang_settings = 'slang;n:namespace;f:function'
466 let s:tlist_def_sml_settings = 'sml;e:exception;c:functor;s:signature;' .
467 \ 'r:structure;t:type;v:value;f:function'
470 let s:tlist_def_sql_settings = 'sql;c:cursor;F:field;P:package;r:record;' .
471 \ 's:subtype;t:table;T:trigger;v:variable;f:function;p:procedure'
474 let s:tlist_def_tcl_settings = 'tcl;c:class;f:method;m:method;p:procedure'
477 let s:tlist_def_vera_settings = 'vera;c:class;d:macro;e:enumerator;' .
478 \ 'f:function;g:enum;m:member;p:program;' .
479 \ 'P:prototype;t:task;T:typedef;v:variable;' .
483 let s:tlist_def_verilog_settings = 'verilog;m:module;c:constant;P:parameter;' .
484 \ 'e:event;r:register;t:task;w:write;p:port;v:variable;f:function'
487 let s:tlist_def_vim_settings = 'vim;a:autocmds;v:variable;f:function'
490 let s:tlist_def_yacc_settings = 'yacc;l:label'
492 "------------------- end of language specific options --------------------
494 " Vim window size is changed by the taglist plugin or not
495 let s:tlist_winsize_chgd = -1
496 " Taglist window is maximized or not
497 let s:tlist_win_maximized = 0
498 " Name of files in the taglist
499 let s:tlist_file_names=''
500 " Number of files in the taglist
501 let s:tlist_file_count = 0
502 " Number of filetypes supported by taglist
503 let s:tlist_ftype_count = 0
504 " Is taglist part of other plugins like winmanager or cream?
505 let s:tlist_app_name = "none"
506 " Are we displaying brief help text
507 let s:tlist_brief_help = 1
508 " List of files removed on user request
509 let s:tlist_removed_flist = ""
510 " Index of current file displayed in the taglist window
511 let s:tlist_cur_file_idx = -1
512 " Taglist menu is empty or not
513 let s:tlist_menu_empty = 1
515 " An autocommand is used to refresh the taglist window when entering any
516 " buffer. We don't want to refresh the taglist window if we are entering the
517 " file window from one of the taglist functions. The 'Tlist_Skip_Refresh'
518 " variable is used to skip the refresh of the taglist window and is set
519 " and cleared appropriately.
520 let s:Tlist_Skip_Refresh = 0
522 " Tlist_Window_Display_Help()
523 function! s:Tlist_Window_Display_Help()
524 if s:tlist_app_name == "winmanager"
525 " To handle a bug in the winmanager plugin, add a space at the
527 call setline('$', ' ')
530 if s:tlist_brief_help
532 call append(0, '" Press <F1> to display help text')
534 " Add the extensive help
535 call append(0, '" <enter> : Jump to tag definition')
536 call append(1, '" o : Jump to tag definition in new window')
537 call append(2, '" p : Preview the tag definition')
538 call append(3, '" <space> : Display tag prototype')
539 call append(4, '" u : Update tag list')
540 call append(5, '" s : Select sort field')
541 call append(6, '" d : Remove file from taglist')
542 call append(7, '" x : Zoom-out/Zoom-in taglist window')
543 call append(8, '" + : Open a fold')
544 call append(9, '" - : Close a fold')
545 call append(10, '" * : Open all folds')
546 call append(11, '" = : Close all folds')
547 call append(12, '" [[ : Move to the start of previous file')
548 call append(13, '" ]] : Move to the start of next file')
549 call append(14, '" q : Close the taglist window')
550 call append(15, '" <F1> : Remove help text')
554 " Tlist_Window_Toggle_Help_Text()
555 " Toggle taglist plugin help text between the full version and the brief
557 function! s:Tlist_Window_Toggle_Help_Text()
558 if g:Tlist_Compact_Format
559 " In compact display mode, do not display help
563 " Include the empty line displayed after the help text
564 let brief_help_size = 1
565 let full_help_size = 16
569 " Set report option to a huge value to prevent informational messages
570 " while deleting the lines
571 let old_report = &report
574 " Remove the currently highlighted tag. Otherwise, the help text
575 " might be highlighted by mistake
578 " Toggle between brief and full help text
579 if s:tlist_brief_help
580 let s:tlist_brief_help = 0
582 " Remove the previous help
583 exe '1,' . brief_help_size . ' delete _'
585 " Adjust the start/end line numbers for the files
586 call s:Tlist_Window_Update_Line_Offsets(0, 1, full_help_size - brief_help_size)
588 let s:tlist_brief_help = 1
590 " Remove the previous help
591 exe '1,' . full_help_size . ' delete _'
593 " Adjust the start/end line numbers for the files
594 call s:Tlist_Window_Update_Line_Offsets(0, 0, full_help_size - brief_help_size)
597 call s:Tlist_Window_Display_Help()
599 " Restore the report option
600 let &report = old_report
602 setlocal nomodifiable
605 " Taglist debug support
606 let s:tlist_debug = 0
608 " File for storing the debug messages
609 let s:tlist_debug_file = ''
612 " Enable logging of taglist debug messages.
613 function! s:Tlist_Debug_Enable(...)
614 let s:tlist_debug = 1
616 " Check whether a valid file name is supplied.
618 let s:tlist_debug_file = fnamemodify(a:1, ':p')
621 exe 'redir! > ' . s:tlist_debug_file
624 " Check whether the log file is present/created
625 if !filewritable(s:tlist_debug_file)
626 call s:Tlist_Warning_Msg('Taglist: Unable to create log file '
627 \ . s:tlist_debug_file)
628 let s:tlist_debug_file = ''
633 " Tlist_Debug_Disable
634 " Disable logging of taglist debug messages.
635 function! s:Tlist_Debug_Disable(...)
636 let s:tlist_debug = 0
637 let s:tlist_debug_file = ''
641 " Display the taglist debug messages in a new window
642 function! s:Tlist_Debug_Show()
644 call s:Tlist_Warning_Msg('Taglist: No debug messages')
648 " Open a new window to display the taglist debug messages
649 new taglist_debug.txt
650 " Delete all the lines (if the buffer already exists)
653 silent! put =s:tlist_msg
654 " Move the cursor to the first line
659 " Log the supplied debug message along with the time
660 function! s:Tlist_Log_Msg(msg)
662 if s:tlist_debug_file != ''
663 exe 'redir >> ' . s:tlist_debug_file
664 silent echon strftime('%H:%M:%S') . ': ' . a:msg . "\n"
667 " Log the message into a variable
668 " Retain only the last 3000 characters
669 let len = strlen(s:tlist_msg)
671 let s:tlist_msg = strpart(s:tlist_msg, len - 3000)
673 let s:tlist_msg = s:tlist_msg . strftime('%H:%M:%S') . ': ' .
679 " Tlist_Warning_Msg()
680 " Display a message using WarningMsg highlight group
681 function! s:Tlist_Warning_Msg(msg)
687 " Last returned file index for file name lookup.
688 " Used to speed up file lookup
689 let s:tlist_file_name_idx_cache = -1
691 " Tlist_Get_File_Index()
692 " Return the index of the specified filename
693 function! s:Tlist_Get_File_Index(fname)
694 if s:tlist_file_count == 0 || a:fname == ''
698 " If the new filename is same as the last accessed filename, then
700 if s:tlist_file_name_idx_cache != -1 &&
701 \ s:tlist_file_name_idx_cache < s:tlist_file_count
702 if s:tlist_{s:tlist_file_name_idx_cache}_filename == a:fname
703 " Same as the last accessed file
704 return s:tlist_file_name_idx_cache
708 " First, check whether the filename is present
709 let s_fname = a:fname . "\n"
710 let i = stridx(s:tlist_file_names, s_fname)
712 let s:tlist_file_name_idx_cache = -1
716 " Second, compute the file name index
717 let nl_txt = substitute(strpart(s:tlist_file_names, 0, i), "[^\n]", '', 'g')
718 let s:tlist_file_name_idx_cache = strlen(nl_txt)
719 return s:tlist_file_name_idx_cache
722 " Last returned file index for line number lookup.
723 " Used to speed up file lookup
724 let s:tlist_file_lnum_idx_cache = -1
726 " Tlist_Window_Get_File_Index_By_Linenum()
727 " Return the index of the filename present in the specified line number
728 " Line number refers to the line number in the taglist window
729 function! s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
730 call s:Tlist_Log_Msg('Tlist_Window_Get_File_Index_By_Linenum (' . a:lnum . ')')
732 " First try to see whether the new line number is within the range
733 " of the last returned file
734 if s:tlist_file_lnum_idx_cache != -1 &&
735 \ s:tlist_file_lnum_idx_cache < s:tlist_file_count
736 if a:lnum >= s:tlist_{s:tlist_file_lnum_idx_cache}_start &&
737 \ a:lnum <= s:tlist_{s:tlist_file_lnum_idx_cache}_end
738 return s:tlist_file_lnum_idx_cache
744 if g:Tlist_Show_One_File
745 " Displaying only one file in the taglist window. Check whether
746 " the line is within the tags displayed for that file
747 if s:tlist_cur_file_idx != -1
748 if a:lnum >= s:tlist_{s:tlist_cur_file_idx}_start
749 \ && a:lnum <= s:tlist_{s:tlist_cur_file_idx}_end
750 let fidx = s:tlist_cur_file_idx
755 " Do a binary search in the taglist
757 let right = s:tlist_file_count - 1
760 let mid = (left + right) / 2
762 if a:lnum >= s:tlist_{mid}_start && a:lnum <= s:tlist_{mid}_end
763 let s:tlist_file_lnum_idx_cache = mid
767 if a:lnum < s:tlist_{mid}_start
774 if left >= 0 && left < s:tlist_file_count
775 \ && a:lnum >= s:tlist_{left}_start
776 \ && a:lnum <= s:tlist_{left}_end
781 let s:tlist_file_lnum_idx_cache = fidx
786 " Tlist_Exe_Cmd_No_Acmds
787 " Execute the specified Ex command after disabling autocommands
788 function! s:Tlist_Exe_Cmd_No_Acmds(cmd)
789 let old_eventignore = &eventignore
792 let &eventignore = old_eventignore
796 " Check whether tag listing is supported for the specified file
797 function! s:Tlist_Skip_File(filename, ftype)
798 " Skip buffers with no names and buffers with filetype not set
799 if a:filename == '' || a:ftype == ''
803 " Skip files which are not supported by exuberant ctags
804 " First check whether default settings for this filetype are available.
805 " If it is not available, then check whether user specified settings are
806 " available. If both are not available, then don't list the tags for this
808 let var = 's:tlist_def_' . a:ftype . '_settings'
810 let var = 'g:tlist_' . a:ftype . '_settings'
816 " Skip files which are not readable or files which are not yet stored
818 if !filereadable(a:filename)
825 " Tlist_User_Removed_File
826 " Returns 1 if a file is removed by a user from the taglist
827 function! s:Tlist_User_Removed_File(filename)
828 return stridx(s:tlist_removed_flist, a:filename . "\n") != -1
831 " Tlist_Update_Remove_List
832 " Update the list of user removed files from the taglist
833 " add == 1, add the file to the removed list
834 " add == 0, delete the file from the removed list
835 function! s:Tlist_Update_Remove_List(filename, add)
837 let s:tlist_removed_flist = s:tlist_removed_flist . a:filename . "\n"
839 let idx = stridx(s:tlist_removed_flist, a:filename . "\n")
840 let text_before = strpart(s:tlist_removed_flist, 0, idx)
841 let rem_text = strpart(s:tlist_removed_flist, idx)
842 let next_idx = stridx(rem_text, "\n")
843 let text_after = strpart(rem_text, next_idx + 1)
845 let s:tlist_removed_flist = text_before . text_after
849 " Tlist_FileType_Init
850 " Initialize the ctags arguments and tag variable for the specified
852 function! s:Tlist_FileType_Init(ftype)
853 call s:Tlist_Log_Msg('Tlist_FileType_Init (' . a:ftype . ')')
854 " If the user didn't specify any settings, then use the default
855 " ctags args. Otherwise, use the settings specified by the user
856 let var = 'g:tlist_' . a:ftype . '_settings'
858 " User specified ctags arguments
859 let settings = {var} . ';'
861 " Default ctags arguments
862 let var = 's:tlist_def_' . a:ftype . '_settings'
864 " No default settings for this file type. This filetype is
868 let settings = s:tlist_def_{a:ftype}_settings . ';'
871 let msg = 'Taglist: Invalid ctags option setting - ' . settings
873 " Format of the option that specifies the filetype and ctags arugments:
875 " <language_name>;flag1:name1;flag2:name2;flag3:name3
878 " Extract the file type to pass to ctags. This may be different from the
879 " file type detected by Vim
880 let pos = stridx(settings, ';')
882 call s:Tlist_Warning_Msg(msg)
885 let ctags_ftype = strpart(settings, 0, pos)
887 call s:Tlist_Warning_Msg(msg)
890 " Make sure a valid filetype is supplied. If the user didn't specify a
891 " valid filetype, then the ctags option settings may be treated as the
893 if ctags_ftype =~ ':'
894 call s:Tlist_Warning_Msg(msg)
898 " Remove the file type from settings
899 let settings = strpart(settings, pos + 1)
901 call s:Tlist_Warning_Msg(msg)
905 " Process all the specified ctags flags. The format is
906 " flag1:name1;flag2:name2;flag3:name3
911 let pos = stridx(settings, ':')
913 call s:Tlist_Warning_Msg(msg)
916 let flag = strpart(settings, 0, pos)
918 call s:Tlist_Warning_Msg(msg)
921 " Remove the flag from settings
922 let settings = strpart(settings, pos + 1)
924 " Extract the tag type name
925 let pos = stridx(settings, ';')
927 call s:Tlist_Warning_Msg(msg)
930 let name = strpart(settings, 0, pos)
932 call s:Tlist_Warning_Msg(msg)
935 let settings = strpart(settings, pos + 1)
939 let s:tlist_{a:ftype}_{cnt}_name = flag
940 let s:tlist_{a:ftype}_{cnt}_fullname = name
941 let ctags_flags = ctags_flags . flag
944 let s:tlist_{a:ftype}_ctags_args = '--language-force=' . ctags_ftype .
945 \ ' --' . ctags_ftype . '-types=' . ctags_flags
946 let s:tlist_{a:ftype}_count = cnt
947 let s:tlist_{a:ftype}_ctags_flags = ctags_flags
949 " Save the filetype name
950 let s:tlist_ftype_{s:tlist_ftype_count}_name = a:ftype
951 let s:tlist_ftype_count = s:tlist_ftype_count + 1
956 " Tlist_Detect_Filetype
957 " Determine the filetype for the specified file using the filetypedetect
959 function! s:Tlist_Detect_Filetype(fname)
960 " Ignore the filetype autocommands
961 let old_eventignore = &eventignore
962 set eventignore=FileType
964 " Save the 'filetype', as this will be changed temporarily
965 let old_filetype = &filetype
967 " Run the filetypedetect group of autocommands to determine
969 exe 'doautocmd filetypedetect BufRead ' . a:fname
971 " Save the detected filetype
972 let ftype = &filetype
974 " Restore the previous state
975 let &filetype = old_filetype
976 let &eventignore = old_eventignore
981 " Tlist_Get_Buffer_Filetype
982 " Get the filetype for the specified buffer
983 function! s:Tlist_Get_Buffer_Filetype(bnum)
984 let buf_ft = getbufvar(a:bnum, '&filetype')
987 " For loaded buffers, the 'filetype' is already determined
991 " For unloaded buffers, if the 'filetype' option is set, return it
996 " Skip non-existent buffers
997 if !bufexists(a:bnum)
1001 " For buffers whose filetype is not yet determined, try to determine
1003 let bname = bufname(a:bnum)
1005 return s:Tlist_Detect_Filetype(bname)
1008 " Tlist_Discard_TagInfo
1009 " Discard the stored tag information for a file
1010 function! s:Tlist_Discard_TagInfo(fidx)
1011 call s:Tlist_Log_Msg('Tlist_Discard_TagInfo (' .
1012 \ s:tlist_{a:fidx}_filename . ')')
1013 let ftype = s:tlist_{a:fidx}_filetype
1015 " Discard information about the tags defined in the file
1017 while i <= s:tlist_{a:fidx}_tag_count
1018 let fidx_i = 's:tlist_' . a:fidx . '_' . i
1020 unlet! {fidx_i}_tag_name
1021 unlet! {fidx_i}_tag_type
1022 unlet! {fidx_i}_ttype_idx
1023 unlet! {fidx_i}_tag_proto
1024 unlet! {fidx_i}_tag_searchpat
1025 unlet! {fidx_i}_tag_linenum
1029 let s:tlist_{a:fidx}_tag_count = 0
1031 " Discard information about tag type groups
1033 while i <= s:tlist_{ftype}_count
1034 let ttype = s:tlist_{ftype}_{i}_name
1035 if s:tlist_{a:fidx}_{ttype} != ''
1036 let fidx_ttype = 's:tlist_' . a:fidx . '_' . ttype
1037 let {fidx_ttype} = ''
1038 let {fidx_ttype}_offset = 0
1039 let cnt = {fidx_ttype}_count
1040 let {fidx_ttype}_count = 0
1043 unlet! {fidx_ttype}_{j}
1050 " Discard the stored menu command also
1051 let s:tlist_{a:fidx}_menu_cmd = ''
1054 " Tlist_Window_Update_Line_Offsets
1055 " Update the line offsets for tags for files starting from start_idx
1056 " and displayed in the taglist window by the specified offset
1057 function! s:Tlist_Window_Update_Line_Offsets(start_idx, increment, offset)
1060 while i < s:tlist_file_count
1061 if s:tlist_{i}_visible
1062 " Update the start/end line number only if the file is visible
1064 let s:tlist_{i}_start = s:tlist_{i}_start + a:offset
1065 let s:tlist_{i}_end = s:tlist_{i}_end + a:offset
1067 let s:tlist_{i}_start = s:tlist_{i}_start - a:offset
1068 let s:tlist_{i}_end = s:tlist_{i}_end - a:offset
1075 " Tlist_Discard_FileInfo
1076 " Discard the stored information for a file
1077 function! s:Tlist_Discard_FileInfo(fidx)
1078 call s:Tlist_Log_Msg('Tlist_Discard_FileInfo (' .
1079 \ s:tlist_{a:fidx}_filename . ')')
1080 call s:Tlist_Discard_TagInfo(a:fidx)
1082 let ftype = s:tlist_{a:fidx}_filetype
1085 while i <= s:tlist_{ftype}_count
1086 let ttype = s:tlist_{ftype}_{i}_name
1087 unlet! s:tlist_{a:fidx}_{ttype}
1088 unlet! s:tlist_{a:fidx}_{ttype}_offset
1089 unlet! s:tlist_{a:fidx}_{ttype}_count
1093 unlet! s:tlist_{a:fidx}_filename
1094 unlet! s:tlist_{a:fidx}_sort_type
1095 unlet! s:tlist_{a:fidx}_filetype
1096 unlet! s:tlist_{a:fidx}_mtime
1097 unlet! s:tlist_{a:fidx}_start
1098 unlet! s:tlist_{a:fidx}_end
1099 unlet! s:tlist_{a:fidx}_valid
1100 unlet! s:tlist_{a:fidx}_visible
1101 unlet! s:tlist_{a:fidx}_tag_count
1102 unlet! s:tlist_{a:fidx}_menu_cmd
1105 " Tlist_Window_Remove_File_From_Display
1106 " Remove the specified file from display
1107 function! s:Tlist_Window_Remove_File_From_Display(fidx)
1108 call s:Tlist_Log_Msg('Tlist_Window_Remove_File_From_Display (' .
1109 \ s:tlist_{a:fidx}_filename . ')')
1110 " If the file is not visible then no need to remove it
1111 if !s:tlist_{a:fidx}_visible
1115 " Remove the tags displayed for the specified file from the window
1116 let start = s:tlist_{a:fidx}_start
1117 " Include the empty line after the last line also
1118 if g:Tlist_Compact_Format
1119 let end = s:tlist_{a:fidx}_end
1121 let end = s:tlist_{a:fidx}_end + 1
1125 exe 'silent! ' . start . ',' . end . 'delete _'
1126 setlocal nomodifiable
1128 " Correct the start and end line offsets for all the files following
1129 " this file, as the tags for this file are removed
1130 call s:Tlist_Window_Update_Line_Offsets(a:fidx + 1, 0, end - start + 1)
1134 " Remove the file under the cursor or the specified file index
1135 " user_request - User requested to remove the file from taglist
1136 function! s:Tlist_Remove_File(file_idx, user_request)
1137 let fidx = a:file_idx
1140 let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
1145 call s:Tlist_Log_Msg('Tlist_Remove_File (' .
1146 \ s:tlist_{fidx}_filename . ', ' . a:user_request . ')')
1148 let save_winnr = winnr()
1149 let winnum = bufwinnr(g:TagList_title)
1151 " Taglist window is open, remove the file from display
1153 if save_winnr != winnum
1154 let old_eventignore = &eventignore
1156 exe winnum . 'wincmd w'
1159 call s:Tlist_Window_Remove_File_From_Display(fidx)
1161 if save_winnr != winnum
1162 exe save_winnr . 'wincmd w'
1163 let &eventignore = old_eventignore
1167 let fname = s:tlist_{fidx}_filename
1170 " As the user requested to remove the file from taglist,
1171 " add it to the removed list
1172 call s:Tlist_Update_Remove_List(fname, 1)
1175 " Remove the file name from the taglist list of filenames
1176 let idx = stridx(s:tlist_file_names, fname . "\n")
1177 let text_before = strpart(s:tlist_file_names, 0, idx)
1178 let rem_text = strpart(s:tlist_file_names, idx)
1179 let next_idx = stridx(rem_text, "\n")
1180 let text_after = strpart(rem_text, next_idx + 1)
1181 let s:tlist_file_names = text_before . text_after
1183 call s:Tlist_Discard_FileInfo(fidx)
1185 " Shift all the file variables by one index
1188 while i < s:tlist_file_count
1191 let s:tlist_{j}_filename = s:tlist_{i}_filename
1192 let s:tlist_{j}_sort_type = s:tlist_{i}_sort_type
1193 let s:tlist_{j}_filetype = s:tlist_{i}_filetype
1194 let s:tlist_{j}_mtime = s:tlist_{i}_mtime
1195 let s:tlist_{j}_start = s:tlist_{i}_start
1196 let s:tlist_{j}_end = s:tlist_{i}_end
1197 let s:tlist_{j}_valid = s:tlist_{i}_valid
1198 let s:tlist_{j}_visible = s:tlist_{i}_visible
1199 let s:tlist_{j}_tag_count = s:tlist_{i}_tag_count
1200 let s:tlist_{j}_menu_cmd = s:tlist_{i}_menu_cmd
1203 while k <= s:tlist_{j}_tag_count
1204 let s:tlist_{j}_{k}_tag = s:tlist_{i}_{k}_tag
1205 let s:tlist_{j}_{k}_tag_name = s:tlist_{i}_{k}_tag_name
1206 let s:tlist_{j}_{k}_tag_type = s:Tlist_Get_Tag_Type_By_Tag(i, k)
1207 let s:tlist_{j}_{k}_ttype_idx = s:tlist_{i}_{k}_ttype_idx
1208 let s:tlist_{j}_{k}_tag_proto = s:Tlist_Get_Tag_Prototype(i, k)
1209 let s:tlist_{j}_{k}_tag_searchpat = s:Tlist_Get_Tag_SearchPat(i, k)
1210 let s:tlist_{j}_{k}_tag_linenum = s:Tlist_Get_Tag_Linenum(i, k)
1214 let ftype = s:tlist_{i}_filetype
1217 while k <= s:tlist_{ftype}_count
1218 let ttype = s:tlist_{ftype}_{k}_name
1219 let s:tlist_{j}_{ttype} = s:tlist_{i}_{ttype}
1220 let s:tlist_{j}_{ttype}_offset = s:tlist_{i}_{ttype}_offset
1221 let s:tlist_{j}_{ttype}_count = s:tlist_{i}_{ttype}_count
1222 if s:tlist_{j}_{ttype} != ''
1224 while l <= s:tlist_{j}_{ttype}_count
1225 let s:tlist_{j}_{ttype}_{l} = s:tlist_{i}_{ttype}_{l}
1232 " As the file and tag information is copied to the new index,
1233 " discard the previous information
1234 call s:Tlist_Discard_FileInfo(i)
1239 " Reduce the number of files displayed
1240 let s:tlist_file_count = s:tlist_file_count - 1
1242 if g:Tlist_Show_One_File
1243 " If the tags for only one file is displayed and if we just
1244 " now removed that file, then invalidate the current file idx
1245 if s:tlist_cur_file_idx == fidx
1246 let s:tlist_cur_file_idx = -1
1251 " Tlist_Window_Goto_Window
1252 " Goto the taglist window
1253 function! s:Tlist_Window_Goto_Window()
1254 let winnum = bufwinnr(g:TagList_title)
1256 if winnr() != winnum
1257 call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w')
1262 " Tlist_Window_Create
1263 " Create a new taglist window. If it is already open, jump to it
1264 function! s:Tlist_Window_Create()
1265 call s:Tlist_Log_Msg('Tlist_Window_Create()')
1266 " If the window is open, jump to it
1267 let winnum = bufwinnr(g:TagList_title)
1269 " Jump to the existing window
1270 if winnr() != winnum
1271 exe winnum . 'wincmd w'
1276 " If used with winmanager don't open windows. Winmanager will handle
1277 " the window/buffer management
1278 if s:tlist_app_name == "winmanager"
1282 " Create a new window. If user prefers a horizontal window, then open
1283 " a horizontally split window. Otherwise open a vertically split
1285 if g:Tlist_Use_Horiz_Window
1286 " Open a horizontally split window
1287 let win_dir = 'botright'
1288 " Horizontal window height
1289 let win_size = g:Tlist_WinHeight
1291 if s:tlist_winsize_chgd == -1
1292 " Open a vertically split window. Increase the window size, if
1293 " needed, to accomodate the new window
1294 if g:Tlist_Inc_Winwidth &&
1295 \ &columns < (80 + g:Tlist_WinWidth)
1296 " Save the original window position
1297 let s:tlist_pre_winx = getwinposx()
1298 let s:tlist_pre_winy = getwinposy()
1300 " one extra column is needed to include the vertical split
1301 let &columns= &columns + g:Tlist_WinWidth + 1
1303 let s:tlist_winsize_chgd = 1
1305 let s:tlist_winsize_chgd = 0
1309 if g:Tlist_Use_Right_Window
1310 " Open the window at the rightmost place
1311 let win_dir = 'botright vertical'
1313 " Open the window at the leftmost place
1314 let win_dir = 'topleft vertical'
1316 let win_size = g:Tlist_WinWidth
1319 " If the tag listing temporary buffer already exists, then reuse it.
1320 " Otherwise create a new buffer
1321 let bufnum = bufnr(g:TagList_title)
1323 " Create a new buffer
1324 let wcmd = g:TagList_title
1326 " Edit the existing buffer
1327 let wcmd = '+buffer' . bufnum
1330 " Create the taglist window
1331 exe 'silent! ' . win_dir . ' ' . win_size . 'split ' . wcmd
1333 " Save the new window position
1334 let s:tlist_winx = getwinposx()
1335 let s:tlist_winy = getwinposy()
1337 " Initialize the taglist window
1338 call s:Tlist_Window_Init()
1342 " Zoom (maximize/minimize) the taglist window
1343 function! s:Tlist_Window_Zoom()
1344 if s:tlist_win_maximized
1345 " Restore the window back to the previous size
1346 if g:Tlist_Use_Horiz_Window
1347 exe 'resize ' . g:Tlist_WinHeight
1349 exe 'vert resize ' . g:Tlist_WinWidth
1351 let s:tlist_win_maximized = 0
1353 " Set the window size to the maximum possible without closing other
1355 if g:Tlist_Use_Horiz_Window
1360 let s:tlist_win_maximized = 1
1365 " When the mouse cursor is over a tag in the taglist window, display the
1366 " tag prototype (balloon)
1367 function! Tlist_Ballon_Expr()
1368 " Get the file index
1369 let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(v:beval_lnum)
1374 " Get the tag output line for the current tag
1375 let tidx = s:Tlist_Window_Get_Tag_Index(fidx, v:beval_lnum)
1380 " Get the tag search pattern and display it
1381 return s:Tlist_Get_Tag_Prototype(fidx, tidx)
1384 " Tlist_Window_Check_Width
1385 " Check the width of the taglist window. For horizontally split windows, the
1386 " 'winfixheight' option is used to fix the height of the window. For
1387 " vertically split windows, Vim doesn't support the 'winfixwidth' option. So
1388 " need to handle window width changes from this function.
1389 function! s:Tlist_Window_Check_Width()
1390 let tlist_winnr = bufwinnr(g:TagList_title)
1391 if tlist_winnr == -1
1395 let width = winwidth(tlist_winnr)
1396 if width != g:Tlist_WinWidth
1397 call s:Tlist_Log_Msg("Tlist_Window_Check_Width: Changing window " .
1398 \ "width from " . width . " to " . g:Tlist_WinWidth)
1399 let save_winnr = winnr()
1400 if save_winnr != tlist_winnr
1401 call s:Tlist_Exe_Cmd_No_Acmds(tlist_winnr . 'wincmd w')
1403 exe 'vert resize ' . g:Tlist_WinWidth
1404 if save_winnr != tlist_winnr
1405 call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
1410 " Tlist_Window_Exit_Only_Window
1411 " If the 'Tlist_Exit_OnlyWindow' option is set, then exit Vim if only the
1412 " taglist window is present.
1413 function! s:Tlist_Window_Exit_Only_Window()
1414 " Before quitting Vim, delete the taglist buffer so that
1415 " the '0 mark is correctly set to the previous buffer.
1417 if winbufnr(2) == -1
1422 if winbufnr(2) == -1
1423 if tabpagenr('$') == 1
1424 " Only one tag page is present
1428 " More than one tab page is present. Close only the current
1437 " Set the default options for the taglist window
1438 function! s:Tlist_Window_Init()
1439 call s:Tlist_Log_Msg('Tlist_Window_Init()')
1441 " The 'readonly' option should not be set for the taglist buffer.
1442 " If Vim is started as "view/gview" or if the ":view" command is
1443 " used, then the 'readonly' option is set for all the buffers.
1444 " Unset it for the taglist buffer
1447 " Set the taglist buffer filetype to taglist
1448 setlocal filetype=taglist
1450 " Define taglist window element highlighting
1451 syntax match TagListComment '^" .*'
1452 syntax match TagListFileName '^[^" ].*$'
1453 syntax match TagListTitle '^ \S.*$'
1454 syntax match TagListTagScope '\s\[.\{-\}\]$'
1456 " Define the highlighting only if colors are supported
1457 if has('gui_running') || &t_Co > 2
1458 " Colors to highlight various taglist window elements
1459 " If user defined highlighting group exists, then use them.
1460 " Otherwise, use default highlight groups.
1461 if hlexists('MyTagListTagName')
1462 highlight link TagListTagName MyTagListTagName
1464 highlight default link TagListTagName Search
1466 " Colors to highlight comments and titles
1467 if hlexists('MyTagListComment')
1468 highlight link TagListComment MyTagListComment
1470 highlight clear TagListComment
1471 highlight default link TagListComment Comment
1473 if hlexists('MyTagListTitle')
1474 highlight link TagListTitle MyTagListTitle
1476 highlight clear TagListTitle
1477 highlight default link TagListTitle Title
1479 if hlexists('MyTagListFileName')
1480 highlight link TagListFileName MyTagListFileName
1482 highlight clear TagListFileName
1483 highlight default TagListFileName guibg=Grey ctermbg=darkgray
1484 \ guifg=white ctermfg=white
1486 if hlexists('MyTagListTagScope')
1487 highlight link TagListTagScope MyTagListTagScope
1489 highlight clear TagListTagScope
1490 highlight default link TagListTagScope Identifier
1493 highlight default TagListTagName term=reverse cterm=reverse
1496 " Folding related settings
1498 setlocal foldminlines=0
1499 setlocal foldmethod=manual
1500 setlocal foldlevel=9999
1501 if g:Tlist_Enable_Fold_Column
1502 setlocal foldcolumn=3
1504 setlocal foldcolumn=0
1506 setlocal foldtext=v:folddashes.getline(v:foldstart)
1508 if s:tlist_app_name != "winmanager"
1509 " Mark buffer as scratch
1510 silent! setlocal buftype=nofile
1511 if s:tlist_app_name == "none"
1512 silent! setlocal bufhidden=delete
1514 silent! setlocal noswapfile
1515 " Due to a bug in Vim 6.0, the winbufnr() function fails for unlisted
1516 " buffers. So if the taglist buffer is unlisted, multiple taglist
1517 " windows will be opened. This bug is fixed in Vim 6.1 and above
1519 silent! setlocal nobuflisted
1523 silent! setlocal nowrap
1525 " If the 'number' option is set in the source window, it will affect the
1526 " taglist window. So forcefully disable 'number' option for the taglist
1528 silent! setlocal nonumber
1530 " Use fixed height when horizontally split window is used
1531 if g:Tlist_Use_Horiz_Window
1536 if !g:Tlist_Use_Horiz_Window && v:version >= 700
1540 " Setup balloon evaluation to display tag prototype
1541 if v:version >= 700 && has('balloon_eval')
1542 setlocal balloonexpr=Tlist_Ballon_Expr()
1546 " Setup the cpoptions properly for the maps to work
1547 let old_cpoptions = &cpoptions
1550 " Create buffer local mappings for jumping to the tags and sorting the list
1551 nnoremap <buffer> <silent> <CR>
1552 \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
1553 nnoremap <buffer> <silent> o
1554 \ :call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR>
1555 nnoremap <buffer> <silent> p
1556 \ :call <SID>Tlist_Window_Jump_To_Tag('preview')<CR>
1557 nnoremap <buffer> <silent> P
1558 \ :call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR>
1560 nnoremap <buffer> <silent> t
1561 \ :call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR>
1562 nnoremap <buffer> <silent> <C-t>
1563 \ :call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR>
1565 nnoremap <buffer> <silent> <2-LeftMouse>
1566 \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
1567 nnoremap <buffer> <silent> s
1568 \ :call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR>
1569 nnoremap <buffer> <silent> + :silent! foldopen<CR>
1570 nnoremap <buffer> <silent> - :silent! foldclose<CR>
1571 nnoremap <buffer> <silent> * :silent! %foldopen!<CR>
1572 nnoremap <buffer> <silent> = :silent! %foldclose<CR>
1573 nnoremap <buffer> <silent> <kPlus> :silent! foldopen<CR>
1574 nnoremap <buffer> <silent> <kMinus> :silent! foldclose<CR>
1575 nnoremap <buffer> <silent> <kMultiply> :silent! %foldopen!<CR>
1576 nnoremap <buffer> <silent> <Space> :call <SID>Tlist_Window_Show_Info()<CR>
1577 nnoremap <buffer> <silent> u :call <SID>Tlist_Window_Update_File()<CR>
1578 nnoremap <buffer> <silent> d :call <SID>Tlist_Remove_File(-1, 1)<CR>
1579 nnoremap <buffer> <silent> x :call <SID>Tlist_Window_Zoom()<CR>
1580 nnoremap <buffer> <silent> [[ :call <SID>Tlist_Window_Move_To_File(-1)<CR>
1581 nnoremap <buffer> <silent> <BS> :call <SID>Tlist_Window_Move_To_File(-1)<CR>
1582 nnoremap <buffer> <silent> ]] :call <SID>Tlist_Window_Move_To_File(1)<CR>
1583 nnoremap <buffer> <silent> <Tab> :call <SID>Tlist_Window_Move_To_File(1)<CR>
1584 nnoremap <buffer> <silent> <F1> :call <SID>Tlist_Window_Toggle_Help_Text()<CR>
1585 nnoremap <buffer> <silent> q :close<CR>
1587 " Insert mode mappings
1588 inoremap <buffer> <silent> <CR>
1589 \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
1590 " Windows needs return
1591 inoremap <buffer> <silent> <Return>
1592 \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
1593 inoremap <buffer> <silent> o
1594 \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR>
1595 inoremap <buffer> <silent> p
1596 \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('preview')<CR>
1597 inoremap <buffer> <silent> P
1598 \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR>
1600 inoremap <buffer> <silent> t
1601 \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR>
1602 inoremap <buffer> <silent> <C-t>
1603 \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR>
1605 inoremap <buffer> <silent> <2-LeftMouse>
1606 \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
1607 inoremap <buffer> <silent> s
1608 \ <C-o>:call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR>
1609 inoremap <buffer> <silent> + <C-o>:silent! foldopen<CR>
1610 inoremap <buffer> <silent> - <C-o>:silent! foldclose<CR>
1611 inoremap <buffer> <silent> * <C-o>:silent! %foldopen!<CR>
1612 inoremap <buffer> <silent> = <C-o>:silent! %foldclose<CR>
1613 inoremap <buffer> <silent> <kPlus> <C-o>:silent! foldopen<CR>
1614 inoremap <buffer> <silent> <kMinus> <C-o>:silent! foldclose<CR>
1615 inoremap <buffer> <silent> <kMultiply> <C-o>:silent! %foldopen!<CR>
1616 inoremap <buffer> <silent> <Space> <C-o>:call
1617 \ <SID>Tlist_Window_Show_Info()<CR>
1618 inoremap <buffer> <silent> u
1619 \ <C-o>:call <SID>Tlist_Window_Update_File()<CR>
1620 inoremap <buffer> <silent> d <C-o>:call <SID>Tlist_Remove_File(-1, 1)<CR>
1621 inoremap <buffer> <silent> x <C-o>:call <SID>Tlist_Window_Zoom()<CR>
1622 inoremap <buffer> <silent> [[ <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR>
1623 inoremap <buffer> <silent> <BS> <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR>
1624 inoremap <buffer> <silent> ]] <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR>
1625 inoremap <buffer> <silent> <Tab> <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR>
1626 inoremap <buffer> <silent> <F1> <C-o>:call <SID>Tlist_Window_Toggle_Help_Text()<CR>
1627 inoremap <buffer> <silent> q <C-o>:close<CR>
1629 " Map single left mouse click if the user wants this functionality
1630 if g:Tlist_Use_SingleClick == 1
1631 " Contributed by Bindu Wavell
1632 " attempt to perform single click mapping, it would be much
1633 " nicer if we could nnoremap <buffer> ... however vim does
1634 " not fire the <buffer> <leftmouse> when you use the mouse
1635 " to enter a buffer.
1636 let clickmap = ':if bufname("%") =~ "__Tag_List__" <bar> ' .
1637 \ 'call <SID>Tlist_Window_Jump_To_Tag("useopen") ' .
1638 \ '<bar> endif <CR>'
1639 if maparg('<leftmouse>', 'n') == ''
1640 " no mapping for leftmouse
1641 exe ':nnoremap <silent> <leftmouse> <leftmouse>' . clickmap
1644 let mapcmd = ':nnoremap <silent> <leftmouse> <leftmouse>'
1645 let mapcmd = mapcmd . substitute(substitute(
1646 \ maparg('<leftmouse>', 'n'), '|', '<bar>', 'g'),
1647 \ '\c^<leftmouse>', '', '')
1648 let mapcmd = mapcmd . clickmap
1653 " Define the taglist autocommands
1654 augroup TagListAutoCmds
1656 " Display the tag prototype for the tag under the cursor.
1657 autocmd CursorHold __Tag_List__ call s:Tlist_Window_Show_Info()
1658 " Highlight the current tag periodically
1659 autocmd CursorHold * silent call s:Tlist_Window_Highlight_Tag(
1660 \ fnamemodify(bufname('%'), ':p'), line('.'), 1, 0)
1662 " Adjust the Vim window width when taglist window is closed
1663 autocmd BufUnload __Tag_List__ call s:Tlist_Post_Close_Cleanup()
1664 " Close the fold for this buffer when leaving the buffer
1665 if g:Tlist_File_Fold_Auto_Close
1666 autocmd BufEnter * silent
1667 \ call s:Tlist_Window_Open_File_Fold(expand('<abuf>'))
1669 " Exit Vim itself if only the taglist window is present (optional)
1670 if g:Tlist_Exit_OnlyWindow
1671 autocmd BufEnter __Tag_List__ nested
1672 \ call s:Tlist_Window_Exit_Only_Window()
1674 if s:tlist_app_name != "winmanager" &&
1675 \ !g:Tlist_Process_File_Always &&
1676 \ (!has('gui_running') || !g:Tlist_Show_Menu)
1677 " Auto refresh the taglist window
1678 autocmd BufEnter * call s:Tlist_Refresh()
1681 if !g:Tlist_Use_Horiz_Window
1683 autocmd WinEnter * call s:Tlist_Window_Check_Width()
1687 autocmd TabEnter * silent call s:Tlist_Refresh_Folds()
1691 " Restore the previous cpoptions settings
1692 let &cpoptions = old_cpoptions
1695 " Tlist_Window_Refresh
1696 " Display the tags for all the files in the taglist window
1697 function! s:Tlist_Window_Refresh()
1698 call s:Tlist_Log_Msg('Tlist_Window_Refresh()')
1699 " Set report option to a huge value to prevent informational messages
1700 " while deleting the lines
1701 let old_report = &report
1704 " Mark the buffer as modifiable
1707 " Delete the contents of the buffer to the black-hole register
1710 " As we have cleared the taglist window, mark all the files
1713 while i < s:tlist_file_count
1714 let s:tlist_{i}_visible = 0
1718 if g:Tlist_Compact_Format == 0
1719 " Display help in non-compact mode
1720 call s:Tlist_Window_Display_Help()
1723 " Mark the buffer as not modifiable
1724 setlocal nomodifiable
1726 " Restore the report option
1727 let &report = old_report
1729 " If the tags for only one file should be displayed in the taglist
1730 " window, then no need to add the tags here. The bufenter autocommand
1731 " will add the tags for that file.
1732 if g:Tlist_Show_One_File
1736 " List all the tags for the previously processed files
1737 " Do this only if taglist is configured to display tags for more than
1738 " one file. Otherwise, when Tlist_Show_One_File is configured,
1739 " tags for the wrong file will be displayed.
1741 while i < s:tlist_file_count
1742 call s:Tlist_Window_Refresh_File(s:tlist_{i}_filename,
1743 \ s:tlist_{i}_filetype)
1747 if g:Tlist_Auto_Update
1748 " Add and list the tags for all buffers in the Vim buffer list
1750 let last_bufnum = bufnr('$')
1751 while i <= last_bufnum
1753 let fname = fnamemodify(bufname(i), ':p')
1754 let ftype = s:Tlist_Get_Buffer_Filetype(i)
1755 " If the file doesn't support tag listing, skip it
1756 if !s:Tlist_Skip_File(fname, ftype)
1757 call s:Tlist_Window_Refresh_File(fname, ftype)
1764 " If Tlist_File_Fold_Auto_Close option is set, then close all the folds
1765 if g:Tlist_File_Fold_Auto_Close
1766 " Close all the folds
1770 " Move the cursor to the top of the taglist window
1774 " Tlist_Post_Close_Cleanup()
1775 " Close the taglist window and adjust the Vim window width
1776 function! s:Tlist_Post_Close_Cleanup()
1777 call s:Tlist_Log_Msg('Tlist_Post_Close_Cleanup()')
1778 " Mark all the files as not visible
1780 while i < s:tlist_file_count
1781 let s:tlist_{i}_visible = 0
1785 " Remove the taglist autocommands
1786 silent! autocmd! TagListAutoCmds
1788 " Clear all the highlights
1791 silent! syntax clear TagListTitle
1792 silent! syntax clear TagListComment
1793 silent! syntax clear TagListTagScope
1795 " Remove the left mouse click mapping if it was setup initially
1796 if g:Tlist_Use_SingleClick
1797 if hasmapto('<LeftMouse>')
1802 if s:tlist_app_name != "winmanager"
1803 if g:Tlist_Use_Horiz_Window || g:Tlist_Inc_Winwidth == 0 ||
1804 \ s:tlist_winsize_chgd != 1 ||
1805 \ &columns < (80 + g:Tlist_WinWidth)
1806 " No need to adjust window width if using horizontally split taglist
1807 " window or if columns is less than 101 or if the user chose not to
1808 " adjust the window width
1810 " If the user didn't manually move the window, then restore the window
1811 " position to the pre-taglist position
1812 if s:tlist_pre_winx != -1 && s:tlist_pre_winy != -1 &&
1813 \ getwinposx() == s:tlist_winx &&
1814 \ getwinposy() == s:tlist_winy
1815 exe 'winpos ' . s:tlist_pre_winx . ' ' . s:tlist_pre_winy
1818 " Adjust the Vim window width
1819 let &columns= &columns - (g:Tlist_WinWidth + 1)
1823 let s:tlist_winsize_chgd = -1
1825 " Reset taglist state variables
1826 if s:tlist_app_name == "winmanager"
1827 let s:tlist_app_name = "none"
1829 let s:tlist_window_initialized = 0
1832 " Tlist_Window_Refresh_File()
1833 " List the tags defined in the specified file in a Vim window
1834 function! s:Tlist_Window_Refresh_File(filename, ftype)
1835 call s:Tlist_Log_Msg('Tlist_Window_Refresh_File (' . a:filename . ')')
1836 " First check whether the file already exists
1837 let fidx = s:Tlist_Get_File_Index(a:filename)
1845 " Check whether this file is removed based on user request
1846 " If it is, then don't display the tags for this file
1847 if s:Tlist_User_Removed_File(a:filename)
1852 if file_listed && s:tlist_{fidx}_visible
1853 " Check whether the file tags are currently valid
1854 if s:tlist_{fidx}_valid
1855 " Goto the first line in the file
1856 exe s:tlist_{fidx}_start
1858 " If the line is inside a fold, open the fold
1859 if foldclosed('.') != -1
1860 exe "silent! " . s:tlist_{fidx}_start . "," .
1861 \ s:tlist_{fidx}_end . "foldopen!"
1866 " Discard and remove the tags for this file from display
1867 call s:Tlist_Discard_TagInfo(fidx)
1868 call s:Tlist_Window_Remove_File_From_Display(fidx)
1871 " Process and generate a list of tags defined in the file
1872 if !file_listed || !s:tlist_{fidx}_valid
1873 let ret_fidx = s:Tlist_Process_File(a:filename, a:ftype)
1880 " Set report option to a huge value to prevent informational messages
1881 " while adding lines to the taglist window
1882 let old_report = &report
1885 if g:Tlist_Show_One_File
1886 " Remove the previous file
1887 if s:tlist_cur_file_idx != -1
1888 call s:Tlist_Window_Remove_File_From_Display(s:tlist_cur_file_idx)
1889 let s:tlist_{s:tlist_cur_file_idx}_visible = 0
1890 let s:tlist_{s:tlist_cur_file_idx}_start = 0
1891 let s:tlist_{s:tlist_cur_file_idx}_end = 0
1893 let s:tlist_cur_file_idx = fidx
1896 " Mark the buffer as modifiable
1899 " Add new files to the end of the window. For existing files, add them at
1900 " the same line where they were previously present. If the file is not
1901 " visible, then add it at the end
1902 if s:tlist_{fidx}_start == 0 || !s:tlist_{fidx}_visible
1903 if g:Tlist_Compact_Format
1904 let s:tlist_{fidx}_start = line('$')
1906 let s:tlist_{fidx}_start = line('$') + 1
1910 let s:tlist_{fidx}_visible = 1
1912 " Goto the line where this file should be placed
1913 if g:Tlist_Compact_Format
1914 exe s:tlist_{fidx}_start
1916 exe s:tlist_{fidx}_start - 1
1919 let txt = fnamemodify(s:tlist_{fidx}_filename, ':t') . ' (' .
1920 \ fnamemodify(s:tlist_{fidx}_filename, ':p:h') . ')'
1921 if g:Tlist_Compact_Format == 0
1925 " Move to the next line
1928 let file_start = s:tlist_{fidx}_start
1930 " Add the tag names grouped by tag type to the buffer with a title
1932 let ttype_cnt = s:tlist_{a:ftype}_count
1933 while i <= ttype_cnt
1934 let ttype = s:tlist_{a:ftype}_{i}_name
1935 " Add the tag type only if there are tags for that type
1936 let fidx_ttype = 's:tlist_' . fidx . '_' . ttype
1937 let ttype_txt = {fidx_ttype}
1939 let txt = ' ' . s:tlist_{a:ftype}_{i}_fullname
1940 if g:Tlist_Compact_Format == 0
1941 let ttype_start_lnum = line('.') + 1
1944 let ttype_start_lnum = line('.')
1947 silent! put =ttype_txt
1949 let {fidx_ttype}_offset = ttype_start_lnum - file_start
1951 " create a fold for this tag type
1952 let fold_start = ttype_start_lnum
1953 let fold_end = fold_start + {fidx_ttype}_count
1954 exe fold_start . ',' . fold_end . 'fold'
1956 " Adjust the cursor position
1957 if g:Tlist_Compact_Format == 0
1958 exe ttype_start_lnum + {fidx_ttype}_count
1960 exe ttype_start_lnum + {fidx_ttype}_count + 1
1963 if g:Tlist_Compact_Format == 0
1964 " Separate the tag types by a empty line
1971 if s:tlist_{fidx}_tag_count == 0
1972 if g:Tlist_Compact_Format == 0
1977 let s:tlist_{fidx}_end = line('.') - 1
1979 " Create a fold for the entire file
1980 exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold'
1981 exe 'silent! ' . s:tlist_{fidx}_start . ',' .
1982 \ s:tlist_{fidx}_end . 'foldopen!'
1984 " Goto the starting line for this file,
1985 exe s:tlist_{fidx}_start
1987 if s:tlist_app_name == "winmanager"
1988 " To handle a bug in the winmanager plugin, add a space at the
1990 call setline('$', ' ')
1993 " Mark the buffer as not modifiable
1994 setlocal nomodifiable
1996 " Restore the report option
1997 let &report = old_report
1999 " Update the start and end line numbers for all the files following this
2001 let start = s:tlist_{fidx}_start
2002 " include the empty line after the last line
2003 if g:Tlist_Compact_Format
2004 let end = s:tlist_{fidx}_end
2006 let end = s:tlist_{fidx}_end + 1
2008 call s:Tlist_Window_Update_Line_Offsets(fidx + 1, 1, end - start + 1)
2010 " Now that we have updated the taglist window, update the tags
2012 if g:Tlist_Show_Menu
2013 call s:Tlist_Menu_Update_File(1)
2018 " Initialize the variables for a new file
2019 function! s:Tlist_Init_File(filename, ftype)
2020 call s:Tlist_Log_Msg('Tlist_Init_File (' . a:filename . ')')
2021 " Add new files at the end of the list
2022 let fidx = s:tlist_file_count
2023 let s:tlist_file_count = s:tlist_file_count + 1
2024 " Add the new file name to the taglist list of file names
2025 let s:tlist_file_names = s:tlist_file_names . a:filename . "\n"
2027 " Initialize the file variables
2028 let s:tlist_{fidx}_filename = a:filename
2029 let s:tlist_{fidx}_sort_type = g:Tlist_Sort_Type
2030 let s:tlist_{fidx}_filetype = a:ftype
2031 let s:tlist_{fidx}_mtime = -1
2032 let s:tlist_{fidx}_start = 0
2033 let s:tlist_{fidx}_end = 0
2034 let s:tlist_{fidx}_valid = 0
2035 let s:tlist_{fidx}_visible = 0
2036 let s:tlist_{fidx}_tag_count = 0
2037 let s:tlist_{fidx}_menu_cmd = ''
2039 " Initialize the tag type variables
2041 while i <= s:tlist_{a:ftype}_count
2042 let ttype = s:tlist_{a:ftype}_{i}_name
2043 let s:tlist_{fidx}_{ttype} = ''
2044 let s:tlist_{fidx}_{ttype}_offset = 0
2045 let s:tlist_{fidx}_{ttype}_count = 0
2052 " Tlist_Get_Tag_Type_By_Tag
2053 " Return the tag type for the specified tag index
2054 function! s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx)
2055 let ttype_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_type'
2057 " Already parsed and have the tag name
2058 if exists(ttype_var)
2062 let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
2063 let {ttype_var} = s:Tlist_Extract_Tagtype(tag_line)
2068 " Tlist_Get_Tag_Prototype
2069 function! s:Tlist_Get_Tag_Prototype(fidx, tidx)
2070 let tproto_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_proto'
2072 " Already parsed and have the tag prototype
2073 if exists(tproto_var)
2077 " Parse and extract the tag prototype
2078 let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
2079 let start = stridx(tag_line, '/^') + 2
2080 let end = stridx(tag_line, '/;"' . "\t")
2081 if tag_line[end - 1] == '$'
2084 let tag_proto = strpart(tag_line, start, end - start)
2085 let {tproto_var} = substitute(tag_proto, '\s*', '', '')
2090 " Tlist_Get_Tag_SearchPat
2091 function! s:Tlist_Get_Tag_SearchPat(fidx, tidx)
2092 let tpat_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_searchpat'
2094 " Already parsed and have the tag search pattern
2099 " Parse and extract the tag search pattern
2100 let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
2101 let start = stridx(tag_line, '/^') + 2
2102 let end = stridx(tag_line, '/;"' . "\t")
2103 if tag_line[end - 1] == '$'
2106 let {tpat_var} = '\V\^' . strpart(tag_line, start, end - start) .
2107 \ (tag_line[end] == '$' ? '\$' : '')
2112 " Tlist_Get_Tag_Linenum
2113 " Return the tag line number, given the tag index
2114 function! s:Tlist_Get_Tag_Linenum(fidx, tidx)
2115 let tline_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_linenum'
2117 " Already parsed and have the tag line number
2118 if exists(tline_var)
2122 " Parse and extract the tag line number
2123 let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
2124 let start = strridx(tag_line, 'line:') + 5
2125 let end = strridx(tag_line, "\t")
2127 let {tline_var} = strpart(tag_line, start) + 0
2129 let {tline_var} = strpart(tag_line, start, end - start) + 0
2135 " Tlist_Parse_Tagline
2136 " Parse a tag line from the ctags output. Separate the tag output based on the
2137 " tag type and store it in the tag type variable.
2138 " The format of each line in the ctags output is:
2140 " tag_name<TAB>file_name<TAB>ex_cmd;"<TAB>extension_fields
2142 function! s:Tlist_Parse_Tagline(tag_line)
2148 " Extract the tag type
2149 let ttype = s:Tlist_Extract_Tagtype(a:tag_line)
2151 " Make sure the tag type is a valid and supported one
2152 if ttype == '' || stridx(s:ctags_flags, ttype) == -1
2153 " Line is not in proper tags format or Tag type is not supported
2157 " Update the total tag count
2158 let s:tidx = s:tidx + 1
2160 " The following variables are used to optimize this code. Vim is slow in
2161 " using curly brace names. To reduce the amount of processing needed, the
2162 " curly brace variables are pre-processed here
2163 let fidx_tidx = 's:tlist_' . s:fidx . '_' . s:tidx
2164 let fidx_ttype = 's:tlist_' . s:fidx . '_' . ttype
2166 " Update the count of this tag type
2167 let ttype_idx = {fidx_ttype}_count + 1
2168 let {fidx_ttype}_count = ttype_idx
2170 " Store the ctags output for this tag
2171 let {fidx_tidx}_tag = a:tag_line
2173 " Store the tag index and the tag type index (back pointers)
2174 let {fidx_ttype}_{ttype_idx} = s:tidx
2175 let {fidx_tidx}_ttype_idx = ttype_idx
2177 " Extract the tag name
2178 let tag_name = strpart(a:tag_line, 0, stridx(a:tag_line, "\t"))
2180 " Extract the tag scope/prototype
2181 if g:Tlist_Display_Prototype
2182 let ttxt = ' ' . s:Tlist_Get_Tag_Prototype(s:fidx, s:tidx)
2184 let ttxt = ' ' . tag_name
2186 " Add the tag scope, if it is available and is configured. Tag
2187 " scope is the last field after the 'line:<num>\t' field
2188 if g:Tlist_Display_Tag_Scope
2189 let tag_scope = s:Tlist_Extract_Tag_Scope(a:tag_line)
2191 let ttxt = ttxt . ' [' . tag_scope . ']'
2196 " Add this tag to the tag type variable
2197 let {fidx_ttype} = {fidx_ttype} . ttxt . "\n"
2200 let {fidx_tidx}_tag_name = tag_name
2203 " Tlist_Process_File
2204 " Get the list of tags defined in the specified file and store them
2205 " in Vim variables. Returns the file index where the tags are stored.
2206 function! s:Tlist_Process_File(filename, ftype)
2207 call s:Tlist_Log_Msg('Tlist_Process_File (' . a:filename . ', ' .
2209 " Check whether this file is supported
2210 if s:Tlist_Skip_File(a:filename, a:ftype)
2214 " If the tag types for this filetype are not yet created, then create
2216 let var = 's:tlist_' . a:ftype . '_count'
2218 if s:Tlist_FileType_Init(a:ftype) == 0
2223 " If this file is already processed, then use the cached values
2224 let fidx = s:Tlist_Get_File_Index(a:filename)
2226 " First time, this file is loaded
2227 let fidx = s:Tlist_Init_File(a:filename, a:ftype)
2229 " File was previously processed. Discard the tag information
2230 call s:Tlist_Discard_TagInfo(fidx)
2233 let s:tlist_{fidx}_valid = 1
2235 " Exuberant ctags arguments to generate a tag list
2236 let ctags_args = ' -f - --format=2 --excmd=pattern --fields=nks '
2238 " Form the ctags argument depending on the sort type
2239 if s:tlist_{fidx}_sort_type == 'name'
2240 let ctags_args = ctags_args . '--sort=yes'
2242 let ctags_args = ctags_args . '--sort=no'
2245 " Add the filetype specific arguments
2246 let ctags_args = ctags_args . ' ' . s:tlist_{a:ftype}_ctags_args
2248 " Ctags command to produce output with regexp for locating the tags
2249 let ctags_cmd = g:Tlist_Ctags_Cmd . ctags_args
2250 let ctags_cmd = ctags_cmd . ' "' . a:filename . '"'
2252 if &shellxquote == '"'
2253 " Double-quotes within double-quotes will not work in the
2254 " command-line.If the 'shellxquote' option is set to double-quotes,
2255 " then escape the double-quotes in the ctags command-line.
2256 let ctags_cmd = escape(ctags_cmd, '"')
2259 " In Windows 95, if not using cygwin, disable the 'shellslash'
2260 " option. Otherwise, this will cause problems when running the
2262 if has('win95') && !has('win32unix')
2263 let old_shellslash = &shellslash
2267 if has('win32') && !has('win32unix') && !has('win95')
2268 \ && (&shell =~ 'cmd.exe')
2269 " Windows does not correctly deal with commands that have more than 1
2270 " set of double quotes. It will strip them all resulting in:
2271 " 'C:\Program' is not recognized as an internal or external command
2272 " operable program or batch file. To work around this, place the
2273 " command inside a batch file and call the batch file.
2274 " Do this only on Win2K, WinXP and above.
2275 " Contributed by: David Fishburn.
2276 let s:taglist_tempfile = fnamemodify(tempname(), ':h') .
2278 exe 'redir! > ' . s:taglist_tempfile
2279 silent echo ctags_cmd
2282 call s:Tlist_Log_Msg('Cmd inside batch file: ' . ctags_cmd)
2283 let ctags_cmd = '"' . s:taglist_tempfile . '"'
2286 call s:Tlist_Log_Msg('Cmd: ' . ctags_cmd)
2288 " Run ctags and get the tag list
2289 let cmd_output = system(ctags_cmd)
2291 " Restore the value of the 'shellslash' option.
2292 if has('win95') && !has('win32unix')
2293 let &shellslash = old_shellslash
2296 if exists('s:taglist_tempfile')
2297 " Delete the temporary cmd file created on MS-Windows
2298 call delete(s:taglist_tempfile)
2303 let msg = "Taglist: Failed to generate tags for " . a:filename
2304 call s:Tlist_Warning_Msg(msg)
2306 call s:Tlist_Warning_Msg(cmd_output)
2311 " Store the modification time for the file
2312 let s:tlist_{fidx}_mtime = getftime(a:filename)
2314 " No tags for current file
2316 call s:Tlist_Log_Msg('No tags defined in ' . a:filename)
2320 call s:Tlist_Log_Msg('Generated tags information for ' . a:filename)
2323 " The following script local variables are used by the
2324 " Tlist_Parse_Tagline() function.
2325 let s:ctags_flags = s:tlist_{a:ftype}_ctags_flags
2329 " Process the ctags output one line at a time. The substitute()
2330 " command is used to parse the tag lines instead of using the
2331 " matchstr()/stridx()/strpart() functions for performance reason
2332 call substitute(cmd_output, "\\([^\n]\\+\\)\n",
2333 \ '\=s:Tlist_Parse_Tagline(submatch(1))', 'g')
2335 " Save the number of tags for this file
2336 let s:tlist_{fidx}_tag_count = s:tidx
2338 " The following script local variables are no longer needed
2339 unlet! s:ctags_flags
2343 " Due to a bug in Vim earlier than version 6.1,
2344 " we cannot use substitute() to parse the ctags output.
2345 " Instead the slow str*() functions are used
2346 let ctags_flags = s:tlist_{a:ftype}_ctags_flags
2349 while cmd_output != ''
2350 " Extract one line at a time
2351 let idx = stridx(cmd_output, "\n")
2352 let one_line = strpart(cmd_output, 0, idx)
2353 " Remove the line from the tags output
2354 let cmd_output = strpart(cmd_output, idx + 1)
2357 " Line is not in proper tags format
2361 " Extract the tag type
2362 let ttype = s:Tlist_Extract_Tagtype(one_line)
2364 " Make sure the tag type is a valid and supported one
2365 if ttype == '' || stridx(ctags_flags, ttype) == -1
2366 " Line is not in proper tags format or Tag type is not
2371 " Update the total tag count
2374 " The following variables are used to optimize this code. Vim is
2375 " slow in using curly brace names. To reduce the amount of
2376 " processing needed, the curly brace variables are pre-processed
2378 let fidx_tidx = 's:tlist_' . fidx . '_' . tidx
2379 let fidx_ttype = 's:tlist_' . fidx . '_' . ttype
2381 " Update the count of this tag type
2382 let ttype_idx = {fidx_ttype}_count + 1
2383 let {fidx_ttype}_count = ttype_idx
2385 " Store the ctags output for this tag
2386 let {fidx_tidx}_tag = one_line
2388 " Store the tag index and the tag type index (back pointers)
2389 let {fidx_ttype}_{ttype_idx} = tidx
2390 let {fidx_tidx}_ttype_idx = ttype_idx
2392 " Extract the tag name
2393 let tag_name = strpart(one_line, 0, stridx(one_line, "\t"))
2395 " Extract the tag scope/prototype
2396 if g:Tlist_Display_Prototype
2397 let ttxt = ' ' . s:Tlist_Get_Tag_Prototype(fidx, tidx)
2399 let ttxt = ' ' . tag_name
2401 " Add the tag scope, if it is available and is configured. Tag
2402 " scope is the last field after the 'line:<num>\t' field
2403 if g:Tlist_Display_Tag_Scope
2404 let tag_scope = s:Tlist_Extract_Tag_Scope(one_line)
2406 let ttxt = ttxt . ' [' . tag_scope . ']'
2411 " Add this tag to the tag type variable
2412 let {fidx_ttype} = {fidx_ttype} . ttxt . "\n"
2415 let {fidx_tidx}_tag_name = tag_name
2418 " Save the number of tags for this file
2419 let s:tlist_{fidx}_tag_count = tidx
2422 call s:Tlist_Log_Msg('Processed ' . s:tlist_{fidx}_tag_count .
2423 \ ' tags in ' . a:filename)
2429 " Update the tags for a file (if needed)
2430 function! Tlist_Update_File(filename, ftype)
2431 call s:Tlist_Log_Msg('Tlist_Update_File (' . a:filename . ')')
2432 " If the file doesn't support tag listing, skip it
2433 if s:Tlist_Skip_File(a:filename, a:ftype)
2437 " Convert the file name to a full path
2438 let fname = fnamemodify(a:filename, ':p')
2440 " First check whether the file already exists
2441 let fidx = s:Tlist_Get_File_Index(fname)
2443 if fidx != -1 && s:tlist_{fidx}_valid
2444 " File exists and the tags are valid
2445 " Check whether the file was modified after the last tags update
2446 " If it is modified, then update the tags
2447 if s:tlist_{fidx}_mtime == getftime(fname)
2451 " If the tags were removed previously based on a user request,
2452 " as we are going to update the tags (based on the user request),
2453 " remove the filename from the deleted list
2454 call s:Tlist_Update_Remove_List(fname, 0)
2457 " If the taglist window is opened, update it
2458 let winnum = bufwinnr(g:TagList_title)
2460 " Taglist window is not present. Just update the taglist
2462 call s:Tlist_Process_File(fname, a:ftype)
2464 if g:Tlist_Show_One_File && s:tlist_cur_file_idx != -1
2465 " If tags for only one file are displayed and we are not
2466 " updating the tags for that file, then no need to
2467 " refresh the taglist window. Otherwise, the taglist
2468 " window should be updated.
2469 if s:tlist_{s:tlist_cur_file_idx}_filename != fname
2470 call s:Tlist_Process_File(fname, a:ftype)
2475 " Save the current window number
2476 let save_winnr = winnr()
2478 " Goto the taglist window
2479 call s:Tlist_Window_Goto_Window()
2481 " Save the cursor position
2482 let save_line = line('.')
2483 let save_col = col('.')
2485 " Update the taglist window
2486 call s:Tlist_Window_Refresh_File(fname, a:ftype)
2488 " Restore the cursor position
2490 call cursor(save_line, save_col)
2493 exe 'normal! ' . save_col . '|'
2496 if winnr() != save_winnr
2497 " Go back to the original window
2498 call s:Tlist_Exe_Cmd_No_Acmds(save_winnr . 'wincmd w')
2502 " Update the taglist menu
2503 if g:Tlist_Show_Menu
2504 call s:Tlist_Menu_Update_File(1)
2508 " Tlist_Window_Close
2509 " Close the taglist window
2510 function! s:Tlist_Window_Close()
2511 call s:Tlist_Log_Msg('Tlist_Window_Close()')
2512 " Make sure the taglist window exists
2513 let winnum = bufwinnr(g:TagList_title)
2515 call s:Tlist_Warning_Msg('Error: Taglist window is not open')
2519 if winnr() == winnum
2520 " Already in the taglist window. Close it and return
2521 if winbufnr(2) != -1
2522 " If a window other than the taglist window is open,
2523 " then only close the taglist window.
2527 " Goto the taglist window, close it and then come back to the
2529 let curbufnr = bufnr('%')
2530 exe winnum . 'wincmd w'
2532 " Need to jump back to the original window only if we are not
2533 " already in that window
2534 let winnum = bufwinnr(curbufnr)
2535 if winnr() != winnum
2536 exe winnum . 'wincmd w'
2541 " Tlist_Window_Mark_File_Window
2542 " Mark the current window as the file window to use when jumping to a tag.
2543 " Only if the current window is a non-plugin, non-preview and non-taglist
2545 function! s:Tlist_Window_Mark_File_Window()
2546 if getbufvar('%', '&buftype') == '' && !&previewwindow
2547 let w:tlist_file_window = "yes"
2552 " Open and refresh the taglist window
2553 function! s:Tlist_Window_Open()
2554 call s:Tlist_Log_Msg('Tlist_Window_Open()')
2555 " If the window is open, jump to it
2556 let winnum = bufwinnr(g:TagList_title)
2558 " Jump to the existing window
2559 if winnr() != winnum
2560 exe winnum . 'wincmd w'
2565 if s:tlist_app_name == "winmanager"
2566 " Taglist plugin is no longer part of the winmanager app
2567 let s:tlist_app_name = "none"
2570 " Get the filename and filetype for the specified buffer
2571 let curbuf_name = fnamemodify(bufname('%'), ':p')
2572 let curbuf_ftype = s:Tlist_Get_Buffer_Filetype('%')
2573 let cur_lnum = line('.')
2575 " Mark the current window as the desired window to open a file when a tag
2577 call s:Tlist_Window_Mark_File_Window()
2579 " Open the taglist window
2580 call s:Tlist_Window_Create()
2582 call s:Tlist_Window_Refresh()
2584 if g:Tlist_Show_One_File
2585 " Add only the current buffer and file
2587 " If the file doesn't support tag listing, skip it
2588 if !s:Tlist_Skip_File(curbuf_name, curbuf_ftype)
2589 call s:Tlist_Window_Refresh_File(curbuf_name, curbuf_ftype)
2593 if g:Tlist_File_Fold_Auto_Close
2594 " Open the fold for the current file, as all the folds in
2595 " the taglist window are closed
2596 let fidx = s:Tlist_Get_File_Index(curbuf_name)
2598 exe "silent! " . s:tlist_{fidx}_start . "," .
2599 \ s:tlist_{fidx}_end . "foldopen!"
2603 " Highlight the current tag
2604 call s:Tlist_Window_Highlight_Tag(curbuf_name, cur_lnum, 1, 1)
2607 " Tlist_Window_Toggle()
2608 " Open or close a taglist window
2609 function! s:Tlist_Window_Toggle()
2610 call s:Tlist_Log_Msg('Tlist_Window_Toggle()')
2611 " If taglist window is open then close it.
2612 let winnum = bufwinnr(g:TagList_title)
2614 call s:Tlist_Window_Close()
2618 call s:Tlist_Window_Open()
2620 " Go back to the original window, if Tlist_GainFocus_On_ToggleOpen is not
2622 if !g:Tlist_GainFocus_On_ToggleOpen
2623 call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
2626 " Update the taglist menu
2627 if g:Tlist_Show_Menu
2628 call s:Tlist_Menu_Update_File(0)
2632 " Tlist_Process_Filelist
2633 " Process multiple files. Each filename is separated by "\n"
2634 " Returns the number of processed files
2635 function! s:Tlist_Process_Filelist(file_names)
2636 let flist = a:file_names
2638 " Enable lazy screen updates
2639 let old_lazyredraw = &lazyredraw
2642 " Keep track of the number of processed files
2645 " Process one file at a time
2647 let nl_idx = stridx(flist, "\n")
2648 let one_file = strpart(flist, 0, nl_idx)
2650 " Remove the filename from the list
2651 let flist = strpart(flist, nl_idx + 1)
2658 if isdirectory(one_file)
2662 let ftype = s:Tlist_Detect_Filetype(one_file)
2665 echon "\rProcessing tags for " . fnamemodify(one_file, ':p:t')
2669 call Tlist_Update_File(one_file, ftype)
2672 " Clear the displayed informational messages
2675 " Restore the previous state
2676 let &lazyredraw = old_lazyredraw
2682 " Process the files in a directory matching the specified pattern
2683 function! s:Tlist_Process_Dir(dir_name, pat)
2684 let flist = glob(a:dir_name . '/' . a:pat) . "\n"
2686 let fcnt = s:Tlist_Process_Filelist(flist)
2688 let len = strlen(a:dir_name)
2689 if a:dir_name[len - 1] == '\' || a:dir_name[len - 1] == '/'
2690 let glob_expr = a:dir_name . '*'
2692 let glob_expr = a:dir_name . '/*'
2694 let all_files = glob(glob_expr) . "\n"
2696 while all_files != ''
2697 let nl_idx = stridx(all_files, "\n")
2698 let one_file = strpart(all_files, 0, nl_idx)
2700 let all_files = strpart(all_files, nl_idx + 1)
2705 " Skip non-directory names
2706 if !isdirectory(one_file)
2711 echon "\rProcessing files in directory " . fnamemodify(one_file, ':t')
2712 let fcnt = fcnt + s:Tlist_Process_Dir(one_file, a:pat)
2718 " Tlist_Add_Files_Recursive
2719 " Add files recursively from a directory
2720 function! s:Tlist_Add_Files_Recursive(dir, ...)
2721 let dir_name = fnamemodify(a:dir, ':p')
2722 if !isdirectory(dir_name)
2723 call s:Tlist_Warning_Msg('Error: ' . dir_name . ' is not a directory')
2728 " User specified file pattern
2731 " Default file pattern
2736 echon "\rProcessing files in directory " . fnamemodify(dir_name, ':t')
2737 let fcnt = s:Tlist_Process_Dir(dir_name, pat)
2739 echon "\rAdded " . fcnt . " files to the taglist"
2743 " Add the specified list of files to the taglist
2744 function! s:Tlist_Add_Files(...)
2748 " Get all the files matching the file patterns supplied as argument
2750 let flist = flist . glob(a:{i}) . "\n"
2755 call s:Tlist_Warning_Msg('Error: No matching files are found')
2759 let fcnt = s:Tlist_Process_Filelist(flist)
2760 echon "\rAdded " . fcnt . " files to the taglist"
2763 " Tlist_Extract_Tagtype
2764 " Extract the tag type from the tag text
2765 function! s:Tlist_Extract_Tagtype(tag_line)
2766 " The tag type is after the tag prototype field. The prototype field
2767 " ends with the /;"\t string. We add 4 at the end to skip the characters
2768 " in this special string..
2769 let start = strridx(a:tag_line, '/;"' . "\t") + 4
2770 let end = strridx(a:tag_line, 'line:') - 1
2771 let ttype = strpart(a:tag_line, start, end - start)
2776 " Tlist_Extract_Tag_Scope
2777 " Extract the tag scope from the tag text
2778 function! s:Tlist_Extract_Tag_Scope(tag_line)
2779 let start = strridx(a:tag_line, 'line:')
2780 let end = strridx(a:tag_line, "\t")
2785 let tag_scope = strpart(a:tag_line, end + 1)
2786 let tag_scope = strpart(tag_scope, stridx(tag_scope, ':') + 1)
2792 " Refresh the taglist
2793 function! s:Tlist_Refresh()
2794 call s:Tlist_Log_Msg('Tlist_Refresh (Skip_Refresh = ' .
2795 \ s:Tlist_Skip_Refresh . ', ' . bufname('%') . ')')
2796 " If we are entering the buffer from one of the taglist functions, then
2797 " no need to refresh the taglist window again.
2798 if s:Tlist_Skip_Refresh
2799 " We still need to update the taglist menu
2800 if g:Tlist_Show_Menu
2801 call s:Tlist_Menu_Update_File(0)
2806 " If part of the winmanager plugin and not configured to process
2807 " tags always and not configured to display the tags menu, then return
2808 if (s:tlist_app_name == 'winmanager') && !g:Tlist_Process_File_Always
2809 \ && !g:Tlist_Show_Menu
2813 " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help
2818 let filename = fnamemodify(bufname('%'), ':p')
2819 let ftype = s:Tlist_Get_Buffer_Filetype('%')
2821 " If the file doesn't support tag listing, skip it
2822 if s:Tlist_Skip_File(filename, ftype)
2826 let tlist_win = bufwinnr(g:TagList_title)
2828 " If the taglist window is not opened and not configured to process
2829 " tags always and not displaying the tags menu, then return
2830 if tlist_win == -1 && !g:Tlist_Process_File_Always && !g:Tlist_Show_Menu
2834 let fidx = s:Tlist_Get_File_Index(filename)
2836 " Check whether this file is removed based on user request
2837 " If it is, then don't display the tags for this file
2838 if s:Tlist_User_Removed_File(filename)
2842 " If the taglist should not be auto updated, then return
2843 if !g:Tlist_Auto_Update
2848 let cur_lnum = line('.')
2851 " Update the tags for the file
2852 let fidx = s:Tlist_Process_File(filename, ftype)
2854 let mtime = getftime(filename)
2855 if s:tlist_{fidx}_mtime != mtime
2856 " Invalidate the tags listed for this file
2857 let s:tlist_{fidx}_valid = 0
2859 " Update the taglist and the window
2860 call Tlist_Update_File(filename, ftype)
2862 " Store the new file modification time
2863 let s:tlist_{fidx}_mtime = mtime
2867 " Update the taglist window
2869 " Disable screen updates
2870 let old_lazyredraw = &lazyredraw
2873 " Save the current window number
2874 let save_winnr = winnr()
2876 " Goto the taglist window
2877 call s:Tlist_Window_Goto_Window()
2879 if !g:Tlist_Auto_Highlight_Tag || !g:Tlist_Highlight_Tag_On_BufEnter
2880 " Save the cursor position
2881 let save_line = line('.')
2882 let save_col = col('.')
2885 " Update the taglist window
2886 call s:Tlist_Window_Refresh_File(filename, ftype)
2888 " Open the fold for the file
2889 exe "silent! " . s:tlist_{fidx}_start . "," .
2890 \ s:tlist_{fidx}_end . "foldopen!"
2892 if g:Tlist_Highlight_Tag_On_BufEnter && g:Tlist_Auto_Highlight_Tag
2893 if g:Tlist_Show_One_File && s:tlist_cur_file_idx != fidx
2894 " If displaying tags for only one file in the taglist
2895 " window and about to display the tags for a new file,
2896 " then center the current tag line for the new file
2897 let center_tag_line = 1
2899 let center_tag_line = 0
2902 " Highlight the current tag
2903 call s:Tlist_Window_Highlight_Tag(filename, cur_lnum, 1, center_tag_line)
2905 " Restore the cursor position
2907 call cursor(save_line, save_col)
2910 exe 'normal! ' . save_col . '|'
2914 " Jump back to the original window
2915 if save_winnr != winnr()
2916 call s:Tlist_Exe_Cmd_No_Acmds(save_winnr . 'wincmd w')
2919 " Restore screen updates
2920 let &lazyredraw = old_lazyredraw
2923 " Update the taglist menu
2924 if g:Tlist_Show_Menu
2925 call s:Tlist_Menu_Update_File(0)
2929 " Tlist_Change_Sort()
2930 " Change the sort order of the tag listing
2931 " caller == 'cmd', command used in the taglist window
2932 " caller == 'menu', taglist menu
2933 " action == 'toggle', toggle sort from name to order and vice versa
2934 " action == 'set', set the sort order to sort_type
2935 function! s:Tlist_Change_Sort(caller, action, sort_type)
2936 call s:Tlist_Log_Msg('Tlist_Change_Sort (caller = ' . a:caller .
2937 \ ', action = ' . a:action . ', sort_type = ' . a:sort_type . ')')
2938 if a:caller == 'cmd'
2939 let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
2944 " Remove the previous highlighting
2946 elseif a:caller == 'menu'
2947 let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
2953 if a:action == 'toggle'
2954 let sort_type = s:tlist_{fidx}_sort_type
2956 " Toggle the sort order from 'name' to 'order' and vice versa
2957 if sort_type == 'name'
2958 let s:tlist_{fidx}_sort_type = 'order'
2960 let s:tlist_{fidx}_sort_type = 'name'
2963 let s:tlist_{fidx}_sort_type = a:sort_type
2966 " Invalidate the tags listed for this file
2967 let s:tlist_{fidx}_valid = 0
2969 if a:caller == 'cmd'
2970 " Save the current line for later restoration
2971 let curline = '\V\^' . getline('.') . '\$'
2973 call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename,
2974 \ s:tlist_{fidx}_filetype)
2976 exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!'
2978 " Go back to the cursor line before the tag list is sorted
2979 call search(curline, 'w')
2981 call s:Tlist_Menu_Update_File(1)
2983 call s:Tlist_Menu_Remove_File()
2985 call s:Tlist_Refresh()
2989 " Tlist_Update_Current_File()
2990 " Update taglist for the current buffer by regenerating the tag list
2991 " Contributed by WEN Guopeng.
2992 function! s:Tlist_Update_Current_File()
2993 call s:Tlist_Log_Msg('Tlist_Update_Current_File()')
2994 if winnr() == bufwinnr(g:TagList_title)
2995 " In the taglist window. Update the current file
2996 call s:Tlist_Window_Update_File()
2998 " Not in the taglist window. Update the current buffer
2999 let filename = fnamemodify(bufname('%'), ':p')
3000 let fidx = s:Tlist_Get_File_Index(filename)
3002 let s:tlist_{fidx}_valid = 0
3004 let ft = s:Tlist_Get_Buffer_Filetype('%')
3005 call Tlist_Update_File(filename, ft)
3009 " Tlist_Window_Update_File()
3010 " Update the tags displayed in the taglist window
3011 function! s:Tlist_Window_Update_File()
3012 call s:Tlist_Log_Msg('Tlist_Window_Update_File()')
3013 let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
3018 " Remove the previous highlighting
3021 " Save the current line for later restoration
3022 let curline = '\V\^' . getline('.') . '\$'
3024 let s:tlist_{fidx}_valid = 0
3026 " Update the taglist window
3027 call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename,
3028 \ s:tlist_{fidx}_filetype)
3030 exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!'
3032 " Go back to the tag line before the list is updated
3033 call search(curline, 'w')
3036 " Tlist_Window_Get_Tag_Type_By_Linenum()
3037 " Return the tag type index for the specified line in the taglist window
3038 function! s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum)
3039 let ftype = s:tlist_{a:fidx}_filetype
3041 " Determine to which tag type the current line number belongs to using the
3042 " tag type start line number and the number of tags in a tag type
3044 while i <= s:tlist_{ftype}_count
3045 let ttype = s:tlist_{ftype}_{i}_name
3047 \ s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset
3048 let end = start_lnum + s:tlist_{a:fidx}_{ttype}_count
3049 if a:lnum >= start_lnum && a:lnum <= end
3055 " Current line doesn't belong to any of the displayed tag types
3056 if i > s:tlist_{ftype}_count
3063 " Tlist_Window_Get_Tag_Index()
3064 " Return the tag index for the specified line in the taglist window
3065 function! s:Tlist_Window_Get_Tag_Index(fidx, lnum)
3066 let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(a:fidx, a:lnum)
3068 " Current line doesn't belong to any of the displayed tag types
3073 " Compute the index into the displayed tags for the tag type
3074 let ttype_lnum = s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset
3075 let tidx = a:lnum - ttype_lnum
3080 " Get the corresponding tag line and return it
3081 return s:tlist_{a:fidx}_{ttype}_{tidx}
3084 " Tlist_Window_Highlight_Line
3085 " Highlight the current line
3086 function! s:Tlist_Window_Highlight_Line()
3087 " Clear previously selected name
3090 " Highlight the current line
3091 if g:Tlist_Display_Prototype == 0
3092 let pat = '/\%' . line('.') . 'l\s\+\zs.*/'
3094 let pat = '/\%' . line('.') . 'l.*/'
3097 exe 'match TagListTagName ' . pat
3100 " Tlist_Window_Open_File
3101 " Open the specified file in either a new window or an existing window
3102 " and place the cursor at the specified tag pattern
3103 function! s:Tlist_Window_Open_File(win_ctrl, filename, tagpat)
3104 call s:Tlist_Log_Msg('Tlist_Window_Open_File (' . a:filename . ',' .
3106 let prev_Tlist_Skip_Refresh = s:Tlist_Skip_Refresh
3107 let s:Tlist_Skip_Refresh = 1
3109 if s:tlist_app_name == "winmanager"
3110 " Let the winmanager edit the file
3111 call WinManagerFileEdit(a:filename, a:win_ctrl == 'newwin')
3114 if a:win_ctrl == 'newtab'
3116 exe 'tabnew ' . escape(a:filename, ' ')
3117 " Open the taglist window in the new tab
3118 call s:Tlist_Window_Open()
3121 if a:win_ctrl == 'checktab'
3122 " Check whether the file is present in any of the tabs.
3123 " If the file is present in the current tab, then use the
3125 if bufwinnr(a:filename) != -1
3126 let file_present_in_tab = 1
3130 let bnum = bufnr(a:filename)
3131 let file_present_in_tab = 0
3132 while i <= tabpagenr('$')
3133 if index(tabpagebuflist(i), bnum) != -1
3134 let file_present_in_tab = 1
3141 if file_present_in_tab
3142 " Goto the tab containing the file
3146 exe 'tabnew ' . escape(a:filename, ' ')
3148 " Open the taglist window
3149 call s:Tlist_Window_Open()
3154 if a:win_ctrl == 'prevwin'
3155 " Open the file in the previous window, if it is usable
3156 let cur_win = winnr()
3158 if &buftype == '' && !&previewwindow
3159 exe "edit " . escape(a:filename, ' ')
3160 let winnum = winnr()
3162 " Previous window is not usable
3163 exe cur_win . 'wincmd w'
3167 " Goto the window containing the file. If the window is not there, open a
3170 let winnum = bufwinnr(a:filename)
3174 " Locate the previously used window for opening a file
3176 let first_usable_win = 0
3179 let bnum = winbufnr(i)
3181 if getwinvar(i, 'tlist_file_window') == 'yes'
3185 if first_usable_win == 0 &&
3186 \ getbufvar(bnum, '&buftype') == '' &&
3187 \ !getwinvar(i, '&previewwindow')
3188 " First non-taglist, non-plugin and non-preview window
3189 let first_usable_win = i
3192 let bnum = winbufnr(i)
3195 " If a previously used window is not found, then use the first
3196 " non-taglist window
3198 let fwin_num = first_usable_win
3202 " Jump to the file window
3203 exe fwin_num . "wincmd w"
3205 " If the user asked to jump to the tag in a new window, then split
3206 " the existing window into two.
3207 if a:win_ctrl == 'newwin'
3210 exe "edit " . escape(a:filename, ' ')
3213 if g:Tlist_Use_Horiz_Window
3214 exe 'leftabove split ' . escape(a:filename, ' ')
3216 if winbufnr(2) == -1
3217 " Only the taglist window is present
3218 if g:Tlist_Use_Right_Window
3219 exe 'leftabove vertical split ' .
3220 \ escape(a:filename, ' ')
3222 exe 'rightbelow vertical split ' .
3223 \ escape(a:filename, ' ')
3226 " Go to the taglist window to change the window size to
3227 " the user configured value
3228 call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
3229 if g:Tlist_Use_Horiz_Window
3230 exe 'resize ' . g:Tlist_WinHeight
3232 exe 'vertical resize ' . g:Tlist_WinWidth
3234 " Go back to the file window
3235 call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
3237 " A plugin or help window is also present
3239 exe 'leftabove split ' . escape(a:filename, ' ')
3243 " Mark the window, so that it can be reused.
3244 call s:Tlist_Window_Mark_File_Window()
3247 " If the file is opened in more than one window, then check
3248 " whether the last accessed window has the selected file.
3249 " If it does, then use that window.
3250 let lastwin_bufnum = winbufnr(winnr('#'))
3251 if bufnr(a:filename) == lastwin_bufnum
3252 let winnum = winnr('#')
3255 exe winnum . 'wincmd w'
3257 " If the user asked to jump to the tag in a new window, then split the
3258 " existing window into two.
3259 if a:win_ctrl == 'newwin'
3267 " Add the current cursor position to the jump list, so that user can
3268 " jump back using the ' and ` marks.
3270 silent call search(a:tagpat, 'w')
3272 " Bring the line to the middle of the window
3275 " If the line is inside a fold, open the fold
3276 if foldclosed('.') != -1
3281 " If the user selects to preview the tag then jump back to the
3283 if a:win_ctrl == 'preview'
3284 " Go back to the taglist window
3285 let winnum = bufwinnr(g:TagList_title)
3286 exe winnum . 'wincmd w'
3288 " If the user has selected to close the taglist window, when a
3289 " tag is selected, close the taglist window
3290 if g:Tlist_Close_On_Select
3291 call s:Tlist_Window_Goto_Window()
3294 " Go back to the window displaying the selected file
3295 let wnum = bufwinnr(a:filename)
3296 if wnum != -1 && wnum != winnr()
3297 call s:Tlist_Exe_Cmd_No_Acmds(wnum . 'wincmd w')
3302 let s:Tlist_Skip_Refresh = prev_Tlist_Skip_Refresh
3305 " Tlist_Window_Jump_To_Tag()
3306 " Jump to the location of the current tag
3307 " win_ctrl == useopen - Reuse the existing file window
3308 " win_ctrl == newwin - Open a new window
3309 " win_ctrl == preview - Preview the tag
3310 " win_ctrl == prevwin - Open in previous window
3311 " win_ctrl == newtab - Open in new tab
3312 function! s:Tlist_Window_Jump_To_Tag(win_ctrl)
3313 call s:Tlist_Log_Msg('Tlist_Window_Jump_To_Tag(' . a:win_ctrl . ')')
3314 " Do not process comment lines and empty lines
3315 let curline = getline('.')
3316 if curline =~ '^\s*$' || curline[0] == '"'
3320 " If inside a closed fold, then use the first line of the fold
3321 " and jump to the file.
3322 let lnum = foldclosed('.')
3324 " Jump to the selected tag or file
3325 let lnum = line('.')
3327 " Open the closed fold
3331 let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
3336 " Get the tag output for the current tag
3337 let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum)
3339 let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, tidx)
3341 " Highlight the tagline
3342 call s:Tlist_Window_Highlight_Line()
3344 " Selected a line which is not a tag name. Just edit the file
3348 call s:Tlist_Window_Open_File(a:win_ctrl, s:tlist_{fidx}_filename, tagpat)
3351 " Tlist_Window_Show_Info()
3352 " Display information about the entry under the cursor
3353 function! s:Tlist_Window_Show_Info()
3354 call s:Tlist_Log_Msg('Tlist_Window_Show_Info()')
3356 " Clear the previously displayed line
3359 " Do not process comment lines and empty lines
3360 let curline = getline('.')
3361 if curline =~ '^\s*$' || curline[0] == '"'
3365 " If inside a fold, then don't display the prototype
3366 if foldclosed('.') != -1
3370 let lnum = line('.')
3372 " Get the file index
3373 let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
3378 if lnum == s:tlist_{fidx}_start
3379 " Cursor is on a file name
3380 let fname = s:tlist_{fidx}_filename
3381 if strlen(fname) > 50
3382 let fname = fnamemodify(fname, ':t')
3384 echo fname . ', Filetype=' . s:tlist_{fidx}_filetype .
3385 \ ', Tag count=' . s:tlist_{fidx}_tag_count
3389 " Get the tag output line for the current tag
3390 let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum)
3392 " Cursor is on a tag type
3393 let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum)
3400 let ftype = s:tlist_{fidx}_filetype
3402 while i <= s:tlist_{ftype}_count
3403 if ttype == s:tlist_{ftype}_{i}_name
3404 let ttype_name = s:tlist_{ftype}_{i}_fullname
3410 echo 'Tag type=' . ttype_name .
3411 \ ', Tag count=' . s:tlist_{fidx}_{ttype}_count
3415 " Get the tag search pattern and display it
3416 echo s:Tlist_Get_Tag_Prototype(fidx, tidx)
3419 " Tlist_Find_Nearest_Tag_Idx
3420 " Find the tag idx nearest to the supplied line number
3421 " Returns -1, if a tag couldn't be found for the specified line number
3422 function! s:Tlist_Find_Nearest_Tag_Idx(fidx, linenum)
3423 let sort_type = s:tlist_{a:fidx}_sort_type
3426 let right = s:tlist_{a:fidx}_tag_count
3428 if sort_type == 'order'
3429 " Tags sorted by order, use a binary search.
3430 " The idea behind this function is taken from the ctags.vim script (by
3431 " Alexey Marinichev) available at the Vim online website.
3433 " If the current line is the less than the first tag, then no need to
3435 let first_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, 1)
3437 if a:linenum < first_lnum
3442 let middle = (right + left + 1) / 2
3443 let middle_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, middle)
3445 if middle_lnum == a:linenum
3450 if middle_lnum > a:linenum
3451 let right = middle - 1
3457 " Tags sorted by name, use a linear search. (contributed by Dave
3459 " Look for a tag with a line number less than or equal to the supplied
3460 " line number. If multiple tags are found, then use the tag with the
3461 " line number closest to the supplied line number. IOW, use the tag
3462 " with the highest line number.
3463 let closest_lnum = 0
3466 let lnum = s:Tlist_Get_Tag_Linenum(a:fidx, left)
3468 if lnum < a:linenum && lnum > closest_lnum
3469 let closest_lnum = lnum
3470 let final_left = left
3471 elseif lnum == a:linenum
3472 let closest_lnum = lnum
3473 let final_left = left
3479 if closest_lnum == 0
3483 let left = final_left
3490 " Tlist_Window_Highlight_Tag()
3491 " Highlight the current tag
3492 " cntx == 1, Called by the taglist plugin itself
3493 " cntx == 2, Forced by the user through the TlistHighlightTag command
3494 " center = 1, move the tag line to the center of the taglist window
3495 function! s:Tlist_Window_Highlight_Tag(filename, cur_lnum, cntx, center)
3496 " Highlight the current tag only if the user configured the
3497 " taglist plugin to do so or if the user explictly invoked the
3498 " command to highlight the current tag.
3499 if !g:Tlist_Auto_Highlight_Tag && a:cntx == 1
3507 " Make sure the taglist window is present
3508 let winnum = bufwinnr(g:TagList_title)
3510 call s:Tlist_Warning_Msg('Error: Taglist window is not open')
3514 let fidx = s:Tlist_Get_File_Index(a:filename)
3519 " If the file is currently not displayed in the taglist window, then retrn
3520 if !s:tlist_{fidx}_visible
3524 " If there are no tags for this file, then no need to proceed further
3525 if s:tlist_{fidx}_tag_count == 0
3529 " Ignore all autocommands
3530 let old_ei = &eventignore
3533 " Save the original window number
3534 let org_winnr = winnr()
3536 if org_winnr == winnum
3537 let in_taglist_window = 1
3539 let in_taglist_window = 0
3542 " Go to the taglist window
3543 if !in_taglist_window
3544 exe winnum . 'wincmd w'
3547 " Clear previously selected name
3550 let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, a:cur_lnum)
3552 " Make sure the current tag line is visible in the taglist window.
3553 " Calling the winline() function makes the line visible. Don't know
3554 " of a better way to achieve this.
3555 let lnum = line('.')
3557 if lnum < s:tlist_{fidx}_start || lnum > s:tlist_{fidx}_end
3558 " Move the cursor to the beginning of the file
3559 exe s:tlist_{fidx}_start
3562 if foldclosed('.') != -1
3568 if !in_taglist_window
3569 exe org_winnr . 'wincmd w'
3572 " Restore the autocommands
3573 let &eventignore = old_ei
3577 " Extract the tag type
3578 let ttype = s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx)
3580 " Compute the line number
3581 " Start of file + Start of tag type + offset
3582 let lnum = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset +
3583 \ s:tlist_{fidx}_{tidx}_ttype_idx
3585 " Goto the line containing the tag
3589 if foldclosed('.') != -1
3594 " Move the tag line to the center of the taglist window
3597 " Make sure the current tag line is visible in the taglist window.
3598 " Calling the winline() function makes the line visible. Don't know
3599 " of a better way to achieve this.
3603 " Highlight the tag name
3604 call s:Tlist_Window_Highlight_Line()
3606 " Go back to the original window
3607 if !in_taglist_window
3608 exe org_winnr . 'wincmd w'
3611 " Restore the autocommands
3612 let &eventignore = old_ei
3616 " Tlist_Get_Tag_Prototype_By_Line
3617 " Get the prototype for the tag on or before the specified line number in the
3619 function! Tlist_Get_Tag_Prototype_By_Line(...)
3621 " Arguments are not supplied. Use the current buffer name
3623 let filename = bufname('%')
3624 let linenr = line('.')
3626 " Filename and line number are specified
3630 " Invalid line number
3634 " Sufficient arguments are not supplied
3635 let msg = 'Usage: Tlist_Get_Tag_Prototype_By_Line <filename> ' .
3637 call s:Tlist_Warning_Msg(msg)
3641 " Expand the file to a fully qualified name
3642 let filename = fnamemodify(filename, ':p')
3647 let fidx = s:Tlist_Get_File_Index(filename)
3652 " If there are no tags for this file, then no need to proceed further
3653 if s:tlist_{fidx}_tag_count == 0
3657 " Get the tag text using the line number
3658 let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr)
3663 return s:Tlist_Get_Tag_Prototype(fidx, tidx)
3666 " Tlist_Get_Tagname_By_Line
3667 " Get the tag name on or before the specified line number in the
3669 function! Tlist_Get_Tagname_By_Line(...)
3671 " Arguments are not supplied. Use the current buffer name
3673 let filename = bufname('%')
3674 let linenr = line('.')
3676 " Filename and line number are specified
3680 " Invalid line number
3684 " Sufficient arguments are not supplied
3685 let msg = 'Usage: Tlist_Get_Tagname_By_Line <filename> <line_number>'
3686 call s:Tlist_Warning_Msg(msg)
3690 " Make sure the current file has a name
3691 let filename = fnamemodify(filename, ':p')
3696 let fidx = s:Tlist_Get_File_Index(filename)
3701 " If there are no tags for this file, then no need to proceed further
3702 if s:tlist_{fidx}_tag_count == 0
3706 " Get the tag name using the line number
3707 let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr)
3712 return s:tlist_{fidx}_{tidx}_tag_name
3715 " Tlist_Window_Move_To_File
3716 " Move the cursor to the beginning of the current file or the next file
3717 " or the previous file in the taglist window
3718 " dir == -1, move to start of current or previous function
3719 " dir == 1, move to start of next function
3720 function! s:Tlist_Window_Move_To_File(dir)
3721 if foldlevel('.') == 0
3722 " Cursor is on a non-folded line (it is not in any of the files)
3723 " Move it to a folded line
3727 " While moving down to the start of the next fold,
3728 " no need to do go to the start of the next file.
3734 let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
3739 let cur_lnum = line('.')
3742 if cur_lnum > s:tlist_{fidx}_start
3743 " Move to the beginning of the current file
3744 exe s:tlist_{fidx}_start
3749 " Move to the beginning of the previous file
3752 " Cursor is at the first file, wrap around to the last file
3753 let fidx = s:tlist_file_count - 1
3756 exe s:tlist_{fidx}_start
3759 " Move to the beginning of the next file
3762 if fidx >= s:tlist_file_count
3763 " Cursor is at the last file, wrap around to the first file
3767 if s:tlist_{fidx}_start != 0
3768 exe s:tlist_{fidx}_start
3774 " Tlist_Session_Load
3775 " Load a taglist session (information about all the displayed files
3776 " and the tags) from the specified file
3777 function! s:Tlist_Session_Load(...)
3778 if a:0 == 0 || a:1 == ''
3779 call s:Tlist_Warning_Msg('Usage: TlistSessionLoad <filename>')
3783 let sessionfile = a:1
3785 if !filereadable(sessionfile)
3786 let msg = 'Taglist: Error - Unable to open file ' . sessionfile
3787 call s:Tlist_Warning_Msg(msg)
3791 " Mark the current window as the file window
3792 call s:Tlist_Window_Mark_File_Window()
3794 " Source the session file
3795 exe 'source ' . sessionfile
3797 let new_file_count = g:tlist_file_count
3798 unlet! g:tlist_file_count
3801 while i < new_file_count
3802 let ftype = g:tlist_{i}_filetype
3803 unlet! g:tlist_{i}_filetype
3805 if !exists('s:tlist_' . ftype . '_count')
3806 if s:Tlist_FileType_Init(ftype) == 0
3812 let fname = g:tlist_{i}_filename
3813 unlet! g:tlist_{i}_filename
3815 let fidx = s:Tlist_Get_File_Index(fname)
3817 let s:tlist_{fidx}_visible = 0
3821 " As we are loading the tags from the session file, if this
3822 " file was previously deleted by the user, now we need to
3823 " add it back. So remove the file from the deleted list.
3824 call s:Tlist_Update_Remove_List(fname, 0)
3827 let fidx = s:Tlist_Init_File(fname, ftype)
3829 let s:tlist_{fidx}_filename = fname
3831 let s:tlist_{fidx}_sort_type = g:tlist_{i}_sort_type
3832 unlet! g:tlist_{i}_sort_type
3834 let s:tlist_{fidx}_filetype = ftype
3835 let s:tlist_{fidx}_mtime = getftime(fname)
3837 let s:tlist_{fidx}_start = 0
3838 let s:tlist_{fidx}_end = 0
3840 let s:tlist_{fidx}_valid = 1
3842 let s:tlist_{fidx}_tag_count = g:tlist_{i}_tag_count
3843 unlet! g:tlist_{i}_tag_count
3846 while j <= s:tlist_{fidx}_tag_count
3847 let s:tlist_{fidx}_{j}_tag = g:tlist_{i}_{j}_tag
3848 let s:tlist_{fidx}_{j}_tag_name = g:tlist_{i}_{j}_tag_name
3849 let s:tlist_{fidx}_{j}_ttype_idx = g:tlist_{i}_{j}_ttype_idx
3850 unlet! g:tlist_{i}_{j}_tag
3851 unlet! g:tlist_{i}_{j}_tag_name
3852 unlet! g:tlist_{i}_{j}_ttype_idx
3857 while j <= s:tlist_{ftype}_count
3858 let ttype = s:tlist_{ftype}_{j}_name
3860 if exists('g:tlist_' . i . '_' . ttype)
3861 let s:tlist_{fidx}_{ttype} = g:tlist_{i}_{ttype}
3862 unlet! g:tlist_{i}_{ttype}
3863 let s:tlist_{fidx}_{ttype}_offset = 0
3864 let s:tlist_{fidx}_{ttype}_count = g:tlist_{i}_{ttype}_count
3865 unlet! g:tlist_{i}_{ttype}_count
3868 while k <= s:tlist_{fidx}_{ttype}_count
3869 let s:tlist_{fidx}_{ttype}_{k} = g:tlist_{i}_{ttype}_{k}
3870 unlet! g:tlist_{i}_{ttype}_{k}
3874 let s:tlist_{fidx}_{ttype} = ''
3875 let s:tlist_{fidx}_{ttype}_offset = 0
3876 let s:tlist_{fidx}_{ttype}_count = 0
3885 " If the taglist window is open, then update it
3886 let winnum = bufwinnr(g:TagList_title)
3888 let save_winnr = winnr()
3890 " Goto the taglist window
3891 call s:Tlist_Window_Goto_Window()
3893 " Refresh the taglist window
3894 call s:Tlist_Window_Refresh()
3896 " Go back to the original window
3897 if save_winnr != winnr()
3898 call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
3903 " Tlist_Session_Save
3904 " Save a taglist session (information about all the displayed files
3905 " and the tags) into the specified file
3906 function! s:Tlist_Session_Save(...)
3907 if a:0 == 0 || a:1 == ''
3908 call s:Tlist_Warning_Msg('Usage: TlistSessionSave <filename>')
3912 let sessionfile = a:1
3914 if s:tlist_file_count == 0
3915 " There is nothing to save
3916 call s:Tlist_Warning_Msg('Warning: Taglist is empty. Nothing to save.')
3920 if filereadable(sessionfile)
3921 let ans = input('Do you want to overwrite ' . sessionfile . ' (Y/N)?')
3929 let old_verbose = &verbose
3932 exe 'redir! > ' . sessionfile
3934 silent! echo '" Taglist session file. This file is auto-generated.'
3935 silent! echo '" File information'
3936 silent! echo 'let tlist_file_count = ' . s:tlist_file_count
3940 while i < s:tlist_file_count
3941 " Store information about the file
3942 silent! echo 'let tlist_' . i . "_filename = '" .
3943 \ s:tlist_{i}_filename . "'"
3944 silent! echo 'let tlist_' . i . '_sort_type = "' .
3945 \ s:tlist_{i}_sort_type . '"'
3946 silent! echo 'let tlist_' . i . '_filetype = "' .
3947 \ s:tlist_{i}_filetype . '"'
3948 silent! echo 'let tlist_' . i . '_tag_count = ' .
3949 \ s:tlist_{i}_tag_count
3950 " Store information about all the tags
3952 while j <= s:tlist_{i}_tag_count
3953 let txt = escape(s:tlist_{i}_{j}_tag, '"\\')
3954 silent! echo 'let tlist_' . i . '_' . j . '_tag = "' . txt . '"'
3955 silent! echo 'let tlist_' . i . '_' . j . '_tag_name = "' .
3956 \ s:tlist_{i}_{j}_tag_name . '"'
3957 silent! echo 'let tlist_' . i . '_' . j . '_ttype_idx' . ' = ' .
3958 \ s:tlist_{i}_{j}_ttype_idx
3962 " Store information about all the tags grouped by their type
3963 let ftype = s:tlist_{i}_filetype
3965 while j <= s:tlist_{ftype}_count
3966 let ttype = s:tlist_{ftype}_{j}_name
3967 if s:tlist_{i}_{ttype}_count != 0
3968 let txt = escape(s:tlist_{i}_{ttype}, '"\')
3969 let txt = substitute(txt, "\n", "\\\\n", 'g')
3970 silent! echo 'let tlist_' . i . '_' . ttype . ' = "' .
3972 silent! echo 'let tlist_' . i . '_' . ttype . '_count = ' .
3973 \ s:tlist_{i}_{ttype}_count
3975 while k <= s:tlist_{i}_{ttype}_count
3976 silent! echo 'let tlist_' . i . '_' . ttype . '_' . k .
3977 \ ' = ' . s:tlist_{i}_{ttype}_{k}
3991 let &verbose = old_verbose
3994 " Tlist_Buffer_Removed
3995 " A buffer is removed from the Vim buffer list. Remove the tags defined
3997 function! s:Tlist_Buffer_Removed(filename)
3998 call s:Tlist_Log_Msg('Tlist_Buffer_Removed (' . a:filename . ')')
4000 " Make sure a valid filename is supplied
4005 " Get tag list index of the specified file
4006 let fidx = s:Tlist_Get_File_Index(a:filename)
4008 " File not present in the taglist
4012 " Remove the file from the list
4013 call s:Tlist_Remove_File(fidx, 0)
4016 " When a buffer is deleted, remove the file from the taglist
4017 autocmd BufDelete * silent call s:Tlist_Buffer_Removed(expand('<afile>:p'))
4019 " Tlist_Window_Open_File_Fold
4020 " Open the fold for the specified file and close the fold for all the
4022 function! s:Tlist_Window_Open_File_Fold(acmd_bufnr)
4023 call s:Tlist_Log_Msg('Tlist_Window_Open_File_Fold (' . a:acmd_bufnr . ')')
4025 " Make sure the taglist window is present
4026 let winnum = bufwinnr(g:TagList_title)
4028 call s:Tlist_Warning_Msg('Taglist: Error - Taglist window is not open')
4032 " Save the original window number
4033 let org_winnr = winnr()
4034 if org_winnr == winnum
4035 let in_taglist_window = 1
4037 let in_taglist_window = 0
4040 if in_taglist_window
4041 " When entering the taglist window, no need to update the folds
4045 " Go to the taglist window
4046 if !in_taglist_window
4047 call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w')
4050 " Close all the folds
4053 " Get tag list index of the specified file
4054 let fname = fnamemodify(bufname(a:acmd_bufnr + 0), ':p')
4055 if filereadable(fname)
4056 let fidx = s:Tlist_Get_File_Index(fname)
4058 " Open the fold for the file
4059 exe "silent! " . s:tlist_{fidx}_start . "," .
4060 \ s:tlist_{fidx}_end . "foldopen"
4064 " Go back to the original window
4065 if !in_taglist_window
4066 call s:Tlist_Exe_Cmd_No_Acmds(org_winnr . 'wincmd w')
4070 " Tlist_Window_Check_Auto_Open
4071 " Open the taglist window automatically on Vim startup.
4072 " Open the window only when files present in any of the Vim windows support
4074 function! s:Tlist_Window_Check_Auto_Open()
4078 let buf_num = winbufnr(i)
4080 let filename = fnamemodify(bufname(buf_num), ':p')
4081 let ft = s:Tlist_Get_Buffer_Filetype(buf_num)
4082 if !s:Tlist_Skip_File(filename, ft)
4087 let buf_num = winbufnr(i)
4091 call s:Tlist_Window_Toggle()
4095 " Tlist_Refresh_Folds
4096 " Remove and create the folds for all the files displayed in the taglist
4097 " window. Used after entering a tab. If this is not done, then the folds
4098 " are not properly created for taglist windows displayed in multiple tabs.
4099 function! s:Tlist_Refresh_Folds()
4100 let winnum = bufwinnr(g:TagList_title)
4105 let save_wnum = winnr()
4106 exe winnum . 'wincmd w'
4108 " First remove all the existing folds
4111 " Create the folds for each in the tag list
4113 while fidx < s:tlist_file_count
4114 let ftype = s:tlist_{fidx}_filetype
4116 " Create the folds for each tag type in a file
4118 while j <= s:tlist_{ftype}_count
4119 let ttype = s:tlist_{ftype}_{j}_name
4120 if s:tlist_{fidx}_{ttype}_count
4121 let s = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset
4122 let e = s + s:tlist_{fidx}_{ttype}_count
4123 exe s . ',' . e . 'fold'
4128 exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold'
4129 exe 'silent! ' . s:tlist_{fidx}_start . ',' .
4130 \ s:tlist_{fidx}_end . 'foldopen!'
4134 exe save_wnum . 'wincmd w'
4137 function! s:Tlist_Menu_Add_Base_Menu()
4138 call s:Tlist_Log_Msg('Adding the base menu')
4141 anoremenu <silent> T&ags.Refresh\ menu :call <SID>Tlist_Menu_Refresh()<CR>
4142 anoremenu <silent> T&ags.Sort\ menu\ by.Name
4143 \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR>
4144 anoremenu <silent> T&ags.Sort\ menu\ by.Order
4145 \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR>
4146 anoremenu T&ags.-SEP1- :
4148 if &mousemodel =~ 'popup'
4149 anoremenu <silent> PopUp.T&ags.Refresh\ menu
4150 \ :call <SID>Tlist_Menu_Refresh()<CR>
4151 anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Name
4152 \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR>
4153 anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Order
4154 \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR>
4155 anoremenu PopUp.T&ags.-SEP1- :
4159 let s:menu_char_prefix =
4160 \ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
4162 " Tlist_Menu_Get_Tag_Type_Cmd
4163 " Get the menu command for the specified tag type
4164 " fidx - File type index
4166 " add_ttype_name - To add or not to add the tag type name to the menu entries
4167 " ttype_idx - Tag type index
4168 function! s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, ttype_idx)
4169 " Curly brace variable name optimization
4170 let ftype_ttype_idx = a:ftype . '_' . a:ttype_idx
4172 let ttype = s:tlist_{ftype_ttype_idx}_name
4174 " If the tag type name contains space characters, escape it. This
4175 " will be used to create the menu entries.
4176 let ttype_fullname = escape(s:tlist_{ftype_ttype_idx}_fullname, ' ')
4179 " Curly brace variable name optimization
4180 let fidx_ttype = a:fidx . '_' . ttype
4182 " Number of tag entries for this tag type
4183 let tcnt = s:tlist_{fidx_ttype}_count
4184 if tcnt == 0 " No entries for this tag type
4190 " Create the menu items for the tags.
4191 " Depending on the number of tags of this type, split the menu into
4192 " multiple sub-menus, if needed.
4193 if tcnt > g:Tlist_Max_Submenu_Items
4196 let final_index = j + g:Tlist_Max_Submenu_Items - 1
4197 if final_index > tcnt
4198 let final_index = tcnt
4201 " Extract the first and last tag name and form the
4203 let tidx = s:tlist_{fidx_ttype}_{j}
4204 let first_tag = s:tlist_{a:fidx}_{tidx}_tag_name
4206 let tidx = s:tlist_{fidx_ttype}_{final_index}
4207 let last_tag = s:tlist_{a:fidx}_{tidx}_tag_name
4209 " Truncate the names, if they are greater than the
4211 let first_tag = strpart(first_tag, 0, g:Tlist_Max_Tag_Length)
4212 let last_tag = strpart(last_tag, 0, g:Tlist_Max_Tag_Length)
4214 " Form the menu command prefix
4215 let m_prefix = 'anoremenu <silent> T\&ags.'
4217 let m_prefix = m_prefix . ttype_fullname . '.'
4219 let m_prefix = m_prefix . first_tag . '\.\.\.' . last_tag . '.'
4221 " Character prefix used to number the menu items (hotkey)
4222 let m_prefix_idx = 0
4224 while j <= final_index
4225 let tidx = s:tlist_{fidx_ttype}_{j}
4227 let tname = s:tlist_{a:fidx}_{tidx}_tag_name
4229 let mcmd = mcmd . m_prefix . '\&' .
4230 \ s:menu_char_prefix[m_prefix_idx] . '\.' .
4231 \ tname . ' :call <SID>Tlist_Menu_Jump_To_Tag(' .
4234 let m_prefix_idx = m_prefix_idx + 1
4239 " Character prefix used to number the menu items (hotkey)
4240 let m_prefix_idx = 0
4242 let m_prefix = 'anoremenu <silent> T\&ags.'
4244 let m_prefix = m_prefix . ttype_fullname . '.'
4248 let tidx = s:tlist_{fidx_ttype}_{j}
4250 let tname = s:tlist_{a:fidx}_{tidx}_tag_name
4252 let mcmd = mcmd . m_prefix . '\&' .
4253 \ s:menu_char_prefix[m_prefix_idx] . '\.' .
4254 \ tname . ' :call <SID>Tlist_Menu_Jump_To_Tag(' . tidx
4257 let m_prefix_idx = m_prefix_idx + 1
4265 " Update the taglist menu with the tags for the specified file
4266 function! s:Tlist_Menu_File_Refresh(fidx)
4267 call s:Tlist_Log_Msg('Refreshing the tag menu for ' . s:tlist_{a:fidx}_filename)
4268 " The 'B' flag is needed in the 'cpoptions' option
4269 let old_cpoptions = &cpoptions
4272 exe s:tlist_{a:fidx}_menu_cmd
4274 " Update the popup menu (if enabled)
4275 if &mousemodel =~ 'popup'
4276 let cmd = substitute(s:tlist_{a:fidx}_menu_cmd, ' T\\&ags\.',
4277 \ ' PopUp.T\\\&ags.', "g")
4281 " The taglist menu is not empty now
4282 let s:tlist_menu_empty = 0
4284 " Restore the 'cpoptions' settings
4285 let &cpoptions = old_cpoptions
4288 " Tlist_Menu_Update_File
4289 " Add the taglist menu
4290 function! s:Tlist_Menu_Update_File(clear_menu)
4291 if !has('gui_running')
4292 " Not running in GUI mode
4296 call s:Tlist_Log_Msg('Updating the tag menu, clear_menu = ' . a:clear_menu)
4298 " Remove the tags menu
4300 call s:Tlist_Menu_Remove_File()
4304 " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help
4309 let filename = fnamemodify(bufname('%'), ':p')
4310 let ftype = s:Tlist_Get_Buffer_Filetype('%')
4312 " If the file doesn't support tag listing, skip it
4313 if s:Tlist_Skip_File(filename, ftype)
4317 let fidx = s:Tlist_Get_File_Index(filename)
4318 if fidx == -1 || !s:tlist_{fidx}_valid
4319 " Check whether this file is removed based on user request
4320 " If it is, then don't display the tags for this file
4321 if s:Tlist_User_Removed_File(filename)
4325 " Process the tags for the file
4326 let fidx = s:Tlist_Process_File(filename, ftype)
4332 let fname = escape(fnamemodify(bufname('%'), ':t'), '.')
4334 exe 'anoremenu T&ags.' . fname . ' <Nop>'
4335 anoremenu T&ags.-SEP2- :
4338 if !s:tlist_{fidx}_tag_count
4342 if s:tlist_{fidx}_menu_cmd != ''
4343 " Update the menu with the cached command
4344 call s:Tlist_Menu_File_Refresh(fidx)
4349 " We are going to add entries to the tags menu, so the menu won't be
4351 let s:tlist_menu_empty = 0
4355 " Determine whether the tag type name needs to be added to the menu
4356 " If more than one tag type is present in the taglisting for a file,
4357 " then the tag type name needs to be present
4358 let add_ttype_name = -1
4360 while i <= s:tlist_{ftype}_count && add_ttype_name < 1
4361 let ttype = s:tlist_{ftype}_{i}_name
4362 if s:tlist_{fidx}_{ttype}_count
4363 let add_ttype_name = add_ttype_name + 1
4368 " Process the tags by the tag type and get the menu command
4370 while i <= s:tlist_{ftype}_count
4371 let mcmd = s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, i)
4373 let cmd = cmd . mcmd
4379 " Cache the menu command for reuse
4380 let s:tlist_{fidx}_menu_cmd = cmd
4383 call s:Tlist_Menu_File_Refresh(fidx)
4386 " Tlist_Menu_Remove_File
4387 " Remove the tags displayed in the tags menu
4388 function! s:Tlist_Menu_Remove_File()
4389 if !has('gui_running') || s:tlist_menu_empty
4393 call s:Tlist_Log_Msg('Removing the tags menu for a file')
4395 " Cleanup the Tags menu
4396 silent! unmenu T&ags
4397 if &mousemodel =~ 'popup'
4398 silent! unmenu PopUp.T&ags
4401 " Add a dummy menu item to retain teared off menu
4402 noremenu T&ags.Dummy l
4404 silent! unmenu! T&ags
4405 if &mousemodel =~ 'popup'
4406 silent! unmenu! PopUp.T&ags
4409 call s:Tlist_Menu_Add_Base_Menu()
4411 " Remove the dummy menu item
4414 let s:tlist_menu_empty = 1
4417 " Tlist_Menu_Refresh
4418 " Refresh the taglist menu
4419 function! s:Tlist_Menu_Refresh()
4420 call s:Tlist_Log_Msg('Refreshing the tags menu')
4421 let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
4423 " Invalidate the cached menu command
4424 let s:tlist_{fidx}_menu_cmd = ''
4427 " Update the taglist, menu and window
4428 call s:Tlist_Update_Current_File()
4431 " Tlist_Menu_Jump_To_Tag
4432 " Jump to the selected tag
4433 function! s:Tlist_Menu_Jump_To_Tag(tidx)
4434 let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
4439 let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, a:tidx)
4444 " Add the current cursor position to the jump list, so that user can
4445 " jump back using the ' and ` marks.
4448 silent call search(tagpat, 'w')
4450 " Bring the line to the middle of the window
4453 " If the line is inside a fold, open the fold
4454 if foldclosed('.') != -1
4460 " Initialize the taglist menu
4461 function! s:Tlist_Menu_Init()
4462 call s:Tlist_Menu_Add_Base_Menu()
4464 " Automatically add the tags defined in the current file to the menu
4465 augroup TagListMenuCmds
4468 if !g:Tlist_Process_File_Always
4469 autocmd BufEnter * call s:Tlist_Refresh()
4471 autocmd BufLeave * call s:Tlist_Menu_Remove_File()
4474 call s:Tlist_Menu_Update_File(0)
4477 " Tlist_Vim_Session_Load
4478 " Initialize the taglist window/buffer, which is created when loading
4479 " a Vim session file.
4480 function! s:Tlist_Vim_Session_Load()
4481 call s:Tlist_Log_Msg('Tlist_Vim_Session_Load')
4483 " Initialize the taglist window
4484 call s:Tlist_Window_Init()
4486 " Refresh the taglist window
4487 call s:Tlist_Window_Refresh()
4491 " Set the name of the external plugin/application to which taglist
4493 " Taglist plugin is part of another plugin like cream or winmanager.
4494 function! Tlist_Set_App(name)
4499 let s:tlist_app_name = a:name
4502 " Winmanager integration
4504 " Initialization required for integration with winmanager
4505 function! TagList_Start()
4506 " If current buffer is not taglist buffer, then don't proceed
4507 if bufname('%') != '__Tag_List__'
4511 call Tlist_Set_App('winmanager')
4513 " Get the current filename from the winmanager plugin
4514 let bufnum = WinManagerGetLastEditedFile()
4516 let filename = fnamemodify(bufname(bufnum), ':p')
4517 let ftype = s:Tlist_Get_Buffer_Filetype(bufnum)
4520 " Initialize the taglist window, if it is not already initialized
4521 if !exists('s:tlist_window_initialized') || !s:tlist_window_initialized
4522 call s:Tlist_Window_Init()
4523 call s:Tlist_Window_Refresh()
4524 let s:tlist_window_initialized = 1
4527 " Update the taglist window
4529 if !s:Tlist_Skip_File(filename, ftype) && g:Tlist_Auto_Update
4530 call s:Tlist_Window_Refresh_File(filename, ftype)
4535 function! TagList_IsValid()
4539 function! TagList_WrapUp()
4544 let &cpo = s:cpo_save