From 4469385ac7cf03936fab7d23fafd562af7f7053f Mon Sep 17 00:00:00 2001 From: jluehrs2 Date: Sun, 9 Sep 2007 16:56:40 -0500 Subject: add my .vim directory --- vim/doc/matchit.txt | 404 ++++ vim/doc/taglist.txt | 1501 ++++++++++++++ vim/ftdetect/nhdes.vim | 1 + vim/indent/lua.vim | 59 + vim/plugin/matchit.vim | 810 ++++++++ vim/plugin/rainbow_paren.vim | 88 + vim/plugin/taglist.vim | 4497 ++++++++++++++++++++++++++++++++++++++++++ vim/skeletons/c | 6 + vim/skeletons/cpp | 6 + vim/skeletons/make | 26 + vim/skeletons/perl | 5 + vim/skeletons/tex | 13 + vim/syntax/nhdes.vim | 86 + 13 files changed, 7502 insertions(+) create mode 100644 vim/doc/matchit.txt create mode 100644 vim/doc/taglist.txt create mode 100644 vim/ftdetect/nhdes.vim create mode 100644 vim/indent/lua.vim create mode 100644 vim/plugin/matchit.vim create mode 100644 vim/plugin/rainbow_paren.vim create mode 100644 vim/plugin/taglist.vim create mode 100644 vim/skeletons/c create mode 100644 vim/skeletons/cpp create mode 100644 vim/skeletons/make create mode 100644 vim/skeletons/perl create mode 100644 vim/skeletons/tex create mode 100644 vim/syntax/nhdes.vim diff --git a/vim/doc/matchit.txt b/vim/doc/matchit.txt new file mode 100644 index 0000000..57373fe --- /dev/null +++ b/vim/doc/matchit.txt @@ -0,0 +1,404 @@ +*matchit.txt* Extended "%" matching + +For instructions on installing this file, type + :help matchit-install +inside Vim. + +For Vim version 6.3. Last change: 2006 Feb 23 + + + VIM REFERENCE MANUAL by Benji Fisher + +*matchit* *matchit.vim* + +1. Extended matching with "%" |matchit-intro| +2. Activation |matchit-activate| +3. Configuration |matchit-configure| +4. Supporting a New Language |matchit-newlang| +5. Known Bugs and Limitations |matchit-bugs| + +The functionality mentioned here is a plugin, see |add-plugin|. +This plugin is only available if 'compatible' is not set. +You can avoid loading this plugin by setting the "loaded_matchit" variable +in your |vimrc| file: > + :let loaded_matchit = 1 + +{Vi does not have any of this} + +============================================================================== +1. Extended matching with "%" *matchit-intro* + + *matchit-%* +% Cycle forward through matching groups, such as "if", "else", "endif", + as specified by |b:match_words|. + + *g%* *v_g%* *o_g%* +g% Cycle backwards through matching groups, as specified by + |b:match_words|. For example, go from "endif" to "else" to "if". + + *[%* *v_[%* *o_[%* +[% Go to [count] previous unmatched group, as specified by + |b:match_words|. Similar to |[{|. + + *]%* *v_]%* *o_]%* +]% Go to [count] next unmatched group, as specified by + |b:match_words|. Similar to |]}|. + + *v_a%* +a% In Visual mode, select the matching group, as specified by + |b:match_words|, containing the cursor. Similar to |v_a[|. + A [count] is ignored, and only the first character of the closing + pattern is selected. + +In Vim, as in plain vi, the percent key, |%|, jumps the cursor from a brace, +bracket, or paren to its match. This can be configured with the 'matchpairs' +option. The matchit plugin extends this in several ways: + + You can match whole words, such as "if" and "endif", not just + single characters. You can also specify a |regular-expression|. + You can define groups with more than two words, such as "if", + "else", "endif". Banging on the "%" key will cycle from the "if" to + the first "else", the next "else", ..., the closing "endif", and back + to the opening "if". Nested structures are skipped. Using |g%| goes + in the reverse direction. + By default, words inside comments and strings are ignored, unless + the cursor is inside a comment or string when you type "%". If the + only thing you want to do is modify the behavior of "%" so that it + behaves this way, you can > + :let b:match_words = &matchpairs +< +See |matchit-details| for details on what the script does, and |b:match_words| +for how to specify matching patterns. + +MODES: *matchit-modes* *matchit-v_%* *matchit-o_%* + +Mostly, % and related motions (|g%| and |[%| and |]%|) work just like built-in +|motion| commands in |Operator-pending| and |Visual| modes. However, you +cannot make these motions |linewise| or |characterwise|, since the |:omap|s +that define them start with "v" in order to make the default behavior +inclusive. (See |o_v|.) In other words, "dV%" will not work. The +work-around is to go through Visual mode: "V%d" will work. + +LANGUAGES: *matchit-languages* + +Currently, the following languages are supported: Ada, ASP with VBS, Csh, +DTD, Entity, Essbase, Fortran, HTML, JSP (same as HTML), LaTeX, Lua, Pascal, +SGML, Shell, Tcsh, Vim, XML. Other languages may already have support via +|filetype-plugin|s. + +To support a new language, see |matchit-newlang| below. + +DETAILS: *matchit-details* *matchit-parse* + +Here is an outline of what matchit.vim does each time you hit the "%" key. If +there are |backref|s in |b:match_words| then the first step is to produce a +version in which these back references have been eliminated; if there are no +|backref|s then this step is skipped. This step is called parsing. For +example, "\(foo\|bar\):end\1" is parsed to yield +"\(foo\|bar\):end\(foo\|bar\)". This can get tricky, especially if there are +nested groups. If debugging is turned on, the parsed version is saved as +|b:match_pat|. + + *matchit-choose* +Next, the script looks for a word on the current line that matches the pattern +just constructed. It includes the patterns from the 'matchpairs' option. +The goal is to do what you expect, which turns out to be a little complicated. +The script follows these rules: + + Insist on a match that ends on or after the cursor. + Prefer a match that includes the cursor position (that is, one that + starts on or before the cursor). + Prefer a match that starts as close to the cursor as possible. + Prefer a match in |b:match_words| to a match in 'matchpairs'. + If more than one pattern in |b:match_words| matches, choose the one + that is listed first. + +Examples: + + Suppose you > + :let b:match_words = '<:>,:' +< and hit "%" with the cursor on or before the "<" in "a is born". + The pattern '<' comes first, so it is preferred over '', which + also matches. If the cursor is on the "t", however, then '' is + preferred, because this matches a bit of text containing the cursor. + If the two groups of patterns were reversed then '<' would never be + preferred. + + Suppose you > + :let b:match_words = 'if:end if' +< (Note the space!) and hit "%" with the cursor at the end of "end if". + Then "if" matches, which is probably not what you want, but if the + cursor starts on the "end " then "end if" is chosen. (You can avoid + this problem by using a more complicated pattern.) + +If there is no match, the script falls back on the usual behavior of |%|. If +debugging is turned on, the matched bit of text is saved as |b:match_match| +and the cursor column of the start of the match is saved as |b:match_col|. + +Next, the script looks through |b:match_words| (original and parsed versions) +for the group and pattern that match. If debugging is turned on, the group is +saved as |b:match_ini| (the first pattern) and |b:match_tail| (the rest). If +there are |backref|s then, in addition, the matching pattern is saved as +|b:match_word| and a table of translations is saved as |b:match_table|. If +there are |backref|s, these are determined from the matching pattern and +|b:match_match| and substituted into each pattern in the matching group. + +The script decides whether to search forwards or backwards and chooses +arguments for the |searchpair()| function. Then, the cursor is moved to the +start of the match, and |searchpair()| is called. By default, matching +structures inside strings and comments are ignored. This can be changed by +setting |b:match_skip|. + +============================================================================== +2. Activation *matchit-activate* + +You can use this script as a plugin, by copying it to your plugin directory. +See |add-global-plugin| for instructions. You can also add a line to your +|vimrc| file, such as > + :source $VIMRUNTIME/macros/matchit.vim +or > + :runtime macros/matchit.vim +Either way, the script should start working the next time you start up Vim. + +The script does nothing unless it finds a |buffer-variable| named +|b:match_words|. The script contains autocommands that set this variable for +various file types: see |matchit-languages| above. For a new language, you +can add autocommands to the script or to your vimrc file, but the recommended +method is to add a line such as > + let b:match_words = '\:\' +to the |filetype-plugin| for your language. See |b:match_words| below for how +this variable is interpreted. + +TROUBLESHOOTING *matchit-troubleshoot* + +The script should work in most installations of Vim. It may not work if Vim +was compiled with a minimal feature set, for example if the |+syntax| option +was not enabled. If your Vim has support for syntax compiled in, but you do +not have |syntax| highlighting turned on, matchit.vim should work, but it may +fail to skip matching groups in comments and strings. If the |filetype| +mechanism is turned off, the |b:match_words| variable will probably not be +defined automatically. + +============================================================================== +3. Configuration *matchit-configure* + +There are several variables that govern the behavior of matchit.vim. Note +that these are variables local to the buffer, not options, so use |:let| to +define them, not |:set|. Some of these variables have values that matter; for +others, it only matters whether the variable has been defined. All of these +can be defined in the |filetype-plugin| or autocommand that defines +|b:match_words| or "on the fly." + +The main variable is |b:match_words|. It is described in the section below on +supporting a new language. + + *MatchError* *matchit-hl* *matchit-highlight* +MatchError is the highlight group for error messages from the script. By +default, it is linked to WarningMsg. If you do not want to be bothered by +error messages, you can define this to be something invisible. For example, +if you use the GUI version of Vim and your command line is normally white, you +can do > + :hi MatchError guifg=white guibg=white +< + *b:match_ignorecase* +If you > + :let b:match_ignorecase = 1 +then matchit.vim acts as if 'ignorecase' is set: for example, "end" and "END" +are equivalent. If you > + :let b:match_ignorecase = 0 +then matchit.vim treats "end" and "END" differently. (There will be no +b:match_infercase option unless someone requests it.) + + *b:match_debug* +Define b:match_debug if you want debugging information to be saved. See +|matchit-debug|, below. + + *b:match_skip* +If b:match_skip is defined, it is passed as the skip argument to +|searchpair()|. This controls when matching structures are skipped, or +ignored. By default, they are ignored inside comments and strings, as +determined by the |syntax| mechanism. (If syntax highlighting is turned off, +nothing is skipped.) You can set b:match_skip to a string, which evaluates to +a non-zero, numerical value if the match is to be skipped or zero if the match +should not be skipped. In addition, the following special values are +supported by matchit.vim: + s:foo becomes (current syntax item) =~ foo + S:foo becomes (current syntax item) !~ foo + r:foo becomes (line before cursor) =~ foo + R:foo becomes (line before cursor) !~ foo +(The "s" is meant to suggest "syntax", and the "r" is meant to suggest +"regular expression".) + +Examples: + + You can get the default behavior with > + :let b:match_skip = 's:comment\|string' +< + If you want to skip matching structures unless they are at the start + of the line (ignoring whitespace) then you can > + :let b:match_skip = 'R:^\s*' +< Do not do this if strings or comments can span several lines, since + the normal syntax checking will not be done if you set b:match_skip. + + In LaTeX, since "%" is used as the comment character, you can > + :let b:match_skip = 'r:%' +< Unfortunately, this will skip anything after "\%", an escaped "%". To + allow for this, and also "\\%" (an excaped backslash followed by the + comment character) you can > + :let b:match_skip = 'r:\(^\|[^\\]\)\(\\\\\)*%' +< + See the $VIMRUNTIME/ftplugin/vim.vim for an example that uses both + syntax and a regular expression. + +============================================================================== +4. Supporting a New Language *matchit-newlang* + *b:match_words* +In order for matchit.vim to support a new language, you must define a suitable +pattern for |b:match_words|. You may also want to set some of the +|matchit-configure| variables, as described above. If your language has a +complicated syntax, or many keywords, you will need to know something about +Vim's |regular-expression|s. + +The format for |b:match_words| is similar to that of the 'matchpairs' option: +it is a comma (,)-separated list of groups; each group is a colon(:)-separated +list of patterns (regular expressions). Commas and backslashes that are part +of a pattern should be escaped with backslashes ('\:' and '\,'). It is OK to +have only one group; the effect is undefined if a group has only one pattern. +A simple example is > + :let b:match_words = '\:\,' + \ . '\:\:\:\' +(In Vim regular expressions, |\<| and |\>| denote word boundaries. Thus "if" +matches the end of "endif" but "\" does not.) Then banging on the "%" +key will bounce the cursor between "if" and the matching "endif"; and from +"while" to any matching "continue" or "break", then to the matching "endwhile" +and back to the "while". It is almost always easier to use |literal-string|s +(single quotes) as above: '\' rather than "\\" and so on. + +Exception: If the ":" character does not appear in b:match_words, then it is +treated as an expression to be evaluated. For example, > + :let b:match_words = 'GetMatchWords()' +allows you to define a function. This can return a different string depending +on the current syntax, for example. + +Once you have defined the appropriate value of |b:match_words|, you will +probably want to have this set automatically each time you edit the +appropriate file type. The recommended way to do this is by adding the +definition to a |filetype-plugin| file. + +Tips: Be careful that your initial pattern does not match your final pattern. +See the example above for the use of word-boundary expressions. It is usually +better to use ".\{-}" (as many as necessary) instead of ".*" (as many as +possible). See |\{-|. For example, in the string "label", "<.*>" +matches the whole string whereas "<.\{-}>" and "<[^>]*>" match "" and +"". + + *matchit-spaces* *matchit-s:notend* +If "if" is to be paired with "end if" (Note the space!) then word boundaries +are not enough. Instead, define a regular expression s:notend that will match +anything but "end" and use it as follows: > + :let s:notend = '\%(\:\' +< *matchit-s:sol* +This is a simplified version of what is done for Ada. The s:notend is a +|script-variable|. Similarly, you may want to define a start-of-line regular +expression > + :let s:sol = '\%(^\|;\)\s*' +if keywords are only recognized after the start of a line or after a +semicolon (;), with optional white space. + + *matchit-backref* *matchit-\1* +In any group, the expressions |\1|, |\2|, ..., |\9| refer to parts of the +INITIAL pattern enclosed in |\(|escaped parentheses|\)|. These are referred +to as back references, or backrefs. For example, > + :let b:match_words = '\:\(h\)\1\>' +means that "bo" pairs with "ho" and "boo" pairs with "hoo" and so on. Note +that "\1" does not refer to the "\(h\)" in this example. If you have +"\(nested \(parentheses\)\) then "\d" refers to the d-th "\(" and everything +up to and including the matching "\)": in "\(nested\(parentheses\)\)", "\1" +refers to everything and "\2" refers to "\(parentheses\)". If you use a +variable such as |s:notend| or |s:sol| in the previous paragraph then remember +to count any "\(" patterns in this variable. You do not have to count groups +defined by |\%(\)|. + +It should be possible to resolve back references from any pattern in the +group. For example, > + :let b:match_words = '\(foo\)\(bar\):more\1:and\2:end\1\2' +would not work because "\2" cannot be determined from "morefoo" and "\1" +cannot be determined from "andbar". On the other hand, > + :let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1' +should work (and have the same effect as "foobar:barfoo:endfoobar"), although +this has not been thoroughly tested. + +You can use |zero-width| patterns such as |\@<=| and |\zs|. (The latter has +not been thouroughly tested in matchit.vim.) For example, if the keyword "if" +must occur at the start of the line, with optional white space, you might use +the pattern "\(^\s*\)\@<=if" so that the cursor will end on the "i" instead of +at the start of the line. For another example, if HTML had only one tag then +one could > + :let b:match_words = '<:>,<\@<=tag>:<\@<=/tag>' +so that "%" can bounce between matching "<" and ">" pairs or (starting on +"tag" or "/tag") between matching tags. Without the |\@<=|, the script would +bounce from "tag" to the "<" in "", and another "%" would not take you +back to where you started. + +DEBUGGING *matchit-debug* *:MatchDebug* + +If you are having trouble figuring out the appropriate definition of +|b:match_words| then you can take advantage of the same information I use when +debugging the script. This is especially true if you are not sure whether +your patterns or my script are at fault! To make this more convenient, I have +made the command :MatchDebug, which defines the variable |b:match_debug| and +creates a Matchit menu. This menu makes it convenient to check the values of +the variables described below. You will probably also want to read +|matchit-details| above. + +Defining the variable |b:match_debug| causes the script to set the following +variables, each time you hit the "%" key. Several of these are only defined +if |b:match_words| includes |backref|s. + + *b:match_pat* +The b:match_pat variable is set to |b:match_words| with |backref|s parsed. + *b:match_match* +The b:match_match variable is set to the bit of text that is recognized as a +match. + *b:match_col* +The b:match_col variable is set to the cursor column of the start of the +matching text. + *b:match_wholeBR* +The b:match_wholeBR variable is set to the comma-separated group of patterns +that matches, with |backref|s unparsed. + *b:match_iniBR* +The b:match_iniBR variable is set to the first pattern in |b:match_wholeBR|. + *b:match_ini* +The b:match_ini variable is set to the first pattern in |b:match_wholeBR|, +with |backref|s resolved from |b:match_match|. + *b:match_tail* +The b:match_tail variable is set to the remaining patterns in +|b:match_wholeBR|, with |backref|s resolved from |b:match_match|. + *b:match_word* +The b:match_word variable is set to the pattern from |b:match_wholeBR| that +matches |b:match_match|. + *b:match_table* +The back reference '\'.d refers to the same thing as '\'.b:match_table[d] in +|b:match_word|. + +============================================================================== +5. Known Bugs and Limitations *matchit-bugs* + +Just because I know about a bug does not mean that it is on my todo list. I +try to respond to reports of bugs that cause real problems. If it does not +cause serious problems, or if there is a work-around, a bug may sit there for +a while. Moral: if a bug (known or not) bothers you, let me know. + +The various |:vmap|s defined in the script (%, |g%|, |[%|, |]%|, |a%|) may +have undesired effects in Select mode |Select-mode-mapping|. At least, if you +want to replace the selection with any character in "ag%[]" there will be a +pause of |'updatetime'| first. + +It would be nice if "\0" were recognized as the entire pattern. That is, it +would be nice if "foo:\end\0" had the same effect as "\(foo\):\end\1". I may +try to implement this in a future version. (This is not so easy to arrange as +you might think!) + +============================================================================== +vim:tw=78:fo=tcq2: diff --git a/vim/doc/taglist.txt b/vim/doc/taglist.txt new file mode 100644 index 0000000..6a62b39 --- /dev/null +++ b/vim/doc/taglist.txt @@ -0,0 +1,1501 @@ +*taglist.txt* Plugin for browsing source code + +Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com) +For Vim version 6.0 and above +Last change: 2007 May 24 + +1. Overview |taglist-intro| +2. Taglist on the internet |taglist-internet| +3. Requirements |taglist-requirements| +4. Installation |taglist-install| +5. Usage |taglist-using| +6. Options |taglist-options| +7. Commands |taglist-commands| +8. Global functions |taglist-functions| +9. Extending |taglist-extend| +10. FAQ |taglist-faq| +11. License |taglist-license| +12. Todo |taglist-todo| + +============================================================================== + *taglist-intro* +1. Overview~ + +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: + + * Displays the tags (functions, classes, structures, variables, etc.) + defined in a file in a vertically or horizontally split Vim window. + * In GUI Vim, optionally displays the tags in the Tags drop-down menu and + in the popup menu. + * 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. + * Groups the tags by their type and displays them in a foldable tree. + * 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 chronological order. + * 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 functions to display the current tag name in the Vim status + line or the window title bar. + * The list of tags and files in the taglist can be saved and + restored across Vim sessions. + * Provides commands to get the name and prototype of the current tag. + * 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* +2. Taglist on the internet~ + +The home page of the taglist plugin is at: +> + http://vim-taglist.sourceforge.net/ +< +You can subscribe to the taglist mailing list to post your questions or +suggestions for improvement or to send bug reports. Visit the following page +for subscribing to the mailing list: +> + http://groups.yahoo.com/group/taglist +< +============================================================================== + *taglist-requirements* +3. Requirements~ + +The taglist plugin requires the following: + + * Vim version 6.0 and above + * Exuberant ctags 5.0 and above + +The taglist plugin will work on all the platforms where the exuberant ctags +utility and Vim are supported (this includes MS-Windows and Unix based +systems). + +The taglist plugin relies on the exuberant ctags utility to dynamically +generate the tag listing. The exuberant ctags utility must be installed in +your system to use this plugin. The exuberant ctags utility is shipped with +most of the Linux distributions. You can download the exuberant ctags utility +from +> + http://ctags.sourceforge.net +< +The taglist plugin doesn't use or create a tags file and there is no need to +create a tags file 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: +> + filetype on +< +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. 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 + + Refer to the |add-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/vimfiles/doc + 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 one of the directories in + the PATH environment variable, 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 ":TlistToggle" command to open/close the taglist + window. You can use the ":help taglist" command to get more information + about using the taglist plugin. + +To uninstall the taglist plugin, remove the plugin/taglist.vim and +doc/taglist.txt files from the $HOME/.vim or $HOME/vimfiles directory. + +============================================================================== + *taglist-using* +5. Usage~ + +The taglist plugin can be used in several different ways. + +1. You can keep the taglist window open during the entire editing session. On + opening the taglist window, the tags defined in all the files in the Vim + buffer list will be displayed in the taglist window. As you edit files, the + tags defined in them will be added to the taglist window. You can select a + tag from the taglist window and jump to it. The current tag will be + highlighted in the taglist window. You can close the taglist window when + you no longer need the window. +2. You can configure the taglist plugin to process the tags defined in all the + edited files always. In this configuration, even if the taglist window is + closed and the taglist menu is not displayed, the taglist plugin will + processes the tags defined in newly edited files. You can then open the + taglist window only when you need to select a tag and then automatically + close the taglist window after selecting the tag. +3. You can configure the taglist plugin to display only the tags defined in + the current file in the taglist window. By default, the taglist plugin + displays the tags defined in all the files in the Vim buffer list. As you + switch between files, the taglist window will be refreshed to display only + the tags defined in the current file. +4. In GUI Vim, you can use the Tags pull-down and popup menu created by the + taglist plugin to display the tags defined in the current file and select a + tag to jump to it. You can use the menu without opening the taglist window. + By default, the Tags menu is disabled. +5. You can configure the taglist plugin to display the name of the current tag + in the Vim window status line or in the Vim window title bar. For this to + work without the taglist window or menu, you need to configure the taglist + plugin to process the tags defined in a file always. +6. You can save the tags defined in multiple files to a taglist session file + and load it when needed. You can also configure the taglist plugin to not + update the taglist window when editing new files. You can then manually add + files to the taglist window. + +Opening the taglist window~ +You can open the taglist window using the ":TlistOpen" or the ":TlistToggle" +commands. The ":TlistOpen" command opens the taglist window and jumps to it. +The ":TlistToggle" command opens or closes (toggle) the taglist window and the +cursor remains in the current window. If the 'Tlist_GainFocus_On_ToggleOpen' +variable is set to 1, then the ":TlistToggle" command opens the taglist window +and moves the cursor to the taglist window. + +You can map a key to invoke these commands. For example, the following command +creates a normal mode mapping for the key to toggle the taglist window. +> + nnoremap :TlistToggle +< +Add the above mapping to your ~/.vimrc or $HOME/_vimrc file. + +To automatically open the taglist window on Vim startup, set the +'Tlist_Auto_Open' variable to 1. + +You can also open the taglist window on startup using the following command +line: +> + $ vim +TlistOpen +< +Closing the taglist window~ +You can close the taglist window from the taglist window by pressing 'q' or +using the Vim ":q" command. You can also use any of the Vim window commands to +close the taglist window. Invoking the ":TlistToggle" command when the taglist +window is opened, closes the taglist window. You can also use the +":TlistClose" command to close the taglist window. + +To automatically close the taglist window when a tag or file is selected, you +can set the 'Tlist_Close_On_Select' variable to 1. To exit Vim when only the +taglist window is present, set the 'Tlist_Exit_OnlyWindow' variable to 1. + +Jumping to a tag or a file~ +You can select a tag in the taglist window either by pressing the key +or by double clicking the tag name using the mouse. To jump to a tag on a +single mouse click set the 'Tlist_Use_SingleClick' variable to 1. + +If the selected file is already opened in a window, then the cursor is moved +to that window. If the file is not currently opened in a window then the file +is opened in the window used by the taglist plugin to show the previously +selected file. If there are no usable windows, then the file is opened in a +new window. The file is not opened in special windows like the quickfix +window, preview window and windows containing buffer with the 'buftype' option +set. + +To jump to the tag in a new window, press the 'o' key. To open the file in the +previous window (Ctrl-W_p) use the 'P' key. You can press the 'p' key to jump +to the tag but still keep the cursor in the taglist window (preview). + +To open the selected file in a tab, use the 't' key. If the file is already +present in a tab then the cursor is moved to that tab otherwise the file is +opened in a new tab. To jump to a tag in a new tab press Ctrl-t. The taglist +window is automatically opened in the newly created tab. + +Instead of jumping to a tag, you can open a file by pressing the 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. When you reach the first or last file, the search +wraps around and the jumps to the next/previous file. + +Highlighting the current tag~ +The taglist plugin automatically highlights the name of the current tag in the +taglist window. The Vim |CursorHold| autocmd event is used for this. If the +current tag name is not visible in the taglist window, then the taglist window +contents are scrolled to make that tag name visible. You can also use the +":TlistHighlightTag" command to force the highlighting of the current tag. + +The tag name is highlighted if no activity is performed for |'updatetime'| +milliseconds. The default value for this Vim option is 4 seconds. To avoid +unexpected problems, you should not set the |'updatetime'| option to a very +low value. + +To disable the automatic highlighting of the current tag name in the taglist +window, set the 'Tlist_Auto_Highlight_Tag' variable to zero. + +When entering a Vim buffer/window, the taglist plugin automatically highlights +the current tag in that buffer/window. If you like to disable the automatic +highlighting of the current tag when entering a buffer, set the +'Tlist_Highlight_Tag_On_BufEnter' variable to zero. + +Adding files to the taglist~ +When the taglist window is opened, all the files in the Vim buffer list are +processed and the supported files are added to the taglist. When you edit a +file in Vim, the taglist plugin automatically processes this file and adds it +to the taglist. If you close the taglist window, the tag information in the +taglist is retained. + +To process files even when the taglist window is not open, set the +'Tlist_Process_File_Always' variable to 1. + +You can manually add multiple files to the taglist without opening them using +the ":TlistAddFiles" and the ":TlistAddFilesRecursive" commands. + +For example, to add all the C files in the /my/project/dir directory to the +taglist, you can use the following command: +> + :TlistAddFiles /my/project/dir/*.c +< +Note that when adding several files with a large number of tags or a large +number of files, it will take several seconds to several minutes for the +taglist plugin to process all the files. You should not interrupt the taglist +plugin by pressing . + +You can recursively add multiple files from a directory tree using the +":TlistAddFilesRecursive" command: +> + :TlistAddFilesRecursive /my/project/dir *.c +< +This command takes two arguments. The first argument specifies the directory +from which to recursively add the files. The second optional argument +specifies the wildcard matching pattern for selecting the files to add. The +default pattern is * and all the files are added. + +Displaying tags for only one file~ +The taglist window displays the tags for all the files in the Vim buffer list +and all the manually added files. To display the tags for only the current +active buffer, set the 'Tlist_Show_One_File' variable to 1. + +Removing files from the taglist~ +You can remove a file from the taglist window, 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 will no longer be displayed in the taglist window in the current +Vim session. To again display the tags for the file, open the file in a Vim +window and then use the ":TlistUpdate" command or use ":TlistAddFiles" command +to add the file to the taglist. + +When a buffer is removed from the Vim buffer list using the ":bdelete" or the +":bwipeout" command, the taglist is updated to remove the stored information +for this buffer. + +Updating the tags displayed for a file~ +The taglist plugin keeps track of the modification time of a file. When the +modification time changes (the file is modified), the taglist plugin +automatically updates the tags listed for that file. The modification time of +a file is checked when you enter a window containing that file or when you +load that file. + +You can also 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 automatically updates 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. + +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. + +Controlling the taglist updates~ +To disable the automatic processing of new files or modified files, you can +set the 'Tlist_Auto_Update' variable to zero. When this variable is set to +zero, the taglist is updated only when you use the ":TlistUpdate" command or +the ":TlistAddFiles" or the ":TlistAddFilesRecursive" commands. You can use +this option to control which files are added to the taglist. + +You can use the ":TlistLock" command to lock the taglist contents. After this +command is executed, new files are not automatically added to the taglist. +When the taglist is locked, you can use the ":TlistUpdate" command to add the +current file or the ":TlistAddFiles" or ":TlistAddFilesRecursive" commands to +add new files to the taglist. To unlock the taglist, use the ":TlistUnlock" +command. + +Displaying the tag prototype~ +To display the prototype of the tag under the cursor in the taglist window, +press the space bar. If you place the cursor on a tag name in the taglist +window, then the tag prototype is displayed at the Vim status line after +|'updatetime'| milliseconds. The default value for the |'updatetime'| Vim +option is 4 seconds. + +You can get the name and prototype of a tag without opening the taglist window +and the taglist menu using the ":TlistShowTag" and the ":TlistShowPrototype" +commands. These commands will work only if the current file is already present +in the taglist. To use these commands without opening the taglist window, set +the 'Tlist_Process_File_Always' variable to 1. + +You can use the ":TlistShowTag" command to display the name of the tag at or +before the specified line number in the specified file. If the file name and +line number are not supplied, then this command will display the name of the +current tag. For example, +> + :TlistShowTag + :TlistShowTag myfile.java 100 +< +You can use the ":TlistShowPrototype" command to display the prototype of the +tag at or before the specified line number in the specified file. If the file +name and the line number are not supplied, then this command will display the +prototype of the current tag. For example, +> + :TlistShowPrototype + :TlistShowPrototype myfile.c 50 +< +In the taglist window, when the mouse is moved over a tag name, the tag +prototype is displayed in a balloon. This works only in GUI versions where +balloon evaluation is supported. + +Taglist window contents~ +The taglist window contains the tags defined in various files in the taglist +grouped by the filename and by the tag type (variable, function, class, etc.). +For tags with scope information (like class members, structures inside +structures, etc.), the scope information is displayed in square brackets "[]" +after the tag name. + +The contents of the taglist buffer/window are managed by the taglist plugin. +The |'filetype'| for the taglist buffer is set to 'taglist'. 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, close the taglist +window and reopen it. + +Opening and closing the tag and file tree~ +In the taglist window, the tag names are 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 folds using the '=' key. You should not manually +create or delete the folds in the taglist window. + +To automatically close the fold for the inactive files/buffers and open only +the fold for the current buffer in the taglist window, set the +'Tlist_File_Fold_Auto_Close' variable to 1. + +Sorting the tags for a file~ +The tags displayed in the taglist window can be sorted either by their name or +by their chronological order. The default sorting method is by the order in +which the tags appear in a file. You can change the default sort method by +setting the 'Tlist_Sort_Type' variable to either "name" or "order". 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. + +Zooming in and out of the taglist window~ +You can press the 'x' key in the taglist window to maximize the taglist +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. + + *taglist-session* +Taglist Session~ +A taglist session refers to the group of files and their tags stored in the +taglist in a Vim session. + +You can save and restore a taglist session (and all the displayed tags) using +the ":TlistSessionSave" and ":TlistSessionLoad" commands. + +To save the information about the tags and files in the taglist to a file, use +the ":TlistSessionSave" command and specify the filename: +> + :TlistSessionSave +< +To load a saved taglist session, use the ":TlistSessionLoad" command: > + + :TlistSessionLoad +< +When you load a taglist session file, the tags stored in the file will be +added to the tags already stored in the taglist. + +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 +for multiple files. + +You can create more than one taglist session file for multiple groups of +files. + +Displaying the 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 Vim |'statusline'| option. + +Changing the taglist window highlighting~ +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 + TagListTitle - Used for tag titles + TagListComment - Used for comments + TagListFileName - Used for filenames + +By default, these highlight groups are linked to the standard Vim highlight +groups. If you want to change the colors used for these highlight groups, +prefix the highlight group name with 'My' and define it in your .vimrc or +.gvimrc file: MyTagListTagName, MyTagListTagScope, MyTagListTitle, +MyTagListComment and MyTagListFileName. For example, to change the colors +used for tag names, you can use the following command: +> + :highlight MyTagListTagName guifg=blue ctermfg=blue +< +Controlling the taglist window~ +To use a horizontally split taglist window, instead of a vertically split +window, set the 'Tlist_Use_Horiz_Window' variable to 1. + +To use a vertically split taglist window on the rightmost side of the Vim +window, set the 'Tlist_Use_Right_Window' variable to 1. + +You can specify the width of the vertically split taglist window, by setting +the 'Tlist_WinWidth' variable. You can specify the height of the horizontally +split taglist window, by setting the 'Tlist_WinHeight' variable. + +When opening a vertically split taglist window, the Vim window width is +increased to accommodate the new taglist window. When the taglist window is +closed, the Vim window is reduced. To disable this, set the +'Tlist_Inc_Winwidth' variable to zero. + +To reduce the number of empty lines in the taglist window, set the +'Tlist_Compact_Format' variable to 1. + +To not display the Vim fold column in the taglist window, set the +'Tlist_Enable_Fold_Column' variable to zero. + +To display the tag prototypes instead of the tag names in the taglist window, +set the 'Tlist_Display_Prototype' variable to 1. + +To not display the scope of the tags next to the tag names, set the +'Tlist_Display_Tag_Scope' variable to zero. + + *taglist-keys* +Taglist window key list~ +The following table lists the description of the keys that can be used +in the taglist window. + + Key Description~ + + Jump to the location where the tag under cursor is + defined. + o Jump to the location where the tag under cursor is + defined in a new window. + P Jump to the tag in the previous (Ctrl-W_p) window. + p Display the tag definition in the file window and + keep the cursor in the taglist window itself. + t Jump to the tag in a new tab. If the file is already + opened in a tab, move to that tab. + Ctrl-t Jump to the tag in a new tab. + Display the prototype of the tag under the cursor. + For file names, display the full path to the file, + file type and the number of tags. For tag types, display the + tag type and the number of tags. + u Update the tags listed in the taglist window + s Change the sort order of the tags (by name or by order) + d Remove the tags for the file under the cursor + x Zoom-in or Zoom-out the taglist window + + Open a fold + - Close a fold + * 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 all the tags +defined in a file are of the same type (e.g. functions), then the sub-menu is +not used. + +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, +to use the file explorer plugin and the taglist plugin at the same time, use +the following setting: > + + let winManagerWindowLayout = 'FileExplorer|TagList' +< +Getting help~ +If you have installed the taglist help file (this file), then you can use the +Vim ":help taglist-" command to get help on the various taglist +topics. + +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 is removed from the taglist window. + + *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. + +You can specify a file name to the ":TlistDebug" command to log the debug +messages to a file. Otherwise, the debug messages are stored in a script-local +variable. In the later case, to minimize memory usage, only the last 3000 +characters from the debug messages are stored. + +============================================================================== + *taglist-options* +6. Options~ + +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 +should use the |:let| command in your .vimrc file to change the setting of any +of these variables. + +The configurable taglist variables are listed below. For a detailed +description of these variables refer to the text below this table. + +|'Tlist_Auto_Highlight_Tag'| Automatically highlight the current tag in the + taglist. +|'Tlist_Auto_Open'| Open the taglist window when Vim starts. +|'Tlist_Auto_Update'| Automatically update the taglist to include + newly edited files. +|'Tlist_Close_On_Select'| Close the taglist window when a file or tag is + selected. +|'Tlist_Compact_Format'| Remove extra information and blank lines from + the taglist window. +|'Tlist_Ctags_Cmd'| Specifies the path to the ctags utility. +|'Tlist_Display_Prototype'| Show prototypes and not tags in the taglist + window. +|'Tlist_Display_Tag_Scope'| Show tag scope next to the tag name. +|'Tlist_Enable_Fold_Column'| Show the fold indicator column in the taglist + window. +|'Tlist_Exit_OnlyWindow'| Close Vim if the taglist is the only window. +|'Tlist_File_Fold_Auto_Close'| Close tag folds for inactive buffers. +|'Tlist_GainFocus_On_ToggleOpen'| + Jump to taglist window on open. +|'Tlist_Highlight_Tag_On_BufEnter'| + On entering a buffer, automatically highlight + the current tag. +|'Tlist_Inc_Winwidth'| Increase the Vim window width to accommodate + the taglist window. +|'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_Process_File_Always'| Process files even when the taglist window is + closed. +|'Tlist_Show_Menu'| Display the tags menu. +|'Tlist_Show_One_File'| Show tags for the current buffer only. +|'Tlist_Sort_Type'| Sort method used for arranging the tags. +|'Tlist_Use_Horiz_Window'| Use a horizontally split window for the + taglist window. +|'Tlist_Use_Right_Window'| Place the taglist window on the right side. +|'Tlist_Use_SingleClick'| Single click on a tag jumps to it. +|'Tlist_WinHeight'| Horizontally split taglist window height. +|'Tlist_WinWidth'| Vertically split taglist window width. + + *'Tlist_Auto_Highlight_Tag'* +Tlist_Auto_Highlight_Tag~ +The taglist plugin will automatically highlight the current tag in the taglist +window. If you want to disable this, then you 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 +< +With the above variable set to 1, you can use the ":TlistHighlightTag" command +to highlight the current tag. + + *'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 zero and +the taglist window will not be opened automatically on Vim startup. +> + let Tlist_Auto_Open = 1 +< +The taglist window is opened only when a supported type of file is opened on +Vim startup. For example, if you open text files, then the taglist window will +not be opened. + + *'Tlist_Auto_Update'* +Tlist_Auto_Update~ +When a new file is edited, the tags defined in the file are automatically +processed and added to the taglist. To stop adding new files to the taglist, +set the 'Tlist_Auto_Update' variable to zero. By default, this variable is set +to 1. +> + let Tlist_Auto_Update = 0 +< +With the above variable set to 1, you can use the ":TlistUpdate" command to +add the tags defined in the current file to the taglist. + + *'Tlist_Close_On_Select'* +Tlist_Close_On_Select~ +If you want to close the taglist window when a file or tag is selected, then +set the 'Tlist_Close_On_Select' variable to 1. By default, this variable is +set zero and when you select a tag or file from the taglist window, the window +is not closed. +> + let Tlist_Close_On_Select = 1 +< + *'Tlist_Compact_Format'* +Tlist_Compact_Format~ +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 1 to get a compact display. +> + let Tlist_Compact_Format = 1 +< + *'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, exctags, 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. Examples: +> + let Tlist_Ctags_Cmd = 'd:\tools\ctags.exe' + let Tlist_Ctags_Cmd = '/usr/local/bin/ctags' +< + *'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 zero and only tag names +will be displayed. +> + 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 zero. By default, +this variable is set to 1 and the tag scopes will be displayed. +> + let Tlist_Display_Tag_Scope = 0 +< + *'Tlist_Enable_Fold_Column'* +Tlist_Enable_Fold_Column~ +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 zero. +> + let Tlist_Enable_Fold_Column = 1 +< + *'Tlist_Exit_OnlyWindow'* +Tlist_Exit_OnlyWindow~ +If you want to exit Vim if only the taglist window is currently opened, then +set the 'Tlist_Exit_OnlyWindow' variable to 1. By default, this variable is +set to zero and the Vim instance will not be closed if only the taglist window +is present. +> + 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 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, +the tags tree for the current buffer is automatically opened and for all the +other buffers is closed. +> + let Tlist_File_Fold_Auto_Close = 1 +< + *'Tlist_GainFocus_On_ToggleOpen'* +Tlist_GainFocus_On_ToggleOpen~ +When the taglist window is opened using the ':TlistToggle' command, this +option controls whether the cursor is moved to the taglist window or remains +in the current window. By default, this option is set to 0 and the cursor +remains in the current window. When this variable is set to 1, the cursor +moves to the taglist window after opening the taglist window. +> + let Tlist_GainFocus_On_ToggleOpen = 1 +< + *'Tlist_Highlight_Tag_On_BufEnter'* +Tlist_Highlight_Tag_On_BufEnter~ +When you enter a Vim buffer/window, the current tag in that buffer/window is +automatically highlighted in the taglist window. If the current tag name is +not visible in the taglist window, then the taglist window contents are +scrolled to make that tag name visible. If you like to disable the automatic +highlighting of the current tag when entering a buffer, you can set the +'Tlist_Highlight_Tag_On_BufEnter' variable to zero. The default setting for +this variable is 1. +> + let Tlist_Highlight_Tag_On_BufEnter = 0 +< + *'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 is 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 zero. +CAUTION: If you are using the MS-Windows version of Vim in a MS-DOS command +window then you must set this variable to zero, otherwise the system may hang +due to a Vim limitation (explained in :help win32-problems) +> + let Tlist_Inc_Winwidth = 0 +< + *'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. The default value for this variable is +10. Change the 'Tlist_Max_Tag_Length' setting if you want to include more or +less characters: +> + let Tlist_Max_Tag_Length = 10 +< + *'Tlist_Process_File_Always'* +Tlist_Process_File_Always~ +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 +< +To use the ":TlistShowTag" and the ":TlistShowPrototype" commands without the +taglist window and the taglist menu, you should set this variable to 1. + + *'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 1: +> + let Tlist_Show_Menu = 1 +< + *'Tlist_Show_One_File'* +Tlist_Show_One_File~ +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 +< + *'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 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 +use a horizontally split window. +> + 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 1: +> + let Tlist_Use_Right_Window = 1 +< + *'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 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 +< +Due to a bug in Vim, if you set 'Tlist_Use_SingleClick' to 1 and try to resize +the taglist window using the mouse, then Vim will crash. This problem is fixed +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_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 +< +The |'winfixheight'| option is set for the taglist window, to maintain the +height of the taglist window, when new Vim windows are opened and existing +windows are closed. + + *'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 +< +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. + +When new Vim windows are opened and existing windows are closed, the taglist +plugin will try to maintain the width of the taglist window to the size +specified by the 'Tlist_WinWidth' variable. + +============================================================================== + *taglist-commands* +7. Commands~ + +The taglist plugin provides the following ex-mode commands: + +|:TlistAddFiles| Add multiple files to the taglist. +|:TlistAddFilesRecursive| + Add files recursively to the taglist. +|:TlistClose| Close the taglist window. +|:TlistDebug| Start logging of taglist debug messages. +|:TlistLock| Stop adding new files to the taglist. +|:TlistMessages| Display the logged taglist plugin debug messages. +|:TlistOpen| Open and jump to the taglist window. +|:TlistSessionSave| Save the information about files and tags in the + taglist to a session file. +|:TlistSessionLoad| Load the information about files and tags stored + in a session file to taglist. +|:TlistShowPrototype| Display the prototype of the tag at or before the + specified line number. +|:TlistShowTag| Display the name of the tag defined at or before the + specified line number. +|:TlistHighlightTag| Highlight the current tag in the taglist window. +|:TlistToggle| Open or close (toggle) the taglist window. +|:TlistUndebug| Stop logging of taglist debug messages. +|:TlistUnlock| Start adding new files to the taglist. +|:TlistUpdate| Update the tags for the current buffer. + + *:TlistAddFiles* +:TlistAddFiles {file(s)} [file(s) ...] + Add one or more specified files to the taglist. You can + specify multiple filenames using wildcards. To specify a + file name with space character, you should escape the space + character with a backslash. + Examples: +> + :TlistAddFiles *.c *.cpp + :TlistAddFiles file1.html file2.html +< + If you specify a large number of files, then it will take some + time for the taglist plugin to process all of them. The + specified files will not be edited in a Vim window and will + not be added to the Vim buffer list. + + *:TlistAddFilesRecursive* +:TlistAddFilesRecursive {directory} [ {pattern} ] + Add files matching {pattern} recursively from the specified + {directory} to the taglist. If {pattern} is not specified, + then '*' is assumed. To specify the current directory, use "." + for {directory}. To specify a directory name with space + character, you should escape the space character with a + backslash. + Examples: +> + :TlistAddFilesRecursive myproject *.java + :TlistAddFilesRecursive smallproject +< + If large number of files are present in the specified + directory tree, then it will take some time for the taglist + plugin to process all of them. + + *:TlistClose* +:TlistClose Close the taglist window. This command can be used from any + one of the Vim windows. + + *:TlistDebug* +:TlistDebug [filename] + Start logging of debug messages from the taglist plugin. + If {filename} is specified, then the debug messages are stored + in the specified file. Otherwise, the debug messages are + stored in a script local variable. If the file {filename} is + already present, then it is overwritten. + + *:TlistLock* +:TlistLock + Lock the taglist and don't process new files. After this + command is executed, newly edited files will not be added to + the taglist. + + *:TlistMessages* +:TlistMessages + Display the logged debug messages from the taglist plugin + in a window. This command works only when logging to a + script-local variable. + + *:TlistOpen* +:TlistOpen Open and jump to the taglist window. Creates the taglist + window, if the window is not opened currently. After executing + this command, the cursor is moved to the taglist window. When + the taglist window is opened for the first time, all the files + in the buffer list are processed and the tags defined in them + are displayed in the taglist window. + + *:TlistSessionSave* +:TlistSessionSave {filename} + Saves the information about files and tags in the taglist to + the specified file. This command can be used to save and + restore the taglist contents across Vim sessions. + + *:TlistSessionLoad* +:TlistSessionLoad {filename} + Load the information about files and tags stored in the + specified session file to the taglist. + + *:TlistShowPrototype* +:TlistShowPrototype [filename] [linenumber] + Display the prototype of the tag at or before 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. + + *:TlistShowTag* +:TlistShowTag [filename] [linenumber] + Display the name of the tag defined at or before 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. + + *:TlistHighlightTag* +:TlistHighlightTag + 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. + + *:TlistToggle* +:TlistToggle 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. After executing this command, the cursor + is not moved from the current window to the taglist window. + + *:TlistUndebug* +:TlistUndebug + Stop logging of debug messages from the taglist plugin. + + *:TlistUnlock* +:TlistUnlock + Unlock the taglist and start processing newly edited files. + + *:TlistUpdate* +:TlistUpdate Update the tags information for the current buffer. This + command can be used to re-process the current file/buffer and + get the tags information. As the taglist plugin uses the file + saved in the disk (instead of the file displayed in a Vim + buffer), you should save a modified buffer before you update + the taglist. Otherwise the listed tags will not include the + new tags created in the buffer. You can use this command even + when the taglist window is not opened. + +============================================================================== + *taglist-functions* +8. Global functions~ + +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()| Update the tags for the specified file +|Tlist_Get_Tag_Prototype_By_Line()| Return the prototype of the tag at or + before the specified line number in the + specified file. +|Tlist_Get_Tagname_By_Line()| Return the name of the tag at or + before the specified line number in + the specified file. +|Tlist_Set_App()| Set the name of the application + controlling the taglist window. + + *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. + + *Tlist_Get_Tag_Prototype_By_Line()* +Tlist_Get_Tag_Prototype_By_Line([{filename}, {linenumber}]) + Return the prototype of the tag at or before 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_Tagname_By_Line()* +Tlist_Get_Tagname_By_Line([{filename}, {linenumber}]) + Return the name of the tag at or before 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()* +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. + +============================================================================== + *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. + +You can extend the taglist plugin to add support for new languages and also +modify the support for the above listed languages. + +You should NOT make modifications to the taglist plugin script file to add +support for new languages. You will lose these changes when you upgrade to the +next version of the taglist plugin. Instead you should follow the below +described instructions to extend the taglist plugin. + +You can extend the taglist plugin by setting variables in the .vimrc or _vimrc +file. The name of these variables depends on the language name and is +described below. + +Modifying support for an existing language~ +To modify the support for an already supported language, you have to set the +tlist_xxx_settings variable in the ~/.vimrc or $HOME/_vimrc file. Replace xxx +with the Vim filetype name for the language file. For example, to modify the +support for the perl language files, you have to set the tlist_perl_settings +variable. To modify the support for java files, you have to set the +tlist_java_settings variable. + +To determine the filetype name used by Vim for a file, use the following +command in the buffer containing the file: + + :set filetype + +The above command will display the Vim filetype for the current buffer. + +The format of the value set in the tlist_xxx_settings variable is + + ;flag1:name1;flag2:name2;flag3:name3 + +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 file. 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'. To get the list of language names +supported by exuberant ctags, use the following command: + + $ ctags --list-maps=all + +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. To get the list of flags supported by +exuberant ctags for the various languages use the following command: + + $ ctags --list-kinds=all + +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 line to your .vimrc file: + + 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 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 tags, use + + 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 default options used by the taglist plugin for a particular file type. To +add to the options used by the taglist plugin for a language, copy the option +values from the taglist plugin file to your .vimrc file and modify it. + +Adding support for a new language~ +If you want to add support for a new language to the taglist plugin, you need +to first extend the exuberant ctags tool. For more information about extending +exuberant ctags, visit the following page: + + http://ctags.sourceforge.net/EXTENDING.html + +To add support for a new language, set the tlist_xxx_settings variable in the +~/.vimrc file appropriately as described above. Replace 'xxx' in the variable +name with the Vim filetype name for the new language. + +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 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 in the taglist window for the tags which +are generated for the flags b, c and l respectively. + +============================================================================== + *taglist-faq* +10. Frequently Asked Questions~ + +Q. The taglist plugin doesn't work. The taglist window is empty and the tags + defined in a file are not displayed. +A. Are you using Vim version 6.0 and above? The taglist plugin relies on the + features supported by Vim version 6.0 and above. You can use the following + command to get the Vim version: +> + $ vim --version +< + Are you using exuberant ctags version 5.0 and above? The taglist plugin + relies on the features supported by exuberant ctags and will not work with + GNU ctags or the Unix ctags utility. You can use the following command to + determine whether the ctags installed in your system is exuberant ctags: +> + $ ctags --version +< + Is exuberant ctags present in one of the directories in your PATH? If not, + you need to set the Tlist_Ctags_Cmd variable to point to the location of + exuberant ctags. Use the following Vim command to verify that this is setup + correctly: +> + :echo system(Tlist_Ctags_Cmd . ' --version') +< + The above command should display the version information for exuberant + ctags. + + Did you turn on the Vim filetype detection? The taglist plugin relies on + the filetype detected by Vim and passes the filetype to the exuberant ctags + utility to parse the tags. Check the output of the following Vim command: +> + :filetype +< + The output of the above command should contain "filetype detection:ON". + To turn on the filetype detection, add the following line to the .vimrc or + _vimrc file: +> + filetype on +< + Is your version of Vim compiled with the support for the system() function? + The following Vim command should display 1: +> + :echo exists('*system') +< + In some Linux distributions (particularly Suse Linux), the default Vim + installation is built without the support for the system() function. The + taglist plugin uses the system() function to invoke the exuberant ctags + utility. You need to rebuild Vim after enabling the support for the + system() function. If you use the default build options, the system() + function will be supported. + + Do you have the |'shellslash'| option set? You can try disabling the + |'shellslash'| option. When the taglist plugin invokes the exuberant ctags + utility with the path to the file, if the incorrect slashes are used, then + you will see errors. + + Check the shell related Vim options values using the following command: +> + :set shell? shellcmdflag? shellpipe? + :set shellquote? shellredir? shellxquote? +< + If these options are set in your .vimrc or _vimrc file, try removing those + lines. + + Are you using a Unix shell in a MS-Windows environment? For example, + the Unix shell from the MKS-toolkit. Do you have the SHELL environment + set to point to this shell? You can try resetting the SHELL environment + variable. + + If you are using a Unix shell on MS-Windows, you should try to use + exuberant ctags that is compiled for Unix-like environments so that + exuberant ctags will understand path names with forward slash characters. + + Is your filetype supported by the exuberant ctags utility? The file types + supported by the exuberant ctags utility are listed in the ctags help. If a + file type is not supported, you have to extend exuberant ctags. You can use + the following command to list the filetypes supported by exuberant ctags: +> + ctags --list-languages +< + Run the following command from the shell prompt and check whether the tags + defined in your file are listed in the output from exuberant ctags: +> + 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. + + Do you have the .ctags or _ctags or the ctags.cnf file in your home + directory for specifying default options or for extending exuberant ctags? + 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 + setting the 'Tlist_Ctags_Cmd' variable to the shortest path name to ctags + or try copying the exuberant ctags to a path without space characters in + the name. For example, if exuberant ctags is installed in the directory + "C:\Program Files\Ctags", then try setting the 'Tlist_Ctags_Cmd' variable + as below: +> + let Tlist_Ctags_Cmd='C:\Progra~1\Ctags\ctags.exe' +< + If you are using a cygwin compiled version of exuberant ctags on MS-Windows, + make sure that either you have the cygwin compiled sort utility installed + and available in your PATH or compile exuberant ctags with internal sort + support. Otherwise, when exuberant ctags sorts the tags output by invoking + the sort utility, it may end up invoking the MS-Windows version of + sort.exe, thereby resulting in failure. + +Q. When I try to open the taglist window, I am seeing the following error + message. How do I fix this problem? + + Taglist: Failed to generate tags for /my/path/to/file + ctags: illegal option -- -^@usage: ctags [-BFadtuwvx] [-f tagsfile] file ... + +A. The taglist plugin will work only with the exuberant ctags tool. You + cannot use the GNU ctags or the Unix ctags program with the taglist plugin. + You will see an error message similar to the one shown above, if you try + use a non-exuberant ctags program with Vim. To fix this problem, either add + the exuberant ctags tool location to the PATH environment variable or set + the 'Tlist_Ctags_Cmd' variable. + +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. +A. The taglist plugin uses the search pattern generated by the exuberant ctags + utility to position the cursor at the location of a tag definition. If a + file has more than one tag with the same name and same prototype, then the + search pattern will be the same. In this case, when searching for the tag + 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. +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 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 + contents are changed. Why is this? +A. The taglist plugin uses the |CursorHold| autocmd to highlight the current + tag. The CursorHold autocmd triggers for every |'updatetime'| milliseconds. + If the |'updatetime'| option is set to a low value, then the CursorHold + autocmd will be triggered frequently. As the taglist plugin changes + the focus to the taglist window to highlight the current tag, this could + interfere with the key movement resulting in changing the contents of + the current buffer. The workaround for this problem is to not set the + |'updatetime'| option to a low value. + +============================================================================== + *taglist-license* +11. License~ +Permission is hereby granted to use and distribute the taglist plugin, with or +without modifications, provided that this copyright notice is copied with it. +Like anything else that's free, taglist.vim is provided *as is* and comes with +no warranty of any kind, either expressed or implied. In no event will the +copyright holder be liable for any damamges resulting from the use of this +software. + +============================================================================== + *taglist-todo* +12. Todo~ + +1. Group tags according to the scope and display them. For example, + group all the tags belonging to a C++/Java class +2. Support for displaying tags in a modified (not-yet-saved) file. +3. Automatically open the taglist window only for selected filetypes. + For other filetypes, close the taglist window. +4. When using the shell from the MKS toolkit, the taglist plugin + doesn't work. +5. The taglist plugin doesn't work with files edited remotely using the + netrw plugin. The exuberant ctags utility cannot process files over + scp/rcp/ftp, etc. + +============================================================================== + +vim:tw=78:ts=8:noet:ft=help: diff --git a/vim/ftdetect/nhdes.vim b/vim/ftdetect/nhdes.vim new file mode 100644 index 0000000..089b391 --- /dev/null +++ b/vim/ftdetect/nhdes.vim @@ -0,0 +1 @@ +au! BufRead,BufNewFile *.des set filetype=nhdes diff --git a/vim/indent/lua.vim b/vim/indent/lua.vim new file mode 100644 index 0000000..b72914a --- /dev/null +++ b/vim/indent/lua.vim @@ -0,0 +1,59 @@ +" Vim indent file +" Language: Lua script +" Maintainer: Marcus Aurelius Farias +" First Author: Max Ischenko +" Last Change: 2005 Jun 23 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetLuaIndent() + +" To make Vim call GetLuaIndent() when it finds '\s*end' or '\s*until' +" on the current line ('else' is default and includes 'elseif'). +setlocal indentkeys+=0=end,0=until + +setlocal autoindent + +" Only define the function once. +if exists("*GetLuaIndent") + finish +endif + +function! GetLuaIndent() + " Find a non-blank line above the current line. + let lnum = prevnonblank(v:lnum - 1) + + " Hit the start of the file, use zero indent. + if lnum == 0 + return 0 + endif + + " Add a 'shiftwidth' after lines that start a block: + " 'function', 'if', 'for', 'while', 'repeat', 'else', 'elseif', '{' + let ind = indent(lnum) + let flag = 0 + let prevline = getline(lnum) + if prevline =~ '^\s*\%(if\>\|for\>\|while\>\|repeat\>\|else\>\|elseif\>\|do\>\|then\>\)' + \ || prevline =~ '\%(--.*\)\@\s*\%(\k\|[.:]\)\{-}\s*(' + let ind = ind + &shiftwidth + let flag = 1 + endif + + " Subtract a 'shiftwidth' after lines ending with + " 'end' when they begin with 'while', 'if', 'for', etc. too. + if flag == 1 && prevline =~ '\\|\' + let ind = ind - &shiftwidth + endif + + " Subtract a 'shiftwidth' on end, else (and elseif), until and '}' + " This is the part that requires 'indentkeys'. + if getline(v:lnum) =~ '^\s*\%(end\|else\|until\|}\)' + let ind = ind - &shiftwidth + endif + + return ind +endfunction diff --git a/vim/plugin/matchit.vim b/vim/plugin/matchit.vim new file mode 100644 index 0000000..a2f2050 --- /dev/null +++ b/vim/plugin/matchit.vim @@ -0,0 +1,810 @@ +" matchit.vim: (global plugin) Extended "%" matching +" Last Change: Sun Feb 26 10:00 AM 2006 EST +" Maintainer: Benji Fisher PhD +" Version: 1.10, for Vim 6.3 +" URL: http://www.vim.org/script.php?script_id=39 + +" Documentation: +" The documentation is in a separate file, matchit.txt . + +" Credits: +" Vim editor by Bram Moolenaar (Thanks, Bram!) +" Original script and design by Raul Segura Acevedo +" Support for comments by Douglas Potts +" Support for back references and other improvements by Benji Fisher +" Support for many languages by Johannes Zellner +" Suggestions for improvement, bug reports, and support for additional +" languages by Jordi-Albert Batalla, Neil Bird, Servatius Brandt, Mark +" Collett, Stephen Wall, Dany St-Amant, and Johannes Zellner. + +" Debugging: +" If you'd like to try the built-in debugging commands... +" :MatchDebug to activate debugging for the current buffer +" This saves the values of several key script variables as buffer-local +" variables. See the MatchDebug() function, below, for details. + +" TODO: I should think about multi-line patterns for b:match_words. +" This would require an option: how many lines to scan (default 1). +" This would be useful for Python, maybe also for *ML. +" TODO: Maybe I should add a menu so that people will actually use some of +" the features that I have implemented. +" TODO: Eliminate the MultiMatch function. Add yet another argument to +" Match_wrapper() instead. +" TODO: Allow :let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1' +" TODO: Make backrefs safer by using '\V' (very no-magic). +" TODO: Add a level of indirection, so that custom % scripts can use my +" work but extend it. + +" allow user to prevent loading +" and prevent duplicate loading +if exists("loaded_matchit") || &cp + finish +endif +let loaded_matchit = 1 +let s:last_mps = "" +let s:last_words = "" + +let s:save_cpo = &cpo +set cpo&vim + +nnoremap % :call Match_wrapper('',1,'n') +nnoremap g% :call Match_wrapper('',0,'n') +vnoremap % :call Match_wrapper('',1,'v') m'gv`` +vnoremap g% :call Match_wrapper('',0,'v') m'gv`` +onoremap % v:call Match_wrapper('',1,'o') +onoremap g% v:call Match_wrapper('',0,'o') + +" Analogues of [{ and ]} using matching patterns: +nnoremap [% :call MultiMatch("bW", "n") +nnoremap ]% :call MultiMatch("W", "n") +vmap [% [%m'gv`` +vmap ]% ]%m'gv`` +" vnoremap [% :call MultiMatch("bW", "v") m'gv`` +" vnoremap ]% :call MultiMatch("W", "v") m'gv`` +onoremap [% v:call MultiMatch("bW", "o") +onoremap ]% v:call MultiMatch("W", "o") + +" text object: +vmap a% [%v]% + +" Auto-complete mappings: (not yet "ready for prime time") +" TODO Read :help write-plugin for the "right" way to let the user +" specify a key binding. +" let g:match_auto = '' +" let g:match_autoCR = '' +" if exists("g:match_auto") +" execute "inoremap " . g:match_auto . ' x"=Autocomplete()Pls' +" endif +" if exists("g:match_autoCR") +" execute "inoremap " . g:match_autoCR . ' =Autocomplete()' +" endif +" if exists("g:match_gthhoh") +" execute "inoremap " . g:match_gthhoh . ' :call Gthhoh()' +" endif " gthhoh = "Get the heck out of here!" + +let s:notslash = '\\\@" + endif + " In s:CleanUp(), we may need to check whether the cursor moved forward. + let startline = line(".") + let startcol = col(".") + " Use default behavior if called with a count or if no patterns are defined. + if v:count + exe "normal! " . v:count . "%" + return s:CleanUp(restore_options, a:mode, startline, startcol) + elseif !exists("b:match_words") || b:match_words == "" + silent! normal! % + return s:CleanUp(restore_options, a:mode, startline, startcol) + end + + " First step: if not already done, set the script variables + " s:do_BR flag for whether there are backrefs + " s:pat parsed version of b:match_words + " s:all regexp based on s:pat and the default groups + " + " Allow b:match_words = "GetVimMatchWords()" . + if b:match_words =~ ":" + let match_words = b:match_words + else + execute "let match_words =" b:match_words + endif +" Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion! + if (match_words != s:last_words) || (&mps != s:last_mps) || + \ exists("b:match_debug") + let s:last_words = match_words + let s:last_mps = &mps + if match_words !~ s:notslash . '\\\d' + let s:do_BR = 0 + let s:pat = match_words + else + let s:do_BR = 1 + let s:pat = s:ParseWords(match_words) + endif + " The next several lines were here before + " BF started messing with this script. + " quote the special chars in 'matchpairs', replace [,:] with \| and then + " append the builtin pairs (/*, */, #if, #ifdef, #else, #elif, #endif) + " let default = substitute(escape(&mps, '[$^.*~\\/?]'), '[,:]\+', + " \ '\\|', 'g').'\|\/\*\|\*\/\|#if\>\|#ifdef\>\|#else\>\|#elif\>\|#endif\>' + let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") . + \ '\/\*:\*\/,#if\%(def\)\=:#else\>:#elif\>:#endif\>' + " s:all = pattern with all the keywords + let s:all = s:pat . (strlen(s:pat) ? "," : "") . default + let s:all = substitute(s:all, s:notslash . '\zs[,:]\+', '\\|', 'g') + let s:all = '\%(' . s:all . '\)' + " let s:all = '\%(' . substitute(s:all, '\\\ze[,:]', '', 'g') . '\)' + if exists("b:match_debug") + let b:match_pat = s:pat + endif + endif + + " Second step: set the following local variables: + " matchline = line on which the cursor started + " curcol = number of characters before match + " prefix = regexp for start of line to start of match + " suffix = regexp for end of match to end of line + " Require match to end on or after the cursor and prefer it to + " start on or before the cursor. + let matchline = getline(startline) + if a:word != '' + " word given + if a:word !~ s:all + echohl WarningMsg|echo 'Missing rule for word:"'.a:word.'"'|echohl NONE + return s:CleanUp(restore_options, a:mode, startline, startcol) + endif + let matchline = a:word + let curcol = 0 + let prefix = '^\%(' + let suffix = '\)$' + " Now the case when "word" is not given + else " Find the match that ends on or after the cursor and set curcol. + let regexp = s:Wholematch(matchline, s:all, startcol-1) + let curcol = match(matchline, regexp) + let suf = strlen(matchline) - matchend(matchline, regexp) + let prefix = (curcol ? '^.\{' . curcol . '}\%(' : '^\%(') + let suffix = (suf ? '\).\{' . suf . '}$' : '\)$') + " If the match comes from the defaults, bail out. + if matchline !~ prefix . + \ substitute(s:pat, s:notslash.'\zs[,:]\+', '\\|', 'g') . suffix + silent! norm! % + return s:CleanUp(restore_options, a:mode, startline, startcol) + endif + endif + if exists("b:match_debug") + let b:match_match = matchstr(matchline, regexp) + let b:match_col = curcol+1 + endif + + " Third step: Find the group and single word that match, and the original + " (backref) versions of these. Then, resolve the backrefs. + " Set the following local variable: + " group = colon-separated list of patterns, one of which matches + " = ini:mid:fin or ini:fin + " + " Reconstruct the version with unresolved backrefs. + let patBR = substitute(match_words.',', + \ s:notslash.'\zs[,:]*,[,:]*', ',', 'g') + let patBR = substitute(patBR, s:notslash.'\zs:\{2,}', ':', 'g') + " Now, set group and groupBR to the matching group: 'if:endif' or + " 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns + " group . "," . groupBR, and we pick it apart. + let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR) + let i = matchend(group, s:notslash . ",") + let groupBR = strpart(group, i) + let group = strpart(group, 0, i-1) + " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix + if s:do_BR " Do the hard part: resolve those backrefs! + let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline) + endif + if exists("b:match_debug") + let b:match_wholeBR = groupBR + let i = matchend(groupBR, s:notslash . ":") + let b:match_iniBR = strpart(groupBR, 0, i-1) + endif + + " Fourth step: Set the arguments for searchpair(). + let i = matchend(group, s:notslash . ":") + let j = matchend(group, '.*' . s:notslash . ":") + let ini = strpart(group, 0, i-1) + let mid = substitute(strpart(group, i,j-i-1), s:notslash.'\zs:', '\\|', 'g') + let fin = strpart(group, j) + "Un-escape the remaining , and : characters. + let ini = substitute(ini, s:notslash . '\zs\\\(:\|,\)', '\1', 'g') + let mid = substitute(mid, s:notslash . '\zs\\\(:\|,\)', '\1', 'g') + let fin = substitute(fin, s:notslash . '\zs\\\(:\|,\)', '\1', 'g') + " searchpair() requires that these patterns avoid \(\) groups. + let ini = substitute(ini, s:notslash . '\zs\\(', '\\%(', 'g') + let mid = substitute(mid, s:notslash . '\zs\\(', '\\%(', 'g') + let fin = substitute(fin, s:notslash . '\zs\\(', '\\%(', 'g') + " Set mid. This is optimized for readability, not micro-efficiency! + if a:forward && matchline =~ prefix . fin . suffix + \ || !a:forward && matchline =~ prefix . ini . suffix + let mid = "" + endif + " Set flag. This is optimized for readability, not micro-efficiency! + if a:forward && matchline =~ prefix . fin . suffix + \ || !a:forward && matchline !~ prefix . ini . suffix + let flag = "bW" + else + let flag = "W" + endif + " Set skip. + if exists("b:match_skip") + let skip = b:match_skip + elseif exists("b:match_comment") " backwards compatibility and testing! + let skip = "r:" . b:match_comment + else + let skip = 's:comment\|string' + endif + let skip = s:ParseSkip(skip) + if exists("b:match_debug") + let b:match_ini = ini + let b:match_tail = (strlen(mid) ? mid.'\|' : '') . fin + endif + + " Fifth step: actually start moving the cursor and call searchpair(). + " Later, :execute restore_cursor to get to the original screen. + let restore_cursor = virtcol(".") . "|" + normal! g0 + let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor + normal! H + let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor + execute restore_cursor + normal! 0 + if curcol + execute "normal!" . curcol . "l" + endif + if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on")) + let skip = "0" + else + execute "if " . skip . "| let skip = '0' | endif" + endif + let sp_return = searchpair(ini, mid, fin, flag, skip) + let final_position = "call cursor(" . line(".") . "," . col(".") . ")" + " Restore cursor position and original screen. + execute restore_cursor + normal! m' + if sp_return > 0 + execute final_position + endif + return s:CleanUp(restore_options, a:mode, startline, startcol, mid.'\|'.fin) +endfun + +" Restore options and do some special handling for Operator-pending mode. +" The optional argument is the tail of the matching group. +fun! s:CleanUp(options, mode, startline, startcol, ...) + execute "set" a:options + " Open folds, if appropriate. + if a:mode != "o" + if &foldopen =~ "percent" + normal! zv + endif + " In Operator-pending mode, we want to include the whole match + " (for example, d%). + " This is only a problem if we end up moving in the forward direction. + elseif (a:startline < line(".")) || + \ (a:startline == line(".") && a:startcol < col(".")) + if a:0 + " Check whether the match is a single character. If not, move to the + " end of the match. + let matchline = getline(".") + let currcol = col(".") + let regexp = s:Wholematch(matchline, a:1, currcol-1) + let endcol = matchend(matchline, regexp) + if endcol > currcol " This is NOT off by one! + execute "normal!" . (endcol - currcol) . "l" + endif + endif " a:0 + endif " a:mode != "o" && etc. + return 0 +endfun + +" Example (simplified HTML patterns): if +" a:groupBR = '<\(\k\+\)>:' +" a:prefix = '^.\{3}\(' +" a:group = '<\(\k\+\)>:' +" a:suffix = '\).\{2}$' +" a:matchline = "12312" or "12312" +" then extract "tag" from a:matchline and return ":" . +fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline) + if a:matchline !~ a:prefix . + \ substitute(a:group, s:notslash . '\zs:', '\\|', 'g') . a:suffix + return a:group + endif + let i = matchend(a:groupBR, s:notslash . ':') + let ini = strpart(a:groupBR, 0, i-1) + let tailBR = strpart(a:groupBR, i) + let word = s:Choose(a:group, a:matchline, ":", "", a:prefix, a:suffix, + \ a:groupBR) + let i = matchend(word, s:notslash . ":") + let wordBR = strpart(word, i) + let word = strpart(word, 0, i-1) + " Now, a:matchline =~ a:prefix . word . a:suffix + if wordBR != ini + let table = s:Resolve(ini, wordBR, "table") + else + " let table = "----------" + let table = "" + let d = 0 + while d < 10 + if tailBR =~ s:notslash . '\\' . d + " let table[d] = d + let table = table . d + else + let table = table . "-" + endif + let d = d + 1 + endwhile + endif + let d = 9 + while d + if table[d] != "-" + let backref = substitute(a:matchline, a:prefix.word.a:suffix, + \ '\'.table[d], "") + " Are there any other characters that should be escaped? + let backref = escape(backref, '*,:') + execute s:Ref(ini, d, "start", "len") + let ini = strpart(ini, 0, start) . backref . strpart(ini, start+len) + let tailBR = substitute(tailBR, s:notslash . '\zs\\' . d, + \ escape(backref, '\\'), 'g') + endif + let d = d-1 + endwhile + if exists("b:match_debug") + if s:do_BR + let b:match_table = table + let b:match_word = word + else + let b:match_table = "" + let b:match_word = "" + endif + endif + return ini . ":" . tailBR +endfun + +" Input a comma-separated list of groups with backrefs, such as +" a:groups = '\(foo\):end\1,\(bar\):end\1' +" and return a comma-separated list of groups with backrefs replaced: +" return '\(foo\):end\(foo\),\(bar\):end\(bar\)' +fun! s:ParseWords(groups) + let groups = substitute(a:groups.",", s:notslash.'\zs[,:]*,[,:]*', ',', 'g') + let groups = substitute(groups, s:notslash . '\zs:\{2,}', ':', 'g') + let parsed = "" + while groups =~ '[^,:]' + let i = matchend(groups, s:notslash . ':') + let j = matchend(groups, s:notslash . ',') + let ini = strpart(groups, 0, i-1) + let tail = strpart(groups, i, j-i-1) . ":" + let groups = strpart(groups, j) + let parsed = parsed . ini + let i = matchend(tail, s:notslash . ':') + while i != -1 + " In 'if:else:endif', ini='if' and word='else' and then word='endif'. + let word = strpart(tail, 0, i-1) + let tail = strpart(tail, i) + let i = matchend(tail, s:notslash . ':') + let parsed = parsed . ":" . s:Resolve(ini, word, "word") + endwhile " Now, tail has been used up. + let parsed = parsed . "," + endwhile " groups =~ '[^,:]' + return parsed +endfun + +" TODO I think this can be simplified and/or made more efficient. +" TODO What should I do if a:start is out of range? +" Return a regexp that matches all of a:string, such that +" matchstr(a:string, regexp) represents the match for a:pat that starts +" as close to a:start as possible, before being preferred to after, and +" ends after a:start . +" Usage: +" let regexp = s:Wholematch(getline("."), 'foo\|bar', col(".")-1) +" let i = match(getline("."), regexp) +" let j = matchend(getline("."), regexp) +" let match = matchstr(getline("."), regexp) +fun! s:Wholematch(string, pat, start) + let group = '\%(' . a:pat . '\)' + let prefix = (a:start ? '\(^.\{,' . a:start . '}\)\zs' : '^') + let len = strlen(a:string) + let suffix = (a:start+1 < len ? '\(.\{,'.(len-a:start-1).'}$\)\@=' : '$') + if a:string !~ prefix . group . suffix + let prefix = '' + endif + return prefix . group . suffix +endfun + +" No extra arguments: s:Ref(string, d) will +" find the d'th occurrence of '\(' and return it, along with everything up +" to and including the matching '\)'. +" One argument: s:Ref(string, d, "start") returns the index of the start +" of the d'th '\(' and any other argument returns the length of the group. +" Two arguments: s:Ref(string, d, "foo", "bar") returns a string to be +" executed, having the effect of +" :let foo = s:Ref(string, d, "start") +" :let bar = s:Ref(string, d, "len") +fun! s:Ref(string, d, ...) + let len = strlen(a:string) + if a:d == 0 + let start = 0 + else + let cnt = a:d + let match = a:string + while cnt + let cnt = cnt - 1 + let index = matchend(match, s:notslash . '\\(') + if index == -1 + return "" + endif + let match = strpart(match, index) + endwhile + let start = len - strlen(match) + if a:0 == 1 && a:1 == "start" + return start - 2 + endif + let cnt = 1 + while cnt + let index = matchend(match, s:notslash . '\\(\|\\)') - 1 + if index == -2 + return "" + endif + " Increment if an open, decrement if a ')': + let cnt = cnt + (match[index]=="(" ? 1 : -1) " ')' + " let cnt = stridx('0(', match[index]) + cnt + let match = strpart(match, index+1) + endwhile + let start = start - 2 + let len = len - start - strlen(match) + endif + if a:0 == 1 + return len + elseif a:0 == 2 + return "let " . a:1 . "=" . start . "| let " . a:2 . "=" . len + else + return strpart(a:string, start, len) + endif +endfun + +" Count the number of disjoint copies of pattern in string. +" If the pattern is a literal string and contains no '0' or '1' characters +" then s:Count(string, pattern, '0', '1') should be faster than +" s:Count(string, pattern). +fun! s:Count(string, pattern, ...) + let pat = escape(a:pattern, '\\') + if a:0 > 1 + let foo = substitute(a:string, '[^'.a:pattern.']', "a:1", "g") + let foo = substitute(a:string, pat, a:2, "g") + let foo = substitute(foo, '[^' . a:2 . ']', "", "g") + return strlen(foo) + endif + let result = 0 + let foo = a:string + let index = matchend(foo, pat) + while index != -1 + let result = result + 1 + let foo = strpart(foo, index) + let index = matchend(foo, pat) + endwhile + return result +endfun + +" s:Resolve('\(a\)\(b\)', '\(c\)\2\1\1\2') should return table.word, where +" word = '\(c\)\(b\)\(a\)\3\2' and table = '-32-------'. That is, the first +" '\1' in target is replaced by '\(a\)' in word, table[1] = 3, and this +" indicates that all other instances of '\1' in target are to be replaced +" by '\3'. The hard part is dealing with nesting... +" Note that ":" is an illegal character for source and target, +" unless it is preceded by "\". +fun! s:Resolve(source, target, output) + let word = a:target + let i = matchend(word, s:notslash . '\\\d') - 1 + let table = "----------" + while i != -2 " There are back references to be replaced. + let d = word[i] + let backref = s:Ref(a:source, d) + " The idea is to replace '\d' with backref. Before we do this, + " replace any \(\) groups in backref with :1, :2, ... if they + " correspond to the first, second, ... group already inserted + " into backref. Later, replace :1 with \1 and so on. The group + " number w+b within backref corresponds to the group number + " s within a:source. + " w = number of '\(' in word before the current one + let w = s:Count( + \ substitute(strpart(word, 0, i-1), '\\\\', '', 'g'), '\(', '1') + let b = 1 " number of the current '\(' in backref + let s = d " number of the current '\(' in a:source + while b <= s:Count(substitute(backref, '\\\\', '', 'g'), '\(', '1') + \ && s < 10 + if table[s] == "-" + if w + b < 10 + " let table[s] = w + b + let table = strpart(table, 0, s) . (w+b) . strpart(table, s+1) + endif + let b = b + 1 + let s = s + 1 + else + execute s:Ref(backref, b, "start", "len") + let ref = strpart(backref, start, len) + let backref = strpart(backref, 0, start) . ":". table[s] + \ . strpart(backref, start+len) + let s = s + s:Count(substitute(ref, '\\\\', '', 'g'), '\(', '1') + endif + endwhile + let word = strpart(word, 0, i-1) . backref . strpart(word, i+1) + let i = matchend(word, s:notslash . '\\\d') - 1 + endwhile + let word = substitute(word, s:notslash . '\zs:', '\\', 'g') + if a:output == "table" + return table + elseif a:output == "word" + return word + else + return table . word + endif +endfun + +" Assume a:comma = ",". Then the format for a:patterns and a:1 is +" a:patterns = ",,..." +" a:1 = ",,..." +" If is the first pattern that matches a:string then return +" if no optional arguments are given; return , if a:1 is given. +fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...) + let tail = (a:patterns =~ a:comma."$" ? a:patterns : a:patterns . a:comma) + let i = matchend(tail, s:notslash . a:comma) + if a:0 + let alttail = (a:1 =~ a:comma."$" ? a:1 : a:1 . a:comma) + let j = matchend(alttail, s:notslash . a:comma) + endif + let current = strpart(tail, 0, i-1) + if a:branch == "" + let currpat = current + else + let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g') + endif + while a:string !~ a:prefix . currpat . a:suffix + let tail = strpart(tail, i) + let i = matchend(tail, s:notslash . a:comma) + if i == -1 + return -1 + endif + let current = strpart(tail, 0, i-1) + if a:branch == "" + let currpat = current + else + let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g') + endif + if a:0 + let alttail = strpart(alttail, j) + let j = matchend(alttail, s:notslash . a:comma) + endif + endwhile + if a:0 + let current = current . a:comma . strpart(alttail, 0, j-1) + endif + return current +endfun + +" Call this function to turn on debugging information. Every time the main +" script is run, buffer variables will be saved. These can be used directly +" or viewed using the menu items below. +if !exists(":MatchDebug") + command! -nargs=0 MatchDebug call s:Match_debug() +endif + +fun! s:Match_debug() + let b:match_debug = 1 " Save debugging information. + " pat = all of b:match_words with backrefs parsed + amenu &Matchit.&pat :echo b:match_pat + " match = bit of text that is recognized as a match + amenu &Matchit.&match :echo b:match_match + " curcol = cursor column of the start of the matching text + amenu &Matchit.&curcol :echo b:match_col + " wholeBR = matching group, original version + amenu &Matchit.wh&oleBR :echo b:match_wholeBR + " iniBR = 'if' piece, original version + amenu &Matchit.ini&BR :echo b:match_iniBR + " ini = 'if' piece, with all backrefs resolved from match + amenu &Matchit.&ini :echo b:match_ini + " tail = 'else\|endif' piece, with all backrefs resolved from match + amenu &Matchit.&tail :echo b:match_tail + " fin = 'endif' piece, with all backrefs resolved from match + amenu &Matchit.&word :echo b:match_word + " '\'.d in ini refers to the same thing as '\'.table[d] in word. + amenu &Matchit.t&able :echo '0:' . b:match_table . ':9' +endfun + +" Jump to the nearest unmatched "(" or "if" or "" if a:spflag == "bW" +" or the nearest unmatched "" or "endif" or ")" if a:spflag == "W". +" Return a "mark" for the original position, so that +" let m = MultiMatch("bW", "n") ... execute m +" will return to the original position. If there is a problem, do not +" move the cursor and return "", unless a count is given, in which case +" go up or down as many levels as possible and again return "". +" TODO This relies on the same patterns as % matching. It might be a good +" idea to give it its own matching patterns. +fun! s:MultiMatch(spflag, mode) + if !exists("b:match_words") || b:match_words == "" + return "" + end + let restore_options = (&ic ? "" : "no") . "ignorecase" + if exists("b:match_ignorecase") + let &ignorecase = b:match_ignorecase + endif + let startline = line(".") + let startcol = col(".") + + " First step: if not already done, set the script variables + " s:do_BR flag for whether there are backrefs + " s:pat parsed version of b:match_words + " s:all regexp based on s:pat and the default groups + " This part is copied and slightly modified from s:Match_wrapper(). + let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") . + \ '\/\*:\*\/,#if\%(def\)\=:$else\>:#elif\>:#endif\>' + " Allow b:match_words = "GetVimMatchWords()" . + if b:match_words =~ ":" + let match_words = b:match_words + else + execute "let match_words =" b:match_words + endif + if (match_words != s:last_words) || (&mps != s:last_mps) || + \ exists("b:match_debug") + let s:last_words = match_words + let s:last_mps = &mps + if match_words !~ s:notslash . '\\\d' + let s:do_BR = 0 + let s:pat = match_words + else + let s:do_BR = 1 + let s:pat = s:ParseWords(match_words) + endif + let s:all = '\%(' . substitute(s:pat . (strlen(s:pat)?",":"") . default, + \ '[,:]\+','\\|','g') . '\)' + if exists("b:match_debug") + let b:match_pat = s:pat + endif + endif + + " Second step: figure out the patterns for searchpair() + " and save the screen, cursor position, and 'ignorecase'. + " - TODO: A lot of this is copied from s:Match_wrapper(). + " - maybe even more functionality should be split off + " - into separate functions! + let cdefault = (s:pat =~ '[^,]$' ? "," : "") . default + let open = substitute(s:pat . cdefault, ':[^,]*,', '\\),\\(', 'g') + let open = '\(' . substitute(open, ':[^,]*$', '\\)', '') + let close = substitute(s:pat . cdefault, ',[^,]*:', '\\),\\(', 'g') + let close = substitute(close, '[^,]*:', '\\(', '') . '\)' + if exists("b:match_skip") + let skip = b:match_skip + elseif exists("b:match_comment") " backwards compatibility and testing! + let skip = "r:" . b:match_comment + else + let skip = 's:comment\|string' + endif + let skip = s:ParseSkip(skip) + " let restore_cursor = line(".") . "G" . virtcol(".") . "|" + " normal! H + " let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor + let restore_cursor = virtcol(".") . "|" + normal! g0 + let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor + normal! H + let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor + execute restore_cursor + + " Third step: call searchpair(). + " Replace '\('--but not '\\('--with '\%(' and ',' with '\|'. + let openpat = substitute(open, '\(\\\@" or ... +" and return "endif" or "endwhile" or "" or ... . +" For now, this uses b:match_words and the same script variables +" as s:Match_wrapper() . Later, it may get its own patterns, +" either from a buffer variable or passed as arguments. +" fun! s:Autocomplete() +" echo "autocomplete not yet implemented :-(" +" if !exists("b:match_words") || b:match_words == "" +" return "" +" end +" let startpos = s:MultiMatch("bW") +" +" if startpos == "" +" return "" +" endif +" " - TODO: figure out whether 'if' or '' matched, and construct +" " - the appropriate closing. +" let matchline = getline(".") +" let curcol = col(".") - 1 +" " - TODO: Change the s:all argument if there is a new set of match pats. +" let regexp = s:Wholematch(matchline, s:all, curcol) +" let suf = strlen(matchline) - matchend(matchline, regexp) +" let prefix = (curcol ? '^.\{' . curcol . '}\%(' : '^\%(') +" let suffix = (suf ? '\).\{' . suf . '}$' : '\)$') +" " Reconstruct the version with unresolved backrefs. +" let patBR = substitute(b:match_words.',', '[,:]*,[,:]*', ',', 'g') +" let patBR = substitute(patBR, ':\{2,}', ':', "g") +" " Now, set group and groupBR to the matching group: 'if:endif' or +" " 'while:endwhile' or whatever. +" let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR) +" let i = matchend(group, s:notslash . ",") +" let groupBR = strpart(group, i) +" let group = strpart(group, 0, i-1) +" " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix +" if s:do_BR +" let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline) +" endif +" " let g:group = group +" +" " - TODO: Construct the closing from group. +" let fake = "end" . expand("") +" execute startpos +" return fake +" endfun + +" Close all open structures. "Get the heck out of here!" +" fun! s:Gthhoh() +" let close = s:Autocomplete() +" while strlen(close) +" put=close +" let close = s:Autocomplete() +" endwhile +" endfun + +" Parse special strings as typical skip arguments for searchpair(): +" s:foo becomes (current syntax item) =~ foo +" S:foo becomes (current syntax item) !~ foo +" r:foo becomes (line before cursor) =~ foo +" R:foo becomes (line before cursor) !~ foo +fun! s:ParseSkip(str) + let skip = a:str + if skip[1] == ":" + if skip[0] == "s" + let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" . + \ strpart(skip,2) . "'" + elseif skip[0] == "S" + let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" . + \ strpart(skip,2) . "'" + elseif skip[0] == "r" + let skip = "strpart(getline('.'),0,col('.'))=~'" . strpart(skip,2). "'" + elseif skip[0] == "R" + let skip = "strpart(getline('.'),0,col('.'))!~'" . strpart(skip,2). "'" + endif + endif + return skip +endfun + +let &cpo = s:save_cpo + +" vim:sts=2:sw=2: diff --git a/vim/plugin/rainbow_paren.vim b/vim/plugin/rainbow_paren.vim new file mode 100644 index 0000000..3578d63 --- /dev/null +++ b/vim/plugin/rainbow_paren.vim @@ -0,0 +1,88 @@ +" this script by Shawn M Moore aka Sartak +" also by Michael R Geddes aka frogonwheels +" originally by anonymous + +" this in the public domain +" last updated 25 Mar 07 + +" this does nothing unless you, +" let g:rainbow = 1 + +" and set which kinds of character pairs you want to rainbow +" let g:rainbow_paren = 1 " () +" let g:rainbow_brace = 1 " {} +" let g:rainbow_bracket = 1 " [] +" let g:rainbow_angle = 1 " <> + +" if you want the different types to nest, such that the braces in ({}) are +" colored the same as the internal parens of (()), then +" let g:rainbow_nested = 1 + +" you probably also want to use something like +" autocmd BufReadPost * source /path/to/rainbow_parens.vim +" autocmd BufNewFile * source /path/to/rainbow_parens.vim + +if exists("g:rainbow") && g:rainbow != 0 + hi level1c ctermfg=darkcyan + hi level2c ctermfg=darkgreen + hi level3c ctermfg=darkyellow + hi level4c ctermfg=darkblue + hi level5c ctermfg=darkmagenta + hi level6c ctermfg=darkred " this color is never nested, it only appears on the outermost layer + + " helper function + func s:DoSyn(cur, top, left, right, uniq) + let uniq = a:uniq + if exists("g:rainbow_nested") && g:rainbow_nested != 0 + let uniq = "" + endif + + let cmd = 'syn region level'.uniq.a:cur.' transparent fold matchgroup=level'.a:cur.'c start=/'.a:left.'/ end=/'.a:right.'/ contains=TOP' + + let i = a:cur + + if i == 1 + let i = a:top + endif + + while i <= a:top + let cmd = cmd . ',level' . uniq . i + let i = i + 1 + endwhile + exe cmd + endfunc + + func s:DoSyntaxes(count) + let i = 1 + + while i <= a:count + " if you define new pairs, make sure to take into account that the + " delimiter is currently / and that it uses regex, so you need to escape + " regex metachars (like what is done for brackets) + + if exists("g:rainbow_paren") && g:rainbow_paren != 0 + call s:DoSyn(i, a:count, "(", ")", "a") + endif + + if exists("g:rainbow_brace") && g:rainbow_brace != 0 + call s:DoSyn(i, a:count, "{", "}", "b") + endif + + if exists("g:rainbow_bracket") && g:rainbow_bracket != 0 + call s:DoSyn(i, a:count, "\\[", "\\]", "c") + endif + + if exists("g:rainbow_angle") && g:rainbow_angle != 0 + call s:DoSyn(i, a:count, "<", ">", "d") + endif + + let i = i + 1 + endwhile + endfun + + call s:DoSyntaxes(6) " 6 is the number of colors we have + + delfun s:DoSyn + delfun s:DoSyntaxes +endif + diff --git a/vim/plugin/taglist.vim b/vim/plugin/taglist.vim new file mode 100644 index 0000000..bcf9ad5 --- /dev/null +++ b/vim/plugin/taglist.vim @@ -0,0 +1,4497 @@ +" File: taglist.vim +" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com) +" Version: 4.4 +" Last Modified: May 24, 2007 +" Copyright: Copyright (C) 2002-2007 Yegappan Lakshmanan +" Permission is hereby granted to use and distribute this code, +" with or without modifications, provided that this copyright +" notice is copied with it. Like anything else that's free, +" taglist.vim is provided *as is* and comes with no warranty of any +" kind, either expressed or implied. In no event will the copyright +" holder be liable for any damamges resulting from the use of this +" software. +" +" 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: +" +" http://vim-taglist.sourceforge.net +" +" You can subscribe to the taglist mailing list to post your questions +" or suggestions for improvement or to report bugs. Visit the following +" page for subscribing to the mailing list: +" +" http://groups.yahoo.com/group/taglist/ +" +" For more information about using this plugin, after installing the +" taglist plugin, use the ":help taglist" command. +" +" Installation +" ------------ +" 1. Download the taglist.zip file and unzip the files to the $HOME/.vim +" or the $HOME/vimfiles or the $VIM/vimfiles directory. This should +" unzip the following two files (the directory structure should be +" preserved): +" +" plugin/taglist.vim - main taglist plugin file +" doc/taglist.txt - documentation (help) file +" +" Refer to the 'add-plugin', 'add-global-plugin' and 'runtimepath' +" Vim help pages for more details about installing Vim plugins. +" 2. Change to the $HOME/.vim/doc or $HOME/vimfiles/doc or +" $VIM/vimfiles/doc directory, start Vim and run the ":helptags ." +" command to process the taglist help 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. +" 5. Restart Vim. +" 6. You can now use the ":TlistToggle" 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 ************************ + +" Line continuation used here +let s:cpo_save = &cpo +set cpo&vim + +if !exists('loaded_taglist') + " First time loading the taglist plugin + " + " To speed up the loading of Vim, the taglist plugin uses autoload + " mechanism to load the taglist functions. + " Only define the configuration variables, user commands and some + " auto-commands and finish sourcing the file + + " 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 loaded_taglist = 'no' + let &cpo = s:cpo_save + finish + endif + + " Location of the exuberant ctags tool + if !exists('Tlist_Ctags_Cmd') + if executable('exuberant-ctags') + " On Debian Linux, exuberant ctags is installed + " as exuberant-ctags + let Tlist_Ctags_Cmd = 'exuberant-ctags' + elseif executable(' exctags') + " On Free-BSD, exuberant ctags is installed as exctags + let Tlist_Ctags_ Cmd = 'exctags' + elseif executable('ctags') + let Tlist_Ctags_Cmd = 'ctags' + elseif executable('ctags.exe') + let Tlist_Ctags_Cmd = 'ctags.exe' + elseif executable('tags') + let Tlist_Ctags_Cmd = 'tags' + else + echomsg 'Taglist: Exuberant ctags (http://ctags.sf.net) ' . + \ 'not found in PATH. Plugin is not loaded.' + " Skip loading the plugin + let loaded_taglist = 'no' + let &cpo = s:cpo_save + finish + endif + endif + + + " Automatically open the taglist window on Vim startup + if !exists('Tlist_Auto_Open') + let Tlist_Auto_Open = 0 + endif + + " When the taglist window is toggle opened, move the cursor to the + " taglist window + if !exists('Tlist_GainFocus_On_ToggleOpen') + let Tlist_GainFocus_On_ToggleOpen = 0 + endif + + " Process files even when the taglist window is not open + if !exists('Tlist_Process_File_Always') + let Tlist_Process_File_Always = 0 + endif + + if !exists('Tlist_Show_Menu') + let Tlist_Show_Menu = 0 + endif + + " Tag listing sort type - 'name' or 'order' + if !exists('Tlist_Sort_Type') + let Tlist_Sort_Type = 'order' + endif + + " Tag listing window split (horizontal/vertical) control + if !exists('Tlist_Use_Horiz_Window') + let Tlist_Use_Horiz_Window = 0 + endif + + " Open the vertically split taglist window on the left or on the right + " side. This setting is relevant only if Tlist_Use_Horiz_Window is set to + " zero (i.e. only for vertically split windows) + if !exists('Tlist_Use_Right_Window') + let Tlist_Use_Right_Window = 0 + endif + + " Increase Vim window width to display vertically split taglist window. + " For MS-Windows version of Vim running in a MS-DOS window, this must be + " set to 0 otherwise the system may hang due to a Vim limitation. + if !exists('Tlist_Inc_Winwidth') + if (has('win16') || has('win95')) && !has('gui_running') + let Tlist_Inc_Winwidth = 0 + else + let Tlist_Inc_Winwidth = 1 + endif + endif + + " Vertically split taglist window width setting + if !exists('Tlist_WinWidth') + let Tlist_WinWidth = 30 + endif + + " Horizontally split taglist window height setting + if !exists('Tlist_WinHeight') + let Tlist_WinHeight = 10 + endif + + " Display tag prototypes or tag names in the taglist window + if !exists('Tlist_Display_Prototype') + let Tlist_Display_Prototype = 0 + endif + + " Display tag scopes in the taglist window + if !exists('Tlist_Display_Tag_Scope') + let Tlist_Display_Tag_Scope = 1 + endif + + " Use single left mouse click to jump to a tag. By default this is disabled. + " Only double click using the mouse will be processed. + if !exists('Tlist_Use_SingleClick') + let Tlist_Use_SingleClick = 0 + endif + + " Control whether additional help is displayed as part of the taglist or + " not. Also, controls whether empty lines are used to separate the tag + " tree. + if !exists('Tlist_Compact_Format') + let Tlist_Compact_Format = 0 + endif + + " Exit Vim if only the taglist window is currently open. By default, this is + " set to zero. + if !exists('Tlist_Exit_OnlyWindow') + let Tlist_Exit_OnlyWindow = 0 + endif + + " Automatically close the folds for the non-active files in the taglist + " window + if !exists('Tlist_File_Fold_Auto_Close') + let Tlist_File_Fold_Auto_Close = 0 + endif + + " Close the taglist window when a tag is selected + if !exists('Tlist_Close_On_Select') + let Tlist_Close_On_Select = 0 + endif + + " Automatically update the taglist window to display tags for newly + " edited files + if !exists('Tlist_Auto_Update') + let Tlist_Auto_Update = 1 + endif + + " Automatically highlight the current tag + if !exists('Tlist_Auto_Highlight_Tag') + let Tlist_Auto_Highlight_Tag = 1 + endif + + " Automatically highlight the current tag on entering a buffer + if !exists('Tlist_Highlight_Tag_On_BufEnter') + let Tlist_Highlight_Tag_On_BufEnter = 1 + endif + + " Enable fold column to display the folding for the tag tree + if !exists('Tlist_Enable_Fold_Column') + let Tlist_Enable_Fold_Column = 1 + endif + + " Display the tags for only one file in the taglist window + if !exists('Tlist_Show_One_File') + let Tlist_Show_One_File = 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 + + " 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__" + + " Taglist debug messages + let s:tlist_msg = '' + + " Define the taglist autocommand to automatically open the taglist window + " on Vim startup + if g:Tlist_Auto_Open + autocmd VimEnter * nested call s:Tlist_Window_Check_Auto_Open() + endif + + " Refresh the taglist + if g:Tlist_Process_File_Always + autocmd BufEnter * call s:Tlist_Refresh() + endif + + if g:Tlist_Show_Menu + autocmd GUIEnter * call s:Tlist_Menu_Init() + endif + + " When the taglist buffer is created when loading a Vim session file, + " the taglist buffer needs to be initialized. The BufFilePost event + " is used to handle this case. + autocmd BufFilePost __Tag_List__ call s:Tlist_Vim_Session_Load() + + " Define the user commands to manage the taglist window + command! -nargs=0 -bar TlistToggle call s:Tlist_Window_Toggle() + command! -nargs=0 -bar TlistOpen call s:Tlist_Window_Open() + " For backwards compatiblity define the Tlist command + command! -nargs=0 -bar Tlist TlistToggle + command! -nargs=+ -complete=file TlistAddFiles + \ call s:Tlist_Add_Files() + command! -nargs=+ -complete=dir TlistAddFilesRecursive + \ call s:Tlist_Add_Files_Recursive() + command! -nargs=0 -bar TlistClose call s:Tlist_Window_Close() + command! -nargs=0 -bar TlistUpdate call s:Tlist_Update_Current_File() + command! -nargs=0 -bar TlistHighlightTag call s:Tlist_Window_Highlight_Tag( + \ fnamemodify(bufname('%'), ':p'), line('.'), 2, 1) + " For backwards compatiblity define the TlistSync command + command! -nargs=0 -bar TlistSync TlistHighlightTag + command! -nargs=* -complete=buffer TlistShowPrototype + \ echo Tlist_Get_Tag_Prototype_By_Line() + command! -nargs=* -complete=buffer TlistShowTag + \ echo Tlist_Get_Tagname_By_Line() + command! -nargs=* -complete=file TlistSessionLoad + \ call s:Tlist_Session_Load() + command! -nargs=* -complete=file TlistSessionSave + \ call s:Tlist_Session_Save() + command! -bar TlistLock let Tlist_Auto_Update=0 + command! -bar TlistUnlock let Tlist_Auto_Update=1 + + " Commands for enabling/disabling debug and to display debug messages + command! -nargs=? -complete=file -bar TlistDebug + \ call s:Tlist_Debug_Enable() + command! -nargs=0 -bar TlistUndebug call s:Tlist_Debug_Disable() + command! -nargs=0 -bar TlistMessages call s:Tlist_Debug_Show() + + " Define autocommands to autoload the taglist plugin when needed. + + " Trick to get the current script ID + map xx xx + let s:tlist_sid = substitute(maparg('xx'), '\(\d\+_\)xx$', + \ '\1', '') + unmap xx + + exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_* source ' . + \ escape(expand(''), ' ') + exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Window_* source ' . + \ escape(expand(''), ' ') + exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Menu_* source ' . + \ escape(expand(''), ' ') + exe 'autocmd FuncUndefined Tlist_* source ' . + \ escape(expand(''), ' ') + exe 'autocmd FuncUndefined TagList_* source ' . + \ escape(expand(''), ' ') + + let loaded_taglist = 'fast_load_done' + + if g:Tlist_Show_Menu && has('gui_running') + call s:Tlist_Menu_Init() + endif + + " restore 'cpo' + let &cpo = s:cpo_save + finish +endif + +if !exists('s:tlist_sid') + " Two or more versions of taglist plugin are installed. Don't + " load this version of the plugin. + finish +endif + +unlet! s:tlist_sid + +if loaded_taglist != 'fast_load_done' + " restore 'cpo' + let &cpo = s:cpo_save + finish +endif + +" Taglist plugin functionality is available +let loaded_taglist = 'available' + +"------------------- end of user configurable options -------------------- + +" Default language specific settings for supported file types and tag types +" +" Variable name format: +" +" s:tlist_def_{vim_ftype}_settings +" +" vim_ftype - Filetype detected by Vim +" +" Value format: +" +" ;:;:;... +" +" ctags_ftype - File type supported by exuberant ctags +" flag - Flag supported by exuberant ctags to generate a tag type +" name - Name of the tag type used in the taglist window to display the +" tags of this type +" + +" assembly language +let s:tlist_def_asm_settings = 'asm;d:define;l:label;m:macro;t:type' + +" aspperl language +let s:tlist_def_aspperl_settings = 'asp;f:function;s:sub;v:variable' + +" aspvbs language +let s:tlist_def_aspvbs_settings = 'asp;f:function;s:sub;v:variable' + +" awk language +let s:tlist_def_awk_settings = 'awk;f:function' + +" beta language +let s:tlist_def_beta_settings = 'beta;f:fragment;s:slot;v:pattern' + +" c language +let s:tlist_def_c_settings = 'c;d:macro;g:enum;s:struct;u:union;t:typedef;' . + \ 'v:variable;f:function' + +" c++ language +let s:tlist_def_cpp_settings = 'c++;n:namespace;v:variable;d:macro;t:typedef;' . + \ 'c:class;g:enum;s:struct;u:union;f:function' + +" c# language +let s:tlist_def_cs_settings = 'c#;d:macro;t:typedef;n:namespace;c:class;' . + \ 'E:event;g:enum;s:struct;i:interface;' . + \ 'p:properties;m:method' + +" cobol language +let s:tlist_def_cobol_settings = 'cobol;d:data;f:file;g:group;p:paragraph;' . + \ 'P:program;s:section' + +" eiffel language +let s:tlist_def_eiffel_settings = 'eiffel;c:class;f:feature' + +" erlang language +let s:tlist_def_erlang_settings = 'erlang;d:macro;r:record;m:module;f:function' + +" expect (same as tcl) language +let s:tlist_def_expect_settings = 'tcl;c:class;f:method;p:procedure' + +" fortran language +let s:tlist_def_fortran_settings = 'fortran;p:program;b:block data;' . + \ 'c:common;e:entry;i:interface;k:type;l:label;m:module;' . + \ 'n:namelist;t:derived;v:variable;f:function;s:subroutine' + +" HTML language +let s:tlist_def_html_settings = 'html;a:anchor;f:javascript function' + +" java language +let s:tlist_def_java_settings = 'java;p:package;c:class;i:interface;' . + \ 'f:field;m:method' + +" javascript language +let s:tlist_def_javascript_settings = 'javascript;f:function' + +" lisp language +let s:tlist_def_lisp_settings = 'lisp;f:function' + +" lua language +let s:tlist_def_lua_settings = 'lua;f:function' + +" makefiles +let s:tlist_def_make_settings = 'make;m:macro' + +" pascal language +let s:tlist_def_pascal_settings = 'pascal;f:function;p:procedure' + +" perl language +let s:tlist_def_perl_settings = 'perl;c:constant;l:label;p:package;s:subroutine' + +" php language +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' + +" rexx language +let s:tlist_def_rexx_settings = 'rexx;s:subroutine' + +" ruby language +let s:tlist_def_ruby_settings = 'ruby;c:class;f:method;F:function;' . + \ 'm:singleton method' + +" scheme language +let s:tlist_def_scheme_settings = 'scheme;s:set;f:function' + +" shell language +let s:tlist_def_sh_settings = 'sh;f:function' + +" C shell language +let s:tlist_def_csh_settings = 'sh;f:function' + +" Z shell language +let s:tlist_def_zsh_settings = 'sh;f:function' + +" slang language +let s:tlist_def_slang_settings = 'slang;n:namespace;f:function' + +" sml language +let s:tlist_def_sml_settings = 'sml;e:exception;c:functor;s:signature;' . + \ 'r:structure;t:type;v:value;f:function' + +" sql language +let s:tlist_def_sql_settings = 'sql;c:cursor;F:field;P:package;r:record;' . + \ 's:subtype;t:table;T:trigger;v:variable;f:function;p:procedure' + +" tcl language +let s:tlist_def_tcl_settings = 'tcl;c:class;f:method;m:method;p:procedure' + +" vera language +let s:tlist_def_vera_settings = 'vera;c:class;d:macro;e:enumerator;' . + \ 'f:function;g:enum;m:member;p:program;' . + \ 'P:prototype;t:task;T:typedef;v:variable;' . + \ 'x:externvar' + +"verilog language +let s:tlist_def_verilog_settings = 'verilog;m:module;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' + +" yacc language +let s:tlist_def_yacc_settings = 'yacc;l:label' + +"------------------- end of language specific options -------------------- + +" Vim window size is changed by the taglist plugin or not +let s:tlist_winsize_chgd = -1 +" Taglist window is maximized or not +let s:tlist_win_maximized = 0 +" Name of files in the taglist +let s:tlist_file_names='' +" Number of files in the taglist +let s:tlist_file_count = 0 +" Number of filetypes supported by taglist +let s:tlist_ftype_count = 0 +" Is taglist part of other plugins like winmanager or cream? +let s:tlist_app_name = "none" +" Are we displaying brief help text +let s:tlist_brief_help = 1 +" List of files removed on user request +let s:tlist_removed_flist = "" +" Index of current file displayed in the taglist window +let s:tlist_cur_file_idx = -1 +" Taglist menu is empty or not +let s:tlist_menu_empty = 1 + +" An autocommand is used to refresh the taglist window when entering any +" buffer. We don't want to refresh the taglist window if we are entering the +" file window from one of the taglist functions. The 'Tlist_Skip_Refresh' +" variable is used to skip the refresh of the taglist window and is set +" and cleared appropriately. +let s:Tlist_Skip_Refresh = 0 + +" Tlist_Window_Display_Help() +function! s:Tlist_Window_Display_Help() + if s:tlist_app_name == "winmanager" + " To handle a bug in the winmanager plugin, add a space at the + " last line + call setline('$', ' ') + endif + + if s:tlist_brief_help + " Add the brief help + call append(0, '" Press to display help text') + else + " Add the extensive help + call append(0, '" : Jump to tag definition') + call append(1, '" o : Jump to tag definition in new window') + call append(2, '" p : Preview the tag definition') + call append(3, '" : Display tag prototype') + call append(4, '" u : Update tag list') + call append(5, '" s : Select sort field') + call append(6, '" d : Remove file from taglist') + call append(7, '" x : Zoom-out/Zoom-in taglist window') + call append(8, '" + : Open a fold') + call append(9, '" - : Close a fold') + call append(10, '" * : Open all folds') + call append(11, '" = : Close all folds') + call append(12, '" [[ : Move to the start of previous file') + call append(13, '" ]] : Move to the start of next file') + call append(14, '" q : Close the taglist window') + call append(15, '" : Remove help text') + endif +endfunction + +" Tlist_Window_Toggle_Help_Text() +" Toggle taglist plugin help text between the full version and the brief +" version +function! s:Tlist_Window_Toggle_Help_Text() + if g:Tlist_Compact_Format + " In compact display mode, do not display help + return + endif + + " Include the empty line displayed after the help text + let brief_help_size = 1 + let full_help_size = 16 + + setlocal modifiable + + " Set report option to a huge value to prevent informational messages + " while deleting the lines + let old_report = &report + set report=99999 + + " Remove the currently highlighted tag. Otherwise, the help text + " might be highlighted by mistake + match none + + " Toggle between brief and full help text + if s:tlist_brief_help + let s:tlist_brief_help = 0 + + " Remove the previous help + exe '1,' . brief_help_size . ' delete _' + + " Adjust the start/end line numbers for the files + call s:Tlist_Window_Update_Line_Offsets(0, 1, full_help_size - brief_help_size) + else + let s:tlist_brief_help = 1 + + " Remove the previous help + exe '1,' . full_help_size . ' delete _' + + " Adjust the start/end line numbers for the files + call s:Tlist_Window_Update_Line_Offsets(0, 0, full_help_size - brief_help_size) + endif + + call s:Tlist_Window_Display_Help() + + " Restore the report option + let &report = old_report + + setlocal nomodifiable +endfunction + +" Taglist debug support +let s:tlist_debug = 0 + +" File for storing the debug messages +let s:tlist_debug_file = '' + +" Tlist_Debug_Enable +" Enable logging of taglist debug messages. +function! s:Tlist_Debug_Enable(...) + let s:tlist_debug = 1 + + " Check whether a valid file name is supplied. + if a:1 != '' + let s:tlist_debug_file = fnamemodify(a:1, ':p') + + " Empty the log file + exe 'redir! > ' . s:tlist_debug_file + redir END + + " Check whether the log file is present/created + if !filewritable(s:tlist_debug_file) + call s:Tlist_Warning_Msg('Taglist: Unable to create log file ' + \ . s:tlist_debug_file) + let s:tlist_debug_file = '' + endif + endif +endfunction + +" Tlist_Debug_Disable +" Disable logging of taglist debug messages. +function! s:Tlist_Debug_Disable(...) + let s:tlist_debug = 0 + let s:tlist_debug_file = '' +endfunction + +" Tlist_Debug_Show +" Display the taglist debug messages in a new window +function! s:Tlist_Debug_Show() + if s:tlist_msg == '' + call s:Tlist_Warning_Msg('Taglist: No debug messages') + return + endif + + " Open a new window to display the taglist debug messages + new taglist_debug.txt + " Delete all the lines (if the buffer already exists) + silent! %delete _ + " Add the messages + silent! put =s:tlist_msg + " Move the cursor to the first line + normal! gg +endfunction + +" Tlist_Log_Msg +" Log the supplied debug message along with the time +function! s:Tlist_Log_Msg(msg) + if s:tlist_debug + if s:tlist_debug_file != '' + exe 'redir >> ' . s:tlist_debug_file + silent echon strftime('%H:%M:%S') . ': ' . a:msg . "\n" + redir END + else + " Log the message into a variable + " 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('%H:%M:%S') . ': ' . + \ a:msg . "\n" + endif + endif +endfunction + +" Tlist_Warning_Msg() +" Display a message using WarningMsg highlight group +function! s:Tlist_Warning_Msg(msg) + echohl WarningMsg + echomsg a:msg + echohl None +endfunction + +" Last returned file index for file name lookup. +" Used to speed up file lookup +let s:tlist_file_name_idx_cache = -1 + +" Tlist_Get_File_Index() +" Return the index of the specified filename +function! s:Tlist_Get_File_Index(fname) + if s:tlist_file_count == 0 || a:fname == '' + return -1 + endif + + " If the new filename is same as the last accessed filename, then + " return that index + if s:tlist_file_name_idx_cache != -1 && + \ s:tlist_file_name_idx_cache < s:tlist_file_count + if s:tlist_{s:tlist_file_name_idx_cache}_filename == a:fname + " Same as the last accessed file + return s:tlist_file_name_idx_cache + endif + endif + + " First, check whether the filename is present + let s_fname = a:fname . "\n" + let i = stridx(s:tlist_file_names, s_fname) + if i == -1 + let s:tlist_file_name_idx_cache = -1 + return -1 + endif + + " Second, compute the file name index + let nl_txt = substitute(strpart(s:tlist_file_names, 0, i), "[^\n]", '', 'g') + let s:tlist_file_name_idx_cache = strlen(nl_txt) + return s:tlist_file_name_idx_cache +endfunction + +" Last returned file index for line number lookup. +" Used to speed up file lookup +let s:tlist_file_lnum_idx_cache = -1 + +" Tlist_Window_Get_File_Index_By_Linenum() +" 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_Window_Get_File_Index_By_Linenum(lnum) + call s:Tlist_Log_Msg('Tlist_Window_Get_File_Index_By_Linenum (' . a:lnum . ')') + + " First try to see whether the new line number is within the range + " of the last returned file + if s:tlist_file_lnum_idx_cache != -1 && + \ s:tlist_file_lnum_idx_cache < s:tlist_file_count + if a:lnum >= s:tlist_{s:tlist_file_lnum_idx_cache}_start && + \ a:lnum <= s:tlist_{s:tlist_file_lnum_idx_cache}_end + return s:tlist_file_lnum_idx_cache + endif + endif + + let fidx = -1 + + if g:Tlist_Show_One_File + " Displaying only one file in the taglist window. Check whether + " the line is within the tags displayed for that file + if s:tlist_cur_file_idx != -1 + if a:lnum >= s:tlist_{s:tlist_cur_file_idx}_start + \ && a:lnum <= s:tlist_{s:tlist_cur_file_idx}_end + let fidx = s:tlist_cur_file_idx + endif + + endif + else + " Do a binary search in the taglist + let left = 0 + let right = s:tlist_file_count - 1 + + while left < right + let mid = (left + right) / 2 + + if a:lnum >= s:tlist_{mid}_start && a:lnum <= s:tlist_{mid}_end + let s:tlist_file_lnum_idx_cache = mid + return mid + endif + + if a:lnum < s:tlist_{mid}_start + let right = mid - 1 + else + let left = mid + 1 + endif + endwhile + + if left >= 0 && left < s:tlist_file_count + \ && a:lnum >= s:tlist_{left}_start + \ && a:lnum <= s:tlist_{left}_end + let fidx = left + endif + endif + + let s:tlist_file_lnum_idx_cache = fidx + + return fidx +endfunction + +" Tlist_Exe_Cmd_No_Acmds +" Execute the specified Ex command after disabling autocommands +function! s:Tlist_Exe_Cmd_No_Acmds(cmd) + let old_eventignore = &eventignore + set eventignore=all + exe a:cmd + let &eventignore = old_eventignore +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 and buffers with filetype not set + if a:filename == '' || a:ftype == '' + return 1 + endif + + " Skip files which are not supported by exuberant ctags + " First check whether default settings for this filetype are available. + " If it is not available, then check whether user specified settings are + " available. If both are not available, then don't list the tags for this + " filetype + let var = 's:tlist_def_' . a:ftype . '_settings' + if !exists(var) + let var = 'g:tlist_' . a:ftype . '_settings' + if !exists(var) + return 1 + endif + endif + + " Skip files which are not readable or files which are not yet stored + " to the disk + if !filereadable(a:filename) + return 1 + endif + + return 0 +endfunction + +" Tlist_User_Removed_File +" Returns 1 if a file is removed by a user from the taglist +function! s:Tlist_User_Removed_File(filename) + return stridx(s:tlist_removed_flist, a:filename . "\n") != -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 idx = stridx(s:tlist_removed_flist, a:filename . "\n") + let text_before = strpart(s:tlist_removed_flist, 0, idx) + let rem_text = strpart(s:tlist_removed_flist, idx) + let next_idx = stridx(rem_text, "\n") + let text_after = strpart(rem_text, next_idx + 1) + + let s:tlist_removed_flist = text_before . text_after + 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' + if exists(var) + " User specified ctags arguments + let settings = {var} . ';' + else + " Default ctags arguments + let var = 's:tlist_def_' . a:ftype . '_settings' + if !exists(var) + " No default settings for this file type. This filetype is + " not supported + return 0 + endif + let settings = s:tlist_def_{a:ftype}_settings . ';' + endif + + let msg = 'Taglist: Invalid ctags option setting - ' . settings + + " Format of the option that specifies the filetype and ctags arugments: + " + " ;flag1:name1;flag2:name2;flag3:name3 + " + + " Extract the file type to pass to ctags. This may be different from the + " file type detected by Vim + let pos = stridx(settings, ';') + if pos == -1 + call s:Tlist_Warning_Msg(msg) + return 0 + endif + let ctags_ftype = strpart(settings, 0, pos) + if ctags_ftype == '' + call s:Tlist_Warning_Msg(msg) + return 0 + endif + " Make sure a valid filetype is supplied. If the user didn't specify a + " valid filetype, then the ctags option settings may be treated as the + " filetype + if ctags_ftype =~ ':' + call s:Tlist_Warning_Msg(msg) + return 0 + endif + + " Remove the file type from settings + let settings = strpart(settings, pos + 1) + if settings == '' + call s:Tlist_Warning_Msg(msg) + return 0 + endif + + " Process all the specified ctags flags. The format is + " flag1:name1;flag2:name2;flag3:name3 + let ctags_flags = '' + let cnt = 0 + while settings != '' + " Extract the flag + let pos = stridx(settings, ':') + if pos == -1 + call s:Tlist_Warning_Msg(msg) + return 0 + endif + let flag = strpart(settings, 0, pos) + if flag == '' + call s:Tlist_Warning_Msg(msg) + return 0 + endif + " Remove the flag from settings + let settings = strpart(settings, pos + 1) + + " Extract the tag type name + let pos = stridx(settings, ';') + if pos == -1 + call s:Tlist_Warning_Msg(msg) + return 0 + endif + let name = strpart(settings, 0, pos) + if name == '' + call s:Tlist_Warning_Msg(msg) + return 0 + endif + let settings = strpart(settings, pos + 1) + + let cnt = cnt + 1 + + let s:tlist_{a:ftype}_{cnt}_name = flag + let s:tlist_{a:ftype}_{cnt}_fullname = name + let ctags_flags = ctags_flags . flag + endwhile + + let s:tlist_{a:ftype}_ctags_args = '--language-force=' . ctags_ftype . + \ ' --' . ctags_ftype . '-types=' . ctags_flags + let s:tlist_{a:ftype}_count = cnt + let s:tlist_{a:ftype}_ctags_flags = ctags_flags + + " Save the filetype name + let s:tlist_ftype_{s:tlist_ftype_count}_name = a:ftype + let s:tlist_ftype_count = s:tlist_ftype_count + 1 + + return 1 +endfunction + +" Tlist_Get_Filetype +" Determine the filetype for the specified file +function! s:Tlist_Get_Filetype(fname) + " Ignore the filetype autocommands + let old_eventignore = &eventignore + set eventignore=FileType + + " Save the 'filetype', as this will be changed temporarily + let old_filetype = &filetype + + " Run the filetypedetect group of autocommands to determine + " the filetype + exe 'doautocmd filetypedetect BufRead ' . a:fname + + " Save the detected filetype + let ftype = &filetype + + " Restore the previous state + let &filetype = old_filetype + let &eventignore = old_eventignore + + return ftype +endfunction + +" Tlist_Get_Buffer_Filetype +" Get the filetype for the specified buffer +function! s:Tlist_Get_Buffer_Filetype(bnum) + if bufloaded(a:bnum) + " For loaded buffers, the 'filetype' is already determined + return getbufvar(a:bnum, '&filetype') + endif + + " For unloaded buffers, if the 'filetype' option is set, return it + let ftype = getbufvar(a:bnum, '&filetype') + if ftype != '' + return ftype + endif + + " Skip non-existent buffers + if !bufexists(a:bnum) + return '' + endif + + " For buffers whose filetype is not yet determined, try to determine + " the filetype + let bname = bufname(a:bnum) + + return s:Tlist_Get_Filetype(bname) +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 + 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 + + let s:tlist_{a:fidx}_tag_count = 0 + + " Discard information about tag type groups + let i = 1 + while i <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{i}_name + if s:tlist_{a:fidx}_{ttype} != '' + let fidx_ttype = 's:tlist_' . a:fidx . '_' . ttype + let {fidx_ttype} = '' + let {fidx_ttype}_offset = 0 + let cnt = {fidx_ttype}_count + let {fidx_ttype}_count = 0 + let j = 1 + while j <= cnt + 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_Window_Update_Line_Offsets +" Update the line offsets for tags for files starting from start_idx +" and displayed in the taglist window by the specified offset +function! s:Tlist_Window_Update_Line_Offsets(start_idx, increment, offset) + let i = a:start_idx + + while i < s:tlist_file_count + if s:tlist_{i}_visible + " Update the start/end line number only if the file is visible + if a:increment + let s:tlist_{i}_start = s:tlist_{i}_start + a:offset + let s:tlist_{i}_end = s:tlist_{i}_end + a:offset + else + let s:tlist_{i}_start = s:tlist_{i}_start - a:offset + let s:tlist_{i}_end = s:tlist_{i}_end - a:offset + endif + endif + let i = i + 1 + endwhile +endfunction + +" Tlist_Discard_FileInfo +" Discard the stored information for a file +function! s:Tlist_Discard_FileInfo(fidx) + call s:Tlist_Log_Msg('Tlist_Discard_FileInfo (' . + \ s:tlist_{a:fidx}_filename . ')') + call s:Tlist_Discard_TagInfo(a:fidx) + + let ftype = s:tlist_{a:fidx}_filetype + + let i = 1 + while i <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{i}_name + unlet! s:tlist_{a:fidx}_{ttype} + unlet! s:tlist_{a:fidx}_{ttype}_offset + unlet! s:tlist_{a:fidx}_{ttype}_count + let i = i + 1 + endwhile + + unlet! s:tlist_{a:fidx}_filename + unlet! s:tlist_{a:fidx}_sort_type + unlet! s:tlist_{a:fidx}_filetype + unlet! s:tlist_{a:fidx}_mtime + unlet! s:tlist_{a:fidx}_start + unlet! s:tlist_{a:fidx}_end + unlet! s:tlist_{a:fidx}_valid + unlet! s:tlist_{a:fidx}_visible + unlet! s:tlist_{a:fidx}_tag_count + unlet! s:tlist_{a:fidx}_menu_cmd +endfunction + +" Tlist_Window_Remove_File_From_Display +" Remove the specified file from display +function! s:Tlist_Window_Remove_File_From_Display(fidx) + call s:Tlist_Log_Msg('Tlist_Window_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 + endif + + " Remove the tags displayed for the specified file from the window + let start = s:tlist_{a:fidx}_start + " Include the empty line after the last line also + if g:Tlist_Compact_Format + let end = s:tlist_{a:fidx}_end + else + let end = s:tlist_{a:fidx}_end + 1 + endif + + setlocal modifiable + exe 'silent! ' . start . ',' . end . 'delete _' + setlocal nomodifiable + + " Correct the start and end line offsets for all the files following + " this file, as the tags for this file are removed + call s:Tlist_Window_Update_Line_Offsets(a:fidx + 1, 0, end - start + 1) +endfunction + +" Tlist_Remove_File +" Remove the file under the cursor or the specified file index +" user_request - User requested to remove the file from taglist +function! s:Tlist_Remove_File(file_idx, user_request) + let fidx = a:file_idx + + if fidx == -1 + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.')) + if fidx == -1 + return + endif + endif + call s:Tlist_Log_Msg('Tlist_Remove_File (' . + \ s:tlist_{fidx}_filename . ', ' . a:user_request . ')') + + let save_winnr = winnr() + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + " Taglist window is open, remove the file from display + + if save_winnr != winnum + let old_eventignore = &eventignore + set eventignore=all + exe winnum . 'wincmd w' + endif + + call s:Tlist_Window_Remove_File_From_Display(fidx) + + if save_winnr != winnum + exe save_winnr . 'wincmd w' + let &eventignore = old_eventignore + endif + endif + + let fname = s:tlist_{fidx}_filename + + if a:user_request + " As the user requested to remove the file from taglist, + " add it to the removed list + call s:Tlist_Update_Remove_List(fname, 1) + endif + + " Remove the file name from the taglist list of filenames + let idx = stridx(s:tlist_file_names, fname . "\n") + let text_before = strpart(s:tlist_file_names, 0, idx) + let rem_text = strpart(s:tlist_file_names, idx) + let next_idx = stridx(rem_text, "\n") + let text_after = strpart(rem_text, next_idx + 1) + let s:tlist_file_names = text_before . text_after + + call s:Tlist_Discard_FileInfo(fidx) + + " Shift all the file variables by one index + let i = fidx + 1 + + while i < s:tlist_file_count + let j = i - 1 + + let s:tlist_{j}_filename = s:tlist_{i}_filename + let s:tlist_{j}_sort_type = s:tlist_{i}_sort_type + let s:tlist_{j}_filetype = s:tlist_{i}_filetype + let s:tlist_{j}_mtime = s:tlist_{i}_mtime + let s:tlist_{j}_start = s:tlist_{i}_start + let s:tlist_{j}_end = s:tlist_{i}_end + let s:tlist_{j}_valid = s:tlist_{i}_valid + let s:tlist_{j}_visible = s:tlist_{i}_visible + let s:tlist_{j}_tag_count = s:tlist_{i}_tag_count + let s:tlist_{j}_menu_cmd = s:tlist_{i}_menu_cmd + + let k = 1 + while k <= s:tlist_{j}_tag_count + 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_By_Tag(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 + + let ftype = s:tlist_{i}_filetype + + let k = 1 + while k <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{k}_name + let s:tlist_{j}_{ttype} = s:tlist_{i}_{ttype} + let s:tlist_{j}_{ttype}_offset = s:tlist_{i}_{ttype}_offset + let s:tlist_{j}_{ttype}_count = s:tlist_{i}_{ttype}_count + if s:tlist_{j}_{ttype} != '' + let l = 1 + while l <= s:tlist_{j}_{ttype}_count + let s:tlist_{j}_{ttype}_{l} = s:tlist_{i}_{ttype}_{l} + let l = l + 1 + endwhile + endif + let k = k + 1 + endwhile + + " As the file and tag information is copied to the new index, + " discard the previous information + call s:Tlist_Discard_FileInfo(i) + + let i = i + 1 + endwhile + + " Reduce the number of files displayed + let s:tlist_file_count = s:tlist_file_count - 1 + + if g:Tlist_Show_One_File + " If the tags for only one file is displayed and if we just + " now removed that file, then invalidate the current file idx + if s:tlist_cur_file_idx == fidx + let s:tlist_cur_file_idx = -1 + endif + endif +endfunction + +" Tlist_Window_Goto_Window +" Goto the taglist window +function! s:Tlist_Window_Goto_Window() + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + if winnr() != winnum + call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w') + endif + endif +endfunction + +" Tlist_Window_Create +" Create a new taglist window. If it is already open, jump to it +function! s:Tlist_Window_Create() + call s:Tlist_Log_Msg('Tlist_Window_Create()') + " If the window is open, jump to it + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + " Jump to the existing window + if winnr() != winnum + exe winnum . 'wincmd w' + endif + return + endif + + " If used with winmanager don't open windows. Winmanager will handle + " the window/buffer management + if s:tlist_app_name == "winmanager" + return + endif + + " Create a new window. If user prefers a horizontal window, then open + " a horizontally split window. Otherwise open a vertically split + " window + if g:Tlist_Use_Horiz_Window + " Open a horizontally split window + let win_dir = 'botright' + " Horizontal window height + let win_size = g:Tlist_WinHeight + else + if s:tlist_winsize_chgd == -1 + " Open a vertically split window. Increase the window size, if + " needed, to accomodate the new window + if g:Tlist_Inc_Winwidth && + \ &columns < (80 + g:Tlist_WinWidth) + " Save the original window position + let s:tlist_pre_winx = getwinposx() + let s:tlist_pre_winy = getwinposy() + + " one extra column is needed to include the vertical split + let &columns= &columns + g:Tlist_WinWidth + 1 + + let s:tlist_winsize_chgd = 1 + else + let s:tlist_winsize_chgd = 0 + endif + endif + + if g:Tlist_Use_Right_Window + " Open the window at the rightmost place + let win_dir = 'botright vertical' + else + " Open the window at the leftmost place + let win_dir = 'topleft vertical' + endif + let win_size = g:Tlist_WinWidth + endif + + " If the tag listing temporary buffer already exists, then reuse it. + " Otherwise create a new buffer + let bufnum = bufnr(g:TagList_title) + if bufnum == -1 + " Create a new buffer + let wcmd = g:TagList_title + else + " Edit the existing buffer + let wcmd = '+buffer' . bufnum + endif + + " Create the taglist window + exe 'silent! ' . win_dir . ' ' . win_size . 'split ' . wcmd + + " Save the new window position + let s:tlist_winx = getwinposx() + let s:tlist_winy = getwinposy() + + " Initialize the taglist window + call s:Tlist_Window_Init() +endfunction + +" Tlist_Window_Zoom +" Zoom (maximize/minimize) the taglist window +function! s:Tlist_Window_Zoom() + if s:tlist_win_maximized + " Restore the window back to the previous size + if g:Tlist_Use_Horiz_Window + exe 'resize ' . g:Tlist_WinHeight + else + exe 'vert resize ' . g:Tlist_WinWidth + endif + let s:tlist_win_maximized = 0 + else + " Set the window size to the maximum possible without closing other + " windows + if g:Tlist_Use_Horiz_Window + resize + else + vert resize + endif + let s:tlist_win_maximized = 1 + endif +endfunction + +" Tlist_Ballon_Expr +" When the mouse cursor is over a tag in the taglist window, display the +" tag prototype (balloon) +function! Tlist_Ballon_Expr() + " Get the file index + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(v:beval_lnum) + if fidx == -1 + return '' + endif + + " Get the tag output line for the current tag + let tidx = s:Tlist_Window_Get_Tag_Index(fidx, v:beval_lnum) + if tidx == 0 + return '' + endif + + " Get the tag search pattern and display it + return s:Tlist_Get_Tag_Prototype(fidx, tidx) +endfunction + +" Tlist_Window_Check_Width +" Check the width of the taglist window. For horizontally split windows, the +" 'winfixheight' option is used to fix the height of the window. For +" vertically split windows, Vim doesn't support the 'winfixwidth' option. So +" need to handle window width changes from this function. +function! s:Tlist_Window_Check_Width() + let tlist_winnr = bufwinnr(g:TagList_title) + if tlist_winnr == -1 + return + endif + + let width = winwidth(tlist_winnr) + if width != g:Tlist_WinWidth + call s:Tlist_Log_Msg("Tlist_Window_Check_Width: Changing window " . + \ "width from " . width . " to " . g:Tlist_WinWidth) + let save_winnr = winnr() + if save_winnr != tlist_winnr + call s:Tlist_Exe_Cmd_No_Acmds(tlist_winnr . 'wincmd w') + endif + exe 'vert resize ' . g:Tlist_WinWidth + if save_winnr != tlist_winnr + call s:Tlist_Exe_Cmd_No_Acmds('wincmd p') + endif + endif +endfunction + +" Tlist_Window_Exit_Only_Window +" If the 'Tlist_Exit_OnlyWindow' option is set, then exit Vim if only the +" taglist window is present. +function! s:Tlist_Window_Exit_Only_Window() + " Before quitting Vim, delete the taglist buffer so that + " the '0 mark is correctly set to the previous buffer. + if v:version < 700 + if winbufnr(2) == -1 + bdelete + quit + endif + else + if winbufnr(2) == -1 + if tabpagenr('$') == 1 + " Only one tag page is present + bdelete + quit + else + " More than one tab page is present. Close only the current + " tab page + close + endif + endif + endif +endfunction + +" Tlist_Window_Init +" Set the default options for the taglist window +function! s:Tlist_Window_Init() + call s:Tlist_Log_Msg('Tlist_Window_Init()') + + " The 'readonly' option should not be set for the taglist buffer. + " If Vim is started as "view/gview" or if the ":view" command is + " used, then the 'readonly' option is set for all the buffers. + " Unset it for the taglist buffer + setlocal noreadonly + + " Set the taglist buffer filetype to taglist + setlocal filetype=taglist + + " Define taglist window element highlighting + 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 default link TagListTagName Search + endif + " Colors to highlight comments and titles + if hlexists('MyTagListComment') + highlight link TagListComment MyTagListComment + else + highlight clear TagListComment + highlight default link TagListComment Comment + endif + if hlexists('MyTagListTitle') + highlight link TagListTitle MyTagListTitle + else + highlight clear TagListTitle + highlight default link TagListTitle Title + endif + if hlexists('MyTagListFileName') + highlight link TagListFileName MyTagListFileName + else + highlight clear TagListFileName + highlight default TagListFileName guibg=Grey ctermbg=darkgray + \ guifg=white ctermfg=white + endif + if hlexists('MyTagListTagScope') + highlight link TagListTagScope MyTagListTagScope + else + highlight clear TagListTagScope + highlight default link TagListTagScope Identifier + endif + else + highlight default TagListTagName term=reverse cterm=reverse + endif + + " Folding related settings + setlocal foldenable + setlocal foldminlines=0 + setlocal foldmethod=manual + setlocal foldlevel=9999 + 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 + silent! setlocal buftype=nofile + if s:tlist_app_name == "none" + silent! setlocal bufhidden=delete + endif + silent! setlocal noswapfile + " Due to a bug in Vim 6.0, the winbufnr() function fails for unlisted + " buffers. So if the taglist buffer is unlisted, multiple taglist + " windows will be opened. This bug is fixed in Vim 6.1 and above + if v:version >= 601 + silent! setlocal nobuflisted + endif + endif + + silent! setlocal nowrap + + " If the 'number' option is set in the source window, it will affect the + " taglist window. So forcefully disable 'number' option for the taglist + " window + silent! setlocal nonumber + + " Use fixed height when horizontally split window is used + if g:Tlist_Use_Horiz_Window + if v:version >= 602 + set winfixheight + endif + endif + if !g:Tlist_Use_Horiz_Window && v:version >= 700 + set winfixwidth + endif + + " Setup balloon evaluation to display tag prototype + if v:version >= 700 && has('balloon_eval') + setlocal balloonexpr=Tlist_Ballon_Expr() + set ballooneval + endif + + " 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_Window_Jump_To_Tag('useopen') + nnoremap o + \ :call Tlist_Window_Jump_To_Tag('newwin') + nnoremap p + \ :call Tlist_Window_Jump_To_Tag('preview') + nnoremap P + \ :call Tlist_Window_Jump_To_Tag('prevwin') + if v:version >= 700 + nnoremap t + \ :call Tlist_Window_Jump_To_Tag('checktab') + nnoremap + \ :call Tlist_Window_Jump_To_Tag('newtab') + endif + nnoremap <2-LeftMouse> + \ :call Tlist_Window_Jump_To_Tag('useopen') + nnoremap s + \ :call Tlist_Change_Sort('cmd', 'toggle', '') + nnoremap + :silent! foldopen + nnoremap - :silent! foldclose + nnoremap * :silent! %foldopen! + nnoremap = :silent! %foldclose + nnoremap :silent! foldopen + nnoremap :silent! foldclose + nnoremap :silent! %foldopen! + nnoremap :call Tlist_Window_Show_Info() + nnoremap u :call Tlist_Window_Update_File() + nnoremap d :call Tlist_Remove_File(-1, 1) + nnoremap x :call Tlist_Window_Zoom() + nnoremap [[ :call Tlist_Window_Move_To_File(-1) + nnoremap :call Tlist_Window_Move_To_File(-1) + nnoremap ]] :call Tlist_Window_Move_To_File(1) + nnoremap :call Tlist_Window_Move_To_File(1) + nnoremap :call Tlist_Window_Toggle_Help_Text() + nnoremap q :close + + " Insert mode mappings + inoremap + \ :call Tlist_Window_Jump_To_Tag('useopen') + " Windows needs return + inoremap + \ :call Tlist_Window_Jump_To_Tag('useopen') + inoremap o + \ :call Tlist_Window_Jump_To_Tag('newwin') + inoremap p + \ :call Tlist_Window_Jump_To_Tag('preview') + inoremap P + \ :call Tlist_Window_Jump_To_Tag('prevwin') + if v:version >= 700 + inoremap t + \ :call Tlist_Window_Jump_To_Tag('checktab') + inoremap + \ :call Tlist_Window_Jump_To_Tag('newtab') + endif + inoremap <2-LeftMouse> + \ :call Tlist_Window_Jump_To_Tag('useopen') + inoremap s + \ :call Tlist_Change_Sort('cmd', 'toggle', '') + inoremap + :silent! foldopen + inoremap - :silent! foldclose + inoremap * :silent! %foldopen! + inoremap = :silent! %foldclose + inoremap :silent! foldopen + inoremap :silent! foldclose + inoremap :silent! %foldopen! + inoremap :call + \ Tlist_Window_Show_Info() + inoremap u + \ :call Tlist_Window_Update_File() + inoremap d :call Tlist_Remove_File(-1, 1) + inoremap x :call Tlist_Window_Zoom() + inoremap [[ :call Tlist_Window_Move_To_File(-1) + inoremap :call Tlist_Window_Move_To_File(-1) + inoremap ]] :call Tlist_Window_Move_To_File(1) + inoremap :call Tlist_Window_Move_To_File(1) + inoremap :call Tlist_Window_Toggle_Help_Text() + inoremap q :close + + " Map single left mouse click if the user wants this functionality + if g:Tlist_Use_SingleClick == 1 + " Contributed by Bindu Wavell + " attempt to perform single click mapping, it would be much + " nicer if we could nnoremap ... however vim does + " not fire the when you use the mouse + " to enter a buffer. + let clickmap = ':if bufname("%") =~ "__Tag_List__" ' . + \ 'call Tlist_Window_Jump_To_Tag("useopen") ' . + \ ' endif ' + if maparg('', 'n') == '' + " no mapping for leftmouse + exe ':nnoremap ' . clickmap + else + " we have a mapping + let mapcmd = ':nnoremap ' + let mapcmd = mapcmd . substitute(substitute( + \ maparg('', 'n'), '|', '', 'g'), + \ '\c^', '', '') + let mapcmd = mapcmd . clickmap + exe mapcmd + endif + endif + + " Define the taglist autocommands + augroup TagListAutoCmds + autocmd! + " Display the tag prototype for the tag under the cursor. + autocmd CursorHold __Tag_List__ call s:Tlist_Window_Show_Info() + " Highlight the current tag periodically + autocmd CursorHold * silent call s:Tlist_Window_Highlight_Tag( + \ fnamemodify(bufname('%'), ':p'), line('.'), 1, 0) + + " Adjust the Vim window width when taglist window is closed + autocmd BufUnload __Tag_List__ call s:Tlist_Post_Close_Cleanup() + " Close the fold for this buffer when leaving the buffer + if g:Tlist_File_Fold_Auto_Close + autocmd BufEnter * silent + \ call s:Tlist_Window_Open_File_Fold(expand('')) + endif + " Exit Vim itself if only the taglist window is present (optional) + if g:Tlist_Exit_OnlyWindow + autocmd BufEnter __Tag_List__ nested + \ call s:Tlist_Window_Exit_Only_Window() + endif + 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 s:Tlist_Refresh() + endif + + if !g:Tlist_Use_Horiz_Window + if v:version < 700 + autocmd WinEnter * call s:Tlist_Window_Check_Width() + endif + endif + augroup end + + " Restore the previous cpoptions settings + let &cpoptions = old_cpoptions +endfunction + +" Tlist_Window_Refresh +" Display the tags for all the files in the taglist window +function! s:Tlist_Window_Refresh() + call s:Tlist_Log_Msg('Tlist_Window_Refresh()') + " Set report option to a huge value to prevent informational messages + " while deleting the lines + let old_report = &report + set report=99999 + + " Mark the buffer as modifiable + setlocal modifiable + + " Delete the contents of the buffer to the black-hole register + silent! %delete _ + + " 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_Window_Display_Help() + endif + + " Mark the buffer as not modifiable + setlocal nomodifiable + + " Restore the report option + let &report = old_report + + " 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 + + " 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_Window_Refresh_File(s:tlist_{i}_filename, + \ s:tlist_{i}_filetype) + let i = i + 1 + endwhile + + if g:Tlist_Auto_Update + " Add and list the tags for all buffers in the Vim buffer list + let i = 1 + let last_bufnum = bufnr('$') + while i <= last_bufnum + if buflisted(i) + let fname = fnamemodify(bufname(i), ':p') + let ftype = s:Tlist_Get_Buffer_Filetype(i) + " If the file doesn't support tag listing, skip it + if !s:Tlist_Skip_File(fname, ftype) + call s:Tlist_Window_Refresh_File(fname, ftype) + endif + endif + let i = i + 1 + endwhile + endif + + " 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 + + " Move the cursor to the top of the taglist window + normal! gg +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 + let s:tlist_{i}_visible = 0 + let i = i + 1 + endwhile + + " Remove the taglist autocommands + silent! autocmd! TagListAutoCmds + + " Clear all the highlights + match none + + 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 + if hasmapto('') + nunmap + endif + endif + + if s:tlist_app_name != "winmanager" + if g:Tlist_Use_Horiz_Window || g:Tlist_Inc_Winwidth == 0 || + \ s:tlist_winsize_chgd != 1 || + \ &columns < (80 + g:Tlist_WinWidth) + " No need to adjust window width if using horizontally split taglist + " window or if columns is less than 101 or if the user chose not to + " adjust the window width + else + " If the user didn't manually move the window, then restore the window + " position to the pre-taglist position + if s:tlist_pre_winx != -1 && s:tlist_pre_winy != -1 && + \ getwinposx() == s:tlist_winx && + \ getwinposy() == s:tlist_winy + exe 'winpos ' . s:tlist_pre_winx . ' ' . s:tlist_pre_winy + endif + + " Adjust the Vim window width + let &columns= &columns - (g:Tlist_WinWidth + 1) + endif + endif + + let s:tlist_winsize_chgd = -1 + + " Reset taglist state variables + if s:tlist_app_name == "winmanager" + let s:tlist_app_name = "none" + endif + let s:tlist_window_initialized = 0 +endfunction + +" Tlist_Window_Refresh_File() +" List the tags defined in the specified file in a Vim window +function! s:Tlist_Window_Refresh_File(filename, ftype) + call s:Tlist_Log_Msg('Tlist_Window_Refresh_File (' . a:filename . ')') + " First check whether the file already exists + let fidx = s:Tlist_Get_File_Index(a:filename) + if fidx != -1 + let file_listed = 1 + else + let file_listed = 0 + endif + + 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 + if s:Tlist_User_Removed_File(a:filename) + return + endif + endif + + 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 foldclosed('.') != -1 + exe "silent! " . s:tlist_{fidx}_start . "," . + \ s:tlist_{fidx}_end . "foldopen!" + endif + return + endif + + " Discard and remove the tags for this file from display + call s:Tlist_Discard_TagInfo(fidx) + call s:Tlist_Window_Remove_File_From_Display(fidx) + endif + + " Process and generate a list of tags defined in the file + if !file_listed || !s:tlist_{fidx}_valid + let ret_fidx = s:Tlist_Process_File(a:filename, a:ftype) + if ret_fidx == -1 + return + endif + let fidx = ret_fidx + endif + + " Set report option to a huge value to prevent informational messages + " while adding lines to the taglist window + let old_report = &report + set report=99999 + + if g:Tlist_Show_One_File + " Remove the previous file + if s:tlist_cur_file_idx != -1 + call s:Tlist_Window_Remove_File_From_Display(s:tlist_cur_file_idx) + let s:tlist_{s:tlist_cur_file_idx}_visible = 0 + let s:tlist_{s:tlist_cur_file_idx}_start = 0 + let s:tlist_{s:tlist_cur_file_idx}_end = 0 + endif + let s:tlist_cur_file_idx = fidx + endif + + " Mark the buffer as modifiable + setlocal modifiable + + " Add new files to the end of the window. For existing files, add them at + " the same line where they were previously present. If the file is not + " visible, then add it at the end + if s:tlist_{fidx}_start == 0 || !s:tlist_{fidx}_visible + if g:Tlist_Compact_Format + let s:tlist_{fidx}_start = line('$') + else + let s:tlist_{fidx}_start = line('$') + 1 + endif + endif + + let s:tlist_{fidx}_visible = 1 + + " Goto the line where this file should be placed + if g:Tlist_Compact_Format + exe s:tlist_{fidx}_start + else + exe s:tlist_{fidx}_start - 1 + endif + + let txt = fnamemodify(s:tlist_{fidx}_filename, ':t') . ' (' . + \ fnamemodify(s:tlist_{fidx}_filename, ':p:h') . ')' + if g:Tlist_Compact_Format == 0 + silent! put =txt + else + silent! put! =txt + " Move to the next line + exe line('.') + 1 + endif + let file_start = s:tlist_{fidx}_start + + " Add the tag names grouped by tag type to the buffer with a title + let i = 1 + 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 + 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 + silent! put =txt + else + let ttype_start_lnum = line('.') + silent! put! =txt + endif + silent! put =ttype_txt + + let {fidx_ttype}_offset = ttype_start_lnum - file_start + + " create a fold for this tag type + 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 + let i = i + 1 + endwhile + + if s:tlist_{fidx}_tag_count == 0 + if g:Tlist_Compact_Format == 0 + silent! put ='' + endif + endif + + let s:tlist_{fidx}_end = line('.') - 1 + + " Create a fold for the entire file + 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 + + if s:tlist_app_name == "winmanager" + " To handle a bug in the winmanager plugin, add a space at the + " last line + call setline('$', ' ') + endif + + " Mark the buffer as not modifiable + setlocal nomodifiable + + " Restore the report option + let &report = old_report + + " Update the start and end line numbers for all the files following this + " file + let start = s:tlist_{fidx}_start + " include the empty line after the last line + if g:Tlist_Compact_Format + let end = s:tlist_{fidx}_end + else + let end = s:tlist_{fidx}_end + 1 + endif + call s:Tlist_Window_Update_Line_Offsets(fidx + 1, 1, end - start + 1) + + " 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 + " Add the new file name to the taglist list of file names + let s:tlist_file_names = s:tlist_file_names . a:filename . "\n" + + " Initialize the file variables + let s:tlist_{fidx}_filename = a:filename + let s:tlist_{fidx}_sort_type = g:Tlist_Sort_Type + let s:tlist_{fidx}_filetype = a:ftype + let s:tlist_{fidx}_mtime = -1 + let s:tlist_{fidx}_start = 0 + let s:tlist_{fidx}_end = 0 + let s:tlist_{fidx}_valid = 0 + let s:tlist_{fidx}_visible = 0 + let s:tlist_{fidx}_tag_count = 0 + let s:tlist_{fidx}_menu_cmd = '' + + " Initialize the tag type variables + let i = 1 + while i <= s:tlist_{a:ftype}_count + let ttype = s:tlist_{a:ftype}_{i}_name + let s:tlist_{fidx}_{ttype} = '' + let s:tlist_{fidx}_{ttype}_offset = 0 + let s:tlist_{fidx}_{ttype}_count = 0 + let i = i + 1 + endwhile + + return fidx +endfunction + +" Tlist_Get_Tag_Type_By_Tag +" Return the tag type for the specified tag index +function! s:Tlist_Get_Tag_Type_By_Tag(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, given the tag index +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) + + " Make sure the tag type is a valid and supported one + if ttype == '' || stridx(s:ctags_flags, ttype) == -1 + " Line is not in proper tags format or 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) + 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 + + " If the tag types for this filetype are not yet created, then create + " them now + let var = 's:tlist_' . a:ftype . '_count' + if !exists(var) + if s:Tlist_FileType_Init(a:ftype) == 0 + return -1 + endif + endif + + " If this file is already processed, then use the cached values + let fidx = s:Tlist_Get_File_Index(a:filename) + if fidx == -1 + " First time, this file is loaded + let fidx = s:Tlist_Init_File(a:filename, a:ftype) + else + " File was previously processed. Discard the tag information + call s:Tlist_Discard_TagInfo(fidx) + endif + + let s:tlist_{fidx}_valid = 1 + + " Exuberant ctags arguments to generate a tag list + let ctags_args = ' -f - --format=2 --excmd=pattern --fields=nks ' + + " Form the ctags argument depending on the sort type + if s:tlist_{fidx}_sort_type == 'name' + let ctags_args = ctags_args . '--sort=yes' + else + let ctags_args = ctags_args . '--sort=no' + endif + + " Add the filetype specific arguments + let ctags_args = ctags_args . ' ' . s:tlist_{a:ftype}_ctags_args + + " Ctags command to produce output with regexp for locating the tags + let ctags_cmd = g:Tlist_Ctags_Cmd . ctags_args + let ctags_cmd = ctags_cmd . ' "' . a:filename . '"' + + if &shellxquote == '"' + " Double-quotes within double-quotes will not work in the + " command-line.If the 'shellxquote' option is set to double-quotes, + " then escape the double-quotes in the ctags command-line. + let ctags_cmd = escape(ctags_cmd, '"') + endif + + " 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 old_shellslash = &shellslash + set noshellslash + endif + + if has('win32') && !has('win32unix') && !has('win95') + \ && (&shell =~ 'cmd.exe') + " Windows does not correctly deal with commands that have more than 1 + " set of double quotes. It will strip them all resulting in: + " 'C:\Program' is not recognized as an internal or external command + " operable program or batch file. To work around this, place the + " command inside a batch file and call the batch file. + " Do this only on Win2K, WinXP and above. + " Contributed by: David Fishburn. + let s:taglist_tempfile = fnamemodify(tempname(), ':h') . + \ '\taglist.cmd' + exe 'redir! > ' . s:taglist_tempfile + silent echo ctags_cmd + redir END + + call s:Tlist_Log_Msg('Cmd inside batch file: ' . ctags_cmd) + let ctags_cmd = '"' . s:taglist_tempfile . '"' + 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 = old_shellslash + endif + + if exists('s:taglist_tempfile') + " Delete the temporary cmd file created on MS-Windows + call delete(s:taglist_tempfile) + endif + + " Handle errors + if v:shell_error + let msg = "Taglist: Failed to generate tags for " . a:filename + call s:Tlist_Warning_Msg(msg) + if cmd_output != '' + call s:Tlist_Warning_Msg(cmd_output) + endif + return fidx + endif + + " Store the modification time for the file + let s:tlist_{fidx}_mtime = getftime(a:filename) + + " No tags for current file + if cmd_output == '' + call s:Tlist_Log_Msg('No tags defined in ' . a:filename) + return fidx + endif + + call s:Tlist_Log_Msg('Generated tags information for ' . a:filename) + + 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 + + " 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]\\+\\)\n", + \ '\=s:Tlist_Parse_Tagline(submatch(1))', 'g') + + " Save the number of tags for this file + let s:tlist_{fidx}_tag_count = s:tidx + + " 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 + + 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 one_line == '' + " Line is not in proper tags format + continue + endif + + " Extract the tag type + let ttype = s:Tlist_Extract_Tagtype(one_line) + + " Make sure the tag type is a valid and supported one + if ttype == '' || stridx(ctags_flags, ttype) == -1 + " Line is not in proper tags format or 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 + + " 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 + 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 + +" Tlist_Update_File +" Update the tags for a file (if needed) +function! Tlist_Update_File(filename, ftype) + call s:Tlist_Log_Msg('Tlist_Update_File (' . 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(fname) + + if fidx != -1 && s:tlist_{fidx}_valid + " File exists and the tags are valid + " 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 + let winnum = bufwinnr(g:TagList_title) + if winnum == -1 + " Taglist window is not present. Just update the taglist + " and return + call s:Tlist_Process_File(fname, a:ftype) + else + if g:Tlist_Show_One_File && s:tlist_cur_file_idx != -1 + " If tags for only one file are displayed and we are not + " updating the tags for that file, then no need to + " refresh the taglist window. Otherwise, the taglist + " window should be updated. + if s:tlist_{s:tlist_cur_file_idx}_filename != fname + call s:Tlist_Process_File(fname, a:ftype) + return + endif + endif + + " Save the current window number + let save_winnr = winnr() + + " Goto the taglist window + call s:Tlist_Window_Goto_Window() + + " Save the cursor position + let save_line = line('.') + let save_col = col('.') + + " Update the taglist window + call s:Tlist_Window_Refresh_File(fname, a:ftype) + + " Restore the cursor position + if v:version >= 601 + call cursor(save_line, save_col) + else + exe save_line + exe 'normal! ' . save_col . '|' + endif + + if winnr() != save_winnr + " Go back to the original window + call s:Tlist_Exe_Cmd_No_Acmds(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_Window_Close +" Close the taglist window +function! s:Tlist_Window_Close() + call s:Tlist_Log_Msg('Tlist_Window_Close()') + " Make sure the taglist window exists + let winnum = bufwinnr(g:TagList_title) + if winnum == -1 + call s:Tlist_Warning_Msg('Error: Taglist window is not open') + return + endif + + if winnr() == winnum + " Already in the taglist window. Close it and return + if winbufnr(2) != -1 + " If a window other than the taglist window is open, + " then only close the taglist window. + close + endif + else + " Goto the taglist window, close it and then come back to the + " original window + let curbufnr = bufnr('%') + exe winnum . 'wincmd w' + close + " Need to jump back to the original window only if we are not + " already in that window + let winnum = bufwinnr(curbufnr) + if winnr() != winnum + exe winnum . 'wincmd w' + endif + endif +endfunction + +" Tlist_Window_Mark_File_Window +" Mark the current window as the file window to use when jumping to a tag. +" Only if the current window is a non-plugin, non-preview and non-taglist +" window +function! s:Tlist_Window_Mark_File_Window() + if getbufvar('%', '&buftype') == '' && !&previewwindow + let w:tlist_file_window = "yes" + endif +endfunction + +" Tlist_Window_Open +" Open and refresh the taglist window +function! s:Tlist_Window_Open() + call s:Tlist_Log_Msg('Tlist_Window_Open()') + " If the window is open, jump to it + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + " Jump to the existing window + if winnr() != winnum + exe winnum . 'wincmd w' + endif + return + endif + + if s:tlist_app_name == "winmanager" + " Taglist plugin is no longer part of the winmanager app + let s:tlist_app_name = "none" + endif + + " 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 selected. + call s:Tlist_Window_Mark_File_Window() + + " Open the taglist window + call s:Tlist_Window_Create() + + call s:Tlist_Window_Refresh() + + if g:Tlist_Show_One_File + " Add only the current buffer and file + " + " If the file doesn't support tag listing, skip it + if !s:Tlist_Skip_File(curbuf_name, curbuf_ftype) + call s:Tlist_Window_Refresh_File(curbuf_name, curbuf_ftype) + endif + endif + + if g:Tlist_File_Fold_Auto_Close + " Open the fold for the current file, as all the folds in + " the taglist window are closed + let fidx = s:Tlist_Get_File_Index(curbuf_name) + if fidx != -1 + exe "silent! " . s:tlist_{fidx}_start . "," . + \ s:tlist_{fidx}_end . "foldopen!" + endif + endif + + " Highlight the current tag + call s:Tlist_Window_Highlight_Tag(curbuf_name, cur_lnum, 1, 1) +endfunction + +" Tlist_Window_Toggle() +" Open or close a taglist window +function! s:Tlist_Window_Toggle() + call s:Tlist_Log_Msg('Tlist_Window_Toggle()') + " If taglist window is open then close it. + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + call s:Tlist_Window_Close() + return + endif + + call s:Tlist_Window_Open() + + " Go back to the original window, if Tlist_GainFocus_On_ToggleOpen is not + " set + if !g:Tlist_GainFocus_On_ToggleOpen + call s:Tlist_Exe_Cmd_No_Acmds('wincmd p') + endif + + " Update the taglist menu + if g:Tlist_Show_Menu + call s:Tlist_Menu_Update_File(0) + endif +endfunction + +" Tlist_Process_Filelist +" Process multiple files. Each filename is separated by "\n" +" Returns the number of processed files +function! s:Tlist_Process_Filelist(file_names) + let flist = a:file_names + + " Enable lazy screen updates + let old_lazyredraw = &lazyredraw + set lazyredraw + + " Keep track of the number of processed files + let fcnt = 0 + + " Process one file at a time + while flist != '' + let nl_idx = stridx(flist, "\n") + let one_file = strpart(flist, 0, nl_idx) + + " Remove the filename from the list + let flist = strpart(flist, nl_idx + 1) + + if one_file == '' + continue + endif + + " Skip directories + if isdirectory(one_file) + continue + endif + + let ftype = s:Tlist_Get_Filetype(one_file) + + echon "\r " + echon "\rProcessing tags for " . fnamemodify(one_file, ':p:t') + + let fcnt = fcnt + 1 + + call Tlist_Update_File(one_file, ftype) + endwhile + + " Clear the displayed informational messages + echon "\r " + + " Restore the previous state + let &lazyredraw = old_lazyredraw + + return fcnt +endfunction + +" Tlist_Process_Dir +" Process the files in a directory matching the specified pattern +function! s:Tlist_Process_Dir(dir_name, pat) + let flist = glob(a:dir_name . '/' . a:pat) . "\n" + + let fcnt = s:Tlist_Process_Filelist(flist) + + let len = strlen(a:dir_name) + if a:dir_name[len - 1] == '\' || a:dir_name[len - 1] == '/' + let glob_expr = a:dir_name . '*' + else + let glob_expr = a:dir_name . '/*' + endif + let all_files = glob(glob_expr) . "\n" + + while all_files != '' + let nl_idx = stridx(all_files, "\n") + let one_file = strpart(all_files, 0, nl_idx) + + let all_files = strpart(all_files, nl_idx + 1) + if one_file == '' + continue + endif + + " Skip non-directory names + if !isdirectory(one_file) + continue + endif + + echon "\r " + echon "\rProcessing files in directory " . fnamemodify(one_file, ':t') + let fcnt = fcnt + s:Tlist_Process_Dir(one_file, a:pat) + endwhile + + return fcnt +endfunction + +" Tlist_Add_Files_Recursive +" Add files recursively from a directory +function! s:Tlist_Add_Files_Recursive(dir, ...) + let dir_name = fnamemodify(a:dir, ':p') + if !isdirectory(dir_name) + call s:Tlist_Warning_Msg('Error: ' . dir_name . ' is not a directory') + return + endif + + if a:0 == 1 + " User specified file pattern + let pat = a:1 + else + " Default file pattern + let pat = '*' + endif + + echon "\r " + echon "\rProcessing files in directory " . fnamemodify(dir_name, ':t') + let fcnt = s:Tlist_Process_Dir(dir_name, pat) + + echon "\rAdded " . fcnt . " files to the taglist" +endfunction + +" Tlist_Add_Files +" Add the specified list of files to the taglist +function! s:Tlist_Add_Files(...) + let flist = '' + let i = 1 + + " Get all the files matching the file patterns supplied as argument + while i <= a:0 + let flist = flist . glob(a:{i}) . "\n" + let i = i + 1 + endwhile + + if flist == '' + call s:Tlist_Warning_Msg('Error: No matching files are found') + return + endif + + let fcnt = s:Tlist_Process_Filelist(flist) + echon "\rAdded " . fcnt . " files to the taglist" +endfunction + +" Tlist_Extract_Tagtype +" Extract the tag type from the tag text +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_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_Scope +" Extract the tag scope from the tag text +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_line, end + 1) + let tag_scope = strpart(tag_scope, stridx(tag_scope, ':') + 1) + + return tag_scope +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 + " 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 + + " 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 tlist_win = bufwinnr(g:TagList_title) + + " 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 + " 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 + + " If the taglist should not be auto updated, then return + if !g:Tlist_Auto_Update + 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 and the window + call Tlist_Update_File(filename, ftype) + + " Store the new file modification time + let s:tlist_{fidx}_mtime = mtime + endif + endif + + " Update the taglist window + if tlist_win != -1 + " Disable screen updates + let old_lazyredraw = &lazyredraw + set nolazyredraw + + " Save the current window number + let save_winnr = winnr() + + " Goto the taglist window + call s:Tlist_Window_Goto_Window() + + if !g:Tlist_Auto_Highlight_Tag || !g:Tlist_Highlight_Tag_On_BufEnter + " Save the cursor position + let save_line = line('.') + let save_col = col('.') + endif + + " Update the taglist window + call s:Tlist_Window_Refresh_File(filename, ftype) + + " Open the fold for the file + exe "silent! " . s:tlist_{fidx}_start . "," . + \ s:tlist_{fidx}_end . "foldopen!" + + if g:Tlist_Highlight_Tag_On_BufEnter && g:Tlist_Auto_Highlight_Tag + if g:Tlist_Show_One_File && s:tlist_cur_file_idx != fidx + " If displaying tags for only one file in the taglist + " window and about to display the tags for a new file, + " then center the current tag line for the new file + let center_tag_line = 1 + else + let center_tag_line = 0 + endif + + " Highlight the current tag + call s:Tlist_Window_Highlight_Tag(filename, cur_lnum, 1, center_tag_line) + else + " Restore the cursor position + if v:version >= 601 + call cursor(save_line, save_col) + else + exe save_line + exe 'normal! ' . save_col . '|' + endif + endif + + " Jump back to the original window + if save_winnr != winnr() + call s:Tlist_Exe_Cmd_No_Acmds(save_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 +" caller == 'cmd', command used in the taglist window +" caller == 'menu', taglist menu +" action == 'toggle', toggle sort from name to order and vice versa +" action == 'set', 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 == 'cmd' + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.')) + if fidx == -1 + return + endif + + " Remove the previous highlighting + match none + elseif a:caller == 'menu' + let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p')) + if fidx == -1 + return + endif + endif + + if a:action == 'toggle' + let sort_type = s:tlist_{fidx}_sort_type + + " Toggle the sort order from 'name' to 'order' and vice versa + if sort_type == 'name' + let s:tlist_{fidx}_sort_type = 'order' + else + let s:tlist_{fidx}_sort_type = 'name' + endif + else + let s:tlist_{fidx}_sort_type = a:sort_type + endif + + " Invalidate the tags listed for this file + let s:tlist_{fidx}_valid = 0 + + if a:caller == 'cmd' + " Save the current line for later restoration + let curline = '\V\^' . getline('.') . '\$' + + call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename, + \ s:tlist_{fidx}_filetype) + + exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!' + + " 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_Current_File() +" Update taglist for the current buffer by regenerating the tag list +" Contributed by WEN Guopeng. +function! s:Tlist_Update_Current_File() + call s:Tlist_Log_Msg('Tlist_Update_Current_File()') + if winnr() == bufwinnr(g:TagList_title) + " In the taglist window. Update the current file + call s:Tlist_Window_Update_File() + 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 + endif + call Tlist_Update_File(filename, &filetype) + endif +endfunction + +" Tlist_Window_Update_File() +" Update the tags displayed in the taglist window +function! s:Tlist_Window_Update_File() + call s:Tlist_Log_Msg('Tlist_Window_Update_File()') + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.')) + if fidx == -1 + return + endif + + " Remove the previous highlighting + match none + + " Save the current line for later restoration + let curline = '\V\^' . getline('.') . '\$' + + let s:tlist_{fidx}_valid = 0 + + " Update the taglist window + call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename, + \ s:tlist_{fidx}_filetype) + + exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!' + + " Go back to the tag line before the list is updated + call search(curline, 'w') +endfunction + +" Tlist_Window_Get_Tag_Type_By_Linenum() +" Return the tag type index for the specified line in the taglist window +function! s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum) + let ftype = s:tlist_{a:fidx}_filetype + + " Determine to which tag type the current line number belongs to using the + " tag type start line number and the number of tags in a tag type + let i = 1 + while i <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{i}_name + let start_lnum = + \ s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset + let end = start_lnum + s:tlist_{a:fidx}_{ttype}_count + if a:lnum >= start_lnum && a:lnum <= end + break + endif + let i = i + 1 + endwhile + + " Current line doesn't belong to any of the displayed tag types + if i > s:tlist_{ftype}_count + return '' + endif + + return ttype +endfunction + +" Tlist_Window_Get_Tag_Index() +" Return the tag index for the specified line in the taglist window +function! s:Tlist_Window_Get_Tag_Index(fidx, lnum) + let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(a:fidx, a:lnum) + + " Current line doesn't belong to any of the displayed tag types + if ttype == '' + return 0 + endif + + " Compute the index into the displayed tags for the tag type + let ttype_lnum = s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset + let tidx = a:lnum - ttype_lnum + if tidx == 0 + return 0 + endif + + " Get the corresponding tag line and return it + return s:tlist_{a:fidx}_{ttype}_{tidx} +endfunction + +" Tlist_Window_Highlight_Line +" Highlight the current line +function! s:Tlist_Window_Highlight_Line() + " Clear previously selected name + match none + + " Highlight the current line + if g:Tlist_Display_Prototype == 0 + let pat = '/\%' . line('.') . 'l\s\+\zs.*/' + else + let pat = '/\%' . line('.') . 'l.*/' + endif + + exe 'match TagListTagName ' . pat +endfunction + +" Tlist_Window_Open_File +" Open the specified file in either a new window or an existing window +" and place the cursor at the specified tag pattern +function! s:Tlist_Window_Open_File(win_ctrl, filename, tagpat) + call s:Tlist_Log_Msg('Tlist_Window_Open_File (' . a:filename . ',' . + \ a:win_ctrl . ')') + let prev_Tlist_Skip_Refresh = s:Tlist_Skip_Refresh + let s:Tlist_Skip_Refresh = 1 + + if s:tlist_app_name == "winmanager" + " Let the winmanager edit the file + call WinManagerFileEdit(a:filename, a:win_ctrl == 'newwin') + else + + if a:win_ctrl == 'newtab' + " Create a new tab + exe 'tabnew ' . escape(a:filename, ' ') + " Open the taglist window in the new tab + call s:Tlist_Window_Open() + endif + + if a:win_ctrl == 'checktab' + " Check whether the file is present in any of the tabs. + " If the file is present in the current tab, then use the + " current tab. + if bufwinnr(a:filename) != -1 + let file_present_in_tab = 1 + let i = tabpagenr() + else + let i = 1 + let bnum = bufnr(a:filename) + let file_present_in_tab = 0 + while i <= tabpagenr('$') + if index(tabpagebuflist(i), bnum) != -1 + let file_present_in_tab = 1 + break + endif + let i += 1 + endwhile + endif + + if file_present_in_tab + " Goto the tab containing the file + exe 'tabnext ' . i + else + " Open a new tab + exe 'tabnew ' . escape(a:filename, ' ') + + " Open the taglist window + call s:Tlist_Window_Open() + endif + endif + + let winnum = -1 + if a:win_ctrl == 'prevwin' + " Open the file in the previous window, if it is usable + let cur_win = winnr() + wincmd p + if &buftype == '' && !&previewwindow + exe "edit " . escape(a:filename, ' ') + let winnum = winnr() + else + " Previous window is not usable + exe cur_win . 'wincmd w' + endif + endif + + " Goto the window containing the file. If the window is not there, open a + " new window + if winnum == -1 + let winnum = bufwinnr(a:filename) + endif + + if winnum == -1 + " Locate the previously used window for opening a file + let fwin_num = 0 + let first_usable_win = 0 + + let i = 1 + let bnum = winbufnr(i) + while bnum != -1 + if getwinvar(i, 'tlist_file_window') == 'yes' + let fwin_num = i + break + endif + if first_usable_win == 0 && + \ getbufvar(bnum, '&buftype') == '' && + \ !getwinvar(i, '&previewwindow') + " First non-taglist, non-plugin and non-preview window + let first_usable_win = i + endif + let i = i + 1 + let bnum = winbufnr(i) + 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" + + " If the user asked to jump to the tag in a new window, then split + " the existing window into two. + if a:win_ctrl == 'newwin' + split + endif + exe "edit " . escape(a:filename, ' ') + else + " Open a new window + if g:Tlist_Use_Horiz_Window + exe 'leftabove split ' . escape(a:filename, ' ') + else + if winbufnr(2) == -1 + " Only the taglist window is present + if g:Tlist_Use_Right_Window + exe 'leftabove vertical split ' . + \ escape(a:filename, ' ') + else + exe 'rightbelow vertical split ' . + \ escape(a:filename, ' ') + endif + + " Go to the taglist window to change the window size to + " the user configured value + call s:Tlist_Exe_Cmd_No_Acmds('wincmd p') + if g:Tlist_Use_Horiz_Window + exe 'resize ' . g:Tlist_WinHeight + else + exe 'vertical resize ' . g:Tlist_WinWidth + endif + " Go back to the file window + call s:Tlist_Exe_Cmd_No_Acmds('wincmd p') + else + " A plugin or help window is also present + wincmd w + exe 'leftabove split ' . escape(a:filename, ' ') + endif + endif + endif + " Mark the window, so that it can be reused. + call s:Tlist_Window_Mark_File_Window() + else + if v:version >= 700 + " If the file is opened in more than one window, then check + " whether the last accessed window has the selected file. + " If it does, then use that window. + let lastwin_bufnum = winbufnr(winnr('#')) + if bufnr(a:filename) == lastwin_bufnum + let winnum = winnr('#') + endif + endif + exe winnum . 'wincmd w' + + " If the user asked to jump to the tag in a new window, then split the + " existing window into two. + if a:win_ctrl == 'newwin' + split + endif + endif + endif + + " Jump to the tag + if a:tagpat != '' + " Add the current cursor position to the jump list, so that user can + " jump back using the ' and ` marks. + mark ' + silent call search(a: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 + endif + + " If the user selects to preview the tag then jump back to the + " taglist window + if a:win_ctrl == 'preview' + " Go back to the taglist window + let winnum = bufwinnr(g:TagList_title) + exe winnum . 'wincmd w' + else + " If the user has selected to close the taglist window, when a + " tag is selected, close the taglist window + if g:Tlist_Close_On_Select + call s:Tlist_Window_Goto_Window() + close + + " Go back to the window displaying the selected file + let wnum = bufwinnr(a:filename) + if wnum != -1 && wnum != winnr() + call s:Tlist_Exe_Cmd_No_Acmds(wnum . 'wincmd w') + endif + endif + endif + + let s:Tlist_Skip_Refresh = prev_Tlist_Skip_Refresh +endfunction + +" Tlist_Window_Jump_To_Tag() +" Jump to the location of the current tag +" win_ctrl == useopen - Reuse the existing file window +" win_ctrl == newwin - Open a new window +" win_ctrl == preview - Preview the tag +" win_ctrl == prevwin - Open in previous window +" win_ctrl == newtab - Open in new tab +function! s:Tlist_Window_Jump_To_Tag(win_ctrl) + call s:Tlist_Log_Msg('Tlist_Window_Jump_To_Tag(' . a:win_ctrl . ')') + " Do not process comment lines and empty lines + let curline = getline('.') + if curline =~ '^\s*$' || curline[0] == '"' + return + endif + + " If inside a closed fold, then use the first line of the fold + " and jump to the file. + let lnum = foldclosed('.') + if lnum == -1 + " Jump to the selected tag or file + let lnum = line('.') + else + " Open the closed fold + .foldopen! + endif + + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum) + if fidx == -1 + return + endif + + " Get the tag output for the current tag + let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum) + if tidx != 0 + let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, tidx) + + " Highlight the tagline + call s:Tlist_Window_Highlight_Line() + else + " Selected a line which is not a tag name. Just edit the file + let tagpat = '' + endif + + call s:Tlist_Window_Open_File(a:win_ctrl, s:tlist_{fidx}_filename, tagpat) +endfunction + +" Tlist_Window_Show_Info() +" Display information about the entry under the cursor +function! s:Tlist_Window_Show_Info() + call s:Tlist_Log_Msg('Tlist_Window_Show_Info()') + + " Clear the previously displayed line + echo + + " Do not process comment lines and empty lines + let curline = getline('.') + if curline =~ '^\s*$' || curline[0] == '"' + return + endif + + " If inside a fold, then don't display the prototype + if foldclosed('.') != -1 + return + endif + + let lnum = line('.') + + " Get the file index + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum) + if fidx == -1 + return + endif + + if lnum == s:tlist_{fidx}_start + " Cursor is on a file name + let fname = s:tlist_{fidx}_filename + if strlen(fname) > 50 + let fname = fnamemodify(fname, ':t') + endif + echo fname . ', Filetype=' . s:tlist_{fidx}_filetype . + \ ', Tag count=' . s:tlist_{fidx}_tag_count + return + endif + + " Get the tag output line for the current tag + let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum) + if tidx == 0 + " Cursor is on a tag type + let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum) + if ttype == '' + return + endif + + let ttype_name = '' + + let ftype = s:tlist_{fidx}_filetype + let i = 1 + while i <= s:tlist_{ftype}_count + if ttype == s:tlist_{ftype}_{i}_name + let ttype_name = s:tlist_{ftype}_{i}_fullname + break + endif + let i = i + 1 + endwhile + + echo 'Tag type=' . ttype_name . + \ ', Tag count=' . s:tlist_{fidx}_{ttype}_count + return + endif + + " Get the tag search pattern and display it + echo s:Tlist_Get_Tag_Prototype(fidx, tidx) +endfunction + +" 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 + let right = s:tlist_{a:fidx}_tag_count + + if sort_type == 'order' + " Tags sorted by order, use a binary search. + " The idea behind this function is taken from the ctags.vim script (by + " Alexey Marinichev) available at the Vim online website. + + " If the current line is the less than the first tag, then no need to + " search + let first_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, 1) + + if a:linenum < first_lnum + return -1 + endif + + while left < right + let middle = (right + left + 1) / 2 + let middle_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, middle) + + if middle_lnum == a:linenum + let left = middle + break + endif + + if middle_lnum > a:linenum + let right = middle - 1 + else + let left = middle + endif + endwhile + else + " Tags sorted by name, use a linear search. (contributed by Dave + " Eggum). + " Look for a tag with a line number less than or equal to the supplied + " line number. If multiple tags are found, then use the tag with the + " line number closest to the supplied line number. IOW, use the tag + " with the highest line number. + let closest_lnum = 0 + let final_left = 0 + 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 -1 + endif + if left >= right + let left = final_left + endif + endif + + return left +endfunction + +" Tlist_Window_Highlight_Tag() +" Highlight the current tag +" cntx == 1, Called by the taglist plugin itself +" cntx == 2, Forced by the user through the TlistHighlightTag command +" center = 1, move the tag line to the center of the taglist window +function! s:Tlist_Window_Highlight_Tag(filename, cur_lnum, cntx, center) + " 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. + if !g:Tlist_Auto_Highlight_Tag && a:cntx == 1 + return + endif + + if a:filename == '' + return + endif + + " Make sure the taglist window is present + let winnum = bufwinnr(g:TagList_title) + if winnum == -1 + call s:Tlist_Warning_Msg('Error: Taglist window is not open') + return + endif + + let fidx = s:Tlist_Get_File_Index(a:filename) + if fidx == -1 + return + endif + + " If the file is currently not displayed in the taglist window, then retrn + if !s:tlist_{fidx}_visible + return + endif + + " If there are no tags for this file, then no need to proceed further + if s:tlist_{fidx}_tag_count == 0 + return + endif + + " Ignore all autocommands + let old_ei = &eventignore + set eventignore=all + + " Save the original window number + let org_winnr = winnr() + + if org_winnr == winnum + let in_taglist_window = 1 + else + let in_taglist_window = 0 + endif + + " Go to the taglist window + if !in_taglist_window + exe winnum . 'wincmd w' + endif + + " Clear previously selected name + match none + + let 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 lnum = line('.') + + 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 foldclosed('.') != -1 + .foldopen + endif + + call winline() + + if !in_taglist_window + exe org_winnr . 'wincmd w' + endif + + " Restore the autocommands + let &eventignore = old_ei + return + endif + + " Extract the tag type + let ttype = s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx) + + " Compute the line number + " Start of file + Start of tag type + offset + let lnum = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset + + \ s:tlist_{fidx}_{tidx}_ttype_idx + + " Goto the line containing the tag + exe lnum + + " Open the fold + if foldclosed('.') != -1 + .foldopen + endif + + if a:center + " Move the tag line to the center of the taglist window + normal! z. + else + " Make sure the current tag line is visible in the taglist window. + " Calling the winline() function makes the line visible. Don't know + " of a better way to achieve this. + call winline() + endif + + " Highlight the tag name + call s:Tlist_Window_Highlight_Line() + + " Go back to the original window + if !in_taglist_window + exe org_winnr . 'wincmd w' + endif + + " Restore the autocommands + let &eventignore = old_ei + return +endfunction + +" Tlist_Get_Tag_Prototype_By_Line +" Get the prototype for the tag on or before the specified line number in the +" current buffer +function! Tlist_Get_Tag_Prototype_By_Line(...) + if a:0 == 0 + " Arguments are not supplied. Use the current buffer name + " and line number + let filename = bufname('%') + let linenr = line('.') + elseif a:0 == 2 + " Filename and line number are specified + let filename = a:1 + let linenr = a:2 + if linenr !~ '\d\+' + " Invalid line number + return "" + endif + else + " Sufficient arguments are not supplied + let msg = 'Usage: Tlist_Get_Tag_Prototype_By_Line ' . + \ '' + call s:Tlist_Warning_Msg(msg) + return "" + endif + + " Expand the file to a fully qualified name + let filename = fnamemodify(filename, ':p') + if filename == '' + return "" + endif + + let fidx = s:Tlist_Get_File_Index(filename) + if fidx == -1 + return "" + endif + + " If there are no tags for this file, then no need to proceed further + if s:tlist_{fidx}_tag_count == 0 + return "" + endif + + " Get the tag text using the line number + let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr) + if tidx == -1 + return "" + endif + + return s:Tlist_Get_Tag_Prototype(fidx, tidx) +endfunction + +" Tlist_Get_Tagname_By_Line +" Get the tag name on or before the specified line number in the +" current buffer +function! Tlist_Get_Tagname_By_Line(...) + if a:0 == 0 + " Arguments are not supplied. Use the current buffer name + " and line number + let filename = bufname('%') + let linenr = line('.') + elseif a:0 == 2 + " Filename and line number are specified + let filename = a:1 + let linenr = a:2 + if linenr !~ '\d\+' + " Invalid line number + return "" + endif + else + " Sufficient arguments are not supplied + let msg = 'Usage: Tlist_Get_Tagname_By_Line ' + call s:Tlist_Warning_Msg(msg) + return "" + endif + + " Make sure the current file has a name + let filename = fnamemodify(filename, ':p') + if filename == '' + return "" + endif + + let fidx = s:Tlist_Get_File_Index(filename) + if fidx == -1 + return "" + endif + + " If there are no tags for this file, then no need to proceed further + if s:tlist_{fidx}_tag_count == 0 + return "" + endif + + " Get the tag name using the line number + let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr) + if tidx == -1 + return "" + endif + + return s:tlist_{fidx}_{tidx}_tag_name +endfunction + +" Tlist_Window_Move_To_File +" Move the cursor to the beginning of the current file or the next file +" or the previous file in the taglist window +" dir == -1, move to start of current or previous function +" dir == 1, move to start of next function +function! s:Tlist_Window_Move_To_File(dir) + if foldlevel('.') == 0 + " Cursor is on a non-folded line (it is not in any of the files) + " Move it to a folded line + if a:dir == -1 + normal! zk + else + " While moving down to the start of the next fold, + " no need to do go to the start of the next file. + normal! zj + return + endif + endif + + let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.')) + if fidx == -1 + return + endif + + let cur_lnum = line('.') + + if a:dir == -1 + if cur_lnum > s:tlist_{fidx}_start + " Move to the beginning of the current file + exe s:tlist_{fidx}_start + return + endif + + if fidx != 0 + " Move to the beginning of the previous file + let fidx = fidx - 1 + else + " Cursor is at the first file, wrap around to the last file + let fidx = s:tlist_file_count - 1 + endif + + exe s:tlist_{fidx}_start + return + else + " Move to the beginning of the next file + let fidx = fidx + 1 + + if fidx >= s:tlist_file_count + " Cursor is at the last file, wrap around to the first file + let fidx = 0 + endif + + if s:tlist_{fidx}_start != 0 + exe s:tlist_{fidx}_start + endif + return + endif +endfunction + +" Tlist_Session_Load +" Load a taglist session (information about all the displayed files +" and the tags) from the specified file +function! s:Tlist_Session_Load(...) + if a:0 == 0 || a:1 == '' + call s:Tlist_Warning_Msg('Usage: TlistSessionLoad ') + return + endif + + let sessionfile = a:1 + + if !filereadable(sessionfile) + let msg = 'Taglist: Error - Unable to open file ' . sessionfile + call s:Tlist_Warning_Msg(msg) + return + endif + + " Mark the current window as the file window + call s:Tlist_Window_Mark_File_Window() + + " Source the session file + exe 'source ' . sessionfile + + let new_file_count = g:tlist_file_count + unlet! g:tlist_file_count + + let i = 0 + while i < new_file_count + let ftype = g:tlist_{i}_filetype + unlet! g:tlist_{i}_filetype + + if !exists('s:tlist_' . ftype . '_count') + if s:Tlist_FileType_Init(ftype) == 0 + let i = i + 1 + continue + endif + endif + + let fname = g:tlist_{i}_filename + unlet! g:tlist_{i}_filename + + let fidx = s:Tlist_Get_File_Index(fname) + if fidx != -1 + let s:tlist_{fidx}_visible = 0 + let i = i + 1 + continue + else + " 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. + call s:Tlist_Update_Remove_List(fname, 0) + endif + + let fidx = s:Tlist_Init_File(fname, ftype) + + let s:tlist_{fidx}_filename = fname + + let s:tlist_{fidx}_sort_type = g:tlist_{i}_sort_type + unlet! g:tlist_{i}_sort_type + + let s:tlist_{fidx}_filetype = ftype + let s:tlist_{fidx}_mtime = getftime(fname) + + let s:tlist_{fidx}_start = 0 + let s:tlist_{fidx}_end = 0 + + let s:tlist_{fidx}_valid = 1 + + 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}_{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 + + let j = 1 + while j <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{j}_name + + if exists('g:tlist_' . i . '_' . ttype) + let s:tlist_{fidx}_{ttype} = g:tlist_{i}_{ttype} + unlet! g:tlist_{i}_{ttype} + let s:tlist_{fidx}_{ttype}_offset = 0 + let s:tlist_{fidx}_{ttype}_count = g:tlist_{i}_{ttype}_count + unlet! g:tlist_{i}_{ttype}_count + + let k = 1 + while k <= s:tlist_{fidx}_{ttype}_count + let s:tlist_{fidx}_{ttype}_{k} = g:tlist_{i}_{ttype}_{k} + unlet! g:tlist_{i}_{ttype}_{k} + let k = k + 1 + endwhile + else + let s:tlist_{fidx}_{ttype} = '' + let s:tlist_{fidx}_{ttype}_offset = 0 + let s:tlist_{fidx}_{ttype}_count = 0 + endif + + let j = j + 1 + endwhile + + let i = i + 1 + endwhile + + " If the taglist window is open, then update it + let winnum = bufwinnr(g:TagList_title) + if winnum != -1 + let save_winnr = winnr() + + " Goto the taglist window + call s:Tlist_Window_Goto_Window() + + " Refresh the taglist window + call s:Tlist_Window_Refresh() + + " Go back to the original window + if save_winnr != winnr() + call s:Tlist_Exe_Cmd_No_Acmds('wincmd p') + endif + endif +endfunction + +" Tlist_Session_Save +" Save a taglist session (information about all the displayed files +" and the tags) into the specified file +function! s:Tlist_Session_Save(...) + if a:0 == 0 || a:1 == '' + call s:Tlist_Warning_Msg('Usage: TlistSessionSave ') + return + endif + + let sessionfile = a:1 + + if s:tlist_file_count == 0 + " There is nothing to save + call s:Tlist_Warning_Msg('Warning: Taglist is empty. Nothing to save.') + return + endif + + if filereadable(sessionfile) + let ans = input('Do you want to overwrite ' . sessionfile . ' (Y/N)?') + if ans !=? 'y' + return + endif + + echo "\n" + endif + + let old_verbose = &verbose + set verbose&vim + + exe 'redir! > ' . sessionfile + + silent! echo '" Taglist session file. This file is auto-generated.' + silent! echo '" File information' + silent! echo 'let tlist_file_count = ' . s:tlist_file_count + + let i = 0 + + while i < s:tlist_file_count + " Store information about the file + silent! echo 'let tlist_' . i . "_filename = '" . + \ s:tlist_{i}_filename . "'" + silent! echo 'let tlist_' . i . '_sort_type = "' . + \ s:tlist_{i}_sort_type . '"' + silent! echo 'let tlist_' . i . '_filetype = "' . + \ s:tlist_{i}_filetype . '"' + 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}_{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 + + " Store information about all the tags grouped by their type + let ftype = s:tlist_{i}_filetype + let j = 1 + while j <= s:tlist_{ftype}_count + let ttype = s:tlist_{ftype}_{j}_name + if s:tlist_{i}_{ttype}_count != 0 + let s:tmp = escape(s:tlist_{i}_{ttype}, '"\\') + let txt = substitute(s:tmp, "\n", "\\\\n", 'g') + silent! echo 'let tlist_' . i . '_' . ttype . ' = "' . + \ txt . '"' + 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 . + \ ' = ' . s:tlist_{i}_{ttype}_{k} + let k = k + 1 + endwhile + endif + let j = j + 1 + endwhile + + silent! echo + + let i = i + 1 + endwhile + + redir END + + let &verbose = old_verbose +endfunction + +" Tlist_Buffer_Removed +" A buffer is removed from the Vim buffer list. Remove the tags defined +" for that file +function! s:Tlist_Buffer_Removed(filename) + call s:Tlist_Log_Msg('Tlist_Buffer_Removed (' . a:filename . ')') + + " Make sure a valid filename is supplied + if a:filename == '' + 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 + return + endif + + " Remove the file from the list + call s:Tlist_Remove_File(fidx, 0) +endfunction + +" When a buffer is deleted, remove the file from the taglist +autocmd BufDelete * silent call s:Tlist_Buffer_Removed(expand(':p')) + +" Tlist_Window_Open_File_Fold +" Open the fold for the specified file and close the fold for all the +" other files +function! s:Tlist_Window_Open_File_Fold(acmd_bufnr) + call s:Tlist_Log_Msg('Tlist_Window_Open_File_Fold (' . a:acmd_bufnr . ')') + + " Make sure the taglist window is present + let winnum = bufwinnr(g:TagList_title) + if winnum == -1 + call s:Tlist_Warning_Msg('Taglist: Error - Taglist window is not open') + return + endif + + " Save the original window number + let org_winnr = winnr() + if org_winnr == winnum + let in_taglist_window = 1 + else + let in_taglist_window = 0 + endif + + if in_taglist_window + " When entering the taglist window, no need to update the folds + return + endif + + " Go to the taglist window + if !in_taglist_window + call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w') + endif + + " Close all the folds + silent! %foldclose + + " Get tag list index of the specified file + let fname = fnamemodify(bufname(a:acmd_bufnr + 0), ':p') + if filereadable(fname) + let fidx = s:Tlist_Get_File_Index(fname) + if fidx != -1 + " Open the fold for the file + exe "silent! " . s:tlist_{fidx}_start . "," . + \ s:tlist_{fidx}_end . "foldopen" + endif + endif + + " Go back to the original window + if !in_taglist_window + call s:Tlist_Exe_Cmd_No_Acmds(org_winnr . 'wincmd w') + endif +endfunction + +" Tlist_Window_Check_Auto_Open +" Open the taglist window automatically on Vim startup. +" Open the window only when files present in any of the Vim windows support +" tags. +function! s:Tlist_Window_Check_Auto_Open() + let open_window = 0 + + let i = 1 + let buf_num = winbufnr(i) + while buf_num != -1 + let filename = fnamemodify(bufname(buf_num), ':p') + if !s:Tlist_Skip_File(filename, getbufvar(buf_num, '&filetype')) + let open_window = 1 + break + endif + let i = i + 1 + let buf_num = winbufnr(i) + endwhile + + if open_window + call s:Tlist_Window_Toggle() + endif +endfunction + +function! s:Tlist_Menu_Add_Base_Menu() + call s:Tlist_Log_Msg('Adding the base menu') + + " Add the menu + anoremenu T&ags.Refresh\ menu :call Tlist_Menu_Refresh() + anoremenu T&ags.Sort\ menu\ by.Name + \ :call Tlist_Change_Sort('menu', 'set', 'name') + anoremenu T&ags.Sort\ menu\ by.Order + \ :call Tlist_Change_Sort('menu', 'set', 'order') + anoremenu T&ags.-SEP1- : + + if &mousemodel =~ 'popup' + anoremenu PopUp.T&ags.Refresh\ menu + \ :call Tlist_Menu_Refresh() + anoremenu PopUp.T&ags.Sort\ menu\ by.Name + \ :call Tlist_Change_Sort('menu', 'set', 'name') + anoremenu PopUp.T&ags.Sort\ menu\ by.Order + \ :call Tlist_Change_Sort('menu', 'set', 'order') + anoremenu 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 +" fidx - File type index +" ftype - File Type +" add_ttype_name - To add or not to add the tag type name to the menu entries +" ttype_idx - Tag type index +function! s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, 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 a:add_ttype_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, ' ') + endif + + " 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.' + if a:add_ttype_name + let m_prefix = m_prefix . ttype_fullname . '.' + endif + let m_prefix = m_prefix . 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 + + 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.' + if a:add_ttype_name + let m_prefix = m_prefix . ttype_fullname . '.' + endif + let j = 1 + while j <= tcnt + let tidx = s:tlist_{fidx_ttype}_{j} + + let tname = s:tlist_{a:fidx}_{tidx}_tag_name + + 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 + + let fname = escape(fnamemodify(bufname('%'), ':t'), '.') + if fname != '' + exe 'anoremenu T&ags.' . fname . ' ' + anoremenu T&ags.-SEP2- : + 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 = '' + + " Determine whether the tag type name needs to be added to the menu + " If more than one tag type is present in the taglisting for a file, + " then the tag type name needs to be present + let add_ttype_name = -1 + let i = 1 + while i <= s:tlist_{ftype}_count && add_ttype_name < 1 + let ttype = s:tlist_{ftype}_{i}_name + if s:tlist_{fidx}_{ttype}_count + let add_ttype_name = add_ttype_name + 1 + endif + let i = i + 1 + endwhile + + " 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, add_ttype_name, 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 + + " Add a dummy menu item to retain teared off menu + noremenu T&ags.Dummy l + + silent! unmenu! T&ags + if &mousemodel =~ 'popup' + silent! unmenu! PopUp.T&ags + endif + + call s:Tlist_Menu_Add_Base_Menu() + + " Remove the dummy menu item + unmenu T&ags.Dummy + + 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_Current_File() +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 + + " Add the current cursor position to the jump list, so that user can + " jump back using the ' and ` marks. + mark ' + + 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_Menu_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 s:Tlist_Refresh() + endif + autocmd BufLeave * call s:Tlist_Menu_Remove_File() + augroup end + + call s:Tlist_Menu_Update_File(0) +endfunction + +" Tlist_Vim_Session_Load +" Initialize the taglist window/buffer, which is created when loading +" a Vim session file. +function! s:Tlist_Vim_Session_Load() + call s:Tlist_Log_Msg('Tlist_Vim_Session_Load') + + " Initialize the taglist window + call s:Tlist_Window_Init() + + " Refresh the taglist window + call s:Tlist_Window_Refresh() +endfunction + +" Tlist_Set_App +" Set the name of the external plugin/application to which taglist +" belongs. +" Taglist plugin is part of another plugin like cream or winmanager. +function! Tlist_Set_App(name) + if a:name == "" + return + endif + + let s:tlist_app_name = a:name +endfunction + +" Winmanager integration + +" Initialization required for integration with winmanager +function! TagList_Start() + " If current buffer is not taglist buffer, then don't proceed + if bufname('%') != '__Tag_List__' + return + endif + + call Tlist_Set_App('winmanager') + + " Get the current filename from the winmanager plugin + let bufnum = WinManagerGetLastEditedFile() + if bufnum != -1 + let filename = fnamemodify(bufname(bufnum), ':p') + let ftype = getbufvar(bufnum, '&filetype') + endif + + " Initialize the taglist window, if it is not already initialized + if !exists('s:tlist_window_initialized') || !s:tlist_window_initialized + call s:Tlist_Window_Init() + call s:Tlist_Window_Refresh() + let s:tlist_window_initialized = 1 + endif + + " Update the taglist window + if bufnum != -1 + if !s:Tlist_Skip_File(filename, ftype) && g:Tlist_Auto_Update + call s:Tlist_Window_Refresh_File(filename, ftype) + endif + endif +endfunction + +function! TagList_IsValid() + return 0 +endfunction + +function! TagList_WrapUp() + return 0 +endfunction + +" restore 'cpo' +let &cpo = s:cpo_save +unlet s:cpo_save + diff --git a/vim/skeletons/c b/vim/skeletons/c new file mode 100644 index 0000000..36ae822 --- /dev/null +++ b/vim/skeletons/c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char* argv[]) +{ + +} diff --git a/vim/skeletons/cpp b/vim/skeletons/cpp new file mode 100644 index 0000000..5f7e48b --- /dev/null +++ b/vim/skeletons/cpp @@ -0,0 +1,6 @@ +#include + +int main(int argc, char* argv[]) +{ + +} diff --git a/vim/skeletons/make b/vim/skeletons/make new file mode 100644 index 0000000..e2c82c7 --- /dev/null +++ b/vim/skeletons/make @@ -0,0 +1,26 @@ +BIN = +OBJ = +CC = gcc +INCLUDES = +DEFINES = +LIBS = +PC_LIBS = +COMMONFLAGS = -Werror -Wall -O0 -g -pipe +CFLAGS = -c $(INCLUDES) $(DEFINES) $(shell pkg-config $(PC_LIBS) --cflags) $(COMMONFLAGS) +LDFLAGS = $(shell pkg-config $(PC_LIBS) --libs) $(LIBS) $(COMMONFLAGS) + +$(BIN) : $(OBJ) + $(CC) $(OBJ) $(LDFLAGS) -o $@ + +%.o : %.c + $(CC) $(CFLAGS) -o $@ $< + +clean : + rm -f $(OBJ) $(BIN) + +dep : + makedepend $(INCLUDES) $(DEFINES) -Y *.c *.h *.cpp *.hpp *.def > /dev/null 2>&1 + rm -f Makefile.bak + +run : $(BIN) + @./$(BIN) diff --git a/vim/skeletons/perl b/vim/skeletons/perl new file mode 100644 index 0000000..a284e72 --- /dev/null +++ b/vim/skeletons/perl @@ -0,0 +1,5 @@ +#!/usr/bin/perl +use strict; +use warnings; + + diff --git a/vim/skeletons/tex b/vim/skeletons/tex new file mode 100644 index 0000000..b1ad35e --- /dev/null +++ b/vim/skeletons/tex @@ -0,0 +1,13 @@ +% vim:foldmethod=marker commentstring=%%%s +% {{{ header +\documentclass[letterpaper,11pt]{article} +\usepackage{jesse} + +\headers{} + {\huge \textbf{}} + {\large Jesse Luehrs\\ \normalsize jluehrs2} +% }}} + +\begin{document} + +\end{document} diff --git a/vim/syntax/nhdes.vim b/vim/syntax/nhdes.vim new file mode 100644 index 0000000..f2eefd3 --- /dev/null +++ b/vim/syntax/nhdes.vim @@ -0,0 +1,86 @@ +" Vim syntax file +" Language: NetHack DES file +" Author: Pasi Kallinen +" Version: 20061119 +" Copyright: Copyright (c) 2006 Pasi Kallinen +" Licence: You may redistribute this under the same terms as NetHack itself + +if exists("b:current_syntax") + finish +endif + +syn sync minlines=30 + +" we're case sensitive +syn case match + +syn region nhDesComment start=/^[ \t]*#/ end=/$/ + +syn keyword nhDesCommandNoArgs + \ NOMAP RANDOM_CORRIDORS WALLIFY + +syn keyword nhDesCommandWithArgs + \ ALTAR BRANCH CHANCE CONTAINER CORRIDOR DOOR DRAWBRIDGE ENGRAVING + \ FLAGS FOUNTAIN GEOMETRY GOLD INIT_MAP LADDER LEVEL MAZE MAZEWALK + \ MESSAGE MONSTER NAME NON_DIGGABLE NON_PASSWALL OBJECT POOL PORTAL + \ RANDOM_MONSTERS RANDOM_OBJECTS RANDOM_PLACES REGION ROOM SINK STAIR + \ SUBROOM TELEPORT_REGION TRAP + +syn keyword nhDesRegister + \ align monster object place + +syn keyword nhDesConstant + \ altar arboreal asleep awake blessed bottom broken burn center chaos + \ closed coaligned \contained cursed down dust east engrave false filled + \ half-left half-right hardfloor hostile law left levregion lit locked + \ mark m_feature m_monster m_object neutral noalign nodoor nommap + \ noncoaligned none north noteleport open peaceful random right sanctum + \ shortsighted shrine south top true uncursed unfilled unlit up west + +syn region nhDesString start=/"/ end=/"/ +syn match nhDesChar /'.'/ + +syn match nhDesMapCharDoor /[+S]/ contained +syn match nhDesMapCharFloor /[\.B]/ contained +syn match nhDesMapCharCorridor /[#H]/ contained +syn match nhDesMapCharWall /[\-\| ]/ contained +syn match nhDesMapCharWater /[WP}{]/ contained +syn match nhDesMapCharThrone /\\/ contained +syn match nhDesMapCharAir /A/ contained +syn match nhDesMapCharCloud /C/ contained +syn match nhDesMapCharLava /L/ contained +syn match nhDesMapCharSink /K/ contained +syn match nhDesMapCharIce /I/ contained +syn match nhDesMapCharTree /T/ contained +syn match nhDesMapCharIronbars /F/ contained +syn match nhDesMapCharLinenum /[0123456789]/ contained +" TODO: Any better way to do this? +syn match nhDesMapCharError /[^+S\.B#H\-\| WP}{\\ACLKITF0-9]/ contained + +syn region nhDesMap matchgroup=nhDesCommandNoArgs start=/^MAP$/ end=/^ENDMAP$/ contains=nhDesMapCharError,nhDesMapCharDoor,nhDesMapCharFloor,nhDesMapCharCorridor,nhDesMapCharWall,nhDesMapCharWater,nhDesMapCharThrone,nhDesMapCharAir,nhDesMapCharCloud,nhDesMapCharLava,nhDesMapCharSink,nhDesMapCharIce,nhDesMapCharTree,nhDesMapCharIronbars,nhDesMapCharLinenum + +hi def link nhDesComment Comment +hi def link nhDesCommandNoArgs KeyWord +hi def link nhDesCommandWithArgs KeyWord +hi def link nhDesRegister Constant +hi def link nhDesConstant Constant +hi def link nhDesString String +hi def link nhDesChar String + +highlight nhDesMapCharDoor ctermbg=black ctermfg=brown +highlight nhDesMapCharFloor ctermbg=black ctermfg=grey +highlight nhDesMapCharCorridor ctermbg=black ctermfg=grey +highlight nhDesMapCharWall ctermbg=black ctermfg=grey +highlight nhDesMapCharWater ctermbg=black ctermfg=darkblue +highlight nhDesMapCharThrone ctermbg=black ctermfg=yellow +highlight nhDesMapCharAir ctermbg=black ctermfg=lightblue +highlight nhDesMapCharCloud ctermbg=black ctermfg=grey +highlight nhDesMapCharLava ctermbg=black ctermfg=red +highlight nhDesMapCharSink ctermbg=black ctermfg=grey +highlight nhDesMapCharIce ctermbg=black ctermfg=lightblue +highlight nhDesMapCharTree ctermbg=black ctermfg=green +highlight nhDesMapCharIronbars ctermbg=black ctermfg=cyan +highlight nhDesMapCharLinenum ctermbg=black ctermfg=darkgrey +highlight nhDesMapCharError ctermbg=red ctermfg=yellow + +let b:current_syntax = "nhdes" -- cgit v1.2.3