能够列出源文件中的tag(function, class, variable, etc)并跳转.
注意:taglist依赖于ctags,所以要先装ctags,否则taglist装了也没法用!
(1)到 http://vim.sourceforge.net/scripts/script.php?script_id=273
下载taglist_42.zip,即
http://vim.sourceforge.net/scripts/download_script.php?src_id=6416
(2)解压得到两个文件
# unzip -d taglist taglist_42.zip
# cd taglist
# tree
.
|-- doc
| `-- taglist.txt
`-- plugin
`-- taglist.vim
(3)安装
cp doc/taglist.txt /usr/share/vim/vim61/doc/
cp plugin/taglist.vim /usr/share/vim/vim61/plugin/
(4)配置和使用
cd /usr/share/vim/vim61/doc/
启动vim,用 “:helptags .”来配置好帮助文件
重启vim,用“:TlistToggle”来打开和关闭taglist窗口。
可以用“:help taglist”来获得更多帮助信
---------------------下面是一篇英文的taglist配置大全-------------------------
注意:taglist依赖于ctags,所以要先装ctags,否则taglist装了也没法用!
(1)到 http://vim.sourceforge.net/scripts/script.php?script_id=273
下载taglist_42.zip,即
http://vim.sourceforge.net/scripts/download_script.php?src_id=6416
(2)解压得到两个文件
# unzip -d taglist taglist_42.zip
# cd taglist
# tree
.
|-- doc
| `-- taglist.txt
`-- plugin
`-- taglist.vim
(3)安装
cp doc/taglist.txt /usr/share/vim/vim61/doc/
cp plugin/taglist.vim /usr/share/vim/vim61/plugin/
(4)配置和使用
cd /usr/share/vim/vim61/doc/
启动vim,用 “:helptags .”来配置好帮助文件
重启vim,用“:TlistToggle”来打开和关闭taglist窗口。
可以用“:help taglist”来获得更多帮助信
---------------------下面是一篇英文的taglist配置大全-------------------------
参考文献:" File: taglist.vim " Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com) " Version: 3.1 " Last Modified: Nov 1, 2003 " " The "Tag List" plugin is a source code browser plugin for Vim and " provides an overview of the structure of source code files and allows " you to efficiently browse through source code files for different " programming languages. You can visit the taglist plugin home page for " more information: " " http: // www.geocities.com/yegappan/taglist " " You can subscribe to the taglist mailing list to post your questions " or suggestions for improvement or to report bugs. Visit the following " page for subscribing to the mailing list: " " http: // groups.yahoo.com/group/taglist/ " " For more information about using this plugin, after installing the " taglist plugin, use the ":help taglist" command. " " Installation " ------------ " 1. Download the taglist.zip file and unzip the files to the $HOME/.vim " or the $HOME/vimfiles or the $VIM/vimfiles directory. This should " unzip the following two files (the directory structure should be " preserved): " " plugin/taglist.vim - main taglist plugin file " doc/taglist.txt - documentation (help) file " " Refer to the 'add-plugin', 'add-global-plugin' and 'runtimepath' " Vim help pages for more details about installing Vim plugins. " 2. Change to the $HOME/.vim/doc or $HOME/vimfiles/doc or " $VIM/doc/vimfiles directory, start Vim and run the ":helptags ." " command to process the taglist help file. " 3. Set the Tlist_Ctags_Cmd variable to point to the location of the " exuberant ctags utility (not to the directory) in the .vimrc file. " 4. If you are running a terminal/console version of Vim and the " terminal doesn't support changing the window width then set the " 'Tlist_Inc_Winwidth' variable to 0 in the .vimrc file. " 5. Restart Vim. " 6. You can now use the ":Tlist" command to open/close the taglist " window. You can use the ":help taglist" command to get more " information about using the taglist plugin. " " ****************** Do not modify after this line ************************ if exists('loaded_taglist') || &cp finish endif let loaded_taglist=1 " Location of the exuberant ctags tool if !exists('Tlist_Ctags_Cmd') let Tlist_Ctags_Cmd = 'ctags' endif " Tag listing sort type - 'name' or 'order' if !exists('Tlist_Sort_Type') let Tlist_Sort_Type = 'order' endif " Tag listing window split (horizontal/vertical) control if !exists('Tlist_Use_Horiz_Window') let Tlist_Use_Horiz_Window = 0 endif " Open the vertically split taglist window on the left or on the right side. " This setting is relevant only if Tlist_Use_Horiz_Window is set to zero (i.e. " only for vertically split windows) if !exists('Tlist_Use_Right_Window') let Tlist_Use_Right_Window = 0 endif " Increase Vim window width to display vertically split taglist window. For " MS-Windows version of Vim running in a MS-DOS window, this must be set to 0 " otherwise the system may hang due to a Vim limitation. if !exists('Tlist_Inc_Winwidth') if (has('win16') || has('win95')) && !has('gui_running') let Tlist_Inc_Winwidth = 0 else let Tlist_Inc_Winwidth = 1 endif endif " Vertically split taglist window width setting if !exists('Tlist_WinWidth') let Tlist_WinWidth = 30 endif " Horizontally split taglist window height setting if !exists('Tlist_WinHeight') let Tlist_WinHeight = 10 endif " Automatically open the taglist window on Vim startup if !exists('Tlist_Auto_Open') let Tlist_Auto_Open = 0 endif " Display tag prototypes or tag names in the taglist window if !exists('Tlist_Display_Prototype') let Tlist_Display_Prototype = 0 endif " Display tag scopes in the taglist window if !exists('Tlist_Display_Tag_Scope') let Tlist_Display_Tag_Scope = 1 endif " Use single left mouse click to jump to a tag. By default this is disabled. " Only double click using the mouse will be processed. if !exists('Tlist_Use_SingleClick') let Tlist_Use_SingleClick = 0 endif " Control whether additional help is displayed as part of the taglist or not. " Also, controls whether empty lines are used to separate the tag tree. if !exists('Tlist_Compact_Format') let Tlist_Compact_Format = 0 endif " Exit Vim if only the taglist window is currently open. By default, this is " set to zero. if !exists('Tlist_Exit_OnlyWindow') let Tlist_Exit_OnlyWindow = 0 endif "------------------- end of user configurable options -------------------- " Initialize the taglist plugin local variables for the supported file types " and tag types " assembly language let s:tlist_def_asm_settings = 'asm;d:define;l:label;m:macro;t:type' " aspperl language let s:tlist_def_aspperl_settings = 'asp;f:function;s:sub;v:variable' " aspvbs language let s:tlist_def_aspvbs_settings = 'asp;f: function;s:sub;v:variable' " awk language let s:tlist_def_awk_settings = 'awk;f:function' " beta language let s:tlist_def_beta_settings = 'beta;f:fragment;s:pattern;v:virtual' " c language let s:tlist_def_c_settings = 'c;d:macro;g:enum;s:struct;u:union;t:typedef;' . \ 'v:variable;f:function' " c++ language let s:tlist_def_cpp_settings = 'c++;v:variable;d:macro;t:typedef;c:class;' . \ 'n:namespace;g:enum;s:struct;u:union;f: function' " c# language let s:tlist_def_cs_settings = 'c#;d:macro;t:typedef;n:namespace;c:class;' . \ 'E:event;g:enum;s:struct;i:interface;' . \ 'p:properties;m:method' " cobol language let s:tlist_def_cobol_settings = 'cobol;d:data;f:file;g:group;p:paragraph;' . \ 'P:program;s:section' " eiffel language let s:tlist_def_eiffel_settings = 'eiffel;c:class;f:feature' " erlang language let s:tlist_def_erlang_settings = 'erlang;d:macro;r:record;m:module;f: function' " expect (same as tcl) language let s:tlist_def_expect_settings = 'expect;c:class;f:method;p:procedure' " fortran language let s:tlist_def_fortran_settings = 'fortran;p:program;b:block data;' . \ 'c:common;e:entry;i:interface;k:type;l:label;m:module;' . \ 'n:namelist;t:derived;v:variable;f: function;s:subroutine' " HTML language let s:tlist_def_html_settings = 'html;a:anchor;f:javascript function' " java language let s:tlist_def_java_settings = 'java;p:package;c:class;i:interface;' . \ 'f:field;m:method' " javascript language let s:tlist_def_javascript_settings = 'javascript;f:function' " lisp language let s:tlist_def_lisp_settings = 'lisp;f: function' " lua language let s:tlist_def_lua_settings = 'lua;f:function' " makefiles let s:tlist_def_make_settings = 'make;m:macro' " pascal language let s:tlist_def_pascal_settings = 'pascal;f:function;p:procedure' " perl language let s:tlist_def_perl_settings = 'perl;p:package;s:subroutine' " php language let s:tlist_def_php_settings = 'php;c:class;f:function' " python language let s:tlist_def_python_settings = 'python;c:class;m:member;f: function' " rexx language let s:tlist_def_rexx_settings = 'rexx;s:subroutine' " ruby language let s:tlist_def_ruby_settings = 'ruby;c:class;f:method;F: function;' . \ 'm:singleton method' " scheme language let s:tlist_def_scheme_settings = 'scheme;s:set;f:function' " shell language let s:tlist_def_sh_settings = 'sh;f: function' " C shell language let s:tlist_def_csh_settings = 'sh;f:function' " Z shell language let s:tlist_def_zsh_settings = 'sh;f: function' " slang language let s:tlist_def_slang_settings = 'slang;n:namespace;f:function' " sml language let s:tlist_def_sml_settings = 'sml;e:exception;c:functor;s:signature;' . \ 'r:structure;t:type;v:value;f: function' " sql language let s:tlist_def_sql_settings = 'sql;c:cursor;F:field;P:package;r:record;' . \ 's:subtype;t:table;T:trigger;v:variable;f:function;p:procedure' " tcl language let s:tlist_def_tcl_settings = 'tcl;c:class;f:method;p:procedure' " vera language let s:tlist_def_vera_settings = 'vera;c:class;d:macro;e:enumerator;' . \ 'f:function;g:enum;m:member;p:program;' . \ 'P:prototype;t:task;T:typedef;v:variable;' . \ 'x:externvar' "verilog language let s:tlist_def_verilog_settings = 'verilog;m:module;P:parameter;r:register;' . \ 't:task;w:write;p:port;v:variable;f: function' " vim language let s:tlist_def_vim_settings = 'vim;a:autocmds;v:variable;f:function' " yacc language let s:tlist_def_yacc_settings = 'yacc;l:label' "------------------- end of language specific options -------------------- " Vim window size is changed or not let s:tlist_winsize_chgd = 0 " Taglist window is maximized or not let s:tlist_win_maximized = 0 " Number of files displayed in the taglist window let s:tlist_file_count = 0 " Number of filetypes supported by taglist let s:tlist_ftype_count = 0 " Current active file index let s:tlist_cur_fidx = -1 " Is taglist part of the winmanager plugin let s:tlist_part_of_winmanager = 0 " Are we displaying brief help text let s:tlist_brief_help = 1 " Do not change the name of the taglist title variable. The winmanager plugin " relies on this name to determine the title for the taglist plugin. let TagList_title = "__Tag_List__" " An autocommand is used to refresh the taglist window when entering any " buffer. We don't want to refresh the taglist window if we are entering the " file window from one of the taglist functions. The 'Tlist_Skip_Refresh' " variable is used to skip the refresh of the taglist window and is set " and cleared appropriately. let s:Tlist_Skip_Refresh = 0 " Tlist_Display_Help() function! s:Tlist_Display_Help() if s:tlist_part_of_winmanager " To handle a bug in the winmanager plugin, add a space at the " last line call setline('$', ' ') endif if s:tlist_brief_help " Add the brief help call append(0, '" Press ? to display help text') else " Add the extensive help call append(0, '" <enter> : Jump to tag definition') call append(1, '" o : Jump to tag definition in new window') call append(2, '" p : Preview the tag definition') call append(3, '" <space> : Display tag prototype') call append(4, '" u : Update tag list') call append(5, '" s : Select sort field') call append(6, '" d : Remove file from taglist') call append(7, '" x : Zoom-out/Zoom-in taglist window') call append(8, '" + : Open a fold') call append(9, '" - : Close a fold') call append(10, '" * : Open all folds') call append(11, '" = : Close all folds') call append(12, '" q : Close the taglist window') call append(13, '" ? : Remove help text') endif endfunction " Tlist_Toggle_Help_Text() " Toggle taglist plugin help text between the full version and the brief " version function! s:Tlist_Toggle_Help_Text() if g:Tlist_Compact_Format " In compact display mode, do not display help return endif " Include the empty line displayed after the help text let brief_help_size = 1 let full_help_size = 14 setlocal modifiable " Set report option to a huge value to prevent informational messages " while deleting the lines let old_report = &report set report=99999 " Remove the currently highlighted tag. Otherwise, the help text " might be highlighted by mistake match none " Toggle between brief and full help text if s:tlist_brief_help let s:tlist_brief_help = 0 " Remove the previous help exe '1,' . brief_help_size . ' delete _' " Adjust the start/end line numbers for the files call s:Tlist_Update_Line_Offsets(0, 1, full_help_size - brief_help_size) else let s:tlist_brief_help = 1 " Remove the previous help exe '1,' . full_help_size . ' delete _' " Adjust the start/end line numbers for the files call s:Tlist_Update_Line_Offsets(0, 0, full_help_size - brief_help_size) endif call s:Tlist_Display_Help() " Restore the report option let &report = old_report setlocal nomodifiable endfunction " Tlist_Warning_Msg() " Display a message using WarningMsg highlight group function! s:Tlist_Warning_Msg(msg) echohl WarningMsg echomsg a:msg echohl None endfunction " Tlist_Get_File_Index() " Return the index of the specified filename function! s:Tlist_Get_File_Index(fname) let i = 0 " Do a linear search while i < s:tlist_file_count if s:tlist_{i}_filename == a:fname return i endif let i = i + 1 endwhile return -1 endfunction " Tlist_Get_File_Index_By_Linenum() " Return the index of the filename present in the specified line number function! s:Tlist_Get_File_Index_By_Linenum(lnum) let i = 0 " TODO: Convert this to a binary search while i < s:tlist_file_count if a:lnum >= s:tlist_{i}_start && a:lnum <= s:tlist_{i}_end return i endif let i = i + 1 endwhile return -1 endfunction " Tlist_Skip_File() " Check whether tag listing is supported for the specified file function! s:Tlist_Skip_File(filename, ftype) " Skip buffers with filetype not set if a:ftype == '' return 1 endif " Skip files which are not supported by exuberant ctags " First check whether default settings for this filetype are available. " If it is not available, then check whether user specified settings are " available. If both are not available, then don't list the tags for this " filetype let var = 's:tlist_def_' . a:ftype . '_settings' if !exists( var) let var = 'g:tlist_' . a:ftype . '_settings' if !exists( var) return 1 endif endif " Skip buffers with no names if a:filename == '' return 1 endif " Skip files which are not readable or files which are not yet stored " to the disk if !filereadable(a:filename) return 1 endif return 0 endfunction " Tlist_FileType_Init " Initialize the ctags arguments and tag variable for the specified " file type function! s:Tlist_FileType_Init(ftype) " If the user didn't specify any settings, then use the default " ctags args. Otherwise, use the settings specified by the user let var = 'g:tlist_' . a:ftype . '_settings' if exists( var) " User specified ctags arguments let settings = {var} . ';' else " Default ctags arguments let var = 's:tlist_def_' . a:ftype . '_settings' if !exists( var) " No default settings for this file type. This filetype is " not supported return 0 endif let settings = s:tlist_def_{a:ftype}_settings . ';' endif let msg = 'Invalid ctags option setting - ' . settings " Format of the option that specifies the filetype and ctags arugments: " " <language_name>;flag1:name1;flag2:name2;flag3:name3 " " Extract the file type to pass to ctags. This may be different from the " file type detected by Vim let pos = stridx(settings, ';') if pos == -1 call s:Tlist_Warning_Msg(msg) return 0 endif let ctags_ftype = strpart(settings, 0, pos) if ctags_ftype == '' call s:Tlist_Warning_Msg(msg) return 0 endif " Make sure a valid filetype is supplied. If the user didn't specify a " valid filetype, then the ctags option settings may be treated as the " filetype if ctags_ftype =~ ':' call s:Tlist_Warning_Msg(msg) return 0 endif " Remove the file type from settings let settings = strpart(settings, pos + 1) if settings == '' call s:Tlist_Warning_Msg(msg) return 0 endif " Process all the specified ctags flags. The format is " flag1:name1;flag2:name2;flag3:name3 let ctags_flags = '' let cnt = 0 while settings != '' " Extract the flag let pos = stridx(settings, ':') if pos == -1 call s:Tlist_Warning_Msg(msg) return 0 endif let flag = strpart(settings, 0, pos) if flag == '' call s:Tlist_Warning_Msg(msg) return 0 endif " Remove the flag from settings let settings = strpart(settings, pos + 1) " Extract the tag type name let pos = stridx(settings, ';') if pos == -1 call s:Tlist_Warning_Msg(msg) return 0 endif let name = strpart(settings, 0, pos) if name == '' call s:Tlist_Warning_Msg(msg) return 0 endif let settings = strpart(settings, pos + 1) let cnt = cnt + 1 let s:tlist_{a:ftype}_{cnt}_name = flag let s:tlist_{a:ftype}_{cnt}_fullname = name let ctags_flags = ctags_flags . flag endwhile let s:tlist_{a:ftype}_ctags_args = '--language-force=' . ctags_ftype . \ ' --' . ctags_ftype . '-types=' . ctags_flags let s:tlist_{a:ftype}_count = cnt let s:tlist_{a:ftype}_ctags_flags = ctags_flags " Save the filetype name let s:tlist_ftype_{s:tlist_ftype_count}_name = a:ftype let s:tlist_ftype_count = s:tlist_ftype_count + 1 return 1 endfunction " Tlist_Discard_TagInfo " Discard the stored tag information for a file function! s:Tlist_Discard_TagInfo(fidx) let ftype = s:tlist_{a:fidx}_filetype " Discard information about the tags defined in the file let i = 1 while i <= s:tlist_{a:fidx}_tag_count unlet s:tlist_{a:fidx}_tag_{i} let i = i + 1 endwhile let s:tlist_{a:fidx}_tag_count = 0 " Discard information about tags groups by their type let i = 1 while i <= s:tlist_{ftype}_count let ttype = s:tlist_{ftype}_{i}_name if s:tlist_{a:fidx}_{ttype} != '' let s:tlist_{a:fidx}_{ttype} = '' let s:tlist_{a:fidx}_{ttype}_start = 0 let cnt = s:tlist_{a:fidx}_{ttype}_count let s:tlist_{a:fidx}_{ttype}_count = 0 let j = 1 while j <= cnt unlet s:tlist_{a:fidx}_{ttype}_{j} let j = j + 1 endwhile endif let i = i + 1 endwhile endfunction " Tlist_Update_Line_Offsets " Update the line offsets for tags for files starting from start_idx " and displayed in the taglist window by the specified offset function! s:Tlist_Update_Line_Offsets(start_idx, increment, offset) let i = a:start_idx while i < s:tlist_file_count if s:tlist_{i}_visible " Update the start/end line number only if the file is visible if a:increment let s:tlist_{i}_start = s:tlist_{i}_start + a:offset let s:tlist_{i}_end = s:tlist_{i}_end + a:offset else let s:tlist_{i}_start = s:tlist_{i}_start - a:offset let s:tlist_{i}_end = s:tlist_{i}_end - a:offset endif endif let i = i + 1 endwhile endfunction " Tlist_Discard_FileInfo " Discard the stored information for a file function! s:Tlist_Discard_FileInfo(fidx) call s:Tlist_Discard_TagInfo(a:fidx) let ftype = s:tlist_{a:fidx}_filetype let i = 1 while i <= s:tlist_{ftype}_count let ttype = s:tlist_{ftype}_{i}_name unlet s:tlist_{a:fidx}_{ttype} unlet s:tlist_{a:fidx}_{ttype}_start unlet s:tlist_{a:fidx}_{ttype}_count let i = i + 1 endwhile unlet s:tlist_{a:fidx}_filename unlet s:tlist_{a:fidx}_sort_type unlet s:tlist_{a:fidx}_filetype unlet s:tlist_{a:fidx}_start unlet s:tlist_{a:fidx}_end unlet s:tlist_{a:fidx}_valid unlet s:tlist_{a:fidx}_visible unlet s:tlist_{a:fidx}_tag_count endfunction " Tlist_Remove_File_From_Display " Remove the specified file from display function! s:Tlist_Remove_File_From_Display(fidx) " Remove the tags displayed for the specified file from the window let start = s:tlist_{a:fidx}_start " Include the empty line after the last line also if g:Tlist_Compact_Format let end = s:tlist_{a:fidx}_end else let end = s:tlist_{a:fidx}_end + 1 endif setlocal modifiable exe 'silent! ' . start . ',' . end . ' delete _' setlocal nomodifiable " Correct the start and end line offsets for all the files following " this file, as the tags for this file are removed call s:Tlist_Update_Line_Offsets(a:fidx + 1, 0, end - start + 1) endfunction " Tlist_Remove_File " Remove the file under the cursor or the specified file index function! s:Tlist_Remove_File(file_idx, update_display) if a:file_idx == -1 let fidx = s:Tlist_Get_File_Index_By_Linenum(line('.')) if fidx == -1 return endif else let fidx = a:file_idx endif if a:update_display call s:Tlist_Remove_File_From_Display(fidx) endif call s:Tlist_Discard_FileInfo(fidx) " Shift all the file variables by one index let i = fidx + 1 while i < s:tlist_file_count let j = i - 1 let s:tlist_{j}_filename = s:tlist_{i}_filename let s:tlist_{j}_sort_type = s:tlist_{i}_sort_type let s:tlist_{j}_filetype = s:tlist_{i}_filetype let s:tlist_{j}_start = s:tlist_{i}_start let s:tlist_{j}_end = s:tlist_{i}_end let s:tlist_{j}_valid = s:tlist_{i}_valid let s:tlist_{j}_visible = s:tlist_{i}_visible let s:tlist_{j}_tag_count = s:tlist_{i}_tag_count let k = 1 while k <= s:tlist_{j}_tag_count let s:tlist_{j}_tag_{k} = s:tlist_{i}_tag_{k} let k = k + 1 endwhile let ftype = s:tlist_{i}_filetype let k = 1 while k <= s:tlist_{ftype}_count let ttype = s:tlist_{ftype}_{k}_name let s:tlist_{j}_{ttype} = s:tlist_{i}_{ttype} let s:tlist_{j}_{ttype}_start = s:tlist_{i}_{ttype}_start let s:tlist_{j}_{ttype}_count = s:tlist_{i}_{ttype}_count if s:tlist_{j}_{ttype} != '' let l = 1 while l <= s:tlist_{j}_{ttype}_count let s:tlist_{j}_{ttype}_{l} = s:tlist_{i}_{ttype}_{l} let l = l + 1 endwhile endif let k = k + 1 endwhile call s:Tlist_Discard_FileInfo(i) let i = i + 1 endwhile " Reduce the number of files displayed let s:tlist_file_count = s:tlist_file_count - 1 endfunction " Tlist_Open_Window " Create a new taglist window. If it is already open, clear it function! s:Tlist_Open_Window() " If used with winmanager don't open windows. Winmanager will handle " the window/buffer management if s:tlist_part_of_winmanager return endif " Cleanup the taglist window listing, if the window is open let winnum = bufwinnr(g:TagList_title) if winnum != -1 " Jump to the existing window if winnr() != winnum exe winnum . 'wincmd w' endif else " Create a new window. If user prefers a horizontal window, then open " a horizontally split window. Otherwise open a vertically split " window if g:Tlist_Use_Horiz_Window " Open a horizontally split window let win_dir = 'botright' " Horizontal window height let win_size = g:Tlist_WinHeight else " Open a horizontally split window. Increase the window size, if " needed, to accomodate the new window if g:Tlist_Inc_Winwidth && \ &columns < (80 + g:Tlist_WinWidth) " one extra column is needed to include the vertical split let &columns= &columns + (g:Tlist_WinWidth + 1) let s:tlist_winsize_chgd = 1 else let s:tlist_winsize_chgd = 0 endif if g:Tlist_Use_Right_Window " Open the window at the rightmost place let win_dir = 'botright vertical' else " Open the window at the leftmost place let win_dir = 'topleft vertical' endif let win_size = g:Tlist_WinWidth endif " If the tag listing temporary buffer already exists, then reuse it. " Otherwise create a new buffer let bufnum = bufnr(g:TagList_title) if bufnum == -1 " Create a new buffer let wcmd = g:TagList_title else " Edit the existing buffer let wcmd = '+buffer' . bufnum endif " Create the taglist window exe 'silent! ' . win_dir . ' ' . win_size . 'split ' . wcmd endif endfunction " Tlist_Zoom_Window " Zoom (maximize/minimize) the taglist window function! s:Tlist_Zoom_Window() if s:tlist_win_maximized " Restore the window back to the previous size if g:Tlist_Use_Horiz_Window exe 'resize ' . g:Tlist_WinHeight else exe 'vert resize ' . g:Tlist_WinWidth endif let s:tlist_win_maximized = 0 else " Set the window size to the maximum possible without closing other " windows if g:Tlist_Use_Horiz_Window resize else vert resize endif let s:tlist_win_maximized = 1 endif endfunction " Tlist_Init_Window " Set the default options for the taglist window function! s:Tlist_Init_Window() " Set report option to a huge value to prevent informational messages " while deleting the lines let old_report = &report set report=99999 " Mark the buffer as modifiable setlocal modifiable " Delete the contents of the buffer to the black-hole register silent! % delete _ " Mark the buffer as not modifiable setlocal nomodifiable " Restore the report option let &report = old_report " Mark the buffer as modifiable setlocal modifiable if g:Tlist_Compact_Format == 0 " Display help in non-compact mode call s:Tlist_Display_Help() endif " Mark the buffer as not modifiable setlocal nomodifiable " Define taglist window element highlighting if has('syntax') syntax match TagListComment '^" .*' syntax match TagListFileName '^[^" ].*$' syntax match TagListTitle '^ \S.*$' syntax match TagListTagScope '\s\[.\{-\}\]$' " Define the highlighting only if colors are supported if has('gui_running') || &t_Co > 2 " Colors to highlight various taglist window elements " If user defined highlighting group exists, then use them. " Otherwise, use default highlight groups. if hlexists('MyTagListTagName') highlight link TagListTagName MyTagListTagName else highlight link TagListTagName Search endif " Colors to highlight comments and titles if hlexists('MyTagListComment') highlight link TagListComment MyTagListComment else highlight clear TagListComment highlight link TagListComment Comment endif if hlexists('MyTagListTitle') highlight link TagListTitle MyTagListTitle else highlight clear TagListTitle highlight link TagListTitle Title endif if hlexists('MyTagListFileName') highlight link TagListFileName MyTagListFileName else highlight clear TagListFileName highlight link TagListFileName LineNr endif if hlexists('MyTagListTagScope') highlight link TagListTagScope MyTagListTagScope else highlight clear TagListTagScope highlight link TagListTagScope Identifier endif else highlight TagListTagName term=reverse cterm=reverse endif endif " Folding related settings if has('folding') setlocal foldenable setlocal foldmethod=manual setlocal foldcolumn=3 setlocal foldtext=v:folddashes.getline(v:foldstart) endif if !s:tlist_part_of_winmanager " Mark buffer as scratch silent! setlocal buftype=nofile silent! setlocal bufhidden=delete silent! setlocal noswapfile " Due to a bug in Vim 6.0, the winbufnr() function fails for unlisted " buffers. So if the taglist buffer is unlisted, multiple taglist " windows will be opened. This bug is fixed in Vim 6.1 and above if v:version >= 601 silent! setlocal nobuflisted endif endif silent! setlocal nowrap " If the 'number' option is set in the source window, it will affect the " taglist window. So forcefully disable 'number' option for the taglist " window silent! setlocal nonumber " Create buffer local mappings for jumping to the tags and sorting the list nnoremap <buffer> <silent> <CR> :call <SID>Tlist_Jump_To_Tag(0)<CR> nnoremap <buffer> <silent> o :call <SID>Tlist_Jump_To_Tag(1)<CR> nnoremap <buffer> <silent> p :call <SID>Tlist_Jump_To_Tag(2)<CR> nnoremap <buffer> <silent> <2-LeftMouse> :call <SID>Tlist_Jump_To_Tag(0)<CR> nnoremap <buffer> <silent> s :call <SID>Tlist_Change_Sort()<CR> nnoremap <buffer> <silent> + :silent! foldopen<CR> nnoremap <buffer> <silent> - :silent! foldclose<CR> nnoremap <buffer> <silent> * :silent! %foldopen!<CR> nnoremap <buffer> <silent> = :silent! %foldclose!<CR> nnoremap <buffer> <silent> <kPlus> :silent! foldopen<CR> nnoremap <buffer> <silent> <kMinus> :silent! foldclose<CR> nnoremap <buffer> <silent> <kMultiply> :silent! %foldopen!<CR> nnoremap <buffer> <silent> <Space> :call <SID>Tlist_Show_Tag_Prototype()<CR> nnoremap <buffer> <silent> u :call <SID>Tlist_Update_Window()<CR> nnoremap <buffer> <silent> d :call <SID>Tlist_Remove_File(-1, 1)<CR> nnoremap <buffer> <silent> x :call <SID>Tlist_Zoom_Window()<CR> nnoremap <buffer> <silent> ? :call <SID>Tlist_Toggle_Help_Text()<CR> nnoremap <buffer> <silent> q :close<CR> " Insert mode mappings inoremap <buffer> <silent> <CR> <C-o>:call <SID>Tlist_Jump_To_Tag(0)<CR> " Windows needs return inoremap <buffer> <silent> <Return> <C-o>:call <SID>Tlist_Jump_To_Tag(0)<CR> inoremap <buffer> <silent> o <C-o>:call <SID>Tlist_Jump_To_Tag(1)<CR> inoremap <buffer> <silent> p <C-o>:call <SID>Tlist_Jump_To_Tag(2)<CR> inoremap <buffer> <silent> <2-LeftMouse> <C-o>:call \ <SID>Tlist_Jump_To_Tag(0)<CR> inoremap <buffer> <silent> s <C-o>:call <SID>Tlist_Change_Sort()<CR> inoremap <buffer> <silent> + <C-o>:silent! foldopen<CR> inoremap <buffer> <silent> - <C-o>:silent! foldclose<CR> inoremap <buffer> <silent> * <C-o>:silent! %foldopen!<CR> inoremap <buffer> <silent> = <C-o>:silent! %foldclose!<CR> inoremap <buffer> <silent> <kPlus> <C-o>:silent! foldopen<CR> inoremap <buffer> <silent> <kMinus> <C-o>:silent! foldclose<CR> inoremap <buffer> <silent> <kMultiply> <C-o>:silent! %foldopen!<CR> inoremap <buffer> <silent> <Space> <C-o>:call \ <SID>Tlist_Show_Tag_Prototype()<CR> inoremap <buffer> <silent> u <C-o>:call <SID>Tlist_Update_Window()<CR> inoremap <buffer> <silent> d <C-o>:call <SID>Tlist_Remove_File(-1, 1)<CR> inoremap <buffer> <silent> x <C-o>:call <SID>Tlist_Zoom_Window()<CR> inoremap <buffer> <silent> ? <C-o>:call <SID>Tlist_Toggle_Help_Text()<CR> inoremap <buffer> <silent> q <C-o>:close<CR> " Map single left mouse click if the user wants this functionality if g:Tlist_Use_SingleClick nnoremap <silent> <LeftMouse> <LeftMouse>:if bufname("%") =~ "__Tag_List__" \ <bar> call <SID>Tlist_Jump_To_Tag(0) <bar> endif <CR> endif " Define the taglist autocommands augroup TagListAutoCmds autocmd! " Display the tag prototype for the tag under the cursor. autocmd CursorHold __Tag_List__ call s:Tlist_Show_Tag_Prototype() " Highlight the current tag autocmd CursorHold * silent call <SID>Tlist_Highlight_Tag( \ fnamemodify(bufname('%'), ':p'), line('.')) " Adjust the Vim window width when taglist window is closed autocmd BufUnload __Tag_List__ call <SID>Tlist_Post_Close_Cleanup() " Exit Vim itself if only the taglist window is present (optional) autocmd BufEnter __Tag_List__ call <SID>Tlist_Check_Only_Window() if !s:tlist_part_of_winmanager " Auto refresh the taglist window autocmd BufEnter * call <SID>Tlist_Refresh_Window() endif augroup end " List all the tags for the previously processed files let i = 0 while i < s:tlist_file_count " Mark the file as not visible, so that Tlist_Explore_File() will " display the tags for this file and mark the file as visible let s:tlist_{i}_visible = 0 call s:Tlist_Explore_File(s:tlist_{i}_filename, s:tlist_{i}_filetype) let i = i + 1 endwhile endfunction " Tlist_Post_Close_Cleanup() " Close the taglist window and adjust the Vim window width function! s:Tlist_Post_Close_Cleanup() " Mark all the files as not visible let i = 0 while i < s:tlist_file_count let s:tlist_{i}_visible = 0 let i = i + 1 endwhile " Remove the taglist autocommands silent! autocmd! TagListAutoCmds " Clear all the highlights match none if has('syntax') silent! syntax clear TagListTitle silent! syntax clear TagListComment silent! syntax clear TagListTagScope endif " Remove the left mouse click mapping if it was setup initially if g:Tlist_Use_SingleClick if hasmapto('<LeftMouse>') nunmap <LeftMouse> endif endif if !s:tlist_part_of_winmanager if g:Tlist_Use_Horiz_Window || g:Tlist_Inc_Winwidth == 0 || \ s:tlist_winsize_chgd == 0 || \ &columns < (80 + g:Tlist_WinWidth) " No need to adjust window width if using horizontally split taglist " window or if columns is less than 101 or if the user chose not to " adjust the window width else " Adjust the Vim window width let &columns= &columns - (g:Tlist_WinWidth + 1) endif endif " Reset taglist state variables let s:tlist_cur_fidx = -1 if s:tlist_part_of_winmanager let s:tlist_part_of_winmanager = 0 let s:tlist_window_initialized = 0 endif endfunction " Tlist_Check_Only_Window " Check if only the taglist window is opened currently. If the " Tlist_Exit_OnlyWindow variable is set, then close the taglist window function! s:Tlist_Check_Only_Window() if g:Tlist_Exit_OnlyWindow if winbufnr(2) == -1 && bufname(winbufnr(1)) == g:TagList_title " If only the taglist window is currently open, then the buffer " number associated with window 2 will be -1. quit endif endif endfunction " Tlist_Explore_File() " List the tags defined in the specified file in a Vim window function! s:Tlist_Explore_File(filename, ftype) " First check whether the file already exists let fidx = s:Tlist_Get_File_Index(a:filename) if fidx != -1 let file_exists = 1 else let file_exists = 0 endif if file_exists && s:tlist_{fidx}_visible " Check whether the file tags are currently valid if s:tlist_{fidx}_valid " Make the selected file as the current file let s:tlist_cur_fidx = fidx " Goto the first line in the file exe s:tlist_{fidx}_start return endif " Discard and remove the tags for this file from display call s:Tlist_Discard_TagInfo(fidx) call s:Tlist_Remove_File_From_Display(fidx) endif " Process and generate a list of tags defined in the file if !file_exists || !s:tlist_{fidx}_valid let ret_fidx = s:Tlist_Process_File(a:filename, a:ftype) if ret_fidx == -1 if file_exists " If the tags for the file were previously displayed and now " we are not able to get the tag information then discard the " file information call s:Tlist_Remove_File(fidx, 0) endif return endif let fidx = ret_fidx endif " Make the selected file as the current file let s:tlist_cur_fidx = fidx " Set report option to a huge value to prevent informational messages " while adding lines to the taglist window let old_report = &report set report=99999 " Mark the buffer as modifiable setlocal modifiable " Add new files to the end of the window. For existing files, add them at " the same line where they were previously present. If the file is not " visible, then add it at the end if s:tlist_{fidx}_start == 0 || !s:tlist_{fidx}_visible if g:Tlist_Compact_Format let s:tlist_{fidx}_start = line('$') else let s:tlist_{fidx}_start = line('$') + 1 endif endif let s:tlist_{fidx}_visible = 1 " Goto the line where this file should be placed if g:Tlist_Compact_Format exe s:tlist_{fidx}_start else exe (s:tlist_{fidx}_start - 1) endif let txt = fnamemodify(s:tlist_{fidx}_filename, ':t') . ' (' . \ fnamemodify(s:tlist_{fidx}_filename, ':p:h') . ')' if g:Tlist_Compact_Format == 0 silent! put =txt else silent! put! =txt " Move to the next line exe line('.') + 1 endif let file_start = s:tlist_{fidx}_start " Add the tag names grouped by tag type to the buffer with a title let i = 1 while i <= s:tlist_{a:ftype}_count let ttype = s:tlist_{a:ftype}_{i}_name " Add the tag type only if there are tags for that type if s:tlist_{fidx}_{ttype} != '' let txt = ' ' . s:tlist_{a:ftype}_{i}_fullname if g:Tlist_Compact_Format == 0 let ttype_start_lnum = line('.') + 1 silent! put =txt else let ttype_start_lnum = line('.') silent! put! =txt endif silent! put =s:tlist_{fidx}_{ttype} if g:Tlist_Compact_Format exe (line('.') + s:tlist_{fidx}_{ttype}_count) endif let s:tlist_{fidx}_{ttype}_start = ttype_start_lnum - file_start " create a fold for this tag type if has('folding') let fold_start = ttype_start_lnum let fold_end = fold_start + s:tlist_{fidx}_{ttype}_count exe fold_start . ',' . fold_end . 'fold' endif if g:Tlist_Compact_Format == 0 silent! put ='' endif endif let i = i + 1 endwhile if s:tlist_{fidx}_tag_count == 0 put ='' endif let s:tlist_{fidx}_end = line('.') - 1 " Create a fold for the entire file if has('folding') exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold' exe 'silent! ' . s:tlist_{fidx}_start . ',' . \ s:tlist_{fidx}_end . 'foldopen!' endif " Goto the starting line for this file, exe s:tlist_{fidx}_start if s:tlist_part_of_winmanager " To handle a bug in the winmanager plugin, add a space at the " last line call setline('$', ' ') endif " Mark the buffer as not modifiable setlocal nomodifiable " Restore the report option let &report = old_report " Update the start and end line numbers for all the files following this " file let start = s:tlist_{fidx}_start " include the empty line after the last line if g:Tlist_Compact_Format let end = s:tlist_{fidx}_end else let end = s:tlist_{fidx}_end + 1 endif call s:Tlist_Update_Line_Offsets(fidx + 1, 1, end - start + 1) return endfunction " Tlist_Init_File " Initialize the variables for a new file function! s:Tlist_Init_File(filename, ftype) " Add new files at the end of the list let fidx = s:tlist_file_count let s:tlist_file_count = s:tlist_file_count + 1 " Initialize the file variables let s:tlist_{fidx}_filename = a:filename let s:tlist_{fidx}_sort_type = g:Tlist_Sort_Type let s:tlist_{fidx}_filetype = a:ftype let s:tlist_{fidx}_start = 0 let s:tlist_{fidx}_end = 0 let s:tlist_{fidx}_valid = 0 let s:tlist_{fidx}_visible = 0 let s:tlist_{fidx}_tag_count = 0 " Initialize the tag type variables let i = 1 while i <= s:tlist_{a:ftype}_count let ttype = s:tlist_{a:ftype}_{i}_name let s:tlist_{fidx}_{ttype} = '' let s:tlist_{fidx}_{ttype}_start = 0 let s:tlist_{fidx}_{ttype}_count = 0 let i = i + 1 endwhile return fidx endfunction " Tlist_Process_File " Get the list of tags defined in the specified file and store them " in Vim variables. Returns the file index where the tags are stored. function! s:Tlist_Process_File(filename, ftype) " Check for valid filename and valid filetype if a:filename == '' || !filereadable(a:filename) || a:ftype == '' return -1 endif " If the tag types for this filetype are not yet created, then create " them now let var = 's:tlist_' . a:ftype . '_count' if !exists(var) if s:Tlist_FileType_Init(a:ftype) == 0 return -1 endif endif " If this file is already processed, then use the cached values let fidx = s:Tlist_Get_File_Index(a:filename) if fidx == -1 " First time, this file is loaded let fidx = s:Tlist_Init_File(a:filename, a:ftype) endif let s:tlist_{fidx}_valid = 1 " Exuberant ctags arguments to generate a tag list let ctags_args = ' -f - --format=2 --excmd=pattern --fields=nks ' " Form the ctags argument depending on the sort type if s:tlist_{fidx}_sort_type == 'name' let ctags_args = ctags_args . ' --sort=yes ' else let ctags_args = ctags_args . ' --sort=no ' endif " Add the filetype specific arguments let ctags_args = ctags_args . ' ' . s:tlist_{a:ftype}_ctags_args " Ctags command to produce output with regexp for locating the tags let ctags_cmd = g:Tlist_Ctags_Cmd . ctags_args let ctags_cmd = ctags_cmd . ' "' . a:filename . '"' " In Windows 95, if not using cygwin, disable the 'shellslash' " option. Otherwise, this will cause problems when running the " ctags command. if has("win95") && !has("win32unix") let myshellslash = &shellslash set noshellslash endif " Run ctags and get the tag list let cmd_output = system(ctags_cmd) " Restore the value of the 'shellslash' option. if has("win95") && !has("win32unix") let &shellslash = myshellslash endif " Handle errors if v:shell_error && cmd_output != '' call s:Tlist_Warning_Msg(cmd_output) return -1 endif " No tags for current file if cmd_output == '' call s:Tlist_Warning_Msg('No tags found for ' . a:filename) return -1 endif " Process the ctags output one line at a time. Separate the tag output " based on the tag type and store it in the tag type variable " The format of each line in the ctags output is: " " tag_name<TAB>file_name<TAB>ex_cmd;"<TAB>extension_fields " while cmd_output != '' " Extract one line at a time let one_line = strpart(cmd_output, 0, stridx(cmd_output, "\n")) " Remove the line from the tags output let cmd_output = strpart(cmd_output, stridx(cmd_output, "\n") + 1) if one_line == '' " Line is not in proper tags format continue endif " Extract the tag type let ttype = s:Tlist_Extract_Tagtype(one_line) if ttype == '' " Line is not in proper tags format continue endif " make sure the tag type is supported if s:tlist_{a:ftype}_ctags_flags !~# ttype continue endif " Extract the tag name if g:Tlist_Display_Prototype == 0 let ttxt = ' ' . strpart(one_line, 0, stridx(one_line, "\t")) " Add the tag scope, if it is available. Tag scope is the last " field after the 'line:<num>\t' field if g:Tlist_Display_Tag_Scope " only if it is selected let start = strridx(one_line, 'line:') let end = strridx(one_line, "\t") if end > start let tscope = strpart(one_line, end + 1) let tscope = strpart(tscope, stridx(tscope, ':') + 1) if tscope != '' let ttxt = ttxt . ' [' . tscope . ']' endif endif endif else let start = stridx(one_line, '/^') + 2 let end = strridx(one_line, '/;"' . "\t") " The search patterns for some tag types doesn't end with " the ;" character if one_line[end - 1] == '$' let end = end -1 endif let ttxt = strpart(one_line, start, end - start) endif " Update the count of this tag type let cnt = s:tlist_{fidx}_{ttype}_count + 1 let s:tlist_{fidx}_{ttype}_count = cnt " Add this tag to the tag type variable let s:tlist_{fidx}_{ttype} = s:tlist_{fidx}_{ttype} . ttxt . "\n" " Update the total tag count let s:tlist_{fidx}_tag_count = s:tlist_{fidx}_tag_count + 1 " Store the ctags output line and the tagtype count let s:tlist_{fidx}_tag_{s:tlist_{fidx}_tag_count} = \ cnt . ':' . one_line " Store the tag output index let s:tlist_{fidx}_{ttype}_{cnt} = s:tlist_{fidx}_tag_count endwhile return fidx endfunction " Tlist_Close_Window " Close the taglist window function! s:Tlist_Close_Window() " Make sure the taglist window exists let winnum = bufwinnr(g:TagList_title) if winnum == -1 call s:Tlist_Warning_Msg('Error: Taglist window is not open') return endif if winnr() == winnum " Already in the taglist window. Close it and return close else " Goto the taglist window, close it and then come back to the " original window let curbufnr = bufnr('%') exe winnum . 'wincmd w' close " Need to jump back to the original window only if we are not " already in that window let winnum = bufwinnr(curbufnr) if winnr() != winnum exe winnum . 'wincmd w' endif endif endfunction " Tlist_Toggle_Window() " Open or close a taglist window function! s:Tlist_Toggle_Window(bufnum) let curline = line('.') " If taglist window is open then close it. let winnum = bufwinnr(g:TagList_title) if winnum != -1 call s:Tlist_Close_Window() return endif " We are not part of winmanager plugin let s:tlist_part_of_winmanager = 0 " Get the filename and filetype for the specified buffer let filename = fnamemodify(bufname(a:bufnum), ':p') let ftype = getbufvar(a:bufnum, '&filetype') " Mark the current window as the desired window to open a file " when a tag is selcted let w:tlist_file_window = "yes" " Open the taglist window call s:Tlist_Open_Window() " Initialize the taglist window call s:Tlist_Init_Window() " List the tags defined in the file call s:Tlist_Explore_File(filename, ftype) " Highlight the current tag call s:Tlist_Highlight_Tag(filename, curline) " Go back to the original window let s:Tlist_Skip_Refresh = 1 wincmd p let s:Tlist_Skip_Refresh = 0 endfunction " Tlist_Extract_Tagtype " Extract the tag type from the tag text function! s:Tlist_Extract_Tagtype(tag_txt) " The tag type is after the tag prototype field. The prototype field " ends with the /;"\t string. We add 4 at the end to skip the characters " in this special string.. let start = strridx(a:tag_txt, '/;"' . "\t") + 4 let end = strridx(a:tag_txt, 'line:') - 1 let ttype = strpart(a:tag_txt, start, end - start) return ttype endfunction " Tlist_Extract_Tag_Prototype " Extract the tag protoype from the tag text function! s:Tlist_Extract_Tag_Prototype(tag_txt) let start = stridx(a:tag_txt, '/^') + 2 let end = strridx(a:tag_txt, '/;"' . "\t") if a:tag_txt[end - 1] == '$' let end = end -1 endif let tag_pat = strpart(a:tag_txt, start, end - start) " Remove all the leading space characters let tag_pat = matchstr(tag_pat, '^\s*\zs.*') return tag_pat endfunction " Tlist_Add_File() " Add a new file to the taglist function! s:Tlist_Add_File(filename, ftype) " Goto the taglist window call s:Tlist_Open_Window() " Update the taglist window call s:Tlist_Explore_File(a:filename, a:ftype) endfunction " Tlist_Refresh_Window() " Refresh the taglist window function! s:Tlist_Refresh_Window() " If we are entering the buffer from one of the taglist functions, then " no need to refresh the taglist window again. if s:Tlist_Skip_Refresh return endif " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help if &buftype != '' return endif let filename = fnamemodify(bufname('%'), ':p') let ftype = &filetype " If the file doesn't support tag listing, skip it if s:Tlist_Skip_File(filename, ftype) return endif let curline = line('.') " Make sure the taglist window is open. Otherwise, no need to refresh let winnum = bufwinnr(g:TagList_title) if winnum == -1 return endif let fidx = s:Tlist_Get_File_Index(filename) if fidx != -1 && s:tlist_cur_fidx == fidx " If the tag listing for the current window is already present, no " need to refresh it return endif " Save the current window number let cur_winnr = winnr() " Goto the taglist window call s:Tlist_Open_Window() " Update the taglist window call s:Tlist_Explore_File(filename, ftype) " Highlight the current tag call s:Tlist_Highlight_Tag(filename, curline) " Refresh the taglist window redraw if !s:tlist_part_of_winmanager " Jump back to the original window exe cur_winnr . 'wincmd w' endif endfunction " Tlist_Change_Sort() " Change the sort order of the tag listing function! s:Tlist_Change_Sort() if s:tlist_cur_fidx == -1 return endif " Remove the previous highlighting match none let fidx = s:tlist_cur_fidx let sort_type = s:tlist_{fidx}_sort_type " Toggle the sort order from 'name' to 'order' and vice versa if sort_type == 'name' let s:tlist_{fidx}_sort_type = 'order' else let s:tlist_{fidx}_sort_type = 'name' endif " Save the current line for later restoration let curline = '\V\^' . getline('.') . '\$' " Invalidate the tags listed for this file let s:tlist_{fidx}_valid = 0 call s:Tlist_Explore_File(s:tlist_{fidx}_filename, s:tlist_{fidx}_filetype) " Go back to the tag line before the list is sorted call search(curline, 'w') endfunction " Tlist_Update_Tags() " Update taglist for the current buffer by regenerating the tag list " Contributed by WEN Guopeng. function! s:Tlist_Update_Tags() " If taglist window is not open, show an error message: let winnum = bufwinnr(g:TagList_title) if winnum == -1 call s:Tlist_Warning_Msg('Error: Taglist window is not open') return 0 endif " Update the tag list window only if it's open if winnr() == winnum " Already in the taglist window, simply update the window content call s:Tlist_Update_Window() else " First check the current buffer is modified or not: if &modified let msg = "No write since last change, tag list may be inaccurate" call s:Tlist_Warning_Msg(msg) endif " Goto the taglist window, update it and get back to the original " window: let curbufnr = bufnr('%') exe winnum . 'wincmd w' call s:Tlist_Update_Window() " Need to jump back to the original window only if we are not " already in that window let winnum = bufwinnr(curbufnr) if winnr() != winnum exe winnum . 'wincmd w' endif endif return 1 endfunction " Tlist_Update_Window() " Update the window by regenerating the tag list function! s:Tlist_Update_Window() let fidx = s:Tlist_Get_File_Index_By_Linenum(line('.')) if fidx == -1 return endif " Remove the previous highlighting match none " Save the current line for later restoration let curline = '\V\^' . getline('.') . '\$' let s:tlist_{fidx}_valid = 0 " Update the taglist window call s:Tlist_Explore_File(s:tlist_{fidx}_filename, s:tlist_{fidx}_filetype) " Go back to the tag line before the list is sorted call search(curline, 'w') endfunction " Tlist_Get_Tag_Index() " Return the tag index for the current line function! s:Tlist_Get_Tag_Index(fidx) let lnum = line('.') let ftype = s:tlist_{a:fidx}_filetype " Determine to which tag type the current line number belongs to using the " tag type start line number and the number of tags in a tag type let i = 1 while i <= s:tlist_{ftype}_count let ttype = s:tlist_{ftype}_{i}_name let start_lnum = s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_start let end = start_lnum + s:tlist_{a:fidx}_{ttype}_count if lnum >= start_lnum && lnum <= end break endif let i = i + 1 endwhile " Current line doesn't belong to any of the displayed tag types if i > s:tlist_{ftype}_count return 0 endif " Compute the index into the displayed tags for the tag type let tidx = lnum - start_lnum if tidx == 0 return 0 endif " Get the corresponding tag line and return it return s:tlist_{a:fidx}_{ttype}_{tidx} endfunction " Tlist_Highlight_Tagline " Higlight the current tagline function! s:Tlist_Highlight_Tagline() " Clear previously selected name match none " Highlight the current selected name if g:Tlist_Display_Prototype == 0 exe 'match TagListTagName /\%' . line('.') . 'l\s\+\zs.*/' else exe 'match TagListTagName /\%' . line('.') . 'l.*/' endif endfunction " Tlist_Jump_To_Tag() " Jump to the location of the current tag " win_ctrl == 0 - Reuse the existing file window " win_ctrl == 1 - Open a new window " win_ctrl == 2 - Preview the tag function! s:Tlist_Jump_To_Tag(win_ctrl) " Do not process comment lines and empty lines let curline = getline('.') if curline =~ '^\s*$' || curline[0] == '"' return endif " If inside a fold, then don't try to jump to the tag if foldclosed('.') != -1 return endif let fidx = s:Tlist_Get_File_Index_By_Linenum(line('.')) if fidx == -1 return endif if fidx != s:tlist_cur_fidx " Selected a tag from some other file. Switch to editing this file let s:tlist_cur_fidx = fidx endif " Get the tag output for the current tag let tidx = s:Tlist_Get_Tag_Index(fidx) if tidx != 0 let fidx = s:tlist_cur_fidx let mtxt = s:tlist_{fidx}_tag_{tidx} let start = stridx(mtxt, '/^') + 2 let end = strridx(mtxt, '/;"' . "\t") if mtxt[end - 1] == '$' let end = end - 1 endif let tagpat = '\V\^' . strpart(mtxt, start, end - start) . \ (mtxt[end] == '$' ? '\$' : '') " Highlight the tagline call s:Tlist_Highlight_Tagline() else " Selected a line which is not a tag name. Just edit the file let tagpat = '' endif call s:Tlist_Open_File(a:win_ctrl, s:tlist_{fidx}_filename, tagpat) endfunction " Tlist_Open_File " Open the specified file in either a new window or an existing window " and place the cursor at the specified tag pattern function! s:Tlist_Open_File(win_ctrl, filename, tagpat) let s:Tlist_Skip_Refresh = 1 if s:tlist_part_of_winmanager " Let the winmanager edit the file call WinManagerFileEdit(a:filename, a:win_ctrl) else " Goto the window containing the file. If the window is not there, open a " new window let winnum = bufwinnr(a:filename) if winnum == -1 " Locate the previously used window for opening a file let fwin_num = 0 let i = 1 while winbufnr(i) != -1 if getwinvar(i, 'tlist_file_window') == "yes" let fwin_num = i break endif let i = i + 1 endwhile if fwin_num != 0 " Jump to the file window exe fwin_num . "wincmd w" " If the user asked to jump to the tag in a new window, then split " the existing window into two. if a:win_ctrl == 1 split endif exe "edit " . a:filename else " Open a new window if g:Tlist_Use_Horiz_Window exe 'leftabove split #' . bufnr(a:filename) " Go to the taglist window to change the window size to the user " configured value wincmd p exe 'resize ' . g:Tlist_WinHeight " Go back to the file window wincmd p else " Open the file in a window and skip refreshing the taglist " window exe 'rightbelow vertical split #' . bufnr(a:filename) " Go to the taglist window to change the window size to the user " configured value wincmd p exe 'vertical resize ' . g:Tlist_WinWidth " Go back to the file window wincmd p endif let w:tlist_file_window = "yes" endif else exe winnum . 'wincmd w' " If the user asked to jump to the tag in a new window, then split the " existing window into two. if a:win_ctrl == 1 split endif endif endif " Jump to the tag if a:tagpat != '' silent call search(a:tagpat, 'w') endif " Bring the line to the middle of the window normal! z. " If the line is inside a fold, open the fold if has('folding') if foldlevel('.') != 0 normal! zv endif endif " If the user selects to preview the tag then jump back to the " taglist window if a:win_ctrl == 2 " Go back to the taglist window let winnum = bufwinnr(g:TagList_title) exe winnum . 'wincmd w' endif let s:Tlist_Skip_Refresh = 0 endfunction " Tlist_Show_Tag_Prototype() " Display the prototype of the tag under the cursor function! s:Tlist_Show_Tag_Prototype() " If we have already display prototype in the tag window, no need to " display it in the status line if g:Tlist_Display_Prototype return endif " Clear the previously displayed line echo " Do not process comment lines and empty lines let curline = getline('.') if curline =~ '^\s*$' || curline[0] == '"' return endif " If inside a fold, then don't display the prototype if foldclosed('.') != -1 return endif " Get the file index let fidx = s:Tlist_Get_File_Index_By_Linenum(line('.')) if fidx == -1 return endif " Get the tag output line for the current tag let tidx = s:Tlist_Get_Tag_Index(fidx) if tidx == 0 return endif let mtxt = s:tlist_{fidx}_tag_{tidx} " Get the tag search pattern and display it echo s:Tlist_Extract_Tag_Prototype(mtxt) endfunction " Tlist_Find_Tag_text " Find the tag text given the line number in the source window function! s:Tlist_Find_Tag_text(fidx, linenum) let sort_type = s:tlist_{a:fidx}_sort_type let left = 1 let right = s:tlist_{a:fidx}_tag_count if sort_type == 'order' " Tag list sorted by order, do a binary search comparing the line " numbers and pick a tag entry that contains the current line and " highlight it. The idea behind this function is taken from the " ctags.vim script (by Alexey Marinichev) available at the Vim online " website. " If the current line is the less than the first tag, then no need to " search let txt = s:tlist_{a:fidx}_tag_1 let start = strridx(txt, 'line:') + strlen('line:') let end = strridx(txt, "\t") if end < start let first_lnum = strpart(txt, start) + 0 else let first_lnum = strpart(txt, start, end - start) + 0 endif if a:linenum < first_lnum return "" endif while left < right let middle = (right + left + 1) / 2 let txt = s:tlist_{a:fidx}_tag_{middle} let start = strridx(txt, 'line:') + strlen('line:') let end = strridx(txt, "\t") if end < start let middle_lnum = strpart(txt, start) + 0 else let middle_lnum = strpart(txt, start, end - start) + 0 endif if middle_lnum == a:linenum let left = middle break endif if middle_lnum > a:linenum let right = middle - 1 else let left = middle endif endwhile else " sorted by name, brute force method (Dave Eggum) let closest_lnum = 0 let final_left = 0 while left < right let txt = s:tlist_{a:fidx}_tag_{left} let start = strridx(txt, 'line:') + strlen('line:') let end = strridx(txt, "\t") if end < start let lnum = strpart(txt, start) + 0 else let lnum = strpart(txt, start, end - start) + 0 endif if lnum < a:linenum && lnum > closest_lnum let closest_lnum = lnum let final_left = left elseif lnum == a:linenum let closest_lnum = lnum break else let left = left + 1 endif endwhile if closest_lnum == 0 return "" endif if left == right let left = final_left endif endif return s:tlist_{a:fidx}_tag_{left} endfunction " Tlist_Highlight_Tag() " Highlight the current tag function! s:Tlist_Highlight_Tag(filename, curline) if a:filename == '' return endif " Make sure the taglist window is present let winnum = bufwinnr(g:TagList_title) if winnum == -1 call s:Tlist_Warning_Msg('Error: Taglist window is not open') return endif let fidx = s:Tlist_Get_File_Index(a:filename) if fidx == -1 return endif " If there are no tags for this file, then no need to proceed further if s:tlist_{fidx}_tag_count == 0 return endif " If part of winmanager then disable winmanager autocommands if s:tlist_part_of_winmanager call WinManagerSuspendAUs() endif " Save the original window number let org_winnr = winnr() if org_winnr == winnum let in_taglist_window = 1 else let in_taglist_window = 0 endif " Go to the taglist window if !in_taglist_window exe winnum . 'wincmd w' endif " Clear previously selected name match none let bno = bufnr(g:TagList_title) let tag_txt = s:Tlist_Find_Tag_text(fidx, a:curline) if tag_txt == "" " Make sure the current tag line is visible in the taglist window. " Calling the winline() function makes the line visible. Don't know " of a better way to achieve this. call winline() if !in_taglist_window let s:Tlist_Skip_Refresh = 1 exe org_winnr . 'wincmd w' let s:Tlist_Skip_Refresh = 0 endif if s:tlist_part_of_winmanager call WinManagerResumeAUs() endif return endif " Extract the tag type let ttype = s:Tlist_Extract_Tagtype(tag_txt) " Extract the tag offset let offset = strpart(tag_txt, 0, stridx(tag_txt, ':')) + 0 " Compute the line number let lnum = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_start + offset " Goto the line containing the tag exe lnum " Open the fold if has('folding') normal! zv endif " Make sure the current tag line is visible in the taglist window. " Calling the winline() function makes the line visible. Don't know " of a better way to achieve this. call winline() " Highlight the tag name call s:Tlist_Highlight_Tagline() " Go back to the original window if !in_taglist_window let s:Tlist_Skip_Refresh = 1 exe org_winnr . 'wincmd w' let s:Tlist_Skip_Refresh = 0 endif if s:tlist_part_of_winmanager call WinManagerResumeAUs() endif return endfunction " Tlist_Get_Tag_Prototype_By_Line " Get the prototype for the tag on or before the specified line number in the " current buffer function! s:Tlist_Get_Tag_Prototype_By_Line(linenum) " Make sure the current file has a name let filename = fnamemodify(bufname("%"), ':p') if filename == '' return "" endif let fidx = s:Tlist_Get_File_Index(filename) if fidx == -1 return endif " If there are no tags for this file, then no need to proceed further if s:tlist_{fidx}_tag_count == 0 return endif let linenr = a:linenum if linenr == "" " Default is the current line let linenr = line('.') endif " Get the tag text using the line number let tag_txt = s:Tlist_Find_Tag_text(fidx, linenr) if tag_txt == "" return "" endif " Extract the tag search pattern and return it return s:Tlist_Extract_Tag_Prototype(tag_txt) endfunction " Tlist_Session_Load " Load a taglist session (information about all the displayed files " and the tags) from the specified file function! s:Tlist_Session_Load( ) if a:0 == 0 || a:1 == '' call s:Tlist_Warning_Msg('Usage: TlistSessionLoad <filename>') return endif let sessionfile = a:1 if !filereadable(sessionfile) call s:Tlist_Warning_Msg('Error: Unable to open file ' . sessionfile) return endif " Mark the current window as the file window if bufname('%') !~ g:TagList_title let w:tlist_file_window = "yes" endif " Open to the taglist window call s:Tlist_Open_Window() " Source the session file exe 'source ' . sessionfile let new_file_count = g:tlist_file_count unlet g:tlist_file_count let i = 0 while i < new_file_count let ftype = g:tlist_{i}_filetype unlet g:tlist_{i}_filetype if !exists("s:tlist_" . ftype . "_count") if s:Tlist_FileType_Init(ftype) == 0 let i = i + 1 continue endif endif let fname = g:tlist_{i}_filename unlet g:tlist_{i}_filename let fidx = s:Tlist_Get_File_Index(fname) if fidx != -1 let s:tlist_{fidx}_visible = 0 let i = i + 1 continue endif let fidx = s:Tlist_Init_File(fname, ftype) let s:tlist_{fidx}_filename = fname let s:tlist_{fidx}_sort_type = g:tlist_{i}_sort_type unlet g:tlist_{i}_sort_type let s:tlist_{fidx}_filetype = ftype let s:tlist_{fidx}_start = 0 let s:tlist_{fidx}_end = 0 let s:tlist_{fidx}_valid = 1 " Mark the file as not visible, so that Tlist_Init_Window() function " will display the tags for this file let s:tlist_{fidx}_visible = 0 let s:tlist_{fidx}_tag_count = g:tlist_{i}_tag_count unlet g:tlist_{i}_tag_count let j = 1 while j <= s:tlist_{fidx}_tag_count let s:tlist_{fidx}_tag_{j} = g:tlist_{i}_tag_{j} unlet g:tlist_{i}_tag_{j} let j = j + 1 endwhile let j = 1 while j <= s:tlist_{ftype}_count let ttype = s:tlist_{ftype}_{j}_name if exists('g:tlist_' . i . '_' . ttype) let s:tlist_{fidx}_{ttype} = g:tlist_{i}_{ttype} unlet g:tlist_{i}_{ttype} let s:tlist_{fidx}_{ttype}_start = 0 let s:tlist_{fidx}_{ttype}_count = g:tlist_{i}_{ttype}_count unlet g:tlist_{i}_{ttype}_count let k = 1 while k <= s:tlist_{fidx}_{ttype}_count let s:tlist_{fidx}_{ttype}_{k} = g:tlist_{i}_{ttype}_{k} unlet g:tlist_{i}_{ttype}_{k} let k = k + 1 endwhile else let s:tlist_{fidx}_{ttype} = '' let s:tlist_{fidx}_{ttype}_start = 0 let s:tlist_{fidx}_{ttype}_count = 0 endif let j = j + 1 endwhile let i = i + 1 endwhile " Initialize the taglist window call s:Tlist_Init_Window() if s:tlist_file_count > 0 " Jump to the beginning of the first file call cursor(s:tlist_0_start, 1) endif endfunction " Tlist_Session_Save " Save a taglist session (information about all the displayed files " and the tags) into the specified file function! s:Tlist_Session_Save( ) if a:0 == 0 || a:1 == '' call s:Tlist_Warning_Msg('Usage: TlistSessionSave <filename>') return endif let sessionfile = a:1 if s:tlist_file_count == 0 " There is nothing to save call s:Tlist_Warning_Msg('Warning: Taglist is empty. Nothing to save.') return endif if filereadable(sessionfile) let ans = input("Do you want to overwrite " . sessionfile . " (Y/N)?") if ans !=? 'y' return endif echo "\n" endif exe 'redir! > ' . sessionfile silent! echo '" Taglist session file. This file is auto-generated.' silent! echo '" File information' silent! echo 'let g:tlist_file_count = ' . s:tlist_file_count let i = 0 while i < s:tlist_file_count " Store information about the file silent! echo 'let g:tlist_' . i . "_filename = '" . \ s:tlist_{i}_filename . "'" silent! echo 'let g:tlist_' . i . '_sort_type = "' . \ s:tlist_{i}_sort_type . '"' silent! echo 'let g:tlist_' . i . '_filetype = "' . \ s:tlist_{i}_filetype . '"' silent! echo 'let g:tlist_' . i . '_tag_count = ' . \ s:tlist_{i}_tag_count " Store information about all the tags let j = 1 while j <= s:tlist_{i}_tag_count let txt = escape(s:tlist_{i}_tag_{j}, '"\\') silent! echo 'let g:tlist_' . i . '_tag_' . j . ' = "' . txt . '"' let j = j + 1 endwhile " Store information about all the tags grouped by their type let ftype = s:tlist_{i}_filetype let j = 1 while j <= s:tlist_{ftype}_count let ttype = s:tlist_{ftype}_{j}_name if s:tlist_{i}_{ttype}_count != 0 let txt = substitute(s:tlist_{i}_{ttype}, "\n", "\\\\n", "g") silent! echo 'let g:tlist_' . i . '_' . ttype . ' = "' . \ txt . '"' silent! echo 'let g:tlist_' . i . '_' . ttype . '_count = ' . \ s:tlist_{i}_{ttype}_count let k = 1 while k <= s:tlist_{i}_{ttype}_count silent! echo 'let g:tlist_' . i . '_' . ttype . '_' . k . \ ' = ' . s:tlist_{i}_{ttype}_{k} let k = k + 1 endwhile endif let j = j + 1 endwhile silent! echo let i = i + 1 endwhile redir END endfunction " Define the taglist autocommand to automatically open the taglist window on " Vim startup if g:Tlist_Auto_Open autocmd VimEnter * nested Tlist endif " Define the user commands to manage the taglist window command! -nargs=0 Tlist call s:Tlist_Toggle_Window(bufnr('%')) command! -nargs=0 TlistClose call s:Tlist_Close_Window() command! -nargs=0 TlistUpdate call s:Tlist_Update_Tags() command! -nargs=0 TlistSync call s:Tlist_Highlight_Tag( \ fnamemodify(bufname('%'), ':p'), line('.')) command! -nargs=? TlistShowPrototype echo s:Tlist_Get_Tag_Prototype_By_Line(<q-args>) command! -nargs=* -complete=file TlistSessionLoad call s:Tlist_Session_Load(<q-args>) command! -nargs=* -complete=file TlistSessionSave call s:Tlist_Session_Save(<q-args>) " Winmanager integration " Initialization required for integration with winmanager function! TagList_Start() let s:tlist_part_of_winmanager = 1 if bufname('%') != '__Tag_List__' return endif " Get the current filename from the winmanager plugin let bufnum = WinManagerGetLastEditedFile() if bufnum != -1 let filename = fnamemodify(bufname(bufnum), ':p') let fidx = s:Tlist_Get_File_Index(filename) if fidx != -1 && fidx == s:tlist_cur_fidx " If the tags for the buffer is already listed, then no need to do " anything return endif let ftype = getbufvar(bufnum, '&filetype') endif " Initialize the taglist window, if it is not already initialized if !exists("s:tlist_window_initialized") || !s:tlist_window_initialized call s:Tlist_Init_Window() let s:tlist_window_initialized = 1 endif " Open the taglist window if bufnum != -1 call s:Tlist_Explore_File(filename, ftype) endif endfunction function! TagList_IsValid() return 0 endfunction function! TagList_WrapUp() return 0 endfunction