diff --git a/doc/taglist.txt b/doc/taglist.txt index 0c9688c..2400a4a 100644 --- a/doc/taglist.txt +++ b/doc/taglist.txt @@ -2,7 +2,7 @@ Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com) For Vim version 6.0 and above -Last change: 2004 August 15 +Last change: 2005 April 4 1. Overview |taglist-intro| 2. Taglist on the internet |taglist-internet| @@ -20,42 +20,42 @@ Last change: 2004 August 15 *taglist-intro* 1. Overview~ -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. The "Tag List" plugin provides the following -features: +The "Tag List" plugin is a source code browser plugin for Vim. This plugin +allows you to efficiently browse through source code files for different +programming languages. The "Tag List" plugin provides the following features: -1. Opens a vertically/horizontally split Vim window with a list of tags - (functions, classes, structures, variables, etc) defined in the - current file. -2. Groups the tags by their type and displays them in a foldable tree. -3. Automatically updates the taglist window as you switch between - files/buffers. -4. As you open new files, the tags defined in new files are added to the - existing file list and the tags defined in all the files are - displayed grouped by the filename. -5. When a tag name is selected from the taglist window, positions the - cursor at the definition of the tag in the source file -6. Automatically highlights the current tag name. -7. Can display the prototype of a tag from the taglist window. -8. Displays the scope of a tag. -9. Can optionally use the tag prototype instead of the tag name. -10. The tag list can be sorted either by name or by line number. -11. Supports the following language files: Assembly, ASP, Awk, Beta, C, - C++, C#, Cobol, Eiffel, Erlang, Fortran, HTML, Java, Javascript, - Lisp, Lua, Make, Pascal, Perl, PHP, Python, Rexx, Ruby, Scheme, - Shell, Slang, SML, Sql, TCL, Verilog, Vim and Yacc. -12. The list of tags displayed in the taglist window can be saved and - restored. -13. Runs in both console/terminal and GUI versions of Vim. -14. The ctags output for a file is cached to speed up displaying the - taglist window. -15. Works with the winmanager plugin. Using the winmanager plugin, you - can use Vim plugins like the file explorer, buffer explorer and the - taglist plugin at the same time like an IDE. -16. Can be easily extended to support new languages. Support for - existing languages can be modified easily. + * Displays the tags (functions, classes, structures, variables, etc) + defined in a file in a vertically or horizontally split Vim window. + * Groups the tags by their type and displays them in a foldable tree. + * Automatically updates the taglist window as you switch between + files/buffers. As you open new files, the tags defined in the new files + are added to the existing file list and the tags defined in all the + files are displayed grouped by the filename. + * When a tag name is selected from the taglist window, positions the + cursor at the definition of the tag in the source file. + * Automatically highlights the current tag name. + * In GUI Vim, optionally displays the tags in the Tags drop-down menu and + in the popup menu. + * Can display the prototype and scope of a tag. + * Can optionally display the tag prototype instead of the tag name in the + taglist window. + * The tag list can be sorted either by name or by line number. + * Supports the following language files: Assembly, ASP, Awk, Beta, C, + C++, C#, Cobol, Eiffel, Erlang, Fortran, HTML, Java, Javascript, Lisp, + Lua, Make, Pascal, Perl, PHP, Python, Rexx, Ruby, Scheme, Shell, Slang, + SML, Sql, TCL, Verilog, Vim and Yacc. + * Can be easily extended to support new languages. Support for + existing languages can be modified easily. + * Provides commands to get the name and prototype of the current tag. + * Provides functions to display the current tag name in the Vim status + line or the window title bar. + * The list of tags displayed in the taglist window can be saved and + restored across Vim sessions. + * Runs in both console/terminal and GUI versions of Vim. + * Works with the winmanager plugin. Using the winmanager plugin, you + can use Vim plugins like the file explorer, buffer explorer and the + taglist plugin at the same time like an IDE. + * Can be used in both Unix and MS-Windows systems. ============================================================================== *taglist-internet* @@ -63,13 +63,13 @@ features: You can visit the taglist plugin home page for more information: > - http://www.geocities.com/yegappan/taglist + http://www.geocities.com/yegappan/taglist < You can subscribe to the taglist mailing list to post your questions or suggestions for improvement or bug reports. Visit the following page for subscribing to the mailing list: > - http://groups.yahoo.com/group/taglist/ + http://groups.yahoo.com/group/taglist/ < ============================================================================== *taglist-requirement* @@ -84,51 +84,55 @@ The taglist plugin will work with Vim version 6.0 and above. The taglist plugin relies on the exuberant ctags utility to dynamically generate the tag listing. You can download the exuberant ctags utility from > - http://ctags.sourceforge.net + http://ctags.sourceforge.net < The exuberant ctags utility must be installed in your system to use this -plugin. You should use exuberant ctags version 5.0 and above. This plugin +plugin. You should use exuberant ctags version 5.0 and above. This plugin doesn't use or create a tags file and there is no need to create a tags file -to use this plugin. +to use this plugin. The taglist plugin will not work with the GNU ctags or the +Unix ctags utility. -This plugin relies on the Vim "filetype" detection mechanism to determine -the type of the current file. You have to turn on the Vim filetype detection -by adding the following line to your .vimrc file: > +This plugin relies on the Vim "filetype" detection mechanism to determine the +type of the current file. You have to turn on the Vim filetype detection by +adding the following line to your .vimrc file: > - filetype on + filetype on < -This plugin will not work in |compatible| mode. Make sure the |compatible| -option is not set. This plugin will not work if you run Vim in the -restricted mode (using the -Z command-line argument). This plugin also -assumes that the system() Vim function is supported. Make sure that the -'C' flag is not set in the 'cpoptions' Vim option. +The taglist plugin will not work if you run Vim in the restricted mode (using +the -Z command-line argument). + +The taglist plugin uses the Vim system() function to invoke the exuberant +ctags utility. If Vim is compiled without the system() function then you +cannot use the taglist plugin. Some of the Linux distributions (Suse) compile +Vim without the system() function for security reasons. ============================================================================== *taglist-install* 4. 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): +1. Download the taglist.zip file and unzip the files to the $HOME/.vim or the + $HOME/vimfiles or the $VIM/vimfiles directory. After this step, you should + have the following two files (the directory structure should be preserved): - plugin/taglist.vim - main taglist plugin file - doc/taglist.txt - documentation (help) file + 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 (path) of the - exuberant ctags utility (not to the directory) in the .vimrc file. +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. Without this step, you cannot jump to the taglist help + topics. +3. If the exuberant ctags utility is not present in your PATH, then 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. + window. You can use the ":help taglist" command to get more information + about using the taglist plugin. ============================================================================== *taglist-using* @@ -140,16 +144,18 @@ open or close (toggle) the taglist window. You can map a key to invoke this command. For example, the following command creates a normal mode mapping for the key to open or close the taglist window. > - nnoremap :Tlist + :nnoremap :Tlist < -Add the above mapping to your ~/.vimrc file. You can also open the taglist +Add the above mapping to your ~/.vimrc file. You can also open the taglist window on startup using the following command line: > - $ vim +Tlist + $ vim +Tlist -< When the taglist window is opened for the first time, all the files in the -buffer list are processed and the tags for those files are displayed. +buffer list are processed and the tags for those files are displayed. If you +close the taglist window, the tags information displayed in the taglist window +will not be lost. The next time you open the taglist window in the same Vim +session, the stored tags information will be displayed. Closing the taglist window~ You can close the taglist window from the taglist window by pressing 'q' or @@ -160,70 +166,82 @@ taglist window by invoking the ":TlistClose" command. Taglist window contents~ As you switch between source files, the taglist window will be automatically -updated with the tag listing for the current source file. The tag names -will grouped by their type (variable, function, class, etc). For tags with -scope information (like class members, structures inside structures, etc), -the scope information will be displayed in square brackets "[]" after the -tagname. +updated with the tags defined in the current source file. The tag names will +grouped by their type (variable, function, class, etc). For tags with scope +information (like class members, structures inside structures, etc), the scope +information will be displayed in square brackets "[]" after the tagname. Opening and closing the tag and file tree~ The tag names will be displayed as a foldable tree using the Vim folding support. You can collapse the tree using the '-' key or using the Vim zc fold command. You can open the tree using the '+' key or using the Vim zo fold command. You can open all the folds using the '*' key or using the Vim -zR fold command You can also use the mouse to open/close the folds. You -can close all the fold using the '=' key. +zR fold command. You can also use the mouse to open/close the folds. You +can close all the folds using the '=' key. Jumping to a tag or a file~ -You can select a tag either by pressing the key or by double -clicking the tag name using the mouse. You can configure the taglist plugin -by setting the 'Tlist_Use_SingleClick' variable to jump to a tag on a single -mouse click. You can press the 'o' key to jump to the tag in a new window. -You can press the 'p' key to jump to the tag but still keep the cursor in -the taglist window itself. +You can select a tag either by pressing the key or by double clicking +the tag name using the mouse. You can jump to a tag using a single mouse click +by setting the 'Tlist_Use_SingleClick' variable. You can press the 'o' key to +jump to the tag in a new window. You can press the 'p' key to jump to the tag +but still keep the cursor in the taglist window itself. You can open a file by pressing key or by double clicking the file name using the mouse. +In the taglist window, you can use the [[ or key to jump to the +beginning of the previous file. You can use the ]] or key to jump to the +beginning of the next file. + Syncing the taglist window~ The taglist plugin will automatically highlight the name of the current tag. The tag name will be highlighted after |updatetime| milliseconds. The default value for this Vim option is 4 seconds. To avoid unexpected problems, you should not set the |updatetime| option to very low values. You can also use -the ":TlistSync" command to force the highlighting of the current tag. You can -map a key to invoke this command. For example, the following command creates a -normal mapping for the key to highlight the current tag name. > - - nnoremap :TlistSync -< -Add the above mapping to your ~/.vimrc file. +the ":TlistSync" command to force the highlighting of the current tag. Displaying the tag prototype~ If you place the cursor on a tag name in the taglist window, then the tag prototype will be displayed at the Vim status line after |updatetime| milliseconds. The default value for the |updatetime| Vim option is 4 seconds. You can also press the space bar to display the prototype of the -tag under the cursor. +tag under the cursor in the taglist window. -You can use the ":TlistShowPrototype" command to display the prototype of -a function in the specified line number. For example, > +You can use the ":TlistShowPrototype" command to display the prototype of the +tag at or below the specified line number. For example, > - :TlistShowPrototype 50 + :TlistShowPrototype myfile.c 50 < -If the line number is not supplied, this command will display the prototype -of the current function. +If the file name and line number are not supplied, then this command will +display the prototype of the current tag. + +You can use the ":TlistShowTag" command to display the name of the tag at or +below the specified line number. For example, +> + :TlistShowTag myfile.java 100 +< +If the file name and line number are not supplied, then this command will +display the name of the current tag. + +The above two commands will work even when the taglist window is closed. To +use this command on newly opened files without the taglist window and the +taglist menu, you should set the Tlist_Process_File_Always variable to 1. Sorting the tags for a file~ -By default, the listed tags will be sorted by the order in which the tags -appear in the file. You can sort the tags by their name, by pressing the "s" -key in the taglist window. You can again sort the tags by their chronological -order using the "s" key. +The tags displayed in the taglist window can be sorted either by name of by +their chronological order. The default sorting order is by the order in which +the tags appear in the file. You can change the default sort order by setting +the Tlist_Sort_Type variable. You can sort the tags by their name by pressing +the "s" key in the taglist window. You can again sort the tags by their +chronological order using the "s" key. Each file in the taglist window can be +sorted using different order. Removing the tags listed for a file from the taglist window~ -You can remove the tags displayed for a file, by pressing the 'd' key -when the cursor is on one of the tags listed for the file in the -taglist window. To again display the tags for the file in the taglist window, -use the ':TlistUpdate' command. +You can remove the tags displayed for a file, by pressing the 'd' key when the +cursor is on one of the tags listed for the file in the taglist window. The +removed file is no longer displayed in the taglist window. To again display +the tags for the file, open the file in a Vim window and then use the +:TlistUpdate command. Zooming in and out of the taglist window~ You can press the 'x' key in the taglist window to maximize the taglist @@ -231,36 +249,46 @@ window width/height. The window will be maximized to the maximum possible width/height without closing the other existing windows. You can again press 'x' to restore the taglist window to the default width/height. -Updating the taglist window~ -You can update or refresh the tags listed for a file by pressing the "u" key -in the taglist window. You can also use the ":TlistUpdate" command to update -the tags for the current buffer after you made some changes to it. You should -save the modified buffer before you update the taglist window. Otherwise the -listed tags will not include the new tags created in the buffer. You can map a -key to invoke this command. For example, the following command creates a -normal mode mapping for the key to update the taglist window. > +Updating the tags displayed for a file~ +You can update or refresh the tags displayed for a file by pressing the "u" +key in the taglist window. If an existing file is modified, after the file is +saved, the taglist plugin will automatically update the tags displayed for the +file. + +You can also use the ":TlistUpdate" command to update the tags for the current +buffer after you made some changes to it. You should save the modified buffer +before you update the taglist window. Otherwise the listed tags will not +include the new tags created in the buffer. - nnoremap :TlistUpdate -< If you have deleted the tags displayed for a file in the taglist window using the 'd' key, you can again display the tags for that file using the ':TlistUpdate' command. +Modifying the contents of the taglist buffer/window~ +The contents of the taglist buffer/window are managed by the taglist plugin. +The Vim 'modifiable' option is turned off for the taglist buffer. You should +not manually edit the taglist buffer, by setting the 'modifiable' flag. If you +manually edit the taglist buffer contents, then the taglist plugin will be out +of sync with the taglist buffer contents and the plugin will no longer work +correctly. To redisplay the taglist buffer contents again, you can close the +taglist window and reopen it. + + *taglist-session* Taglist Session~ A taglist session refers to the group of files and their tags displayed in the taglist window in a Vim session. -You can save and restore taglist sessions (and all the displayed tags) -using the TlistSessionSave and TlistSessionLoad commands. +You can save and restore a taglist session (and all the displayed tags) using +the :TlistSessionSave and :TlistSessionLoad commands. -To save all the tags displayed in the taglist window in a file, use the -TlistSessionSave command and specify the filename: > +To save all the tags displayed in the taglist window to a file, use the +:TlistSessionSave command and specify the filename: > - :TlistSessionSave + :TlistSessionSave < To load the saved taglist session, use the TlistSessionLoad command: > - :TlistSessionLoad + :TlistSessionLoad < Information about the tags displayed for the files in the taglist window will be stored in the taglist session file. This will be used to restore the @@ -271,11 +299,37 @@ window. The taglist session feature can be used to save the tags for large files or a group of frequently used files (like a project). By using the taglist session file, you can minimize the amount to time it takes to load/refresh the taglist -window for those files. +window for multiple files. + +You can create more than one taglist session file for multiple groups of +files. + +Displaying tag name in the Vim status line or the window title bar~ +You can use the Tlist_Get_Tagname_By_Line() function provided by the taglist +plugin to display the current tag name in the Vim status line or the window +title bar. Similarly, you can use the Tlist_Get_Tag_Prototype_By_Line() +function to display the current tag prototype in the Vim status line or the +window title bar. + +For example, the following command can be used to display the current tag name +in the status line: +> + :set statusline=%<%f%=%([%{Tlist_Get_Tagname_By_Line()}]%) +< +The following command can be used to display the current tag name in the +window title bar: +> + :set title titlestring=%<%f\ %([%{Tlist_Get_Tagname_By_Line()}]%) +< +Note that the current tag name can be displayed only after the file is +processed by the taglist plugin. For this, you have to either set the +'Tlist_Process_File_Always' variable to 1 or open the taglist window or use +the taglist menu. For more information about configuring the Vim status line, +refer to the documentation for the |'statusline'| option. Changing the taglist window highlighting~ -The following highlight groups are defined and used to highlight the various -entities in the taglist window: +The following Vim highlight groups are defined and used to highlight the +various entities in the taglist window: TagListTagName - Used for tag names TagListTagScope - Used for tag scope @@ -284,22 +338,22 @@ entities in the taglist window: TagListFileName - Used for filenames By default, these highlight groups are linked to the standard Vim highlight -groups. If you want to change these highlight groups, you can prepend 'My' +groups. If you want to change these highlight groups, you can prefix 'My' to the above highlight group names and define them in your .vimrc file. The taglist plugin will use the defined highlight groups instead of the default groups. For example, to change the highlighting used for tag names, you can use: > - highlight MyTagListTagName guifg=cyan + :highlight MyTagListTagName guifg=cyan < Getting help~ -You can press the "?" key in the taglist window to display help information -about using the taglist window. If you again press the '?' key, the help -information will be removed. +You can press the "?" key in the taglist window to display the help +information about using the taglist window. If you again press the '?' key, +the help information will be removed from the taglist window. *taglist-keys* Taglist window key list~ -The following table lists the description of the keys that you can use +The following table lists the description of the keys that can be used in the taglist window. Key Description~ @@ -320,22 +374,68 @@ in the taglist window. * Open all folds = Close all folds [[ Jump to the beginning of the previous file + Jump to the beginning of the previous file ]] Jump to the beginning of the next file + Jump to the beginning of the next file q Close the taglist window ? Display help The above keys will work in both the normal mode and the insert mode. + *taglist-menu* +Taglist menu~ +When using GUI Vim, the taglist plugin can display the tags defined in the +current file in the drop-down menu and the popup menu. By default, this +feature is turned off. To turn on this feature, set the 'Tlist_Show_Menu' +variable to 1. + +You can jump to a tag by selecting the tag name from the menu. You can use the +taglist menu independent of the taglist window i.e. you don't need to open the +taglist window to get the taglist menu. + +When you switch between files/buffers, the taglist menu is automatically +updated to display the tags defined in the current file/buffer. + +The tags are grouped by their type (variables, functions, classes, methods, +etc) and displayed as a separate sub-menu for each type. + +If the number of items in a tag type submenu exceeds the value specified by +the Tlist_Max_Submenu_Items variable, then the submenu will be split into +multiple submenus. The default setting for Tlist_Max_Submenu_Items is 25. The +first and last tag names in the submenu are used to form the submenu name. The +menu items are prefixed by alpha-numeric characters for easy selection by +keyboard. + +If the popup menu support is enabled (the 'mousemodel' option contains +"popup"), then the tags menu is added to the popup menu. You can access +the popup menu by right clicking on the GUI window. + +You can regenerate the tags menu by selecting the 'Tags->Refresh menu' entry. +You can sort the tags listed in the menu either by name or by order by +selecting the 'Tags->Sort menu by->Name/Order' menu entry. + +You can tear-off the Tags menu and keep it on the side of the Vim window +for quickly locating the tags. + Using the taglist plugin with the winmanager plugin~ You can use the taglist plugin with the winmanager plugin. This will allow you to use the file explorer, buffer explorer and the taglist plugin at the same time in different windows. To use the taglist plugin with the winmanager -plugin, set 'TagList' in the 'winManagerWindowLayout' variable. For example, +plugin, set 'TagList' in the 'winManagerWindowLayout' variable. For example, to use the file explorer plugin and the taglist plugin at the same time, use the following setting: > - let winManagerWindowLayout = 'FileExplorer|TagList' + let winManagerWindowLayout = 'FileExplorer|TagList' < + *taglist-debug* +Debugging the taglist plugin~ +You can use the ":TlistDebug" command to enable logging of the debug messages +from the taglist plugin. To display the logged debug messages, you can use the +":TlistMessages" command. To disable the logging of the debug messages, use +the ":TlistUndebug" command. The debug messages are stored in a script-local +variable by the taglist plugin. To minimize memory usage, only the last 3000 +characters from the debug messages are stored. + ============================================================================== *taglist-configure* 6. Configuration~ @@ -344,169 +444,221 @@ A number of Vim variables control the behavior of the taglist plugin. These variables are initialized to a default value. By changing these variables you can change the behavior of the taglist plugin. You need to change these settings only if you want to change the behavior of the taglist plugin. You -need to use the |let| command in your .vimrc file to change the setting of any +should use the |let| command in your .vimrc file to change the setting of any of these variables. -Tlist_Ctags_Cmd~ -The 'Tlist_Ctags_Cmd' variable specifies the location (path) of the ctags -utility. The exuberant ctags tool is installed under different names in -different installations. When the taglist plugin starts up, it checks for the -names exuberant-ctags, ctags, ctags.exe and tags in the PATH environment -variable. If any one of the named executable is found, then Tlist_Ctags_Cmd is -set to that name. Set this variable to point to the location of the ctags -utility in your system. Note that this variable should point to the fully -qualified exuberant ctags location and NOT to the directory in which exuberant -ctags is installed. If the exuberant ctags tool is not found in either PATH -or in the specified location, then the taglist plugin will not be loaded. -> - let Tlist_Ctags_Cmd = 'd:\tools\ctags.exe' - let Tlist_Ctags_Cmd = '/usr/local/bin/ctags' -< -Tlist_Sort_Type~ -The 'Tlist_Sort_Type' variable specifies the way in which the tags in the -taglist window should be sorted. The tags can be sorted either alphabetically -by their name or by the order of their appearances in the file (chronological -order). By default, the tag names will be listed in the order in which they -are defined in the file. You can change the sort type (from name to order or -from order to name) by pressing the "s" key in the taglist window. You can -also change the default order by setting 'Tlist_Sort_Type' to "name" or -"order": > +The configurable taglist variables are listed below. For a detailed +description of these variables refer to the text after this table. - let Tlist_Sort_Type = "name" +|'Tlist_Ctags_Cmd'| Specifies the path to the ctags utility. +|'Tlist_Sort_Type'| Sort method used for arranging the tags. +|'Tlist_Use_Horiz_Window'| Use a horizontal split window for the taglist. +|'Tlist_Use_Right_Window'| Put the taglist window on the right side. +|'Tlist_Auto_Open'| Open the taglist window when VIM starts. +|'Tlist_Display_Prototype'| Show prototypes, not just tags. +|'Tlist_Display_Tag_Scope'| Show tag scope next to the tag name. +|'Tlist_Show_One_File'| Show tags for the current buffer only. +|'Tlist_WinWidth'| Set the taglist window width. +|'Tlist_Inc_Winwidth'| Expand the current window to accommodate the + taglist. +|'Tlist_WinHeight'| If horizontal is set, set the window height. +|'Tlist_Use_SingleClick'| Single click on a tag jumps to it. +|'Tlist_Compact_Format'| Remove extra information and blank lines from + the taglist. +|'Tlist_Exit_OnlyWindow'| Close VIM if the taglist is the only window. +|'Tlist_File_Fold_Auto_Close'| Close tag folds for all buffers not shown. +|'Tlist_Enable_Fold_Column'| Show the fold indicator column. +|'Tlist_Auto_Highlight_Tag'| Highlight the current tag in the taglist. +|'Tlist_Process_File_Always'| Process tags for files when taglist is closed. +|'Tlist_Show_Menu'| Display the tags menu. +|'Tlist_Max_Submenu_Items'| Maximum number of items in a tags sub-menu. +|'Tlist_Max_Tag_Length'| Maximum tag length used in a tag menu entry. + + *'Tlist_Ctags_Cmd'* +Tlist_Ctags_Cmd~ +The 'Tlist_Ctags_Cmd' variable specifies the location (path) of the exuberant +ctags utility. If exuberant ctags is present in any one of the directories in +the PATH environment variable, then there is no need to set this variable. + +The exuberant ctags tool can be installed under different names. When the +taglist plugin starts up, if the Tlist_Ctags_Cmd variable is not set, it +checks for the names exuberant-ctags, ctags, ctags.exe and tags in the PATH +environment variable. If any one of the named executable is found, then the +Tlist_Ctags_Cmd variable is set to that name. + +If exuberant ctags is not present in one of the directories specified in the +PATH environment variable, then set this variable to point to the location of +the ctags utility in your system. Note that this variable should point to the +fully qualified exuberant ctags location and NOT to the directory in which +exuberant ctags is installed. If the exuberant ctags tool is not found in +either PATH or in the specified location, then the taglist plugin will not be +loaded. +> + let Tlist_Ctags_Cmd = 'd:\tools\ctags.exe' + let Tlist_Ctags_Cmd = '/usr/local/bin/ctags' < + *'Tlist_Sort_Type'* +Tlist_Sort_Type~ +The 'Tlist_Sort_Type' variable specifies the sort order for the tags in the +taglist window. The tags can be sorted either alphabetically by their name or +by the order of their appearance in the file (chronological order). By +default, the tag names will be listed by the order in which they are defined +in the file. You can change the sort type (from name to order or from order to +name) by pressing the "s" key in the taglist window. You can also change the +default sort order by setting 'Tlist_Sort_Type' to "name" or "order": > + + let Tlist_Sort_Type = "name" +< + *'Tlist_Use_Horiz_Window'* Tlist_Use_Horiz_Window~ -Be default, the tag names will be listed in a vertically split window. If you +Be default, the tag names are displayed in a vertically split window. If you prefer a horizontally split window, then set the 'Tlist_Use_Horiz_Window' variable to 1. If you are running MS-Windows version of Vim in a MS-DOS command window, then you should use a horizontally split window instead of a -vertically split window. Also, if you are using an older version of xterm in -a Unix system that doesn't support changing the xterm window width, you should +vertically split window. Also, if you are using an older version of xterm in a +Unix system that doesn't support changing the xterm window width, you should use a horizontally split window. > - let Tlist_Use_Horiz_Window = 1 + let Tlist_Use_Horiz_Window = 1 < + *'Tlist_Use_Right_Window'* Tlist_Use_Right_Window~ By default, the vertically split taglist window will appear on the left hand side. If you prefer to open the window on the right hand side, you can set the 'Tlist_Use_Right_Window' variable to one: > - let Tlist_Use_Right_Window = 1 + let Tlist_Use_Right_Window = 1 < + *'Tlist_Auto_Open'* Tlist_Auto_Open~ To automatically open the taglist window, when you start Vim, you can set the 'Tlist_Auto_Open' variable to 1. By default, this variable is set to 0 and the taglist window will not be opened automatically on Vim startup. > - let Tlist_Auto_Open = 1 + let Tlist_Auto_Open = 1 < + *'Tlist_Display_Prototype'* Tlist_Display_Prototype~ -By default, only the tag name will be displayed in the taglist window. If -you like to see tag prototypes instead of names, set the -'Tlist_Display_Prototype' variable to 1. By default, this variable is set to 0 -and only tag names will be displayed. > +By default, only the tag name will be displayed in the taglist window. If you +like to see tag prototypes instead of names, set the 'Tlist_Display_Prototype' +variable to 1. By default, this variable is set to 0 and only tag names will +be displayed. > - let Tlist_Display_Prototype = 1 + let Tlist_Display_Prototype = 1 < + *'Tlist_Display_Tag_Scope'* Tlist_Display_Tag_Scope~ By default, the scope of a tag (like a C++ class) will be displayed in square brackets next to the tag name. If you don't want the tag scopes to be displayed, then set the 'Tlist_Display_Tag_Scope' to 0. By default, this variable is set to 1 and the tag scopes will be displayed. > - let Tlist_Display_Tag_Scope = 0 + let Tlist_Display_Tag_Scope = 0 < + *'Tlist_Show_One_File'* Tlist_Show_One_File~ -By default, the taglist plugin will display tags for all the loaded buffers in -the taglist window. If you prefer to display the tags only for the current -buffer, then you can set the 'Tlist_Show_One_File' to 1. When this variable is -set to 1, as you switch between buffers, the taglist window will be refreshed -to display the tags for the current buffer and the tags for the previous -buffer will be removed. +By default, the taglist plugin will display the tags defined in all the loaded +buffers in the taglist window. If you prefer to display the tags defined only +in the current buffer, then you can set the 'Tlist_Show_One_File' to 1. When +this variable is set to 1, as you switch between buffers, the taglist window +will be refreshed to display the tags for the current buffer and the tags for +the previous buffer will be removed. > - let Tlist_Show_One_File = 1 + let Tlist_Show_One_File = 1 < + *'Tlist_WinWidth'* Tlist_WinWidth~ The default width of the vertically split taglist window is 30. This can be changed by modifying the 'Tlist_WinWidth' variable: > - let Tlist_WinWidth = 20 + let Tlist_WinWidth = 20 < Note that the value of the |winwidth| option setting determines the minimum width of the current window. If you set the 'Tlist_WinWidth' variable to a value less than that of the |winwidth| option setting, then Vim will use the value of the |winwidth| option. + *'Tlist_Inc_Winwidth'* Tlist_Inc_Winwidth~ By default, when the width of the window is less than 100 and a new taglist window is opened vertically, then the window width will be increased by the value set in the Tlist_WinWidth variable to accommodate the new window. The value of this variable is used only if you are using a vertically split -taglist window. If your terminal doesn't support changing the window width -from Vim (older version of xterm running in a Unix system) or if you see any -weird problems in the screen due to the change in the window width or if you -prefer not to adjust the window width then set the 'Tlist_Inc_Winwidth' -variable to 0. CAUTION: If you are using the MS-Windows version of Vim in a -MS-DOS command window then you must set this variable to 0, otherwise the -system may hang due to a Vim limitation (explained in :help win32-problems) > +taglist window. - let Tlist_Inc_Winwidth = 0 +If your terminal doesn't support changing the window width from Vim (older +version of xterm running in a Unix system) or if you see any weird problems in +the screen due to the change in the window width or if you prefer not to +adjust the window width then set the 'Tlist_Inc_Winwidth' variable to 0. +CAUTION: If you are using the MS-Windows version of Vim in a MS-DOS command +window then you must set this variable to 0, otherwise the system may hang due +to a Vim limitation (explained in :help win32-problems) > + + let Tlist_Inc_Winwidth = 0 < + *'Tlist_WinHeight'* Tlist_WinHeight~ The default height of the horizontally split taglist window is 10. This can be changed by modifying the 'Tlist_WinHeight' variable: > - let Tlist_WinHeight = 20 + let Tlist_WinHeight = 20 < + *'Tlist_Use_SingleClick'* Tlist_Use_SingleClick~ By default, when you double click on the tag name using the left mouse button, the cursor will be positioned at the definition of the tag. You -can set the Tlist_Use_SingleClick variable to one to jump to a tag when +can set the Tlist_Use_SingleClick variable to 1 to jump to a tag when you single click on the tag name using the mouse. By default this variable is set to zero. > - let Tlist_Use_SingleClick = 1 + let Tlist_Use_SingleClick = 1 < -Due to a bug in Vim, if you set Tlist_Use_SingleClick to one and try to -resize the taglist window using the mouse, then Vim will crash. The fix for -this bug will be available in the next version of Vim. In the meantime, -instead of resizing the taglist window using the mouse, you can use normal -Vim window resizing commands to resize the taglist window. +Due to a bug in Vim, if you set Tlist_Use_SingleClick to one and try to resize +the taglist window using the mouse, then Vim will crash. The fix for this bug +will be available in Vim 6.3 and above. In the meantime, instead of resizing +the taglist window using the mouse, you can use normal Vim window resizing +commands to resize the taglist window. + *'Tlist_Compact_Format'* Tlist_Compact_Format~ -By default, the taglist window will contain text that display the name of -the file, sort order information and the key to press to get help. Also, -empty lines will be used to separate different groups of tags. If you -don't need these information, you can set the Tlist_Compact_Format variable -to one to get a compact display. > +By default, empty lines are used to separate different tag types displayed for +a file and the tags displayed for different files in the taglist window. If +you want to display as many tags as possible in the taglist window, you can +set the Tlist_Compact_Format variable to one to get a compact display. > - let Tlist_Compact_Format = 1 + let Tlist_Compact_Format = 1 < + *'Tlist_Exit_OnlyWindow'* Tlist_Exit_OnlyWindow~ -If you want to exit Vim if only the taglist window is currently open, then +If you want to exit Vim if only the taglist window is currently opened, then set the Tlist_Exit_OnlyWindow variable to one. By default, this variable is -set to zero and the Vim instance will not be closed if only the taglist -window is open. > +set to zero and the Vim instance will not be closed if only the taglist window +is present. > - let Tlist_Exit_OnlyWindow = 1 + let Tlist_Exit_OnlyWindow = 1 < + *'Tlist_File_Fold_Auto_Close'* Tlist_File_Fold_Auto_Close~ -By default, the tags tree displayed in the taglist window for all the buffers -will be opened. You can close/fold the tags tree for the files manually. To +By default, the tags tree displayed in the taglist window for all the files is +opened. You can close/fold the tags tree for the files manually. To automatically close the tags tree for inactive files, you can set the -Tlist_File_Fold_Auto_Close variable to 1. When this variable is set to 1, if -a Vim buffer is no longer displayed in a Vim window, the corresponding tags -tree in the taglist window will be collapsed/folded. When a buffer is loaded -in a Vim window, the corresponding tags tree will be opened. +Tlist_File_Fold_Auto_Close variable to 1. When this variable is set to 1, if a +Vim buffer is no longer displayed in a Vim window, the corresponding tags tree +in the taglist window will be collapsed/folded. When a buffer is loaded in a +Vim window, the corresponding tags tree will be opened. > - let Tlist_File_Fold_Auto_Close = 1 + let Tlist_File_Fold_Auto_Close = 1 < + *'Tlist_Enable_Fold_Column'* Tlist_Enable_Fold_Column~ -By default, the tags tree includes a fold column. If you wish to disable this -(for example, if you are working with a narrow Vim window or terminal), set -the Tlist_Enable_Fold_Column variable to 0. +By default, the Vim fold column is enabled and displayed in the taglist +window. If you wish to disable this (for example, when you are working with a +narrow Vim window or terminal), you can set the Tlist_Enable_Fold_Column +variable to 0. > - let Tlist_Enable_Fold_Column = 1 + let Tlist_Enable_Fold_Column = 1 < + *'Tlist_Auto_Highlight_Tag'* Tlist_Auto_Highlight_Tag~ By default, the taglist plugin will highlight the current tag in the taglist window. If you want to disable the highlighting of the current tag, then you @@ -514,144 +666,209 @@ can set the Tlist_Auto_Highlight_Tag variable to zero. Note that even though the current tag highlighting is disabled, the tags for a new file will still be added to the taglist window. > - let Tlist_Auto_Highlight_Tag = 0 + let Tlist_Auto_Highlight_Tag = 0 < + *'Tlist_Process_File_Always'* Tlist_Process_File_Always~ -By default, the taglist plugin will generate and process tags for new files -only when the taglist window is opened. When the taglist window is closed, the -taglist plugin will stop processing the tags for new files. You can set the -Tlist_Process_File_Always variable to 1 to generate the list of tags for new -files even when the taglist window is closed. When you open the taglist -window, the tags for all the files opened so far will be displayed. -> - let Tlist_Process_File_Always = 1 -< +By default, the taglist plugin will generate and process the tags defined in +the newly opened files only when the taglist window is opened or when the +taglist menu is enabled. When the taglist window is closed, the taglist plugin +will stop processing the tags for newly opened files. +You can set the Tlist_Process_File_Always variable to 1 to generate the list +of tags for new files even when the taglist window is closed and the taglist +menu is disabled. +> + let Tlist_Process_File_Always = 1 +< +You should set this variable to 1, if you want to use the :TlistShowTag and +:TlistShowPrototype commands without the taglist window and the taglist menu. + + *'Tlist_Show_Menu'* +Tlist_Show_Menu~ +When using GUI Vim, you can display the tags defined in the current file in a +menu named "Tags". By default, this feature is turned off. To turn on this +feature, set the Tlist_Show_Menu variable to one: +> + let Tlist_Show_Menu = 1 +< + *'Tlist_Max_Submenu_Items'* +Tlist_Max_Submenu_Items~ +If a file contains too many tags of a particular type (function, variable, +class, etc.), greater than that specified by the Tlist_Max_Submenu_Items +variable, then the menu for that tag type will be split into multiple +sub-menus. The default setting for the Tlist_Max_Submenu_Items variable is 25. +This can be changed by setting the Tlist_Max_Submenu_Items variable: +> + let Tlist_Max_Submenu_Items = 20 +< +The name of the submenu is formed using the names of the first and the last +tag entries in that submenu. + + *'Tlist_Max_Tag_Length'* +Tlist_Max_Tag_Length~ +Only the first Tlist_Max_Tag_Length characters from the tag names will be used +to form the tag type submenu name. Change the Tlist_Max_Tag_Length setting if +you want to include more or less characters: +> + let Tlist_Max_Tag_Length = 10 +< ============================================================================== *taglist-commands* 7. Commands~ The taglist plugin provides the following ex-mode commands: -Tlist~ -Open or close (toggle) the taglist window. Opens the taglist window, if the -window is not opened currently. Closes the taglist window, if the taglist -window is already opened. When the taglist window is opened for the first -time, all the files in the buffer list are processed and the tags are -displayed in the taglist window. +|:Tlist| Open or close (toggle) the taglist window. +|:TlistClose| Close the taglist window. +|:TlistUpdate| Update the tags for the current buffer. +|:TlistSync| Highlight the current tag in the taglist window. +|:TlistShowPrototype| Display the prototype of the tag at or below the + specified line number. +|:TlistShowTag| Display the name of the tag defined at or below the + specified line number. +|:TlistSessionSave| Save the information about files and tags in use. +|:TlistSessionLoad| Load information about files and tags last saved. +|:TlistDebug| Start logging of taglist debug messages. +|:TlistUndebug| Stop logging of taglist debug messages. +|:TlistMessages| Display the logged taglist plugin debug messages. -TlistClose~ -Close the taglist window. This command can be used from any one of the Vim -windows. + *:Tlist* +:Tlist Open or close (toggle) the taglist window. Opens the taglist + window, if the window is not opened currently. Closes the + taglist window, if the taglist window is already opened. When + the taglist window is opened for the first time, all the files + in the buffer list are processed and the tags are displayed in + the taglist window. -TlistUpdate~ -Update the tags for the current buffer. When a file is changed and saved to -disk, the taglist window will not be automatically updated to display the new -tags in the file. The ":TlistUpdate" command can be used to force an update of -the tags for the current file/buffer. As the taglist plugin uses the file -saved in the disk (instead of the file displayed in a Vim buffer), you should -save the modified buffer before you update the taglist window. Otherwise the -listed tags will not include the new tags created in the buffer. + *:TlistClose* +:TlistClose Close the taglist window. This command can be used from any + one of the Vim windows. -TlistSync~ -Highlight the current tag in the taglist window. By default, the taglist -plugin periodically updates the taglist window to highlight the current tag. -The ":TlistSync" command can be used to force the taglist plugin to highlight -the current tag. + *:TlistUpdate* +:TlistUpdate Update the tags displayed for the current buffer. This + command can be used to force an update of the tags for the + current file/buffer. As the taglist plugin uses the file saved + in the disk (instead of the file displayed in a Vim buffer), + you should save the modified buffer before you update the + taglist window. Otherwise the listed tags will not include the + new tags created in the buffer. -TlistShowPrototype~ -Display the prototype of the tag near the specified line number. If the line -number is not specified, the current line number is used. A tag spans multiple -lines starting from the line where it is defined to the line before the next -tag. The ":TlistShowPrototype" command displays the prototype for the tag for -any line number in this range. + *:TlistSync* +:TlistSync Highlight the current tag in the taglist window. By default, + the taglist plugin periodically updates the taglist window to + highlight the current tag. This command can be used to force + the taglist plugin to highlight the current tag. -TlistShowTag~ -Display the name of the tag defined near the specified line number. If the -line number is not specified, the current line number is used. A tag spans -multiple lines starting from the line where it is defined to the line before -the next tag. The ":TlistShowTag" command displays the tag name for any line -number in this range. + *:TlistShowPrototype* +:TlistShowPrototype [filename] [linenumber] + Display the prototype of the tag at or below the specified + line number. If the file name and the line number are not + specified, then the current file name and line number are + used. A tag spans multiple lines starting from the line where + it is defined to the line before the next tag. This command + displays the prototype for the tag for any line number in this + range. -TlistSessionSave~ -Save the information about files and tags displayed in the taglist window to -the specified session file. + *:TlistShowTag* +:TlistShowTag [filename] [linenumber] + Display the name of the tag defined at or below the specified + line number. If the file name and the line number are not + specified, then the current file name and line number are + used. A tag spans multiple lines starting from the line where + it is defined to the line before the next tag. This command + displays the tag name for any line number in this range. -TlistSessionLoad~ -Load information about files and tags stored from the specified session file -and update the taglist window with those files. + *:TlistSessionSave* +:TlistSessionSave {filename} + Save the information about files and tags displayed in the + taglist window to the specified file. This command can be used + to save and restore the taglist window contents across Vim + sessions. + + *:TlistSessionLoad* +:TlistSessionLoad {filename} + Load the information about files and tags stored in the + specified session file and update the taglist window with + the tags stored in the session file. + + *:TlistDebug* +:TlistDebug + Start logging of debug messages from the taglist plugin. + The debug messages are stored in a script local variable by + the taglist plugin. + + *:TlistUndebug* +:TlistUndebug + Stop logging of debug messages from the taglist plugin. + + *:TlistMessages* +:TlistMessages + Display the logged debug messages from the taglist plugin. ============================================================================== *taglist-functions* 8. Global functions~ -The taglist plugin function provides several global functions that can be -invoked from other Vim plugins to interact with the taglist plugin. These -functions are described below. +The taglist plugin provides several global functions that can be used from +other Vim plugins to interact with the taglist plugin. These functions are +described below. -Tlist_Update_File_Tags()~ -The Tlist_Update_File_Tags() function updates the tags for the specified file. -The second argument specifies the Vim filetype for the specified file. If the -taglist plugin has not processed the specified file previously, then the -exuberant ctags tool is invoked to generate the tags for the file. +|Tlist_Update_File_Tags()| Update the tags for the specified file +|Tlist_Get_Tag_Prototype_By_Line()| Return the prototype of the tag at or + below the specified line number in the + specified file. +|Tlist_Get_Tagname_By_Line()| Return the name of the tag at or below + the specified line number in the + specified file. +|Tlist_Set_App()| Set the name of the app controlling + the taglist window. -The syntax for this function is -> - Tlist_Update_File_Tags(filename, filetype) -< -Tlist_Get_Tag_Prototype_By_Line()~ -The Tlist_Get_Tag_Prototype_By_Line() function returns the prototype of the -tag at or below the specified line number in the specified file. If the -filename and line number are not specified, then the current buffer name and -the current line number are used. + *Tlist_Update_File_Tags()* +Tlist_Update_File_Tags({filename}, {filetype}) + Update the tags for the file {filename}. The second argument + specifies the Vim filetype for the file. If the taglist plugin + has not processed the file previously, then the exuberant + ctags tool is invoked to generate the tags for the file. -The syntax for this function is -> - Tlist_Get_Tag_Prototype_By_Line([filename, linenumber]) -< -Tlist_Get_Tagname_By_Line()~ -The Tlist_Get_Tagname_By_Line() function returns the name of the tag at or -below the specified line number in the specified file. If the filename and -line number are not specified, then the current buffer name and the current -line number are used. + *Tlist_Get_Tag_Prototype_By_Line()* +Tlist_Get_Tag_Prototype_By_Line([{filename}, {linenumber}]) + Return the prototype of the tag at or below the specified + line number in the specified file. If the filename and line + number are not specified, then the current buffer name and the + current line number are used. -The syntax for this function is -> - Tlist_Get_Tagname_By_Line([filename, linenumber]) -< -This function can be used to display the current tag name in the status line -or in the title bar. For example, the following 'statusline' setting will -display the current tag name in the status line: -> - set statusline=%<%f\ %h%m%r%{Tlist_Get_Tagname_By_Line()}%=%-14.(%l,%c%V%)\ %P -< -Note that the above 'statusline' setting will work only after the file is -processed by the taglist plugin. For this, you have to either open the taglist -window or you have to set the 'Tlist_Process_File_Always' option. + *Tlist_Get_Tagname_By_Line()* +Tlist_Get_Tagname_By_Line([{filename}, {linenumber}]) + Return the name of the tag at or below the specified line + number in the specified file. If the filename and line number + are not specified, then the current buffer name and the + current line number are used. -Tlist_Set_App()~ -The Tlist_Set_App() function sets the name of the plugin that controls the -taglist plugin window and buffer. For example, the winmanager plugin or the -cream package use the taglist plugin and control the taglist window and -buffer. These two plugins invoke this function and specify the name as -"winmanager" or "cream" respectively. By default, the taglist plugin is a -standalone plugin and controls the taglist window and buffer. If the taglist -window is controlled by an external plugin, then the appname should be set -appropriately. + *Tlist_Set_App()* +Tlist_Set_App({appname}) + Set the name of the plugin that controls the taglist plugin + window and buffer. This can be used to integrate the taglist + plugin with other Vim plugins. + + For example, the winmanager plugin and the Cream package use + this function and specify the appname as "winmanager" and + "cream" respectively. + + By default, the taglist plugin is a stand-alone plugin and + controls the taglist window and buffer. If the taglist window + is controlled by an external plugin, then the appname should + be set appropriately. -The syntax for this function is -> - Tlist_Set_App(appname) -< ============================================================================== *taglist-extend* 9. Extending~ The taglist plugin supports all the languages supported by the exuberant ctags -tool, which includes the following languages: Assembly ASP, Awk, Beta, C, C++, -C#, Cobol, Eiffel, Erlang, Fortran, HTML, Java, Javascript, Lisp, Lua, Make, -Pascal, Perl, PHP, Python, Rexx, Ruby, Scheme, Shell, Slang, SML, Sql, TCL, -Verilog, Vim and Yacc. +tool, which includes the following languages: Assembly, ASP, Awk, Beta, C, +C++, C#, Cobol, Eiffel, Erlang, Fortran, HTML, Java, Javascript, Lisp, Lua, +Make, Pascal, Perl, PHP, Python, Rexx, Ruby, Scheme, Shell, Slang, SML, Sql, +TCL, Verilog, Vim and Yacc. You can modify the taglist plugin support for the above listed languages. You can also extend the taglist plugin to add support for new languages. @@ -665,64 +882,70 @@ the support for an already supported language by setting the following variables in the .vimrc file. To modify the support for an already supported language, you have to set the -tlist_xxx_settings variable. Replace xxx with the Vim filetype name. To +tlist_xxx_settings variable. Replace xxx with the Vim filetype name. To determine the filetype name used by Vim for a file, use the following command -in the buffer containing the desired file: > +in the buffer containing the file: > - :set filetype + :set filetype < For example, to modify the support for the perl language files, you have to set the tlist_perl_settings variable. The format of the value set in the tlist_xxx_settings variable is > - ;flag1:name1;flag2:name2;flag3:name3 + ;flag1:name1;flag2:name2;flag3:name3 < -The different fields are separated by the ';' character. The first field -'language_name' is the name used by exuberant ctags. This name can be -different from the file type name used by Vim. For example, for C++, the -language name used by ctags is 'c++' but the filetype name used by Vim is -'cpp'. The remaining fields follow the format "flag:name". The sub-field -'flag' is the language specific flag used by exuberant ctags to generate the -corresponding tags. For example, for the C language, to list only the -functions, the 'f' flag should be used. For more information about the flags +The different fields in the value are separated by the ';' character. + +The first field 'language_name' is the name used by exuberant ctags to refer +to this language files. This name can be different from the file type name +used by Vim. For example, for C++, the language name used by ctags is 'c++' +but the filetype name used by Vim is 'cpp'. + +The remaining fields follow the format "flag:name". The sub-field 'flag' is +the language specific flag used by exuberant ctags to generate the +corresponding tags. For example, for the C language, to list only the +functions, the 'f' flag is used. For more information about the flags supported by exuberant ctags for a particular language, read the help text -from the 'ctags --help' comand. The sub-field 'name' specifies the title -text to use for displaying the tags of a particular type. For example, -'name' can be set to 'functions'. This field can be set to any text -string name. +from the 'ctags --help' command. The sub-field 'name' specifies the title text +to use for displaying the tags of a particular type. For example, 'name' can +be set to 'functions'. This field can be set to any text string name. For example, to list only the classes and functions defined in a C++ language file, add the following lines to your .vimrc file > - let tlist_cpp_settings = 'c++;c:class;f:function' + let tlist_cpp_settings = 'c++;c:class;f:function' < In the above setting, 'cpp' is the Vim filetype name and 'c++' is the name used by the exuberant ctags tool. 'c' and 'f' are the flags passed to -exuberant ctags to list classes and functions and 'class' is the title used -for the class tags and 'function' is the title used for function tags. +exuberant ctags to list C++ classes and functions and 'class' is the title +used for the class tags and 'function' is the title used for the function tags +in the taglist window. For example, to display only functions defined in a C file and to use "My -Functions" as the title for the function group, use > +Functions" as the title for the function tags, use > - let tlist_c_settings = 'c;f:My Functions' + let tlist_c_settings = 'c;f:My Functions' < When you set the tlist_xxx_settings variable, you will override the default setting used by the taglist plugin for the 'xxx' language. You cannot add to -the options used by the taglist plugin for a particular file type. +the default options used by the taglist plugin for a particular file type. To add support for a new language, set the tlist_xxx_settings variable -appropriately as described above. For example, to extend the taglist plugin -to support the latex language, you can use the following line (assuming, you -have already extended exuberant ctags to support the latex language): > +appropriately as described above. Replace 'xxx' in the variable name with the +Vim filetype name for the new language. - let tlist_tex_settings='latex;b:bibitem;c:command;l:label' +For example, to extend the taglist plugin to support the latex language, you +can use the following line (assuming, you have already extended exuberant +ctags to support the latex language): > + + let tlist_tex_settings='latex;b:bibitem;c:command;l:label' < With the above line, when you edit files of filetype "tex" in Vim, the taglist -plugin will invoke the exuberant ctags tool with the "latex" filetype and with +plugin will invoke the exuberant ctags tool passing the "latex" filetype and the flags b, c and l to generate the tags. The text heading 'bibitem', -'command' and 'label' will be used for the tags which are generated for the -flags b, c and l respectively. +'command' and 'label' will be used in the taglist window for the tags which +are generated for the flags b, c and l respectively. ============================================================================== *taglist-faq* @@ -742,7 +965,7 @@ A. Are you using Vim version 6.0 and above? The taglist plugin relies on the utility to parse the tags. Add the following line to the .vimrc or _vimrc file to enable Vim filetype detection: > - filetype on + filetype on < Is your version of Vim compiled with the support for the system() function? In some Linux distributions (particularly Suse Linux), the default Vim @@ -769,7 +992,7 @@ A. Are you using Vim version 6.0 and above? The taglist plugin relies on the Run the following command from the shell and see whether you see your tags in the output from exuberant ctags: - ctags -f - --format=2 --excmd=pattern --fields=nks + ctags -f - --format=2 --excmd=pattern --fields=nks If you see your tags in the output from the above command, then the exuberant ctags utility is properly parsing your file. @@ -779,6 +1002,20 @@ A. Are you using Vim version 6.0 and above? The taglist plugin relies on the If you do have this file, check the options in this file and make sure these options are not interfering with the operation of the taglist plugin. + If you are using MS-Windows, check the value of the TEMP and TMP + environment variables. If these environment variables are set to a path + with space characters in the name, then try using the DOS 8.3 short name + for the path or set them to a path without the space characters in the + name. For example, if the temporary directory name is "C:\Documents and + Settings\xyz\Local Settings\Temp", then try setting the TEMP variable to + the following: + + set TEMP=C:\DOCUMEN~1\xyz\LOCALS~1\Temp + + If exuberant ctags is installed in a directory with space characters in the + name, then try adding the directory to the PATH environment variable or try + copying the exuberant ctags to a path without space characters in the name. + Q. A file has more than one tag with the same name. When I select a tag name from the taglist window, the cursor is positioned at the incorrect tag location. @@ -789,17 +1026,21 @@ A. The taglist plugin uses the search pattern generated by the exuberant ctags pattern, the cursor may be positioned at the incorrect location. Q. I have made some modifications to my file and introduced new - functions/classes/variables. I have not yet saved my file. The taglist - plugin is not displaying the new tags when I update the taglist window. + functions/classes/variables. I have not yet saved my file. The taglist + plugin is not displaying the new tags when I update the taglist window. A. The exuberant ctags utility will process only files that are present in the disk. To list the tags defined in a file, you have to save the file and then update the taglist window. Q. I have created a ctags file using the exuberant ctags utility for my source tree. How do I configure the taglist plugin to use this tags file? -A. The taglist plugin doesn't use the tags file generated by exuberant ctags. - For every opened file, the taglist plugin invokes the exuberant ctags - utility to get the list of tags. +A. The taglist plugin doesn't a tags file stored in disk. For every opened + file, the taglist plugin invokes the exuberant ctags utility to get the + list of tags dynamically. The Vim system() function is used to invoke + exuberant ctags and get the ctags output. This function internally uses a + temporary file to store the output. This file is deleted after the output + from the command is read. So you will never see the file that contains the + output of exuberant ctags. Q. When I set the |updatetime| option to a low value (less than 1000) and if I keep pressing a key with the taglist window open, the current buffer diff --git a/plugin/taglist.vim b/plugin/taglist.vim index 114cc14..67008e1 100644 --- a/plugin/taglist.vim +++ b/plugin/taglist.vim @@ -1,13 +1,13 @@ " File: taglist.vim " Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com) -" Version: 3.4 -" Last Modified: August 15, 2004 +" Version: 4.0 Beta1 +" Last Modified: April 4, 2005 " -" 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 +" The "Tag List" plugin is a source code browser plugin for Vim and provides +" an overview of the structure of the programming language 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: +" programming languages. You can visit the taglist plugin home page for more +" information: " " http://www.geocities.com/yegappan/taglist " @@ -35,8 +35,9 @@ " 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. +" 3. If the exuberant ctags utility is not present in your PATH, then 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. @@ -44,13 +45,27 @@ " 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 +" +if exists('loaded_taglist') finish endif let loaded_taglist='yes' +" Line continuation used here +let s:cpo_save = &cpo +set cpo&vim + +" The taglist plugin requires the built-in Vim system() function. If this +" function is not available, then don't load the plugin. +if !exists('*system') + echomsg 'Taglist: Vim system() built-in function is not available. ' . + \ 'Plugin is not loaded.' + let &cpo = s:cpo_save + finish +endif + " Location of the exuberant ctags tool if !exists('Tlist_Ctags_Cmd') if executable('exuberant-ctags') @@ -64,7 +79,8 @@ if !exists('Tlist_Ctags_Cmd') else echomsg 'Taglist: Exuberant ctags (http://ctags.sf.net) ' . \ 'not found in PATH. Plugin is not loaded.' - " Taglist plugin functionality is not available + " Skip loading the plugin + let &cpo = s:cpo_save finish endif endif @@ -168,6 +184,18 @@ if !exists('Tlist_Show_One_File') let Tlist_Show_One_File = 0 endif +if !exists('Tlist_Show_Menu') + let Tlist_Show_Menu = 0 +endif + +if !exists('Tlist_Max_Submenu_Items') + let Tlist_Max_Submenu_Items = 20 +endif + +if !exists('Tlist_Max_Tag_Length') + let Tlist_Max_Tag_Length = 10 +endif + "------------------- end of user configurable options -------------------- " Initialize the taglist plugin local variables for the supported file types @@ -242,10 +270,10 @@ let s:tlist_def_make_settings = 'make;m:macro' let s:tlist_def_pascal_settings = 'pascal;f:function;p:procedure' " perl language -let s:tlist_def_perl_settings = 'perl;p:package;s:subroutine' +let s:tlist_def_perl_settings = 'perl;c:constant;l:label;p:package;s:subroutine' " php language -let s:tlist_def_php_settings = 'php;c:class;f:function' +let s:tlist_def_php_settings = 'php;c:class;d:constant;v:variable;f:function' " python language let s:tlist_def_python_settings = 'python;c:class;m:member;f:function' @@ -281,7 +309,7 @@ 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' +let s:tlist_def_tcl_settings = 'tcl;c:class;f:method;m:method;p:procedure' " vera language let s:tlist_def_vera_settings = 'vera;c:class;d:macro;e:enumerator;' . @@ -290,8 +318,8 @@ let s:tlist_def_vera_settings = 'vera;c:class;d:macro;e:enumerator;' . \ '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' +let s:tlist_def_verilog_settings = 'verilog;m:module;c:constant;P:parameter;' . + \ 'e:event;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' @@ -301,7 +329,7 @@ let s:tlist_def_yacc_settings = 'yacc;l:label' "------------------- end of language specific options -------------------- -" Vim window size is changed or not +" Vim window size is changed by the taglist plugin or not let s:tlist_winsize_chgd = 0 " Taglist window is maximized or not let s:tlist_win_maximized = 0 @@ -313,9 +341,11 @@ let s:tlist_ftype_count = 0 let s:tlist_app_name = "none" " Are we displaying brief help text let s:tlist_brief_help = 1 -" List of files deleted on user request -let s:tlist_deleted_flist = "" +" List of files removed on user request +let s:tlist_removed_flist = "" let s:tlist_cur_file_idx = -1 +" Taglist menu is empty or not +let s:tlist_menu_empty = 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__" @@ -410,6 +440,28 @@ function! s:Tlist_Toggle_Help_Text() setlocal nomodifiable endfunction +" Taglist debug support +let s:tlist_msg = '' +let s:tlist_debug = 0 + +" Commands for enabling/disabling debug and to display debug messages +command! -nargs=0 TlistDebug let s:tlist_debug = 1 +command! -nargs=0 TlistUndebug let s:tlist_debug = 0 +command! -nargs=0 TlistMessages echo s:tlist_msg + +" Tlist_Log_Msg +" Log the supplied debug message along with the time +function! s:Tlist_Log_Msg(msg) + if s:tlist_debug + " Retain only the last 3000 characters + let len = strlen(s:tlist_msg) + if len > 3000 + let s:tlist_msg = strpart(s:tlist_msg, len - 3000) + endif + let s:tlist_msg = s:tlist_msg . strftime('%T') . ': ' . a:msg . "\n" + endif +endfunction + " Tlist_Warning_Msg() " Display a message using WarningMsg highlight group function! s:Tlist_Warning_Msg(msg) @@ -438,6 +490,7 @@ endfunction " Return the index of the filename present in the specified line number " Line number refers to the line number in the taglist window function! s:Tlist_Get_File_Index_By_Linenum(lnum) + call s:Tlist_Log_Msg('Tlist_Get_File_Index_By_Linenum (' . a:lnum . ')') let i = 0 " TODO: Convert this to a binary search @@ -454,13 +507,8 @@ endfunction " Tlist_Skip_File() " Check whether tag listing is supported for the specified file function! s:Tlist_Skip_File(filename, ftype) - " Skip buffers with no names - if a:filename == '' - return 1 - endif - - " Skip buffers with filetype not set - if a:ftype == '' + " Skip buffers with no names and buffers with filetype not set + if a:filename == '' || a:ftype == '' return 1 endif @@ -486,10 +534,32 @@ function! s:Tlist_Skip_File(filename, ftype) return 0 endfunction +" Tlist_User_Removed_File +" Returns 1 if a file is removed by a user from the taglist +function! s:Tlist_User_Removed_File(filename) + let esc_fname = escape(a:filename, '\') . "\n" + return match(s:tlist_removed_flist, esc_fname) != -1 +endfunction + +" Tlist_Update_Remove_List +" Update the list of user removed files from the taglist +" add == 1, add the file to the removed list +" add == 0, delete the file from the removed list +function! s:Tlist_Update_Remove_List(filename, add) + if a:add + let s:tlist_removed_flist = s:tlist_removed_flist . a:filename . "\n" + else + let esc_fname = escape(a:filename, '\') . "\n" + let s:tlist_removed_flist = substitute(s:tlist_removed_flist, + \ esc_fname, '', '') + endif +endfunction + " Tlist_FileType_Init " Initialize the ctags arguments and tag variable for the specified " file type function! s:Tlist_FileType_Init(ftype) + call s:Tlist_Log_Msg('Tlist_FileType_Init (' . a: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' @@ -552,7 +622,7 @@ function! s:Tlist_FileType_Init(ftype) call s:Tlist_Warning_Msg(msg) return 0 endif - let flag = strpart(settings, 0, pos) + let flag = strpart(settings, 0, pos) if flag == '' call s:Tlist_Warning_Msg(msg) return 0 @@ -595,12 +665,21 @@ endfunction " Tlist_Discard_TagInfo " Discard the stored tag information for a file function! s:Tlist_Discard_TagInfo(fidx) + call s:Tlist_Log_Msg('Tlist_Discard_TagInfo (' . + \ s:tlist_{a:fidx}_filename . ')') 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 fidx_i = 's:tlist_' . a:fidx . '_' . i + unlet! {fidx_i}_tag + unlet! {fidx_i}_tag_name + unlet! {fidx_i}_tag_type + unlet! {fidx_i}_ttype_idx + unlet! {fidx_i}_tag_proto + unlet! {fidx_i}_tag_searchpat + unlet! {fidx_i}_tag_linenum let i = i + 1 endwhile @@ -611,18 +690,22 @@ function! s:Tlist_Discard_TagInfo(fidx) 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 fidx_ttype = 's:tlist_' . a:fidx . '_' . ttype + let {fidx_ttype} = '' + let {fidx_ttype}_start = 0 + let cnt = {fidx_ttype}_count + let {fidx_ttype}_count = 0 let j = 1 while j <= cnt - unlet! s:tlist_{a:fidx}_{ttype}_{j} + unlet! {fidx_ttype}_{j} let j = j + 1 endwhile endif let i = i + 1 endwhile + + " Discard the stored menu command also + let s:tlist_{a:fidx}_menu_cmd = '' endfunction " Tlist_Update_Line_Offsets @@ -649,6 +732,8 @@ endfunction " Tlist_Discard_FileInfo " Discard the stored information for a file function! s:Tlist_Discard_FileInfo(fidx) + call s:Tlist_Log_Msg('Tlist_Discard_FileInfo (' . + \ s:tlist_{a:fidx}_filename . ')') call s:Tlist_Discard_TagInfo(a:fidx) let ftype = s:tlist_{a:fidx}_filetype @@ -671,11 +756,14 @@ function! s:Tlist_Discard_FileInfo(fidx) unlet! s:tlist_{a:fidx}_valid unlet! s:tlist_{a:fidx}_visible unlet! s:tlist_{a:fidx}_tag_count + unlet! s:tlist_{a:fidx}_menu_cmd endfunction " Tlist_Remove_File_From_Display " Remove the specified file from display function! s:Tlist_Remove_File_From_Display(fidx) + call s:Tlist_Log_Msg('Tlist_Remove_File_From_Display (' . + \ s:tlist_{a:fidx}_filename . ')') " If the file is not visible then no need to remove it if !s:tlist_{a:fidx}_visible return @@ -711,14 +799,15 @@ function! s:Tlist_Remove_File(file_idx, user_request) return endif endif + call s:Tlist_Log_Msg('Tlist_Remove_File (' . + \ s:tlist_{fidx}_filename . ', ' . a:user_request . ')') call s:Tlist_Remove_File_From_Display(fidx) if a:user_request " As the user requested to remove the file from taglist, " add it to the removed list - let s:tlist_deleted_flist = s:tlist_deleted_flist . - \ s:tlist_{fidx}_filename . "\n" + call s:Tlist_Update_Remove_List(s:tlist_{fidx}_filename, 1) endif call s:Tlist_Discard_FileInfo(fidx) @@ -738,10 +827,17 @@ function! s:Tlist_Remove_File(file_idx, user_request) 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 s:tlist_{j}_menu_cmd = s:tlist_{i}_menu_cmd let k = 1 while k <= s:tlist_{j}_tag_count - let s:tlist_{j}_tag_{k} = s:tlist_{i}_tag_{k} + let s:tlist_{j}_{k}_tag = s:tlist_{i}_{k}_tag + let s:tlist_{j}_{k}_tag_name = s:tlist_{i}_{k}_tag_name + let s:tlist_{j}_{k}_tag_type = s:Tlist_Get_Tag_Type(i, k) + let s:tlist_{j}_{k}_ttype_idx = s:tlist_{i}_{k}_ttype_idx + let s:tlist_{j}_{k}_tag_proto = s:Tlist_Get_Tag_Prototype(i, k) + let s:tlist_{j}_{k}_tag_searchpat = s:Tlist_Get_Tag_SearchPat(i, k) + let s:tlist_{j}_{k}_tag_linenum = s:Tlist_Get_Tag_Linenum(i, k) let k = k + 1 endwhile @@ -786,6 +882,7 @@ endfunction " Tlist_Open_Window " Create a new taglist window. If it is already open, jump to it function! s:Tlist_Open_Window() + call s:Tlist_Log_Msg('Tlist_Open_Window()') " If the window is open, jump to it let winnum = bufwinnr(g:TagList_title) if winnum != -1 @@ -816,7 +913,7 @@ function! s:Tlist_Open_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 &columns= &columns + g:Tlist_WinWidth + 1 let s:tlist_winsize_chgd = 1 else let s:tlist_winsize_chgd = 0 @@ -876,65 +973,62 @@ endfunction " Tlist_Init_Window " Set the default options for the taglist window function! s:Tlist_Init_Window() + call s:Tlist_Log_Msg('Tlist_Init_Window()') " Define taglist window element highlighting - if has('syntax') - syntax match TagListComment '^" .*' - syntax match TagListFileName '^[^" ].*$' - syntax match TagListTitle '^ \S.*$' - syntax match TagListTagScope '\s\[.\{-\}\]$' + 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 + " 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 TagListTagName term=reverse cterm=reverse + 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 " Folding related settings - if has('folding') - setlocal foldenable - setlocal foldminlines=0 - setlocal foldmethod=manual - if g:Tlist_Enable_Fold_Column - setlocal foldcolumn=3 - else - setlocal foldcolumn=0 - endif - setlocal foldtext=v:folddashes.getline(v:foldstart) + setlocal foldenable + setlocal foldminlines=0 + setlocal foldmethod=manual + if g:Tlist_Enable_Fold_Column + setlocal foldcolumn=3 + else + setlocal foldcolumn=0 endif + setlocal foldtext=v:folddashes.getline(v:foldstart) if s:tlist_app_name != "winmanager" " Mark buffer as scratch @@ -958,12 +1052,16 @@ function! s:Tlist_Init_Window() " window silent! setlocal nonumber + " Setup the cpoptions properly for the maps to work + let old_cpoptions = &cpoptions + set cpoptions&vim + " Create buffer local mappings for jumping to the tags and sorting the list nnoremap :call Tlist_Jump_To_Tag(0) nnoremap o :call Tlist_Jump_To_Tag(1) nnoremap p :call Tlist_Jump_To_Tag(2) nnoremap <2-LeftMouse> :call Tlist_Jump_To_Tag(0) - nnoremap s :call Tlist_Change_Sort() + nnoremap s :call Tlist_Change_Sort(1, 1, '') nnoremap + :silent! foldopen nnoremap - :silent! foldclose nnoremap * :silent! %foldopen! @@ -976,7 +1074,9 @@ function! s:Tlist_Init_Window() nnoremap d :call Tlist_Remove_File(-1, 1) nnoremap x :call Tlist_Zoom_Window() nnoremap [[ :call Tlist_Move_To_File(-1) + nnoremap :call Tlist_Move_To_File(-1) nnoremap ]] :call Tlist_Move_To_File(1) + nnoremap :call Tlist_Move_To_File(1) nnoremap ? :call Tlist_Toggle_Help_Text() nnoremap q :close @@ -986,9 +1086,10 @@ function! s:Tlist_Init_Window() inoremap :call Tlist_Jump_To_Tag(0) inoremap o :call Tlist_Jump_To_Tag(1) inoremap p :call Tlist_Jump_To_Tag(2) - inoremap <2-LeftMouse> :call + inoremap <2-LeftMouse> :call \ Tlist_Jump_To_Tag(0) - inoremap s :call Tlist_Change_Sort() + inoremap s + \ :call Tlist_Change_Sort(1, 1, '') inoremap + :silent! foldopen inoremap - :silent! foldclose inoremap * :silent! %foldopen! @@ -996,13 +1097,15 @@ function! s:Tlist_Init_Window() inoremap :silent! foldopen inoremap :silent! foldclose inoremap :silent! %foldopen! - inoremap :call + inoremap :call \ Tlist_Show_Tag_Prototype() inoremap u :call Tlist_Update_Window() inoremap d :call Tlist_Remove_File(-1, 1) inoremap x :call Tlist_Zoom_Window() inoremap [[ :call Tlist_Move_To_File(-1) + inoremap :call Tlist_Move_To_File(-1) inoremap ]] :call Tlist_Move_To_File(1) + inoremap :call Tlist_Move_To_File(1) inoremap ? :call Tlist_Toggle_Help_Text() inoremap q :close @@ -1020,11 +1123,11 @@ function! s:Tlist_Init_Window() exe ':nnoremap ' . clickmap else " we have a mapping - let mapcmd = ':nnoremap ' - let mapcmd = mapcmd . substitute(substitute( - \ maparg('', 'n'), '|', '', 'g'), + let mapcmd = ':nnoremap ' + let mapcmd = mapcmd . substitute(substitute( + \ maparg('', 'n'), '|', '', 'g'), \ '\c^', '', '') - let mapcmd = mapcmd . clickmap + let mapcmd = mapcmd . clickmap exe mapcmd endif endif @@ -1034,9 +1137,10 @@ function! s:Tlist_Init_Window() 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 + " Highlight the current tag periodically autocmd CursorHold * silent call Tlist_Highlight_Tag( \ fnamemodify(bufname('%'), ':p'), line('.'), 1) + " Adjust the Vim window width when taglist window is closed autocmd BufUnload __Tag_List__ call Tlist_Post_Close_Cleanup() " Close the fold for this buffer when it's not visible in any window @@ -1047,16 +1151,22 @@ function! s:Tlist_Init_Window() \ fnamemodify(expand(''), ':p'), 2) " Exit Vim itself if only the taglist window is present (optional) autocmd BufEnter __Tag_List__ call Tlist_Check_Only_Window() - if s:tlist_app_name != "winmanager" && !g:Tlist_Process_File_Always + if s:tlist_app_name != "winmanager" && + \ !g:Tlist_Process_File_Always && + \ (!has('gui_running') || !g:Tlist_Show_Menu) " Auto refresh the taglist window autocmd BufEnter * call Tlist_Refresh() endif augroup end + + " Restore the previous cpoptions settings + let &cpoptions = old_cpoptions endfunction " Tlist_Refresh_Window " Display the tags for all the files in the taglist window function! s:Tlist_Refresh_Window() + call s:Tlist_Log_Msg('Tlist_Refresh_Window()') " Set report option to a huge value to prevent informational messages " while deleting the lines let old_report = &report @@ -1068,6 +1178,14 @@ function! s:Tlist_Refresh_Window() " Delete the contents of the buffer to the black-hole register silent! %delete _ + " As we have cleared the taglist window, 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 + if g:Tlist_Compact_Format == 0 " Display help in non-compact mode call s:Tlist_Display_Help() @@ -1079,35 +1197,35 @@ function! s:Tlist_Refresh_Window() " Restore the report option let &report = old_report - if !g:Tlist_Show_One_File - " List all the tags for the previously processed files - " Do this only if taglist is configured to display tags for more than - " one file. Otherwise, when Tlist_Show_One_File is configured, - " tags for the wrong file will be displayed. - 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 + " If the tags for only one file should be displayed in the taglist + " window, then no need to add the tags here. The bufenter autocommand + " will add the tags for that file. + if g:Tlist_Show_One_File + return + endif - " If Tlist_File_Fold_Auto_Close option is set, then close all the - " folds - if g:Tlist_File_Fold_Auto_Close - if has('folding') - " Close all the folds - silent! %foldclose - endif - endif + " List all the tags for the previously processed files + " Do this only if taglist is configured to display tags for more than + " one file. Otherwise, when Tlist_Show_One_File is configured, + " tags for the wrong file will be displayed. + let i = 0 + while i < s:tlist_file_count + call s:Tlist_Explore_File(s:tlist_{i}_filename, s:tlist_{i}_filetype) + let i = i + 1 + endwhile + + " If Tlist_File_Fold_Auto_Close option is set, then close all the + " folds + if g:Tlist_File_Fold_Auto_Close + " Close all the folds + silent! %foldclose endif endfunction " Tlist_Post_Close_Cleanup() " Close the taglist window and adjust the Vim window width function! s:Tlist_Post_Close_Cleanup() + call s:Tlist_Log_Msg('Tlist_Post_Close_Cleanup()') " Mark all the files as not visible let i = 0 while i < s:tlist_file_count @@ -1121,11 +1239,9 @@ function! s:Tlist_Post_Close_Cleanup() " Clear all the highlights match none - if has('syntax') - silent! syntax clear TagListTitle - silent! syntax clear TagListComment - silent! syntax clear TagListTagScope - endif + silent! syntax clear TagListTitle + silent! syntax clear TagListComment + silent! syntax clear TagListTagScope " Remove the left mouse click mapping if it was setup initially if g:Tlist_Use_SingleClick @@ -1170,32 +1286,32 @@ endfunction " Tlist_Explore_File() " List the tags defined in the specified file in a Vim window function! s:Tlist_Explore_File(filename, ftype) + call s:Tlist_Log_Msg('Tlist_Explore_File (' . a:filename . ')') " First check whether the file already exists let fidx = s:Tlist_Get_File_Index(a:filename) if fidx != -1 - let file_exists = 1 + let file_listed = 1 else - let file_exists = 0 + let file_listed = 0 endif - if !file_exists + if !file_listed " Check whether this file is removed based on user request " If it is, then don't display the tags for this file - let esc_fname = escape(a:filename, '\') . "\n" - if match(s:tlist_deleted_flist, esc_fname) != -1 + if s:Tlist_User_Removed_File(a:filename) return endif endif - if file_exists && s:tlist_{fidx}_visible + if file_listed && s:tlist_{fidx}_visible " Check whether the file tags are currently valid if s:tlist_{fidx}_valid " Goto the first line in the file exe s:tlist_{fidx}_start " If the line is inside a fold, open the fold - if has('folding') - exe "silent! " . s:tlist_{fidx}_start . "," . + if foldclosed('.') != -1 + exe "silent! " . s:tlist_{fidx}_start . "," . \ s:tlist_{fidx}_end . "foldopen!" endif return @@ -1207,7 +1323,7 @@ function! s:Tlist_Explore_File(filename, ftype) endif " Process and generate a list of tags defined in the file - if !file_exists || !s:tlist_{fidx}_valid + if !file_listed || !s:tlist_{fidx}_valid let ret_fidx = s:Tlist_Process_File(a:filename, a:ftype) if ret_fidx == -1 return @@ -1251,7 +1367,7 @@ function! s:Tlist_Explore_File(filename, ftype) if g:Tlist_Compact_Format exe s:tlist_{fidx}_start else - exe (s:tlist_{fidx}_start - 1) + exe s:tlist_{fidx}_start - 1 endif let txt = fnamemodify(s:tlist_{fidx}_filename, ':t') . ' (' . @@ -1267,10 +1383,13 @@ function! s:Tlist_Explore_File(filename, ftype) " 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_cnt = s:tlist_{a:ftype}_count + while i <= ttype_cnt 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 fidx_ttype = 's:tlist_' . fidx . '_' . ttype + let ttype_txt = {fidx_ttype} + if ttype_txt != '' let txt = ' ' . s:tlist_{a:ftype}_{i}_fullname if g:Tlist_Compact_Format == 0 let ttype_start_lnum = line('.') + 1 @@ -1279,22 +1398,24 @@ function! s:Tlist_Explore_File(filename, ftype) let ttype_start_lnum = line('.') silent! put! =txt endif - silent! put =s:tlist_{fidx}_{ttype} + silent! put =ttype_txt - if g:Tlist_Compact_Format - exe (line('.') + s:tlist_{fidx}_{ttype}_count) - endif - - let s:tlist_{fidx}_{ttype}_start = ttype_start_lnum - file_start + let {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' + let fold_start = ttype_start_lnum + let fold_end = fold_start + {fidx_ttype}_count + exe fold_start . ',' . fold_end . 'fold' + + " Adjust the cursor position + if g:Tlist_Compact_Format == 0 + exe ttype_start_lnum + {fidx_ttype}_count + else + exe ttype_start_lnum + {fidx_ttype}_count + 1 endif if g:Tlist_Compact_Format == 0 + " Separate the tag types by a empty line silent! put ='' endif endif @@ -1308,11 +1429,9 @@ function! s:Tlist_Explore_File(filename, ftype) 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 + exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold' + exe 'silent! ' . s:tlist_{fidx}_start . ',' . + \ s:tlist_{fidx}_end . 'foldopen!' " Goto the starting line for this file, exe s:tlist_{fidx}_start @@ -1340,12 +1459,17 @@ function! s:Tlist_Explore_File(filename, ftype) endif call s:Tlist_Update_Line_Offsets(fidx + 1, 1, end - start + 1) - return + " Now that we have updated the taglist window, update the tags + " menu (if present) + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(1) + endif endfunction " Tlist_Init_File " Initialize the variables for a new file function! s:Tlist_Init_File(filename, ftype) + call s:Tlist_Log_Msg('Tlist_Init_File (' . a:filename . ')') " 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 @@ -1360,6 +1484,7 @@ function! s:Tlist_Init_File(filename, ftype) let s:tlist_{fidx}_valid = 0 let s:tlist_{fidx}_visible = 0 let s:tlist_{fidx}_tag_count = 0 + let s:tlist_{fidx}_menu_cmd = '' " Initialize the tag type variables let i = 1 @@ -1374,12 +1499,169 @@ function! s:Tlist_Init_File(filename, ftype) return fidx endfunction +" Tlist_Get_Tag_Type +function! s:Tlist_Get_Tag_Type(fidx, tidx) + let ttype_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_type' + + " Already parsed and have the tag name + if exists(ttype_var) + return {ttype_var} + endif + + let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag + let {ttype_var} = s:Tlist_Extract_Tagtype(tag_line) + + return {ttype_var} +endfunction + +" Tlist_Get_Tag_Prototype +function! s:Tlist_Get_Tag_Prototype(fidx, tidx) + let tproto_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_proto' + + " Already parsed and have the tag prototype + if exists(tproto_var) + return {tproto_var} + endif + + " Parse and extract the tag prototype + let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag + let start = stridx(tag_line, '/^') + 2 + let end = stridx(tag_line, '/;"' . "\t") + if tag_line[end - 1] == '$' + let end = end -1 + endif + let tag_proto = strpart(tag_line, start, end - start) + let {tproto_var} = substitute(tag_proto, '\s*', '', '') + + return {tproto_var} +endfunction + +" Tlist_Get_Tag_SearchPat +function! s:Tlist_Get_Tag_SearchPat(fidx, tidx) + let tpat_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_searchpat' + + " Already parsed and have the tag search pattern + if exists(tpat_var) + return {tpat_var} + endif + + " Parse and extract the tag search pattern + let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag + let start = stridx(tag_line, '/^') + 2 + let end = stridx(tag_line, '/;"' . "\t") + if tag_line[end - 1] == '$' + let end = end -1 + endif + let {tpat_var} = '\V\^' . strpart(tag_line, start, end - start) . + \ (tag_line[end] == '$' ? '\$' : '') + + return {tpat_var} +endfunction + +" Tlist_Get_Tag_Linenum +" Return the tag line number +function! s:Tlist_Get_Tag_Linenum(fidx, tidx) + let tline_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_linenum' + + " Already parsed and have the tag line number + if exists(tline_var) + return {tline_var} + endif + + " Parse and extract the tag line number + let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag + let start = strridx(tag_line, 'line:') + 5 + let end = strridx(tag_line, "\t") + if end < start + let {tline_var} = strpart(tag_line, start) + 0 + else + let {tline_var} = strpart(tag_line, start, end - start) + 0 + endif + + return {tline_var} +endfunction + +" Tlist_Parse_Tagline +" Parse a tag line from the ctags output. 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_namefile_nameex_cmd;"extension_fields +" +function! s:Tlist_Parse_Tagline(tag_line) + if a:tag_line == '' + " Skip empty lines + return + endif + + " Extract the tag type + let ttype = s:Tlist_Extract_Tagtype(a:tag_line) + + if ttype == '' + " Line is not in proper tags format + return + endif + + " make sure the tag type is supported + if stridx(s:ctags_flags, ttype) == -1 + " Tag type is not supported + return + endif + + " Update the total tag count + let s:tidx = s:tidx + 1 + + " The following variables are used to optimize this code. Vim is slow in + " using curly brace names. To reduce the amount of processing needed, the + " curly brace variables are pre-processed here + let fidx_tidx = 's:tlist_' . s:fidx . '_' . s:tidx + let fidx_ttype = 's:tlist_' . s:fidx . '_' . ttype + + " Update the count of this tag type + let ttype_idx = {fidx_ttype}_count + 1 + let {fidx_ttype}_count = ttype_idx + + " Store the ctags output for this tag + let {fidx_tidx}_tag = a:tag_line + + " Store the tag index and the tag type index (back pointers) + let {fidx_ttype}_{ttype_idx} = s:tidx + let {fidx_tidx}_ttype_idx = ttype_idx + + " Extract the tag name + let tag_name = strpart(a:tag_line, 0, stridx(a:tag_line, "\t")) + + " Extract the tag scope/prototype + if g:Tlist_Display_Prototype + let ttxt = ' ' . s:Tlist_Get_Tag_Prototype(s:fidx, s:tidx) + else + let ttxt = ' ' . tag_name + + " Add the tag scope, if it is available and is configured. Tag + " scope is the last field after the 'line:\t' field + if g:Tlist_Display_Tag_Scope + let tag_scope = s:Tlist_Extract_Tag_Scope(a:tag_line) + if tag_scope != '' + let ttxt = ttxt . ' [' . tag_scope . ']' + endif + endif + endif + + " Add this tag to the tag type variable + let {fidx_ttype} = {fidx_ttype} . ttxt . "\n" + + " Save the tag name + let {fidx_tidx}_tag_name = tag_name +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 == '' + call s:Tlist_Log_Msg('Tlist_Process_File (' . a:filename . ', ' . + \ a:ftype . ')') + " Check whether this file is supported + if s:Tlist_Skip_File(a:filename, a:ftype) return -1 endif @@ -1407,11 +1689,11 @@ function! s:Tlist_Process_File(filename, ftype) " 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 + " Form the ctags argument depending on the sort type if s:tlist_{fidx}_sort_type == 'name' - let ctags_args = ctags_args . ' --sort=yes ' + let ctags_args = ctags_args . '--sort=yes' else - let ctags_args = ctags_args . ' --sort=no ' + let ctags_args = ctags_args . '--sort=no' endif " Add the filetype specific arguments @@ -1424,24 +1706,28 @@ function! s:Tlist_Process_File(filename, ftype) " 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 + if has('win95') && !has('win32unix') + let old_shellslash = &shellslash set noshellslash endif + call s:Tlist_Log_Msg('Cmd: ' . ctags_cmd) + " 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 + if has('win95') && !has('win32unix') + let &shellslash = old_shellslash endif " Handle errors - if v:shell_error && cmd_output != '' + if v:shell_error let msg = "Taglist: Failed to generate tags for " . a:filename call s:Tlist_Warning_Msg(msg) - call s:Tlist_Warning_Msg(cmd_output) + if cmd_output != '' + call s:Tlist_Warning_Msg(cmd_output) + endif return fidx endif @@ -1451,72 +1737,117 @@ function! s:Tlist_Process_File(filename, ftype) return fidx endif + call s:Tlist_Log_Msg('Generated tags information for ' . a:filename) + " Store the modification time for the file let s:tlist_{fidx}_mtime = getftime(a:filename) - " 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_namefile_nameex_cmd;"extension_fields - " - while cmd_output != '' - " Extract one line at a time - let idx = stridx(cmd_output, "\n") - let one_line = strpart(cmd_output, 0, idx) - " Remove the line from the tags output - let cmd_output = strpart(cmd_output, idx + 1) + if v:version > 601 + " The following script local variables are used by the + " Tlist_Parse_Tagline() function. + let s:ctags_flags = s:tlist_{a:ftype}_ctags_flags + let s:fidx = fidx + let s:tidx = 0 - if one_line == '' - " Line is not in proper tags format - continue - endif + " Process the ctags output one line at a time. The substitute() + " command is used to parse the tag lines instead of using the + " matchstr()/stridx()/strpart() functions for performance reason + call substitute(cmd_output, '\(.\{-}\)\n', + \ '\=s:Tlist_Parse_Tagline(submatch(1))', 'g') - " Extract the tag type - let ttype = s:Tlist_Extract_Tagtype(one_line) + " Save the number of tags for this file + let s:tlist_{fidx}_tag_count = s:tidx - if ttype == '' - " Line is not in proper tags format - continue - endif + " The following script local variables are no longer needed + unlet! s:ctags_flags + unlet! s:tidx + unlet! s:fidx + else + " Due to a bug in Vim earlier than version 6.1, + " we cannot use substitute() to parse the ctags output. + " Instead the slow str*() functions are used + let ctags_flags = s:tlist_{a:ftype}_ctags_flags + let tidx = 0 - " make sure the tag type is supported - if s:tlist_{a:ftype}_ctags_flags !~# ttype - " Tag type is not supported - continue - endif + while cmd_output != '' + " Extract one line at a time + let idx = stridx(cmd_output, "\n") + let one_line = strpart(cmd_output, 0, idx) + " Remove the line from the tags output + let cmd_output = strpart(cmd_output, idx + 1) - " Extract the tag name - if g:Tlist_Display_Prototype == 0 - let ttxt = ' ' . strpart(one_line, 0, stridx(one_line, "\t")) + if one_line == '' + " Line is not in proper tags format + continue + endif - " Add the tag scope, if it is available. Tag scope is the last - " field after the 'line:\t' field - if g:Tlist_Display_Tag_Scope " only if it is selected - let tag_scope = s:Tlist_Extract_Tag_Scope(one_line) - if tag_scope != '' - let ttxt = ttxt . ' [' . tag_scope . ']' + " 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 stridx(ctags_flags, ttype) == -1 + " Tag type is not supported + continue + endif + + " Update the total tag count + let tidx = tidx + 1 + + " The following variables are used to optimize this code. Vim is + " slow in using curly brace names. To reduce the amount of + " processing needed, the curly brace variables are pre-processed + " here + let fidx_tidx = 's:tlist_' . fidx . '_' . tidx + let fidx_ttype = 's:tlist_' . fidx . '_' . ttype + + " Update the count of this tag type + let ttype_idx = {fidx_ttype}_count + 1 + let {fidx_ttype}_count = ttype_idx + + " Store the ctags output for this tag + let {fidx_tidx}_tag = one_line + + " Store the tag index and the tag type index (back pointers) + let {fidx_ttype}_{ttype_idx} = tidx + let {fidx_tidx}_ttype_idx = ttype_idx + + " Extract the tag name + let tag_name = strpart(one_line, 0, stridx(one_line, "\t")) + + " Extract the tag scope/prototype + if g:Tlist_Display_Prototype + let ttxt = ' ' . s:Tlist_Get_Tag_Prototype(fidx, tidx) + else + let ttxt = ' ' . tag_name + + " Add the tag scope, if it is available and is configured. Tag + " scope is the last field after the 'line:\t' field + if g:Tlist_Display_Tag_Scope + let tag_scope = s:Tlist_Extract_Tag_Scope(one_line) + if tag_scope != '' + let ttxt = ttxt . ' [' . tag_scope . ']' + endif endif endif - else - let ttxt = s:Tlist_Extract_Tag_Prototype(one_line) - 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 {fidx_ttype} = {fidx_ttype} . ttxt . "\n" - " Add this tag to the tag type variable - let s:tlist_{fidx}_{ttype} = s:tlist_{fidx}_{ttype} . ttxt . "\n" + " Save the tag name + let {fidx_tidx}_tag_name = tag_name + endwhile - " 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 + " Save the number of tags for this file + let s:tlist_{fidx}_tag_count = tidx + endif + + call s:Tlist_Log_Msg('Processed ' . s:tlist_{fidx}_tag_count . + \ ' tags in ' . a:filename) return fidx endfunction @@ -1524,24 +1855,30 @@ endfunction " Tlist_Update_File_Tags " Update the tags for a file (if needed) function! Tlist_Update_File_Tags(filename, ftype) + call s:Tlist_Log_Msg('Tlist_Update_File_Tags (' . a:filename . ')') " If the file doesn't support tag listing, skip it if s:Tlist_Skip_File(a:filename, a:ftype) return endif + " Convert the file name to a full path + let fname = fnamemodify(a:filename, ':p') + " First check whether the file already exists - let fidx = s:Tlist_Get_File_Index(a:filename) + let fidx = s:Tlist_Get_File_Index(fname) if fidx != -1 && s:tlist_{fidx}_valid " File exists and the tags are valid - return - else - " Check whether this file is removed based on user request - " If it is, then don't display the tags for this file - let esc_fname = escape(a:filename, '\') . "\n" - if match(s:tlist_deleted_flist, esc_fname) != -1 + " Check whether the file was modified after the last tags update + " If it is modified, then update the tags + if s:tlist_{fidx}_mtime == getftime(fname) return endif + else + " If the tags were removed previously based on a user request, + " as we are going to update the tags (based on the user request), + " remove the filename from the deleted list + call s:Tlist_Update_Remove_List(fname, 0) endif " If the taglist window is opened, update it @@ -1549,7 +1886,7 @@ function! Tlist_Update_File_Tags(filename, ftype) if winnum == -1 " Taglist window is not present. Just update the taglist " and return - call s:Tlist_Process_File(a:filename, a:ftype) + call s:Tlist_Process_File(fname, a:ftype) else " Save the current window number let save_winnr = winnr() @@ -1558,18 +1895,24 @@ function! Tlist_Update_File_Tags(filename, ftype) call s:Tlist_Open_Window() " Update the taglist window - call s:Tlist_Explore_File(a:filename, a:ftype) + call s:Tlist_Explore_File(fname, a:ftype) if winnr() != save_winnr " Go back to the original window exe save_winnr . 'wincmd w' endif endif + + " Update the taglist menu + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(1) + endif endfunction " Tlist_Close_Window " Close the taglist window function! s:Tlist_Close_Window() + call s:Tlist_Log_Msg('Tlist_Close_Window()') " Make sure the taglist window exists let winnum = bufwinnr(g:TagList_title) if winnum == -1 @@ -1602,8 +1945,7 @@ endfunction " Tlist_Toggle_Window() " Open or close a taglist window function! s:Tlist_Toggle_Window() - let curline = line('.') - + call s:Tlist_Log_Msg('Tlist_Toggle_Window()') " If taglist window is open then close it. let winnum = bufwinnr(g:TagList_title) if winnum != -1 @@ -1619,6 +1961,7 @@ function! s:Tlist_Toggle_Window() " Get the filename and filetype for the specified buffer let curbuf_name = fnamemodify(bufname('%'), ':p') let curbuf_ftype = getbufvar('%', '&filetype') + let cur_lnum = line('.') " Mark the current window as the desired window to open a file " when a tag is selcted @@ -1637,70 +1980,60 @@ function! s:Tlist_Toggle_Window() call s:Tlist_Explore_File(curbuf_name, curbuf_ftype) endif else - " Add and list the tags for all the buffers in the bufferlist + " Add and list the tags for all loaded buffers in the Vim buffer list let i = 1 - while i < bufnr('$') - let fname = fnamemodify(bufname(i), ':p') - let ftype = getbufvar(i, '&filetype') - " If the file doesn't support tag listing, skip it - if !s:Tlist_Skip_File(fname, ftype) - call s:Tlist_Explore_File(fname, ftype) + let last_bufnum = bufnr('$') + while i <= last_bufnum + if bufexists(i) && bufloaded(i) + let fname = fnamemodify(bufname(i), ':p') + let ftype = getbufvar(i, '&filetype') + " If the file doesn't support tag listing, skip it + if !s:Tlist_Skip_File(fname, ftype) + call s:Tlist_Explore_File(fname, ftype) + endif endif let i = i + 1 endwhile endif " Highlight the current tag - call s:Tlist_Highlight_Tag(curbuf_name, curline, 1) + call s:Tlist_Highlight_Tag(curbuf_name, cur_lnum, 1) " Go back to the original window let prev_Tlist_Skip_Refresh = s:Tlist_Skip_Refresh let s:Tlist_Skip_Refresh = 1 wincmd p let s:Tlist_Skip_Refresh = prev_Tlist_Skip_Refresh + + " Update the taglist menu + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(0) + endif endfunction " Tlist_Extract_Tagtype " Extract the tag type from the tag text -function! s:Tlist_Extract_Tagtype(tag_txt) +function! s:Tlist_Extract_Tagtype(tag_line) " 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) + let start = strridx(a:tag_line, '/;"' . "\t") + 4 + let end = strridx(a:tag_line, 'line:') - 1 + let ttype = strpart(a:tag_line, 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") - " The search patterns for some tag types doesn't end with - " the ;" character - 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 = substitute(tag_pat, '\s*', '', '') - - return tag_pat -endfunction - " Tlist_Extract_Tag_Scope " Extract the tag scope from the tag text -function! s:Tlist_Extract_Tag_Scope(tag_txt) - let start = strridx(a:tag_txt, 'line:') - let end = strridx(a:tag_txt, "\t") +function! s:Tlist_Extract_Tag_Scope(tag_line) + let start = strridx(a:tag_line, 'line:') + let end = strridx(a:tag_line, "\t") if end <= start return '' endif - let tag_scope = strpart(a:tag_txt, end + 1) + let tag_scope = strpart(a:tag_line, end + 1) let tag_scope = strpart(tag_scope, stridx(tag_scope, ':') + 1) return tag_scope @@ -1709,9 +2042,22 @@ endfunction " Tlist_Refresh() " Refresh the taglist function! s:Tlist_Refresh() + call s:Tlist_Log_Msg('Tlist_Refresh (Skip_Refresh = ' . + \ s:Tlist_Skip_Refresh . ', ' . bufname('%') . ')') " 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 || (s:tlist_app_name == "winmanager") + if s:Tlist_Skip_Refresh + " We still need to update the taglist menu + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(0) + endif + return + endif + + " If part of the winmanager plugin and not configured to process + " tags always and not configured to display the tags menu, then return + if (s:tlist_app_name == 'winmanager') && !g:Tlist_Process_File_Always + \ && !g:Tlist_Show_Menu return endif @@ -1728,131 +2074,158 @@ function! s:Tlist_Refresh() return endif - let curline = line('.') + let tlist_win = bufwinnr(g:TagList_title) - " Make sure the taglist window is open. Otherwise, no need to refresh - let winnum = bufwinnr(g:TagList_title) - if winnum == -1 - if g:Tlist_Process_File_Always - call Tlist_Update_File_Tags(filename, ftype) - endif + " If the taglist window is not opened and not configured to process + " tags always and not displaying the tags menu, then return + if tlist_win == -1 && !g:Tlist_Process_File_Always && !g:Tlist_Show_Menu return endif let fidx = s:Tlist_Get_File_Index(filename) - if fidx != -1 + if fidx == -1 + " Check whether this file is removed based on user request + " If it is, then don't display the tags for this file + if s:Tlist_User_Removed_File(filename) + return + endif + endif + + let cur_lnum = line('.') + + if fidx == -1 + " Update the tags for the file + let fidx = s:Tlist_Process_File(filename, ftype) + else let mtime = getftime(filename) if s:tlist_{fidx}_mtime != mtime " Invalidate the tags listed for this file let s:tlist_{fidx}_valid = 0 - " Update the taglist window - call Tlist_Update_File_Tags(s:tlist_{fidx}_filename, - \ s:tlist_{fidx}_filetype) + " Update the taglist and the window + call Tlist_Update_File_Tags(filename, ftype) " Store the new file modification time let s:tlist_{fidx}_mtime = mtime endif - - if s:tlist_{fidx}_visible - " If the tag listing for the current window is already present, no - " need to refresh it - if !g:Tlist_Auto_Highlight_Tag - return - endif - - " Highlight the current tag - call s:Tlist_Highlight_Tag(filename, curline, 1) - - return - endif - endif - - " Save the current window number - let cur_winnr = winnr() - - " Goto the taglist window - call s:Tlist_Open_Window() - - if !g:Tlist_Auto_Highlight_Tag - " Save the cursor position - let save_line = line('.') - let save_col = col('.') endif " Update the taglist window - call s:Tlist_Explore_File(filename, ftype) + if tlist_win != -1 + " Disable screen updates + let old_lazyredraw = &lazyredraw + set nolazyredraw - " Highlight the current tag - call s:Tlist_Highlight_Tag(filename, curline, 1) + " Save the current window number + let cur_winnr = winnr() - if !g:Tlist_Auto_Highlight_Tag - " Restore the cursor position - call cursor(save_line, save_col) - endif + " Goto the taglist window + call s:Tlist_Open_Window() - " Refresh the taglist window - redraw + if !g:Tlist_Auto_Highlight_Tag + " Save the cursor position + let save_line = line('.') + let save_col = col('.') + endif - if s:tlist_app_name != "winmanager" - " Jump back to the original window - exe cur_winnr . 'wincmd w' + " Update the taglist window + call s:Tlist_Explore_File(filename, ftype) + + " Highlight the current tag + call s:Tlist_Highlight_Tag(filename, cur_lnum, 1) + + if !g:Tlist_Auto_Highlight_Tag + " Restore the cursor position + call cursor(save_line, save_col) + endif + + if s:tlist_app_name != "winmanager" + " Jump back to the original window + exe cur_winnr . 'wincmd w' + endif + + " Restore screen updates + let &lazyredraw = old_lazyredraw + endif + + " Update the taglist menu + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(0) endif endfunction " Tlist_Change_Sort() " Change the sort order of the tag listing -function! s:Tlist_Change_Sort() - let fidx = s:Tlist_Get_File_Index_By_Linenum(line('.')) - if fidx == -1 - return +" caller == 1, taglist window +" caller == 2, taglist menu +" action == 1, toggle sort from name to order and vice versa +" action == 2, set the sort order to sort_type +function! s:Tlist_Change_Sort(caller, action, sort_type) + call s:Tlist_Log_Msg('Tlist_Change_Sort (caller = ' . a:caller . + \ ', action = ' . a:action . ', sort_type = ' . a:sort_type . ')') + if a:caller == 1 + let fidx = s:Tlist_Get_File_Index_By_Linenum(line('.')) + if fidx == -1 + return + endif + + " Remove the previous highlighting + match none + elseif a:caller == 2 + let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p')) + if fidx == -1 + return + endif endif - " Remove the previous highlighting - match none + if a:action == 1 + let sort_type = s:tlist_{fidx}_sort_type - 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' + " 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 else - let s:tlist_{fidx}_sort_type = 'name' + let s:tlist_{fidx}_sort_type = a:sort_type 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) + if a:caller == 1 + " Save the current line for later restoration + let curline = '\V\^' . getline('.') . '\$' - " Go back to the cursor line before the tag list is sorted - call search(curline, 'w') + call s:Tlist_Explore_File(s:tlist_{fidx}_filename, + \ s:tlist_{fidx}_filetype) + + " Go back to the cursor line before the tag list is sorted + call search(curline, 'w') + + call s:Tlist_Menu_Update_File(1) + else + call s:Tlist_Menu_Remove_File() + + call s:Tlist_Refresh() + endif endfunction " Tlist_Update_Tags() " Update taglist for the current buffer by regenerating the tag list " Contributed by WEN Guopeng. function! s:Tlist_Update_Tags() + call s:Tlist_Log_Msg('Tlist_Update_Tags()') if winnr() == bufwinnr(g:TagList_title) " In the taglist window. Update the current file call s:Tlist_Update_Window() - return else " Not in the taglist window. Update the current buffer let filename = fnamemodify(bufname('%'), ':p') let fidx = s:Tlist_Get_File_Index(filename) if fidx != -1 let s:tlist_{fidx}_valid = 0 - else - " As the user requested to update the tags for the current - " file, remove it from the deleted list (if it was previously - " deleted on user request) - let esc_fname = escape(filename, '\') . "\n" - let s:tlist_deleted_flist = substitute(s:tlist_deleted_flist, - \ esc_fname, '', '') endif call Tlist_Update_File_Tags(filename, &filetype) endif @@ -1861,6 +2234,7 @@ endfunction " Tlist_Update_Window() " Update the window by regenerating the tag list function! s:Tlist_Update_Window() + call s:Tlist_Log_Msg('Tlist_Update_Window()') let fidx = s:Tlist_Get_File_Index_By_Linenum(line('.')) if fidx == -1 return @@ -1935,6 +2309,7 @@ endfunction " win_ctrl == 1 - Open a new window " win_ctrl == 2 - Preview the tag function! s:Tlist_Jump_To_Tag(win_ctrl) + call s:Tlist_Log_Msg('Tlist_Jump_To_Tag()') " Do not process comment lines and empty lines let curline = getline('.') if curline =~ '^\s*$' || curline[0] == '"' @@ -1954,14 +2329,7 @@ function! s:Tlist_Jump_To_Tag(win_ctrl) " Get the tag output for the current tag let tidx = s:Tlist_Get_Tag_Index(fidx) if tidx != 0 - 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] == '$' ? '\$' : '') + let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, tidx) " Highlight the tagline call s:Tlist_Highlight_Tagline() @@ -1977,6 +2345,7 @@ endfunction " 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) + call s:Tlist_Log_Msg('Tlist_Open_File (' . a:filename . ')') let prev_Tlist_Skip_Refresh = s:Tlist_Skip_Refresh let s:Tlist_Skip_Refresh = 1 @@ -1990,16 +2359,27 @@ function! s:Tlist_Open_File(win_ctrl, filename, tagpat) if winnum == -1 " Locate the previously used window for opening a file let fwin_num = 0 + let first_usable_win = 0 let i = 1 while winbufnr(i) != -1 - if getwinvar(i, 'tlist_file_window') == "yes" + if getwinvar(i, 'tlist_file_window') == 'yes' let fwin_num = i break endif + if first_usable_win == 0 && bufname(winbufnr(i)) != g:TagList_title + " First non-taglist window + let first_usable_win = i + endif let i = i + 1 endwhile + " If a previously used window is not found, then use the first + " non-taglist window + if fwin_num == 0 + let fwin_num = first_usable_win + endif + if fwin_num != 0 " Jump to the file window exe fwin_num . "wincmd w" @@ -2031,8 +2411,9 @@ function! s:Tlist_Open_File(win_ctrl, filename, tagpat) " Go back to the file window wincmd p endif - let w:tlist_file_window = "yes" endif + " Mark the window, so that it can be reused. + let w:tlist_file_window = "yes" else exe winnum . 'wincmd w' @@ -2053,10 +2434,8 @@ function! s:Tlist_Open_File(win_ctrl, filename, tagpat) normal! z. " If the line is inside a fold, open the fold - if has('folding') - if foldlevel('.') != 0 - normal! zv - endif + if foldclosed('.') != -1 + .foldopen endif " If the user selects to preview the tag then jump back to the @@ -2073,7 +2452,8 @@ 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 + call s:Tlist_Log_Msg('Tlist_Show_Tag_Prototype()') + " If we already display prototype in the tag window, no need to " display it in the status line if g:Tlist_Display_Prototype return @@ -2105,15 +2485,14 @@ function! s:Tlist_Show_Tag_Prototype() return endif - let mtxt = s:tlist_{fidx}_tag_{tidx} - " Get the tag search pattern and display it - echo s:Tlist_Extract_Tag_Prototype(mtxt) + echo s:Tlist_Get_Tag_Prototype(fidx, tidx) 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) +" Tlist_Find_Nearest_Tag_Idx +" Find the tag idx nearest to the supplied line number +" Returns -1, if a tag couldn't be found for the specified line number +function! s:Tlist_Find_Nearest_Tag_Idx(fidx, linenum) let sort_type = s:tlist_{a:fidx}_sort_type let left = 1 @@ -2128,32 +2507,15 @@ function! s:Tlist_Find_Tag_text(fidx, linenum) " If the current line is the less than the first tag, then no need to " search - let txt = s:tlist_{a:fidx}_tag_1 - " 5 == length of 'line:' - let start = strridx(txt, 'line:') + 5 - 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 + let first_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, 1) if a:linenum < first_lnum - return "" + return -1 endif while left < right let middle = (right + left + 1) / 2 - let txt = s:tlist_{a:fidx}_tag_{middle} - - " 5 == length of 'line:' - let start = strridx(txt, 'line:') + 5 - 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 + let middle_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, middle) if middle_lnum == a:linenum let left = middle @@ -2170,44 +2532,36 @@ function! s:Tlist_Find_Tag_text(fidx, linenum) " 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} - - " 5 == length of 'line:' - let start = strridx(txt, 'line:') + 5 - let end = strridx(txt, "\t") - if end < start - let lnum = strpart(txt, start) + 0 - else - let lnum = strpart(txt, start, end - start) + 0 - endif + while left <= right + let lnum = s:Tlist_Get_Tag_Linenum(a:fidx, left) if lnum < a:linenum && lnum > closest_lnum let closest_lnum = lnum let final_left = left elseif lnum == a:linenum let closest_lnum = lnum + let final_left = left break else let left = left + 1 endif endwhile if closest_lnum == 0 - return "" + return -1 endif - if left == right + if left >= right let left = final_left endif endif - return s:tlist_{a:fidx}_tag_{left} + return left endfunction " Tlist_Highlight_Tag() " Highlight the current tag " cntx == 1, Called by the taglist plugin itself " cntx == 2, Forced by the user through the TlistSync command -function! s:Tlist_Highlight_Tag(filename, curline, cntx) +function! s:Tlist_Highlight_Tag(filename, cur_lnum, cntx) " Highlight the current tag only if the user configured the " taglist plugin to do so or if the user explictly invoked the " command to highlight the current tag. @@ -2240,6 +2594,9 @@ function! s:Tlist_Highlight_Tag(filename, curline, cntx) if s:tlist_app_name == "winmanager" call WinManagerSuspendAUs() endif + " Ignore all autocommands + let old_ei = &eventignore + set eventignore=all " Save the original window number let org_winnr = winnr() @@ -2258,20 +2615,20 @@ function! s:Tlist_Highlight_Tag(filename, curline, cntx) " Clear previously selected name match none - let tag_txt = s:Tlist_Find_Tag_text(fidx, a:curline) - if tag_txt == "" + let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, a:cur_lnum) + if tidx == -1 " 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. - let cur_lnum = line('.') + let lnum = line('.') - if cur_lnum < s:tlist_{fidx}_start || cur_lnum > s:tlist_{fidx}_end + if lnum < s:tlist_{fidx}_start || lnum > s:tlist_{fidx}_end " Move the cursor to the beginning of the file exe s:tlist_{fidx}_start endif - if has('folding') - normal! zv + if foldclosed('.') != -1 + .foldopen endif call winline() @@ -2285,24 +2642,26 @@ function! s:Tlist_Highlight_Tag(filename, curline, cntx) if s:tlist_app_name == "winmanager" call WinManagerResumeAUs() endif + + " Restore the autocommands + let &eventignore = old_ei 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 + let ttype = s:Tlist_Get_Tag_Type(fidx, tidx) " Compute the line number - let lnum = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_start + offset + " Start of file + Start of tag type + offset + let lnum = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_start + + \ s:tlist_{fidx}_{tidx}_ttype_idx " Goto the line containing the tag exe lnum " Open the fold - if has('folding') - normal! zv + if foldclosed('.') != -1 + .foldopen endif " Make sure the current tag line is visible in the taglist window. @@ -2325,6 +2684,8 @@ function! s:Tlist_Highlight_Tag(filename, curline, cntx) call WinManagerResumeAUs() endif + " Restore the autocommands + let &eventignore = old_ei return endfunction @@ -2370,13 +2731,12 @@ function! Tlist_Get_Tag_Prototype_By_Line(...) endif " Get the tag text using the line number - let tag_txt = s:Tlist_Find_Tag_text(fidx, linenr) - if tag_txt == "" + let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr) + if tidx == -1 return "" endif - " Extract the tag search pattern and return it - return s:Tlist_Extract_Tag_Prototype(tag_txt) + return s:Tlist_Get_Tag_Prototype(fidx, tidx) endfunction " Tlist_Get_Tagname_By_Line @@ -2420,16 +2780,12 @@ function! Tlist_Get_Tagname_By_Line(...) endif " Get the tag name using the line number - let tag_txt = s:Tlist_Find_Tag_text(fidx, linenr) - if tag_txt == "" + let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr) + if tidx == -1 return "" endif - " Remove the line number at the beginning - let start = stridx(tag_txt, ':') + 1 - - " Extract the tag name and return it - return strpart(tag_txt, start, stridx(tag_txt, "\t") - start) + return s:tlist_{fidx}_{tidx}_tag_name endfunction " Tlist_Move_To_File @@ -2526,7 +2882,7 @@ function! s:Tlist_Session_Load(...) let ftype = g:tlist_{i}_filetype unlet! g:tlist_{i}_filetype - if !exists("s:tlist_" . ftype . "_count") + if !exists('s:tlist_' . ftype . '_count') if s:Tlist_FileType_Init(ftype) == 0 let i = i + 1 continue @@ -2545,9 +2901,7 @@ function! s:Tlist_Session_Load(...) " As we are loading the tags from the session file, if this " file was previously deleted by the user, now we need to " add it back. So remove the file from the deleted list. - let esc_fname = escape(fname, '\') . "\n" - let s:tlist_deleted_flist = substitute(s:tlist_deleted_flist, - \ esc_fname, '', '') + call s:Tlist_Update_Remove_List(fname, 0) endif let fidx = s:Tlist_Init_File(fname, ftype) @@ -2564,17 +2918,18 @@ function! s:Tlist_Session_Load(...) 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 s:tlist_{fidx}_{j}_tag = g:tlist_{i}_{j}_tag + let s:tlist_{fidx}_{j}_tag_name = g:tlist_{i}_{j}_tag_name + let s:tlist_{fidx}_{j}_ttype_idx = g:tlist_{i}_{j}_ttype_idx + unlet! g:tlist_{i}_{j}_tag + unlet! g:tlist_{i}_{j}_tag_name + unlet! g:tlist_{i}_{j}_ttype_idx let j = j + 1 endwhile @@ -2616,7 +2971,8 @@ function! s:Tlist_Session_Load(...) wincmd p let s:Tlist_Skip_Refresh = prev_Tlist_Skip_Refresh - call s:Tlist_Refresh() + " Highlight the current tag + call s:Tlist_Highlight_Tag(fnamemodify(bufname('%'), ':p'), line('.'), 1) endfunction " Tlist_Session_Save @@ -2637,7 +2993,7 @@ function! s:Tlist_Session_Save(...) endif if filereadable(sessionfile) - let ans = input("Do you want to overwrite " . sessionfile . " (Y/N)?") + let ans = input('Do you want to overwrite ' . sessionfile . ' (Y/N)?') if ans !=? 'y' return endif @@ -2655,19 +3011,23 @@ function! s:Tlist_Session_Save(...) while i < s:tlist_file_count " Store information about the file - silent! echo 'let tlist_' . i . "_filename = '" . + silent! echo 'let tlist_' . i . "_filename = '" . \ s:tlist_{i}_filename . "'" - silent! echo 'let tlist_' . i . '_sort_type = "' . + silent! echo 'let tlist_' . i . '_sort_type = "' . \ s:tlist_{i}_sort_type . '"' - silent! echo 'let tlist_' . i . '_filetype = "' . + silent! echo 'let tlist_' . i . '_filetype = "' . \ s:tlist_{i}_filetype . '"' - silent! echo 'let tlist_' . i . '_tag_count = ' . + silent! echo 'let 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 tlist_' . i . '_tag_' . j . ' = "' . txt . '"' + let txt = escape(s:tlist_{i}_{j}_tag, '"\\') + silent! echo 'let tlist_' . i . '_' . j . '_tag = "' . txt . '"' + silent! echo 'let tlist_' . i . '_' . j . '_tag_name = "' . + \ s:tlist_{i}_{j}_tag_name . '"' + silent! echo 'let tlist_' . i . '_' . j . '_ttype_idx' . ' = ' . + \ s:tlist_{i}_{j}_ttype_idx let j = j + 1 endwhile @@ -2677,14 +3037,14 @@ function! s:Tlist_Session_Save(...) 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 tlist_' . i . '_' . ttype . ' = "' . + let txt = substitute(s:tlist_{i}_{ttype}, "\n", "\\\\n", 'g') + silent! echo 'let tlist_' . i . '_' . ttype . ' = "' . \ txt . '"' - silent! echo 'let tlist_' . i . '_' . ttype . '_count = ' . + silent! echo 'let tlist_' . i . '_' . ttype . '_count = ' . \ s:tlist_{i}_{ttype}_count let k = 1 while k <= s:tlist_{i}_{ttype}_count - silent! echo 'let tlist_' . i . '_' . ttype . '_' . k . + silent! echo 'let tlist_' . i . '_' . ttype . '_' . k . \ ' = ' . s:tlist_{i}_{ttype}_{k} let k = k + 1 endwhile @@ -2705,6 +3065,7 @@ endfunction " action == 1, Close the fold for the file " action == 2, Remove the file from the taglist window function! s:Tlist_Update_File_Display(filename, action) + call s:Tlist_Log_Msg('Tlist_Update_File_Display (' . a:filename . ')') " Make sure a valid filename is supplied if a:filename == '' return @@ -2717,6 +3078,13 @@ function! s:Tlist_Update_File_Display(filename, action) return endif + " Get tag list index of the specified file + let fidx = s:Tlist_Get_File_Index(a:filename) + if fidx == -1 + " File not present in the taglist window + return + endif + " Save the original window number let org_winnr = winnr() if org_winnr == winnum @@ -2730,32 +3098,22 @@ function! s:Tlist_Update_File_Display(filename, action) exe winnum . 'wincmd w' endif - " Get tag list index of the specified file - let idx = s:Tlist_Get_File_Index(a:filename) - if idx != -1 - " Save the cursor position - let save_lnum = line('.') + " Save the cursor position + let save_lnum = line('.') - " Perform the requested action on the file - if a:action == 1 - " Close the fold for the file - - if g:Tlist_File_Fold_Auto_Close - " Close the fold for the file - if has('folding') - exe "silent! " . s:tlist_{idx}_start . "," . - \ s:tlist_{idx}_end . "foldclose" - endif - endif - elseif a:action == 2 - " Remove the file from the list - call s:Tlist_Remove_File(idx, 0) - endif - - " Move the cursor to the original location - exe save_lnum + " Perform the requested action on the file + if a:action == 1 && g:Tlist_File_Fold_Auto_Close + " Close the fold for the file + exe "silent! " . s:tlist_{fidx}_start . "," . + \ s:tlist_{fidx}_end . "foldclose" + elseif a:action == 2 + " Remove the file from the list + call s:Tlist_Remove_File(fidx, 0) endif + " Move the cursor to the original location + exe save_lnum + " Go back to the original window if !in_taglist_window let prev_Tlist_Skip_Refresh = s:Tlist_Skip_Refresh @@ -2782,15 +3140,346 @@ 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('.'), 2) -command! -nargs=* -complete=buffer TlistShowPrototype +command! -nargs=* -complete=buffer TlistShowPrototype \ echo Tlist_Get_Tag_Prototype_By_Line() -command! -nargs=* -complete=buffer TlistShowTag +command! -nargs=* -complete=buffer TlistShowTag \ echo Tlist_Get_Tagname_By_Line() -command! -nargs=* -complete=file TlistSessionLoad +command! -nargs=* -complete=file TlistSessionLoad \ call s:Tlist_Session_Load() -command! -nargs=* -complete=file TlistSessionSave +command! -nargs=* -complete=file TlistSessionSave \ call s:Tlist_Session_Save() +function! s:Tlist_Add_Base_Menu() + call s:Tlist_Log_Msg('Adding the base menu') + + " Add the menu + amenu T&ags.Refresh\ menu :call Tlist_Menu_Refresh() + amenu T&ags.Sort\ menu\ by.Name + \ :call Tlist_Change_Sort(2, 2, 'name') + amenu T&ags.Sort\ menu\ by.Order + \ :call Tlist_Change_Sort(2, 2, 'order') + amenu T&ags.-SEP1- : + + if &mousemodel =~ 'popup' + amenu PopUp.T&ags.Refresh\ menu + \ :call Tlist_Menu_Refresh() + amenu PopUp.T&ags.Sort\ menu\ by.Name + \ :call Tlist_Change_Sort(2, 2, 'name') + amenu PopUp.T&ags.Sort\ menu\ by.Order + \ :call Tlist_Change_Sort(2, 2, 'order') + amenu PopUp.T&ags.-SEP1- : + endif +endfunction + +let s:menu_char_prefix = + \ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + +" Tlist_Menu_Get_Tag_Type_Cmd +" Get the menu command for the specified tag type +function! s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, ttype_idx) + " Curly brace variable name optimization + let ftype_ttype_idx = a:ftype . '_' . a:ttype_idx + + let ttype = s:tlist_{ftype_ttype_idx}_name + " If the tag type name contains space characters, escape it. This + " will be used to create the menu entries. + let ttype_fullname = escape(s:tlist_{ftype_ttype_idx}_fullname, ' ') + + " Curly brace variable name optimization + let fidx_ttype = a:fidx . '_' . ttype + + " Number of tag entries for this tag type + let tcnt = s:tlist_{fidx_ttype}_count + if tcnt == 0 " No entries for this tag type + return '' + endif + + let mcmd = '' + + " Create the menu items for the tags. + " Depending on the number of tags of this type, split the menu into + " multiple sub-menus, if needed. + if tcnt > g:Tlist_Max_Submenu_Items + let j = 1 + while j <= tcnt + let final_index = j + g:Tlist_Max_Submenu_Items - 1 + if final_index > tcnt + let final_index = tcnt + endif + + " Extract the first and last tag name and form the + " sub-menu name + let tidx = s:tlist_{fidx_ttype}_{j} + let first_tag = s:tlist_{a:fidx}_{tidx}_tag_name + + let tidx = s:tlist_{fidx_ttype}_{final_index} + let last_tag = s:tlist_{a:fidx}_{tidx}_tag_name + + " Truncate the names, if they are greater than the + " max length + let first_tag = strpart(first_tag, 0, g:Tlist_Max_Tag_Length) + let last_tag = strpart(last_tag, 0, g:Tlist_Max_Tag_Length) + + " Form the menu command prefix + let m_prefix = 'anoremenu T\&ags.' . + \ ttype_fullname . '.' . + \ first_tag . '\.\.\.' . last_tag . '.' + + " Character prefix used to number the menu items (hotkey) + let m_prefix_idx = 0 + + while j <= final_index + let tidx = s:tlist_{fidx_ttype}_{j} + + let tname = s:tlist_{a:fidx}_{tidx}_tag_name + + " If there is more than one tag with the same name, then + " add a count to the end of the menu name. Otherwise only + " one menu entry will be added for multiple tags with the + " same name (overloaded functions). + "let var_name = ttype . '_' . + " \ substitute(tname, '\W', '__tagname__', 'g') + "if exists(var_name) + " let {var_name} = {var_name} + 1 + " let tname = tname . '\ (' . {var_name} . ')' + "else + " let {var_name} = 1 + "endif + + let mcmd = mcmd . m_prefix . '\&' . + \ s:menu_char_prefix[m_prefix_idx] . '\.' . + \ tname . ' :call Tlist_Menu_Jump_To_Tag(' . + \ tidx . ')|' + + let m_prefix_idx = m_prefix_idx + 1 + let j = j + 1 + endwhile + endwhile + else + " Character prefix used to number the menu items (hotkey) + let m_prefix_idx = 0 + + let m_prefix = 'anoremenu T\&ags.' . ttype_fullname . '.' + let j = 1 + while j <= tcnt + let tidx = s:tlist_{fidx_ttype}_{j} + + let tname = s:tlist_{a:fidx}_{tidx}_tag_name + + " If there is more than one tag with the same name, then + " add a count to the end of the menu name. Otherwise only + " one menu entry will be added for multiple tags with the + " same name (overloaded functions). + "let var_name = ttype . '_' . + " \ substitute(tname, '\W', '__tagname__', 'g') + "if exists(var_name) + " let {var_name} = {var_name} + 1 + " let tname = tname . '\ (' . {var_name} . ')' + "else + " let {var_name} = 1 + "endif + + let mcmd = mcmd . m_prefix . '\&' . + \ s:menu_char_prefix[m_prefix_idx] . '\.' . + \ tname . ' :call Tlist_Menu_Jump_To_Tag(' . tidx + \ . ')|' + + let m_prefix_idx = m_prefix_idx + 1 + let j = j + 1 + endwhile + endif + + return mcmd +endfunction + +" Update the taglist menu with the tags for the specified file +function! s:Tlist_Menu_File_Refresh(fidx) + call s:Tlist_Log_Msg('Refreshing the tag menu for ' . s:tlist_{a:fidx}_filename) + " The 'B' flag is needed in the 'cpoptions' option + let old_cpoptions = &cpoptions + set cpoptions&vim + + exe s:tlist_{a:fidx}_menu_cmd + + " Update the popup menu (if enabled) + if &mousemodel =~ 'popup' + let cmd = substitute(s:tlist_{a:fidx}_menu_cmd, ' T\\&ags\.', + \ ' PopUp.T\\\&ags.', "g") + exe cmd + endif + + " The taglist menu is not empty now + let s:tlist_menu_empty = 0 + + " Restore the 'cpoptions' settings + let &cpoptions = old_cpoptions +endfunction + +" Tlist_Menu_Update_File +" Add the taglist menu +function! s:Tlist_Menu_Update_File(clear_menu) + if !has('gui_running') + " Not running in GUI mode + return + endif + + call s:Tlist_Log_Msg('Updating the tag menu, clear_menu = ' . a:clear_menu) + + " Remove the tags menu + if a:clear_menu + call s:Tlist_Menu_Remove_File() + 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 fidx = s:Tlist_Get_File_Index(filename) + if fidx == -1 || !s:tlist_{fidx}_valid + " Check whether this file is removed based on user request + " If it is, then don't display the tags for this file + if s:Tlist_User_Removed_File(filename) + return + endif + + " Process the tags for the file + let fidx = s:Tlist_Process_File(filename, ftype) + if fidx == -1 + return + endif + endif + + if !s:tlist_{fidx}_tag_count + return + endif + + if s:tlist_{fidx}_menu_cmd != '' + " Update the menu with the cached command + call s:Tlist_Menu_File_Refresh(fidx) + + return + endif + + " We are going to add entries to the tags menu, so the menu won't be + " empty + let s:tlist_menu_empty = 0 + + let cmd = '' + + " Process the tags by the tag type and get the menu command + let i = 1 + while i <= s:tlist_{ftype}_count + let mcmd = s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, i) + if mcmd != '' + let cmd = cmd . mcmd + endif + + let i = i + 1 + endwhile + + " Cache the menu command for reuse + let s:tlist_{fidx}_menu_cmd = cmd + + " Update the menu + call s:Tlist_Menu_File_Refresh(fidx) +endfunction + +" Tlist_Menu_Remove_File +" Remove the tags displayed in the tags menu +function! s:Tlist_Menu_Remove_File() + if !has('gui_running') || s:tlist_menu_empty + return + endif + + call s:Tlist_Log_Msg('Removing the tags menu for a file') + + " Cleanup the Tags menu + silent! unmenu T&ags + if &mousemodel =~ 'popup' + silent! unmenu PopUp.T&ags + endif + + call s:Tlist_Add_Base_Menu() + + silent! unmenu! T&ags + if &mousemodel =~ 'popup' + silent! unmenu! PopUp.T&ags + endif + + call s:Tlist_Add_Base_Menu() + + let s:tlist_menu_empty = 1 +endfunction + +" Tlist_Menu_Refresh +" Refresh the taglist menu +function! s:Tlist_Menu_Refresh() + call s:Tlist_Log_Msg('Refreshing the tags menu') + let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p')) + if fidx != -1 + " Invalidate the cached menu command + let s:tlist_{fidx}_menu_cmd = '' + endif + + " Update the taglist, menu and window + call s:Tlist_Update_Tags() +endfunction + +" Tlist_Menu_Jump_To_Tag +" Jump to the selected tag +function! s:Tlist_Menu_Jump_To_Tag(tidx) + let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p')) + if fidx == -1 + return + endif + + let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, a:tidx) + if tagpat == '' + return + endif + + silent call search(tagpat, 'w') + + " Bring the line to the middle of the window + normal! z. + + " If the line is inside a fold, open the fold + if foldclosed('.') != -1 + .foldopen + endif +endfunction + +" Tlist_Menu_Init +" Initialize the taglist menu +function! s:Tlist_Menu_Init() + call s:Tlist_Add_Base_Menu() + + " Automatically add the tags defined in the current file to the menu + augroup TagListMenuCmds + autocmd! + + if !g:Tlist_Process_File_Always + autocmd BufEnter * call Tlist_Refresh() + endif + autocmd BufLeave * call s:Tlist_Menu_Remove_File() + augroup end + + call s:Tlist_Menu_Update_File(0) +endfunction + +if g:Tlist_Show_Menu + autocmd GUIEnter * call Tlist_Menu_Init() +endif + " Tlist_Set_App " Set the name of the external plugin/application to which taglist " belongs. @@ -2812,7 +3501,7 @@ function! TagList_Start() return endif - call Tlist_Set_App("winmanager") + call Tlist_Set_App('winmanager') " Get the current filename from the winmanager plugin let bufnum = WinManagerGetLastEditedFile() @@ -2822,7 +3511,7 @@ function! TagList_Start() endif " Initialize the taglist window, if it is not already initialized - if !exists("s:tlist_window_initialized") || !s:tlist_window_initialized + if !exists('s:tlist_window_initialized') || !s:tlist_window_initialized call s:Tlist_Init_Window() call s:Tlist_Refresh_Window() let s:tlist_window_initialized = 1 @@ -2843,3 +3532,8 @@ endfunction function! TagList_WrapUp() return 0 endfunction + +" restore 'cpo' +let &cpo = s:cpo_save +unlet s:cpo_save +