Added taglist support.
authorIain Patterson <me@iain.cx>
Mon, 18 Jun 2007 11:35:41 +0000 (11:35 +0000)
committerIain Patterson <me@iain.cx>
Mon, 18 Jun 2007 11:35:41 +0000 (11:35 +0000)
git-svn-id: https://svn.cambridge.iain.cx/profile/trunk@51 6be0d1a5-5cfe-0310-89b6-964be062b18b

.vim/plugin/taglist.vim [new file with mode: 0644]
.vimrc

diff --git a/.vim/plugin/taglist.vim b/.vim/plugin/taglist.vim
new file mode 100644 (file)
index 0000000..1393f65
--- /dev/null
@@ -0,0 +1,1887 @@
+" File: taglist.vim
+" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
+" Version: 2.3
+" Last Modified: Feb 10, 2003
+"
+" Overview
+" --------
+" The "Tag List" plugin can be used to efficiently browse through your
+" source files. The "Tag List" plugin provides the following features:
+"
+" 1. Opens a vertically/horizontally split Vim window with a list of tags
+"    (functions, classes, structures, variables, etc) defined in the current
+"    file.
+" 2. Groups the tags by their type and displays them in a foldable tree.
+" 3. Automatically updates the taglist window as you switch between
+"    files/buffers.
+" 4. When a tag name is selected from the taglist window, positions the cursor
+"    at the definition of the tag in the source file
+" 5. Automatically highlights the current tag name.
+" 6. Can display the prototype of a tag from the taglist window.
+" 7. Displays the scope of a tag.
+" 8. Can optionally use the tag prototype instead of the tag name.
+" 9. The tag list can be sorted either by name or by line number.
+" 10. Supports the following language files: Assembly, ASP, Awk, C, C++,
+"     Cobol, Eiffel, Fortran, Java, Lisp, Lua, Make, Pascal, Perl, PHP,
+"     Python, Rexx, Ruby, Scheme, Shell, Slang, Sql, TCL, Verilog, Vim and
+"     Yacc.
+" 11. Runs in all the platforms where the exuberant ctags utility and Vim are
+"     supported (this includes MS-Windows and Unix based systems).
+" 12. Runs in both console/terminal and GUI versions of Vim.
+" 13. The ctags output for a file is cached to speed up displaying the taglist
+"     window.
+" 14. Works with the winmanager plugin. Using the winmanager plugin, you can
+"     use multiple Vim plugins at the same time efficiently.
+" 15. Can be easily extended to support new languages. Support for existing
+"     languages can be modified easily.
+"
+" To see the screenshots of the taglist plugin in different environments,
+" visit the following page:
+"
+"       http://www.geocities.com/yegappan/taglist/screenshots.html
+"
+" This plugin relies on the exuberant ctags utility to dynamically generate
+" the tag listing. You can download the exuberant ctags utility from
+"
+"               http://ctags.sourceforge.net.
+"
+" The exuberant ctags utility must be installed in your system to use this
+" plugin. You should use exuberant ctags version 5.0 and above.  This plugin
+" doesn't use or create a tags file and there is no need to create a tags file
+" to use this plugin.
+"
+" This script relies on the Vim "filetype" detection mechanism to determine
+" the type of the current file. To turn on filetype detection use
+"
+"               :filetype on
+"
+" This plugin will not work in 'compatible' mode.  Make sure the 'compatible'
+" option is not set. This plugin will not work if you run Vim in the
+" restricted mode (using the -Z command-line argument). This plugin also
+" assumes that the system() Vim function is supported.
+"
+" Installation
+" ------------
+" 1. Copy the taglist.vim script to the $HOME/.vim/plugin directory. Refer to
+"    ':help add-plugin', ':help add-global-plugin' and ':help runtimepath' for
+"    more details about Vim plugins.
+" 2. Set the Tlist_Ctags_Cmd variable to point to the location of the
+"    exuberant ctags utility (not to the directory).
+" 3. 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.
+" 4. Restart Vim.
+" 5. You can use the ":Tlist" command to open/close the taglist window. 
+"
+" Usage
+" -----
+" You can open the taglist window by using the ":Tlist" command. Invoking this
+" command will toggle (open or close) the taglist window. You can map a key to
+" invoke this command:
+"
+"               nnoremap <silent> <F8> :Tlist<CR>
+"
+" Add the above mapping to your ~/.vimrc file.  You can also open the taglist
+" window on startup using the following command line:
+"
+"               $ vim +Tlist
+"
+" 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 ":Tlist" command when the taglist
+" window is opened, will close the taglist window.
+"
+" As you switch between source files, the taglist window will be automatically
+" updated with the tag listing for the current source file.  The tag names
+" will grouped by their type (variable, function, class, etc). For tags with
+" scope information (like class members, structures inside structures, etc),
+" the scope information will be displayed in square brackets "[]" after the
+" tagname.
+" 
+" The tag names will be  displayed as a foldable tree using the Vim folding
+" support. You can collapse the tree using the '-' key or using the Vim zc
+" fold command. You can open the tree using the '+' key or using the Vim zo
+" fold command. You can open all the fold using the '*' key or using the Vim
+" zR fold command You can also use the mouse to open/close the folds.
+"
+" You can select a tag either by pressing the <Enter> key or by double
+" clicking the tag name using the mouse. You can configure the taglist plugin
+" by setting the 'Tlist_Use_SingleClick' variable to jump to a tag on a single
+" mouse click.
+"
+" The script will automatically highlight the name of the current tag.  The
+" tag name will be highlighted after 'updatetime' milliseconds. The default
+" value for this Vim option is 4 seconds.  You can also use the ":TlistSync"
+" command to force the highlighting of the current tag. You can map a key to
+" invoke this command:
+"
+"               nnoremap <silent> <F9> :TlistSync<CR>
+"
+" Add the above mapping to your ~/.vimrc file.
+"
+" If you place the cursor on a tag name in the "Tag List" window, then the tag
+" prototype will be displayed at the Vim status line after 'updatetime'
+" milliseconds. The default value for the 'updatetime' Vim option is 4
+" seconds. You can also press the space bar to display the prototype of the
+" tag under the cursor.
+"
+" By default, the tag list will be sorted by the order in which the tags
+" appear in the file. You can sort the tags either by name or by order by
+" pressing the "s" key in 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.
+"
+" You can press the '?' key to display help information about using the
+" taglist window. If you again press the '?' key, the help information will be
+" removed.
+"
+" The following table lists the description of the keys that you can use
+" in the taglist window.
+"
+"       Key           Description
+"
+"       <CR>          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.
+"       <Space>       Display the prototype of the tag under the cursor.
+"       u             Update the tags listed in the taglist window
+"       s             Change the sort order of the tags (by name or by order)
+"       x             Zoom-in or Zoom-out the taglist window
+"       +             Open a fold
+"       -             Close a fold
+"       *             Open all folds
+"       q             Close the taglist window
+"       ?             Display help
+"
+"
+" You can use the ":TlistShowPrototype" command to display the prototype of
+" a function in the specified line number. For example,
+"
+"               :TlistShowPrototype 50
+"
+" If the line number is not supplied, this command will display the prototype
+" of the current function.
+"
+" You can also 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'
+"
+" Configuration
+" -------------
+" By changing the following variables you can configure the behavior of this
+" script. Set the following variables in your .vimrc file using the 'let'
+" command.
+"
+" The script uses the Tlist_Ctags_Cmd variable to locate the ctags utility.
+" By default, this is set to ctags. 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.
+"
+"               let Tlist_Ctags_Cmd = 'd:\tools\ctags.exe'
+"               let Tlist_Ctags_Cmd = '/usr/local/bin/ctags'
+"
+" By default, the tag names will be listed in the order in which they are
+" defined in the file. You can alphabetically sort the tag names by pressing
+" the "s" key in the taglist window. You can also change the default order by
+" setting the variable Tlist_Sort_Type to "name" or "order":
+"
+"               let Tlist_Sort_Type = "name"
+"
+" Be default, the tag names will be listed 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
+"
+" By default, the vertically split taglist window will appear on the left hand
+" side. If you prefer to open the window on the right hand side, you can set
+" the Tlist_Use_Right_Window variable to one:
+"
+"               let Tlist_Use_Right_Window = 1
+"
+" To automatically open the taglist window, when you start Vim, you can set
+" the Tlist_Auto_Open variable to 1. By default, this variable is set to 0 and
+" the taglist window will not be opened automatically on Vim startup.
+"
+"               let Tlist_Auto_Open = 1
+"
+" By default, only the tag name will be displayed in the taglist window. If
+" you like to see tag prototypes instead of names, set the
+" Tlist_Display_Prototype variable to 1. By default, this variable is set to 0
+" and only tag names will be displayed.
+"
+"               let Tlist_Display_Prototype = 1
+"
+" The default width of the vertically split taglist window will be 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.
+"
+" By default, when the width of the window is less than 100 and a new taglist
+" window is opened vertically, then the window width will be increased by the
+" value set in the Tlist_WinWidth variable to accommodate the new window.  The
+" value of this variable is used only if you are using a vertically split
+" taglist window.  If your terminal doesn't support changing the window width
+" from Vim (older version of xterm running in a Unix system) or if you see any
+" weird problems in the screen due to the change in the window width or if you
+" prefer not to adjust the window width then set the 'Tlist_Inc_Winwidth'
+" variable to 0.  CAUTION: If you are using the MS-Windows version of Vim in a
+" MS-DOS command window then you must set this variable to 0, otherwise the
+" system may hang due to a Vim limitation (explained in :help win32-problems)
+"
+"               let Tlist_Inc_Winwidth = 0
+"
+" By default, when you double click on the tag name using the left mouse 
+" button, the cursor will be positioned at the definition of the tag. You 
+" can set the Tlist_Use_SingleClick variable to one to jump to a tag when
+" 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 one and try to
+" resize the taglist window using the mouse, then Vim will crash. The fix for
+" this bug will be available in the next version of Vim. In the meantime,
+" instead of resizing the taglist window using the mouse, you can use normal
+" Vim window resizing commands to resize the taglist window.
+"
+" By default, the taglist window will contain text that display the name of
+" the file, sort order information and the key to press to get help. Also,
+" empty lines will be used to separate different groups of tags. If you
+" don't need these information, you can set the Tlist_Compact_Format variable
+" to one to get a compact display.
+"
+"               let Tlist_Compact_Format = 1
+"
+" Extending
+" ---------
+" You can extend exuberant ctags to add support for new languages. For more
+" information, visit the following page
+"
+"               http://ctags.sourceforge.net/EXTENDING.html
+"
+" You can extend the taglist plugin to add support for new languages or modify
+" the support for an already supported language by setting the following
+" variables in the .vimrc file.
+"
+" To modify the support for an already supported language, you have to set the
+" tlist_xxx_settings variable. Replace xxx with the Vim filetype name.  To
+" determine the filetype name used by Vim for a file, use the command
+"
+"               :set filetype
+"
+" The format of the value set in the tlist_xxx_settings variable is
+"
+"          <language_name>;flag1:name1;flag2:name2;flag3:name3
+"
+" The different fields are separated by the ';' character.  The first field
+" 'language_name' is the name used by exuberant ctags. This name can be
+" different from the file type name used by Vim. For example, for C++, the
+" language name used by ctags is 'c++' but the filetype name used by Vim is
+" 'cpp'. The remaining fields follow the format "flag:name". The sub-field
+" 'flag' is the language specific flag used by exuberant ctags to generate the
+" corresponding tags.  For example, for the C language, to list only the
+" functions, the 'f' flag should be used. For more information about the flags
+" supported by exuberant ctags for a particular language, read the help text
+" from the 'ctags --help' comand. The sub-field 'name' specifies the title
+" text to use for displaying the tags of a particular type. For example,
+" 'name' can be set to 'functions'.
+"
+" For example, to list only the classes and functions defined in a C++
+" language file, add the following lines to your .vimrc file
+"
+"       let tlist_cpp_settings = 'c++;c:class;f:function'
+"
+" In the above setting, 'cpp' is the Vim filetype name and 'c++' is the name
+" used by the exuberant ctags tool. 'c' and 'f' are the flags passed to
+" exuberant ctags to list classes and functions.
+"
+" For example, to display only functions defined in a C file and to use "My
+" Functions" as the title for the function group, use 
+"
+"       let tlist_c_settings = 'c;f:My Functions'
+"
+" To add support for a new language, set the tlist_xxx_settings variable
+" appropriately as described above.
+"
+" ****************** Do not modify after this line ************************
+if exists('loaded_taglist') || &cp
+    finish
+endif
+let loaded_taglist=1
+
+" Location of the exuberant ctags tool
+if !exists('Tlist_Ctags_Cmd')
+    let Tlist_Ctags_Cmd = 'ctags'
+endif
+
+" Tag listing sort type - 'name' or 'order'
+if !exists('Tlist_Sort_Type')
+    let Tlist_Sort_Type = 'order'
+endif
+
+" Tag listing window split (horizontal/vertical) control
+if !exists('Tlist_Use_Horiz_Window')
+    let Tlist_Use_Horiz_Window = 0
+endif
+
+" Open the vertically split taglist window on the left or on the right side.
+" This setting is relevant only if Tlist_Use_Horiz_Window is set to zero (i.e.
+" only for vertically split windows)
+if !exists('Tlist_Use_Right_Window')
+    let Tlist_Use_Right_Window = 0
+endif
+
+" Increase Vim window width to display vertically split taglist window.  For
+" MS-Windows version of Vim running in a MS-DOS window, this must be set to 0
+" otherwise the system may hang due to a Vim limitation.
+if !exists('Tlist_Inc_Winwidth')
+    if (has('win16') || has('win95')) && !has('gui_running')
+        let Tlist_Inc_Winwidth = 0
+    else
+        let Tlist_Inc_Winwidth = 1
+    endif
+endif
+
+" Vertically split taglist window width setting
+if !exists('Tlist_WinWidth')
+    let Tlist_WinWidth = 30
+endif
+
+" Horizontally split taglist window height setting
+if !exists('Tlist_WinHeight')
+    let Tlist_WinHeight = 10
+endif
+
+" Automatically open the taglist window on Vim startup
+if !exists('Tlist_Auto_Open')
+    let Tlist_Auto_Open = 0
+endif
+
+" Display tag prototypes or tag names in the taglist window
+if !exists('Tlist_Display_Prototype')
+    let Tlist_Display_Prototype = 0
+endif
+
+" 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
+
+" 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'
+
+" aspvbs language
+let s:tlist_def_aspvbs_settings = 'asp;f:function;s:sub'
+
+" awk language
+let s:tlist_def_awk_settings = 'awk;f:function'
+
+" beta language
+let s:tlist_def_beta_settings = 'beta;f:fragment;s:pattern;v:virtual'
+
+" c language
+let s:tlist_def_c_settings = 'c;d:macro;g:enum;s:struct;u:union;t:typedef;' .
+                           \ 'v:variable;f:function'
+
+" c++ language
+let s:tlist_def_cpp_settings = 'c++;v:variable;d:macro;t:typedef;c:class;' .
+                             \ 'g:enum;s:struct;u:union;f:function'
+
+" 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'
+
+" 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'
+
+" java language
+let s:tlist_def_java_settings = 'java;p:package;c:class;i:interface;' .
+                              \ 'f:field;m:method'
+
+" lisp language
+let s:tlist_def_lisp_settings = 'lisp;f:function'
+
+" lua language
+let s:tlist_def_lua_settings = 'lua;f:function'
+
+" makefiles
+let s:tlist_def_make_settings = 'make;m:macro'
+
+" pascal language
+let s:tlist_def_pascal_settings = 'pascal;f:function;p:procedure'
+
+" perl language
+let s:tlist_def_perl_settings = 'perl;p:package;s:subroutine'
+
+" php language
+let s:tlist_def_php_settings = 'php;c:class;f:function'
+
+" python language
+let s:tlist_def_python_settings = 'python;c:class;m:member;f:function'
+
+" rexx language
+let s:tlist_def_rexx_settings = 'rexx;s:subroutine'
+
+" ruby language
+let s:tlist_def_ruby_settings = 'ruby;c:class;f:method;F:function;' .
+                              \ 'm:singleton method'
+
+" scheme language
+let s:tlist_def_scheme_settings = 'scheme;s:set;f:function'
+
+" shell language
+let s:tlist_def_sh_settings = 'sh;f:function'
+
+" C shell language
+let s:tlist_def_csh_settings = 'sh;f:function'
+
+" Z shell language
+let s:tlist_def_zsh_settings = 'sh;f:function'
+
+" slang language
+let s:tlist_def_slang_settings = 'slang;n:namespace;f:function'
+
+" sql language
+let s:tlist_def_sql_settings = 'sql;c:cursor;F:field;P:package;r:record;' .
+            \ 's:subtype;t:table;T:trigger;v:variable;f:function;p:procedure'
+
+" tcl language
+let s:tlist_def_tcl_settings = 'tcl;c:class;f:method;p:procedure'
+
+"verilog language
+let s:tlist_def_verilog_settings = 'verilog;m:module;P:parameter;r:reg;' .
+                                 \ 't:task;w:write;p:port;v:variable;f:function'
+
+" vim language
+let s:tlist_def_vim_settings = 'vim;v:variable;f:function'
+
+" yacc language
+let s:tlist_def_yacc_settings = 'yacc;l:label'
+
+" Initialize the taglist script local variables for the supported file types
+" and tag types
+let s:tlist_winsize_chgd = 0
+let s:tlist_win_maximized = 0
+let s:tlist_part_of_winmanager = 0
+" 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__"
+
+function! s:Tlist_Show_Help()
+    if g:Tlist_Compact_Format == 1
+        " In compact display mode, do not display help
+        return
+    endif
+    if exists("s:tlist_show_help") && s:tlist_show_help == 1
+        let s:tlist_show_help = 0
+    else
+        let s:tlist_show_help = 1
+    endif
+
+    call s:Tlist_Open_Window()
+
+    call s:Tlist_Init_Window(b:tlist_bufnum)
+
+    " Update the taglist window
+    call s:Tlist_Explore_File(b:tlist_bufnum)
+endfunction
+
+" 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
+let s:Tlist_Skip_Refresh = 0
+
+function! s:Tlist_Warning_Msg(msg)
+    echohl WarningMsg
+    echomsg a:msg
+    echohl None
+endfunction
+
+" Tlist_Skip_Buffer()
+" Check whether tag listing is supported for the specified buffer.
+function! s:Tlist_Skip_Buffer(bufnum)
+    " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help
+    if getbufvar(a:bufnum, '&buftype') != ''
+        return 1
+    endif
+
+    let ftype = getbufvar(a:bufnum, '&filetype')
+
+    " Skip buffers with filetype not set
+    if 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_' . ftype . '_settings'
+    if !exists(var)
+        let var = 'g:tlist_' . ftype . '_settings'
+        if !exists(var)
+            return 1
+        endif
+    endif
+
+    let filename = fnamemodify(bufname(a:bufnum), '%:p')
+
+    " Skip buffers with no names
+    if filename == ''
+        return 1
+    endif
+
+    " Skip files which are not readable or files which are not yet stored
+    " to the disk
+    if !filereadable(filename)
+        return 1
+    endif
+
+    return 0
+endfunction
+
+" Tlist_FileType_Init
+" Initialize the ctags arguments and tag variable for the specified
+" file type
+function! s:Tlist_FileType_Init(ftype)
+    " If the user didn't specify any settings, then use the default
+    " ctags args. Otherwise, use the settings specified by the user
+    let var = 'g:tlist_' . a:ftype . '_settings'
+    if exists(var)
+        " User specified ctags arguments
+        let settings = {var} . ';'
+    else
+        " Default ctags arguments
+        let var = 's:tlist_def_' . a:ftype . '_settings'
+        if !exists(var)
+            " No default settings for this file type. This filetype is
+            " not supported
+            return 0
+        endif
+        let settings = s:tlist_def_{a:ftype}_settings . ';'
+    endif
+
+    let msg = 'Invalid ctags option setting - ' . settings
+
+    " Extract the file type to pass to ctags. This can 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
+
+    return 1
+endfunction
+
+" Tlist_Cleanup()
+" Cleanup all the taglist window variables.
+function! s:Tlist_Cleanup()
+    if has('syntax')
+        silent! syntax clear TagListTitle
+    endif
+    match none
+
+    if exists('b:tlist_ftype') && b:tlist_ftype != ''
+        let count_var_name = 's:tlist_' . b:tlist_ftype . '_count'
+        if exists(count_var_name)
+            let old_ftype = b:tlist_ftype
+            let i = 1
+            while i <= s:tlist_{old_ftype}_count
+                let ttype = s:tlist_{old_ftype}_{i}_name
+                let j = 1
+                let var_name = 'b:tlist_' . old_ftype . '_' . ttype . '_count'
+                if exists(var_name)
+                    let cnt = b:tlist_{old_ftype}_{ttype}_count
+                else
+                    let cnt = 0
+                endif
+                while j <= cnt
+                    unlet! b:tlist_{old_ftype}_{ttype}_{j}
+                    let j = j + 1
+                endwhile
+                unlet! b:tlist_{old_ftype}_{ttype}_count
+                unlet! b:tlist_{old_ftype}_{ttype}_start
+                let i = i + 1
+            endwhile
+        endif
+    endif
+
+    " Clean up all the variables containing the tags output
+    if exists('b:tlist_tag_count')
+        while b:tlist_tag_count > 0
+            unlet! b:tlist_tag_{b:tlist_tag_count}
+            let b:tlist_tag_count = b:tlist_tag_count - 1
+        endwhile
+    endif
+
+    unlet! b:tlist_bufnum
+    unlet! b:tlist_bufname
+    unlet! b:tlist_ftype
+endfunction
+
+" Tlist_Open_Window
+" Create a new taglist window. If it is already open, clear it
+function! s:Tlist_Open_Window()
+    " If used with winmanager don't open windows. Winmanager will handle
+    " the window/buffer management
+    if s:tlist_part_of_winmanager
+        return
+    endif
+
+    " Cleanup the taglist window listing, if the window is open
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum != -1
+        " Jump to the existing window
+        if winnr() != winnum
+            exe winnum . 'wincmd w'
+        endif
+    else
+        " Create a new window. If user prefers a horizontal window, then open
+        " a horizontally split window. Otherwise open a vertically split
+        " window
+        if g:Tlist_Use_Horiz_Window == 1
+            " If a single window is used for all files, then open the tag
+            " listing window at the very bottom
+            let win_dir = 'botright'
+            " Horizontal window height
+            let win_size = g:Tlist_WinHeight
+        else
+            " Increase the window size, if needed, to accomodate the new
+            " window
+            if g:Tlist_Inc_Winwidth == 1 &&
+                        \ &columns < (80 + g:Tlist_WinWidth)
+                " one extra column is needed to include the vertical split
+                let &columns= &columns + (g:Tlist_WinWidth + 1)
+                let s:tlist_winsize_chgd = 1
+            else
+                let s:tlist_winsize_chgd = 0
+            endif
+
+            " Open the window at the leftmost place
+            if g:Tlist_Use_Right_Window == 1
+                let win_dir = 'botright vertical'
+            else
+                let win_dir = 'topleft vertical'
+            endif
+            let win_size = g:Tlist_WinWidth
+        endif
+
+        " If the tag listing temporary buffer already exists, then reuse it.
+        " Otherwise create a new buffer
+        let bufnum = bufnr(g:TagList_title)
+        if bufnum == -1
+            " Create a new buffer
+            let wcmd = g:TagList_title
+        else
+            " Edit the existing buffer
+            let wcmd = '+buffer' . bufnum
+        endif
+
+        " Create the taglist window
+        exe 'silent! ' . win_dir . ' ' . win_size . 'split ' . wcmd
+    endif
+endfunction
+
+" Tlist_Zoom_Window
+" Zoom (maximize/minimize) the taglist window
+function! s:Tlist_Zoom_Window()
+    if s:tlist_win_maximized == 1
+        if g:Tlist_Use_Horiz_Window == 1
+            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 == 1
+            resize
+        else
+            vert resize
+        endif
+        let s:tlist_win_maximized = 1
+    endif
+endfunction
+
+" Tlist_Init_Window
+" Set the default options for the taglist window
+function! s:Tlist_Init_Window(bufnum)
+    " Set report option to a huge value to prevent informations messages
+    " while deleting the lines
+    let old_report = &report
+    set report=99999
+
+    " Mark the buffer as modifiable
+    setlocal modifiable
+
+    " Delete the contents of the buffer to the black-hole register
+    silent! %delete _
+
+    " Mark the buffer as not modifiable
+    setlocal nomodifiable
+
+    " Restore the report option
+    let &report = old_report
+
+    " Clean up all the old variables used for the last filetype
+    call <SID>Tlist_Cleanup()
+
+    let filename = fnamemodify(bufname(a:bufnum), ':p')
+
+    " Set the sort type. First time, use the global setting. After that use
+    " the previous setting
+    let b:tlist_sort_type = getbufvar(a:bufnum, 'tlist_sort_type')
+    if b:tlist_sort_type == ''
+        let b:tlist_sort_type = g:Tlist_Sort_Type
+    endif
+
+    let b:tlist_tag_count = 0
+    let b:tlist_bufnum = a:bufnum
+    let b:tlist_bufname = fnamemodify(bufname(a:bufnum), ':p')
+    let b:tlist_ftype = getbufvar(a:bufnum, '&filetype')
+
+    " Mark the buffer as modifiable
+    setlocal modifiable
+
+    if s:tlist_part_of_winmanager
+        " To handle a bug in the winmanager plugin, add a space at the
+        " last line
+        call setline('$', ' ')
+    endif
+
+    if g:Tlist_Compact_Format == 0
+        if exists("s:tlist_show_help") && s:tlist_show_help == 1
+            call append(0, '" <enter> : Jump to tag definition')
+            call append(1, '" o : Jump to tag definition in new window')
+            call append(2, '" <space> : Display tag prototype')
+            call append(3, '" u : Update tag list')
+            call append(4, '" s : Select sort field')
+            call append(5, '" x : Zoom-out/Zoom-in taglist window')
+            call append(6, '" + : Open a fold')
+            call append(7, '" - : Close a fold')
+            call append(8, '" * : Open all folds')
+            call append(9, '" q : Close the taglist window')
+            call append(10, '" ? : Remove help text')
+            call append(11, '" Sorted by ' . b:tlist_sort_type)
+            call append(12, '"= ' . fnamemodify(filename, ':t') . ' (' . 
+                                   \ fnamemodify(filename, ':p:h') . ')')
+        else
+            call append(0, '" Press ? to display help text')
+            call append(1, '" Sorted by ' . b:tlist_sort_type)
+            call append(2, '"= ' . fnamemodify(filename, ':t') . ' (' . 
+                                   \ fnamemodify(filename, ':p:h') . ')')
+        endif
+    endif
+
+    " Mark the buffer as not modifiable
+    setlocal nomodifiable
+
+    " Highlight the comments
+    if has('syntax')
+        syntax match TagListComment '^" .*'
+        syntax match TagListSortBy  '^" Sorted by .*'
+        syntax match TagListCurDir  '^"= .*'
+
+        " Colors used to highlight the selected tag name
+        highlight clear TagName
+        if has('gui_running') || &t_Co > 2
+            highlight link TagName Search
+        else
+            highlight TagName term=reverse cterm=reverse
+        endif
+
+        " Colors to highlight comments and titles
+        highlight clear TagListComment
+        highlight link TagListComment Comment
+        highlight clear TagListTitle
+        highlight link TagListTitle Title
+        highlight clear TagListSortBy
+        highlight link TagListSortBy String
+        highlight clear TagListCurDir
+        highlight link TagListCurDir Statement
+    endif
+
+    " Folding related settings
+    if has('folding')
+        setlocal foldenable
+        setlocal foldmethod=manual
+        setlocal foldcolumn=2
+        setlocal foldtext=v:folddashes.getline(v:foldstart)
+    endif
+
+    if !s:tlist_part_of_winmanager
+    " Mark buffer as scratch
+    silent! setlocal buftype=nofile
+    silent! setlocal bufhidden=delete
+    silent! setlocal noswapfile
+    " Due to a bug in Vim 6.0, the winbufnr() function fails for unlisted
+    " buffers. So if the taglist buffer is unlisted, multiple taglist
+    " windows will be opened. This bug is fixed in Vim 6.1 and above
+    if v:version >= 601
+        silent! setlocal nobuflisted
+    endif
+    endif
+
+    silent! setlocal nowrap
+
+    " If the 'number' option is set in the source window, it will affect the
+    " taglist window. So forcefully disable 'number' option for the taglist
+    " window
+    silent! setlocal nonumber
+
+    " Create buffer local mappings for jumping to the tags and sorting the list
+    nnoremap <buffer> <silent> <CR> :call <SID>Tlist_Jump_To_Tag(0)<CR>
+    nnoremap <buffer> <silent> o :call <SID>Tlist_Jump_To_Tag(1)<CR>
+    nnoremap <buffer> <silent> <2-LeftMouse> :call <SID>Tlist_Jump_To_Tag(0)<CR>
+    nnoremap <buffer> <silent> s :call <SID>Tlist_Change_Sort()<CR>
+    nnoremap <buffer> <silent> + :silent! foldopen<CR>
+    nnoremap <buffer> <silent> - :silent! foldclose<CR>
+    nnoremap <buffer> <silent> * :silent! %foldopen!<CR>
+    nnoremap <buffer> <silent> <kPlus> :silent! foldopen<CR>
+    nnoremap <buffer> <silent> <kMinus> :silent! foldclose<CR>
+    nnoremap <buffer> <silent> <kMultiply> :silent! %foldopen!<CR>
+    nnoremap <buffer> <silent> <Space> :call <SID>Tlist_Show_Tag_Prototype()<CR>
+    nnoremap <buffer> <silent> u :call <SID>Tlist_Update_Window()<CR>
+    nnoremap <buffer> <silent> x :call <SID>Tlist_Zoom_Window()<CR>
+    nnoremap <buffer> <silent> ? :call <SID>Tlist_Show_Help()<CR>
+    nnoremap <buffer> <silent> q :close<CR>
+
+    " Map single left mouse click if the user wants this functionality
+    if g:Tlist_Use_SingleClick == 1
+    nnoremap <silent> <LeftMouse> <LeftMouse>:if bufname("%") =~ "__Tag_List__"
+                        \ <bar> call <SID>Tlist_Jump_To_Tag(0) <bar> endif <CR>
+    endif
+
+    " Define the autocommand to highlight the current tag
+    augroup TagListAutoCmds
+        autocmd!
+        " Display the tag prototype for the tag under the cursor.
+        autocmd CursorHold __Tag_List__ call s:Tlist_Show_Tag_Prototype()
+        " Highlight the current tag 
+        autocmd CursorHold * silent call <SID>Tlist_Highlight_Tag(bufnr('%'), 
+                                        \ line('.'))
+        autocmd BufUnload __Tag_List__ call <SID>Tlist_Close_Window()
+        if !s:tlist_part_of_winmanager
+        " Adjust the Vim window width when taglist window is closed
+        " Auto refresh the taglisting window
+        autocmd BufEnter * call <SID>Tlist_Refresh_Window()
+        endif
+    augroup end
+endfunction
+
+" Tlist_Close_Window()
+" Close the taglist window and adjust the Vim window width
+function! s:Tlist_Close_Window()
+    " Remove the autocommands for the taglist window
+    silent! autocmd! TagListAutoCmds
+
+    " Clear all the highlights
+    match none
+
+    if has('syntax')
+        silent! syntax clear TagListTitle
+    endif
+
+    " Remove the left mouse click mapping if it was setup initially
+    if g:Tlist_Use_SingleClick == 1
+        if hasmapto('<LeftMouse>')
+            nunmap <LeftMouse>
+        endif
+    endif
+
+    if !s:tlist_part_of_winmanager
+    if g:Tlist_Use_Horiz_Window || g:Tlist_Inc_Winwidth == 0 ||
+                \ s:tlist_winsize_chgd == 0 ||
+                \ &columns < (80 + g:Tlist_WinWidth)
+        " No need to adjust window width if horizontally split tag listing
+        " window or if columns is less than 101 or if the user chose not to
+        " adjust the window width
+    else
+        " Adjust the Vim window width
+        let &columns= &columns - (g:Tlist_WinWidth + 1)
+    endif
+    endif
+endfunction
+
+" Tlist_Explore_File()
+" List the tags defined in the specified file in a Vim window
+function! s:Tlist_Explore_File(bufnum)
+    " Get the filename and file type
+    let filename = fnamemodify(bufname(a:bufnum), ':p')
+    let ftype = getbufvar(a:bufnum, '&filetype')
+
+    " Check for valid filename and valid filetype
+    if filename == '' || !filereadable(filename) || ftype == ''
+        return
+    endif
+
+    " If the tag types for this filetype are not yet created, then create
+    " them now
+    let var = 's:tlist_' . ftype . '_count'
+    if !exists(var)
+        if s:Tlist_FileType_Init(ftype) == 0
+            return
+        endif
+    endif
+
+    " If the cached ctags output exists for the specified buffer, then use it.
+    " Otherwise run ctags to get the output
+    let valid_cache = getbufvar(a:bufnum, 'tlist_valid_cache')
+    if valid_cache != ''
+        " Load the cached processed tags output from the buffer local
+        " variables
+        let b:tlist_tag_count = getbufvar(a:bufnum, 'tlist_tag_count') + 0
+        let i = 1
+        while i <= b:tlist_tag_count
+            let var_name = 'tlist_tag_' . i
+            let b:tlist_tag_{i} =  getbufvar(a:bufnum, var_name)
+            let i = i + 1
+        endwhile
+
+        let i = 1
+        while i <= s:tlist_{ftype}_count
+            let ttype = s:tlist_{ftype}_{i}_name
+            let var_name = 'tlist_' . ttype . '_start'
+            let b:tlist_{ftype}_{ttype}_start = 
+                        \ getbufvar(a:bufnum, var_name) + 0
+            let var_name = 'tlist_' . ttype . '_count'
+            let cnt = getbufvar(a:bufnum, var_name) + 0
+            let b:tlist_{ftype}_{ttype}_count = cnt
+            let var_name = 'tlist_' . ttype
+            let l:tlist_{ftype}_{ttype} = getbufvar(a:bufnum, var_name)
+            let j = 1
+            while j <= cnt
+                let var_name = 'tlist_' . ttype . '_' . j
+                let b:tlist_{ftype}_{ttype}_{j} = getbufvar(a:bufnum, var_name)
+                let j = j + 1
+            endwhile
+            let i = i + 1
+        endwhile
+    else
+        " 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 b:tlist_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_{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 . ' "' . filename . '"'
+
+        " Run ctags and get the tag list
+        let cmd_output = system(ctags_cmd)
+
+        " Cache the ctags output with a buffer local variable
+        call setbufvar(a:bufnum, 'tlist_valid_cache', 'Yes')
+        call setbufvar(a:bufnum, 'tlist_sort_type', b:tlist_sort_type)
+
+        " Handle errors
+        if v:shell_error && cmd_output != ''
+            call s:Tlist_Warning_Msg(cmd_output)
+            return
+        endif
+
+        " No tags for current file
+        if cmd_output == ''
+            call s:Tlist_Warning_Msg('No tags found for ' . filename)
+            return
+        endif
+
+        " Initialize variables for the new filetype
+        let i = 1
+        while i <= s:tlist_{ftype}_count
+            let ttype = s:tlist_{ftype}_{i}_name
+            let b:tlist_{ftype}_{ttype}_start = 0
+            let b:tlist_{ftype}_{ttype}_count = 0
+            let l:tlist_{ftype}_{ttype} = ''
+            let i = i + 1
+        endwhile
+
+        " Process the ctags output one line at a time. Separate the tag output
+        " based on the tag type and store it in the tag type variable
+        while cmd_output != ''
+            " Extract one line at a time
+            let one_line = strpart(cmd_output, 0, stridx(cmd_output, "\n"))
+            " Remove the line from the tags output
+            let cmd_output = strpart(cmd_output, stridx(cmd_output, "\n") + 1)
+
+            if one_line == ''
+                " Line is not in proper tags format
+                continue
+            endif
+
+            " Extract the tag type
+            let ttype = s:Tlist_Extract_Tagtype(one_line)
+
+            if ttype == ''
+                " Line is not in proper tags format
+                continue
+            endif
+
+            " make sure the tag type is supported
+            if s:tlist_{ftype}_ctags_flags !~# ttype
+                continue
+            endif
+
+            " Extract the tag name
+            if g:Tlist_Display_Prototype == 0
+                let ttxt = '  ' . strpart(one_line, 0, stridx(one_line, "\t"))
+
+                " Add the tag scope, if it is available. Tag scope is the last
+                " field after the 'line:<num>\t' field
+                let start = strridx(one_line, 'line:')
+                let end = strridx(one_line, "\t")
+                if end > start
+                    let tscope = strpart(one_line, end + 1)
+                    let tscope = strpart(tscope, stridx(tscope, ':') + 1)
+                    if tscope != ''
+                        let ttxt = ttxt . ' [' . tscope . ']'
+                    endif
+                endif
+            else
+                let start = stridx(one_line, '/^') + 2
+                let end = strridx(one_line, '/;"' . "\t")
+                if one_line[end - 1] == '$'
+                    let end = end -1
+                endif
+                let ttxt = strpart(one_line, start, end - start)
+            endif
+
+            " Update the count of this tag type
+            let cnt = b:tlist_{ftype}_{ttype}_count + 1
+            let b:tlist_{ftype}_{ttype}_count = cnt
+
+            " Add this tag to the tag type variable
+            let l:tlist_{ftype}_{ttype} = l:tlist_{ftype}_{ttype} . ttxt . "\n"
+
+            " Update the total tag count
+            let b:tlist_tag_count = b:tlist_tag_count + 1
+            let b:tlist_tag_{b:tlist_tag_count} = cnt . ':' . one_line
+
+            let b:tlist_{ftype}_{ttype}_{cnt} = b:tlist_tag_count
+        endwhile
+
+        " Cache the processed tags output using buffer local variables
+        call setbufvar(a:bufnum, 'tlist_tag_count', b:tlist_tag_count)
+        let i = 1
+        while i <= b:tlist_tag_count
+            let var_name = 'tlist_tag_' . i
+            call setbufvar(a:bufnum, var_name, b:tlist_tag_{i})
+            let i = i + 1
+        endwhile
+
+        let i = 1
+        while i <= s:tlist_{ftype}_count
+            let ttype = s:tlist_{ftype}_{i}_name
+            let var_name = 'tlist_' . ttype . '_start'
+            call setbufvar(a:bufnum, var_name, b:tlist_{ftype}_{ttype}_start)
+            let cnt = b:tlist_{ftype}_{ttype}_count
+            let var_name = 'tlist_' . ttype . '_count'
+            call setbufvar(a:bufnum, var_name, cnt)
+            let var_name = 'tlist_' . ttype
+            call setbufvar(a:bufnum, var_name, l:tlist_{ftype}_{ttype})
+            let j = 1
+            while j <= cnt
+                let var_name = 'tlist_' . ttype . '_' . j
+                call setbufvar(a:bufnum, var_name, b:tlist_{ftype}_{ttype}_{j})
+                let j = j + 1
+            endwhile
+            let i = i + 1
+        endwhile
+    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
+
+    " Mark the buffer as modifiable
+    setlocal modifiable
+
+    " Add the tag names grouped by tag type to the buffer with a title
+    let i = 1
+    while i <= s:tlist_{ftype}_count
+        let ttype = s:tlist_{ftype}_{i}_name
+        " Add the tag type only if there are tags for that type
+        if l:tlist_{ftype}_{ttype} != ''
+            if g:Tlist_Compact_Format == 0
+                let b:tlist_{ftype}_{ttype}_start = line('.') + 1
+                silent! put =s:tlist_{ftype}_{i}_fullname
+            else
+                let b:tlist_{ftype}_{ttype}_start = line('.')
+                silent! put! =s:tlist_{ftype}_{i}_fullname
+            endif
+            silent! put =l:tlist_{ftype}_{ttype}
+
+            " create a fold for this tag type
+            if has('folding')
+                let fold_start = b:tlist_{ftype}_{ttype}_start
+                let fold_end = fold_start + b:tlist_{ftype}_{ttype}_count
+                exe fold_start . ',' . fold_end  . 'fold'
+            endif
+
+            " Syntax highlight the tag type names
+            if has('syntax')
+                exe 'syntax match TagListTitle /\%' . 
+                            \ b:tlist_{ftype}_{ttype}_start . 'l.*/'
+            endif
+            " Separate the tag types with a empty line
+            normal! G
+            if g:Tlist_Compact_Format == 0
+                silent! put =''
+            endif
+        endif
+        let i = i + 1
+    endwhile
+
+    if s:tlist_part_of_winmanager
+        " To handle a bug in the winmanager plugin, add a space at the
+        " last line
+        call setline('$', ' ')
+    endif
+
+    " Mark the buffer as not modifiable
+    setlocal nomodifiable
+
+    " Restore the report option
+    let &report = old_report
+
+    " Initially open all the folds
+    if has('folding')
+        silent! %foldopen!
+    endif
+
+    " Goto the first line in the buffer
+    go
+
+    return
+endfunction
+
+" Tlist_Toggle_Window()
+" Open or close a taglist window
+function! s:Tlist_Toggle_Window(bufnum)
+    let curline = line('.')
+
+    " If taglist window is open then close it.
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum != -1
+        if winnr() == winnum
+            " Already in the taglist window. Close it and return
+            close
+        else
+            " Goto the taglist window, close it and then come back to the
+            " original window
+            let curbufnr = bufnr('%')
+            exe winnum . 'wincmd w'
+            close
+            " Need to jump back to the original window only if we are not
+            " already in that window
+            let winnum = bufwinnr(curbufnr)
+            if winnr() != winnum
+                exe winnum . 'wincmd w'
+            endif
+        endif
+        return
+    endif
+
+    let s:tlist_part_of_winmanager = 0
+
+    " Open the taglist window
+    call s:Tlist_Open_Window()
+
+    " Initialize the taglist window
+    call s:Tlist_Init_Window(a:bufnum)
+
+    " List the tags defined in a file
+    call s:Tlist_Explore_File(a:bufnum)
+
+    " Highlight the current tag
+    call s:Tlist_Highlight_Tag(a:bufnum, curline)
+
+    " Go back to the original window
+    let s:Tlist_Skip_Refresh = 1
+    wincmd p
+    let s:Tlist_Skip_Refresh = 0
+endfunction
+
+" Tlist_Extract_Tagtype
+" Extract the tag type from the tag text
+function! s:Tlist_Extract_Tagtype(tag_txt)
+    " The tag type is after the tag prototype field. The prototype field
+    " ends with the /;"\t string. We add 4 at the end to skip the characters
+    " in this special string..
+    let start = strridx(a:tag_txt, '/;"' . "\t") + 4
+    let end = strridx(a:tag_txt, 'line:') - 1
+    let ttype = strpart(a:tag_txt, start, end - start)
+
+    return ttype
+endfunction
+
+" Tlist_Extract_Tag_Prototype
+" Extract the tag protoype from the tag text
+function! s:Tlist_Extract_Tag_Prototype(tag_txt)
+    let start = stridx(a:tag_txt, '/^') + 2
+    let end = strridx(a:tag_txt, '/;"' . "\t")
+    if a:tag_txt[end - 1] == '$'
+        let end = end -1
+    endif
+    let tag_pat = strpart(a:tag_txt, start, end - start)
+
+    " Remove all the leading space characters
+    let tag_pat = matchstr(tag_pat, '^\s*\zs.*')
+
+    return tag_pat
+endfunction
+
+" Tlist_Refresh_Window()
+" Refresh the taglist window
+function! s:Tlist_Refresh_Window()
+    " We are entering the buffer from one of the taglist functions. So no need
+    " to refresh the taglist window again
+    if s:Tlist_Skip_Refresh == 1
+        return
+    endif
+
+    " If the buffer doesn't support tag listing, skip it
+    if s:Tlist_Skip_Buffer(bufnr('%'))
+        return
+    endif
+
+    let filename = expand('%:p')
+
+    let curline = line('.')
+
+    " Make sure the taglist window is open. Otherwise, no need to refresh
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum == -1
+        return
+    endif
+
+    let bno = bufnr(g:TagList_title)
+
+    let cur_bufnr = bufnr('%')
+
+    " If the tag listing for the current window is already present, no need to
+    " refresh it
+    if getbufvar(bno, 'tlist_bufnum') == cur_bufnr && 
+                \ getbufvar(bno, 'tlist_bufname') == filename
+        return
+    endif
+
+    " Save the current window number
+    let cur_winnr = winnr()
+
+    call s:Tlist_Open_Window()
+
+    call s:Tlist_Init_Window(cur_bufnr)
+
+    " Update the taglist window
+    call s:Tlist_Explore_File(cur_bufnr)
+
+    " Highlight the current tag
+    call s:Tlist_Highlight_Tag(cur_bufnr, curline)
+
+    " Refresh the taglist window
+    redraw
+
+    if !s:tlist_part_of_winmanager
+    " Jump back to the original window
+    exe cur_winnr . 'wincmd w'
+    endif
+endfunction
+
+" Tlist_Change_Sort()
+" Change the sort order of the tag listing
+function! s:Tlist_Change_Sort()
+    if !exists('b:tlist_bufnum') || !exists('b:tlist_ftype')
+        return
+    endif
+
+    let sort_type = getbufvar(b:tlist_bufnum, 'tlist_sort_type')
+
+    " Toggle the sort order from 'name' to 'order' and vice versa
+    if sort_type == 'name'
+        call setbufvar(b:tlist_bufnum, 'tlist_sort_type', 'order')
+    else
+        call setbufvar(b:tlist_bufnum, 'tlist_sort_type', 'name')
+    endif
+
+    " Save the current line for later restoration
+    let curline = '\V\^' . getline('.') . '\$'
+
+    " Clear out the cached taglist information
+    call setbufvar(b:tlist_bufnum, 'tlist_valid_cache', '')
+
+    call s:Tlist_Open_Window()
+
+    call s:Tlist_Init_Window(b:tlist_bufnum)
+
+    call s:Tlist_Explore_File(b:tlist_bufnum)
+
+    " Go back to the tag line before the list is sorted
+    call search(curline, 'w')
+endfunction
+
+" Tlist_Update_Window()
+" Update the window by regenerating the tag list
+function! s:Tlist_Update_Window()
+    if !exists('b:tlist_bufnum') || !exists('b:tlist_ftype')
+        return
+    endif
+
+    " Save the current line for later restoration
+    let curline = '\V\^' . getline('.') . '\$'
+
+    " Clear out the cached taglist information
+    call setbufvar(b:tlist_bufnum, 'tlist_valid_cache', '')
+
+    call s:Tlist_Open_Window()
+
+    call s:Tlist_Init_Window(b:tlist_bufnum)
+
+    " Update the taglist window
+    call s:Tlist_Explore_File(b:tlist_bufnum)
+
+    " Go back to the tag line before the list is sorted
+    call search(curline, 'w')
+endfunction
+
+" Tlist_Get_Tag_Linenr()
+" Return the tag line for the current line
+function! s:Tlist_Get_Tag_Linenr()
+    if !exists('b:tlist_ftype')
+        return 0
+    endif
+
+    let lnum = line('.')
+    let ftype = b:tlist_ftype
+
+    " 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 end = b:tlist_{ftype}_{ttype}_start + b:tlist_{ftype}_{ttype}_count
+        if lnum >= b:tlist_{ftype}_{ttype}_start && lnum <= end
+            break
+        endif
+        let i = i + 1
+    endwhile
+
+    " Current line doesn't belong to any of the displayed tag types
+    if i > s:tlist_{ftype}_count
+        return 0
+    endif
+
+    " Compute the offset into the displayed tags for the tag type
+    let offset = lnum - b:tlist_{ftype}_{ttype}_start
+    if offset == 0
+        return 0
+    endif
+
+    " Get the corresponding tag line and return it
+    return b:tlist_{ftype}_{ttype}_{offset}
+endfunction
+
+function! s:Tlist_Highlight_Tagline()
+    " Clear previously selected name
+    match none
+
+    " Highlight the current selected name
+    if g:Tlist_Display_Prototype == 0
+        exe 'match TagName /\%' . line('.') . 'l\s\+\zs.*/'
+    else
+        exe 'match TagName /\%' . line('.') . 'l.*/'
+    endif
+endfunction
+
+" Tlist_Jump_To_Tag()
+" Jump to the location of the current tag
+function! s:Tlist_Jump_To_Tag(new_window)
+    " Do not process comment lines and empty lines
+    let curline = getline('.')
+    if curline == '' || curline[0] == '"'
+        return
+    endif
+
+    " If inside a fold, then don't try to jump to the tag
+    if foldclosed('.') != -1
+        return
+    endif
+
+    " Get the tag output for the current tag
+    let lnum = s:Tlist_Get_Tag_Linenr()
+    if lnum == 0
+        return
+    endif
+
+    let mtxt = b:tlist_tag_{lnum}
+    let start = stridx(mtxt, '/^') + 2
+    let end = strridx(mtxt, '/;"' . "\t")
+    if mtxt[end - 1] == '$'
+        let end = end - 1
+    endif
+    let tagpat = '\V\^' . strpart(mtxt, start, end - start) .
+                                        \ (mtxt[end] == '$' ? '\$' : '')
+
+    " Highlight the tagline
+    call s:Tlist_Highlight_Tagline()
+
+    let s:Tlist_Skip_Refresh = 1
+
+    if s:tlist_part_of_winmanager
+        call WinManagerFileEdit(bufname(b:tlist_bufnum), a:new_window)
+    else
+    " Goto the window containing the file.  If the window is not there, open a
+    " new window
+    let winnum = bufwinnr(b:tlist_bufnum)
+    if winnum == -1
+        if g:Tlist_Use_Horiz_Window == 1
+            exe 'leftabove split #' . b:tlist_bufnum
+            " Go to the taglist window to change the window size to the user
+            " configured value
+            wincmd p
+            exe 'resize ' . g:Tlist_WinHeight
+            " Go back to the file window
+            wincmd p
+        else
+            " Open the file in a window and skip refreshing the taglist window
+            exe 'rightbelow vertical split #' . b:tlist_bufnum
+            " Go to the taglist window to change the window size to the user
+            " configured value
+            wincmd p
+            exe 'vertical resize ' . g:Tlist_WinWidth
+            " Go back to the file window
+            wincmd p
+        endif
+    else
+        exe winnum . 'wincmd w'
+
+        " If the user asked to jump to the tag in a new window, then split the
+        " existing window into two.
+        if a:new_window
+            split
+        endif
+    endif
+    endif
+
+    " Jump to the tag
+    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 has('folding')
+        if foldlevel('.') != 0
+            normal zo
+        endif
+    endif
+
+    let s:Tlist_Skip_Refresh = 0
+endfunction
+
+" Tlist_Show_Tag_Prototype()
+" Display the prototype of the tag under the cursor
+function! s:Tlist_Show_Tag_Prototype()
+    " If we have already display prototype in the tag window, no need to
+    " display it in the status line
+    if g:Tlist_Display_Prototype == 1
+        return
+    endif
+
+    " Clear the previously displayed line
+    echo
+
+    " Do not process comment lines and empty lines
+    let curline = getline('.')
+    if curline == '' || curline[0] == '"'
+        return
+    endif
+
+    " If inside a fold, then don't display the prototype
+    if foldclosed('.') != -1
+        return
+    endif
+
+    " Get the tag output line for the current tag
+    let lnum = s:Tlist_Get_Tag_Linenr()
+    if lnum == 0
+        return
+    endif
+
+    let mtxt = b:tlist_tag_{lnum}
+
+    " Get the tag search pattern and display it
+    echo s:Tlist_Extract_Tag_Prototype(mtxt)
+endfunction
+
+" Tlist_Locate_Tag_Text
+" Locate the tag text given the line number in the source window
+function! s:Tlist_Locate_Tag_Text(sort_type, linenum)
+    let left = 1
+    let right = b:tlist_tag_count
+
+    if a:sort_type == 'order'
+        " Tag list sorted by order, do a binary search comparing the line
+        " numbers
+
+        " If the current line is the less than the first tag, then no need to
+        " search
+        let txt = b:tlist_tag_1
+        let start = strridx(txt, 'line:') + strlen('line:')
+        let end = strridx(txt, "\t")
+        if end < start
+            let first_lnum = strpart(txt, start) + 0
+        else
+            let first_lnum = strpart(txt, start, end - start) + 0
+        endif
+
+        if a:linenum < first_lnum
+            return ""
+        endif
+
+        while left < right
+            let middle = (right + left + 1) / 2
+            let txt = b:tlist_tag_{middle}
+
+            let start = strridx(txt, 'line:') + strlen('line:')
+            let end = strridx(txt, "\t")
+            if end < start
+                let middle_lnum = strpart(txt, start) + 0
+            else
+                let middle_lnum = strpart(txt, start, end - start) + 0
+            endif
+
+            if middle_lnum == a:linenum
+                let left = middle
+                break
+            endif
+
+            if middle_lnum > a:linenum
+                let right = middle - 1
+            else
+                let left = middle
+            endif
+        endwhile
+    else
+        " sorted by name, brute force method (Dave Eggum)
+        let closest_lnum = 0
+        let final_left = 0
+        while left < right
+            let txt = b:tlist_tag_{left}
+
+            let start = strridx(txt, 'line:') + strlen('line:')
+            let end = strridx(txt, "\t")
+            if end < start
+                let lnum = strpart(txt, start) + 0
+            else
+                let lnum = strpart(txt, start, end - start) + 0
+            endif
+
+            if lnum < a:linenum && lnum > closest_lnum
+                let closest_lnum = lnum
+                let final_left = left
+            elseif lnum == a:linenum
+                let closest_lnum = lnum
+                break
+            else
+                let left = left + 1
+            endif
+        endwhile
+        if closest_lnum == 0
+            return ""
+        endif
+        if left == right
+            let left = final_left
+        endif
+    endif
+
+    return b:tlist_tag_{left}
+endfunction
+
+" Tlist_Highlight_Tag()
+" Do a binary search in the array of tag names and pick a tag entry that
+" contains the current line and highlight it.  The idea behind this function
+" is taken from the ctags.vim script available at the Vim online website.
+function! s:Tlist_Highlight_Tag(bufnum, curline)
+    let filename = fnamemodify(bufname(a:bufnum), ':p')
+    if filename == ''
+        return
+    endif
+
+    " Make sure the taglist window is present
+    let winnum = bufwinnr(g:TagList_title)
+    if winnum == -1
+        return
+    endif
+
+    let bno = bufnr(g:TagList_title)
+
+    " Make sure we have the tag listing for the current file
+    if getbufvar(bno, 'tlist_bufnum') != a:bufnum
+        return
+    endif
+
+    " If there are no tags for this file, then no need to proceed further
+    if getbufvar(bno, 'tlist_tag_count') == 0
+        return
+    endif
+
+    " If part of winmanager then disable winmanager autocommands
+    if s:tlist_part_of_winmanager
+        call WinManagerSuspendAUs()
+    endif
+
+    " Save the original window number
+    let org_winnr = winnr()
+
+    if org_winnr == winnum
+        let in_taglist_window = 1
+    else
+        let in_taglist_window = 0
+    endif
+
+    " Go to the taglist window
+    if !in_taglist_window
+        exe winnum . 'wincmd w'
+    endif
+
+    " Clear previously selected name
+    match none
+
+    let tag_txt = s:Tlist_Locate_Tag_Text(getbufvar(bno, 'tlist_sort_type'),
+                                          \ a:curline)
+    if tag_txt == ""
+        if !in_taglist_window
+            let s:Tlist_Skip_Refresh = 1
+            exe org_winnr . 'wincmd w'
+            let s:Tlist_Skip_Refresh = 0
+        endif
+        if s:tlist_part_of_winmanager
+            call WinManagerResumeAUs()
+        endif
+        return
+    endif
+
+    " Extract the tag type
+    let ttype = s:Tlist_Extract_Tagtype(tag_txt)
+
+    " Extract the tag offset
+    let offset = strpart(tag_txt, 0, stridx(tag_txt, ':')) + 0
+
+    " Compute the line number
+    let lnum = b:tlist_{b:tlist_ftype}_{ttype}_start + offset
+
+    " Goto the line containing the tag
+    exe lnum
+
+    " Open the fold
+    if has('folding')
+        silent! .foldopen
+    endif
+
+    " Call winline() to make sure the target line is visible in the taglist
+    " window. This is a side effect of calling winline(). Don't know of a
+    " better way to achieve this.
+    call winline()
+
+    " Highlight the tag name
+    call s:Tlist_Highlight_Tagline()
+
+    " Go back to the original window
+    if !in_taglist_window
+        let s:Tlist_Skip_Refresh = 1
+        exe org_winnr . 'wincmd w'
+        let s:Tlist_Skip_Refresh = 0
+    endif
+
+    if s:tlist_part_of_winmanager
+        call WinManagerResumeAUs()
+    endif
+
+    return
+endfunction
+
+" Tlist_Get_Tag_Prototype_By_Line
+function! s:Tlist_Get_Tag_Prototype_By_Line(linenum)
+    " Make sure the current file has a name
+    let filename = fnamemodify(bufname("%"), ':p')
+    if filename == ''
+        return ""
+    endif
+
+    let linenr = a:linenum
+    if linenr == ""
+        " Default is the current line
+        let linenr = line('.')
+    endif
+
+    " If there are no tags for this file, then no need to proceed further
+    if !exists("b:tlist_tag_count") || b:tlist_tag_count == 0
+        return ""
+    endif
+
+    " Get the tag text using the line number
+    let tag_txt = s:Tlist_Locate_Tag_Text(b:tlist_sort_type, linenr)
+    if tag_txt == ""
+        return ""
+    endif
+
+    " Extract the tag search pattern and return it
+    return s:Tlist_Extract_Tag_Prototype(tag_txt)
+endfunction
+
+" Define tag listing autocommand to automatically open the taglist window on
+" Vim startup
+if g:Tlist_Auto_Open
+    autocmd VimEnter * nested Tlist
+endif
+
+" Define the 'Tlist' and 'TlistSync' user commands to open/close taglist
+" window
+command! -nargs=0 Tlist call s:Tlist_Toggle_Window(bufnr('%'))
+command! -nargs=0 TlistSync call s:Tlist_Highlight_Tag(bufnr('%'), line('.'))
+command! -nargs=? TlistShowPrototype echo s:Tlist_Get_Tag_Prototype_By_Line(<q-args>)
+
+" Winmanager integration
+
+" Initialization required for integration with winmanager
+function! TagList_Start()
+    let s:tlist_part_of_winmanager = 1
+
+    if bufname('%') != '__Tag_List__'
+        return
+    endif
+
+    let bufnum = WinManagerGetLastEditedFile()
+
+    " If the tags for the buffer is already listed, then no need to do
+    " anything
+    if exists('b:tlist_bufnum') && bufnum == b:tlist_bufnum
+        return
+    endif
+
+    call s:Tlist_Init_Window(bufnum)
+
+    " Open the taglist window
+    call s:Tlist_Explore_File(bufnum)
+endfunction
+
+function! TagList_IsValid()
+    return 0
+endfunction
+
+function! TagList_WrapUp()
+    return 0
+endfunction
diff --git a/.vimrc b/.vimrc
index eac19ca..6a4438e 100755 (executable)
--- a/.vimrc
+++ b/.vimrc
@@ -93,7 +93,7 @@ map <C-"> viwvbi"<ESC>ea"<ESC>
 map - yyp:s/./-/g<RETURN>:let @/=''<RETURN>:<RETURN>
 map = yyp:s/./=/g<RETURN>:let @/=''<RETURN>:<RETURN>
 command! W :w
-se tags=~/.ctags
+se tags=~/.tags,./tags,tags
 
 " Make * and # work the way you expect in visual mode.
 vnoremap * y/\V<C-R>=substitute(escape(@@,"/\\"),"\n","\\\\n","ge")<CR><CR>
@@ -140,6 +140,8 @@ map Qf :se foldenable!<CR>:<CR>
 map Qn :se number!<CR>:<CR>
 " Toggle paste mode with Qp.
 map Qp :se paste!<CR>:<CR>
+" Toggle tags with Qt.
+map Qt :Tlist<CR>
 
 " Vim 7 has tabs.  Default "next tab" mapping is gt.  Add "previous tab" as gb.
 map gb :tabPrev<CR>