diff options
Diffstat (limited to '.vim/plugin')
| -rw-r--r-- | .vim/plugin/SyntaxFolds.vim | 323 | ||||
| -rw-r--r-- | .vim/plugin/c.vim | 2678 | ||||
| -rw-r--r-- | .vim/plugin/filebrowser.vim | 251 | ||||
| -rw-r--r-- | .vim/plugin/imaps.vim | 831 | ||||
| -rw-r--r-- | .vim/plugin/libList.vim | 249 | ||||
| -rw-r--r-- | .vim/plugin/minibufexpl.vim | 1838 | ||||
| -rw-r--r-- | .vim/plugin/openssl.vim | 201 | ||||
| -rw-r--r-- | .vim/plugin/remoteOpen.vim | 163 | ||||
| -rw-r--r-- | .vim/plugin/taglist.vim | 4546 | 
9 files changed, 11080 insertions, 0 deletions
| diff --git a/.vim/plugin/SyntaxFolds.vim b/.vim/plugin/SyntaxFolds.vim new file mode 100644 index 0000000..27c622c --- /dev/null +++ b/.vim/plugin/SyntaxFolds.vim @@ -0,0 +1,323 @@ +" ============================================================================== +"        File: syntaxFolds.vim +"      Author: Srinath Avadhanula +"              ( srinath@fastmail.fm ) +" Last Change: Sun Oct 27 01:00 AM 2002 PST +" Description: Emulation of the syntax folding capability of vim using manual +"              folding +" +" This script provides an emulation of the syntax folding of vim using manual +" folding. Just as in syntax folding, the folds are defined by regions. Each +" region is specified by a call to FoldRegions() which accepts 4 parameters: +" +"    call FoldRegions(startpat, endpat, startoff, endoff) +" +"    startpat: a line matching this pattern defines the beginning of a fold. +"    endpat  : a line matching this pattern defines the end of a fold. +"    startoff: this is the offset from the starting line at which folding will +"              actually start +"    endoff  : like startoff, but gives the offset of the actual fold end from +"              the line satisfying endpat. +"              startoff and endoff are necessary when the folding region does +"              not have a specific end pattern corresponding to a start +"              pattern. for example in latex, +"              \begin{section} +"              defines the beginning of a section, but its not necessary to +"              have a corresponding +"              \end{section} +"              the section is assumed to end 1 line _before_ another section +"              starts. +"    startskip: a pattern which defines the beginning of a "skipped" region. +" +"               For example, suppose we define a \itemize fold as follows: +"               startpat =  '^\s*\\item', +"               endpat = '^\s*\\item\|^\s*\\end{\(enumerate\|itemize\|description\)}', +"               startoff = 0, +"               endoff = -1 +" +"               This defines a fold which starts with a line beginning with an +"               \item and ending one line before a line beginning with an +"               \item or \end{enumerate} etc. +" +"               Then, as long as \item's are not nested things are fine. +"               However, once items begin to nest, the fold started by one +"               \item can end because of an \item in an \itemize +"               environment within this \item. i.e, the following can happen: +" +"               \begin{itemize} +"               \item Some text <------- fold will start here +"                     This item will contain a nested item +"                     \begin{itemize} <----- fold will end here because next line contains \item... +"                     \item Hello +"                     \end{itemize} <----- ... instead of here. +"               \item Next item of the parent itemize +"               \end{itemize} +" +"               Therefore, in order to completely define a folding item which +"               allows nesting, we need to also define a "skip" pattern. +"               startskip and end skip do that. +"               Leave '' when there is no nesting. +"    endskip: the pattern which defines the end of the "skip" pattern for +"             nested folds. +" +"    Example:  +"    1. A syntax fold region for a latex section is +"           startpat = "\\section{" +"           endpat   = "\\section{" +"           startoff = 0 +"           endoff   = -1 +"           startskip = '' +"           endskip = '' +"    Note that the start and end patterns are thus the same and endoff has a +"    negative value to capture the effect of a section ending one line before +"    the next starts. +"    2. A syntax fold region for the \itemize environment is: +"           startpat = '^\s*\\item', +"           endpat = '^\s*\\item\|^\s*\\end{\(enumerate\|itemize\|description\)}', +"           startoff = 0, +"           endoff = -1, +"           startskip = '^\s*\\begin{\(enumerate\|itemize\|description\)}', +"           endskip = '^\s*\\end{\(enumerate\|itemize\|description\)}' +"     Note the use of startskip and endskip to allow nesting. +" +" +" Each time a call is made to FoldRegions(), all the regions (which might be +" disjoint, but not nested) are folded up. +" Nested folds can be created by successive calls to FoldRegions(). The first +" call defines the region which is deepest in the folding. See MakeTexFolds() +" for an idea of how this works for latex files. + +" Function: AddSyntaxFoldItem (start, end, startoff, endoff [, skipStart, skipEnd]) {{{ +function! AddSyntaxFoldItem(start, end, startoff, endoff, ...) +	if a:0 > 0 +		let skipStart = a:1 +		let skipEnd = a:2 +	else +		let skipStart = '' +		let skipEnd = '' +	end +	if !exists('b:numFoldItems') +		let b:numFoldItems = 0 +	end +	let b:numFoldItems = b:numFoldItems + 1 + +	exe 'let b:startPat_'.b:numFoldItems.' = a:start' +	exe 'let b:endPat_'.b:numFoldItems.' = a:end' +	exe 'let b:startOff_'.b:numFoldItems.' = a:startoff' +	exe 'let b:endOff_'.b:numFoldItems.' = a:endoff' +	exe 'let b:skipStartPat_'.b:numFoldItems.' = skipStart' +	exe 'let b:skipEndPat_'.b:numFoldItems.' = skipEnd' +endfunction  + + +" }}} +" Function: MakeSyntaxFolds (force) {{{ +" Description: This function calls FoldRegions() several times with the +"     parameters specifying various regions resulting in a nested fold +"     structure for the file. +function! MakeSyntaxFolds(force, ...) +	if exists('b:doneFolding') && a:force == 0 +		return +	end + +	let skipEndPattern = '' +	if a:0 > 0 +		let line1 = a:1 +		let skipEndPattern = '\|'.a:2 +	else +		let line1 = 1 +		let r = line('.') +		let c = virtcol('.') +		 +		setlocal fdm=manual +		normal! zE +	end +	if !exists('b:numFoldItems') +		b:numFoldItems = 1000000 +	end +	 +	let i = 1 + +	let maxline = line('.') + +	while exists('b:startPat_'.i) && i <= b:numFoldItems +		exe 'let startPat = b:startPat_'.i +		exe 'let endPat = b:endPat_'.i +		exe 'let startOff = b:startOff_'.i +		exe 'let endOff = b:endOff_'.i +		 +		let skipStart = '' +		let skipEnd = '' +		if exists('b:skipStartPat_'.i) +			exe 'let skipStart = b:skipStartPat_'.i +			exe 'let skipEnd = b:skipEndPat_'.i +		end +		exe line1 +		let lastLoc = line1 + +		if skipStart != '' +			call InitStack('BeginSkipArray') +			call FoldRegionsWithSkip(startPat, endPat, startOff, endOff, skipStart, skipEnd, 1, line('$')) +			" call PrintError('done folding ['.startPat.']') +		else +			call FoldRegionsWithNoSkip(startPat, endPat, startOff, endOff, 1, line('$'), '') +		end + +		let i = i + 1 +	endwhile + +	exe maxline +	 +	if a:0 == 0 +		exe r +		exe "normal! ".c."|" +		if foldlevel(r) > 1 +			exe "normal! ".(foldlevel(r) - 1)."zo" +		end +		let b:doneFolding = 0 +	end +endfunction + + +" }}} +" FoldRegionsWithSkip: folding things such as \item's which can be nested. {{{ +function! FoldRegionsWithSkip(startpat, endpat, startoff, endoff, startskip, endskip, line1, line2) +	exe a:line1 +	" count the regions which have been skipped as we go along. do not want to +	" create a fold which with a beginning or end line in one of the skipped +	" regions. +	let skippedRegions = '' + +	" start searching for either the starting pattern or the end pattern. +	while search(a:startskip.'\|'.a:endskip, 'W') +	 +		if getline('.') =~ a:endskip + +			let lastBegin = Pop('BeginSkipArray') +			" call PrintError('popping '.lastBegin.' from stack and folding till '.line('.')) +			call FoldRegionsWithNoSkip(a:startpat, a:endpat, a:startoff, a:endoff, lastBegin, line('.'), skippedRegions) +			let skippedRegions = skippedRegions.lastBegin.','.line('.').'|' + + +		" if this is the beginning of a skip region, then, push this line as +		" the beginning of a skipped region. +		elseif getline('.') =~ a:startskip + +			" call PrintError('pushing '.line('.').' ['.getline('.').'] into stack') +			call Push('BeginSkipArray', line('.')) + +		end +	endwhile + +	" call PrintError('with skip starting at '.a:line1.' returning at line# '.line('.')) +endfunction + +" }}} +" FoldRegionsWithNoSkip: folding things such as \sections which do not nest. {{{ +function! FoldRegionsWithNoSkip(startpat, endpat, startoff, endoff, line1, line2, skippedRegions) +	exe a:line1 + +	" call PrintError('line1 = '.a:line1.', searching from '.line('.').'... for ['.a:startpat.'') +	let lineBegin = s:MySearch(a:startpat, 'in') +	" call PrintError('... and finding it at '.lineBegin) + +	while lineBegin <= a:line2 +		if IsInSkippedRegion(lineBegin, a:skippedRegions) +			let lineBegin = s:MySearch(a:startpat, 'out') +			" call PrintError(lineBegin.' is being skipped') +			continue +		end +		let lineEnd = s:MySearch(a:endpat, 'out') +		while IsInSkippedRegion(lineEnd, a:skippedRegions) && lineEnd <= a:line2 +			let lineEnd = s:MySearch(a:endpat, 'out') +		endwhile +		if lineEnd > a:line2 +			exe (lineBegin + a:startoff).','.a:line2.' fold' +			break +		else +			" call PrintError ('for ['.a:startpat.'] '.(lineBegin + a:startoff).','.(lineEnd + a:endoff).' fold') +			exe (lineBegin + a:startoff).','.(lineEnd + a:endoff).' fold' +		end + +		" call PrintError('line1 = '.a:line1.', searching from '.line('.').'... for ['.a:startpat.'') +		let lineBegin = s:MySearch(a:startpat, 'in') +		" call PrintError('... and finding it at '.lineBegin) +	endwhile + +	exe a:line2 +	return +endfunction + +" }}} +" InitStack: initialize a stack {{{ +function! InitStack(name) +	exe 'let s:'.a:name.'_numElems = 0' +endfunction +" }}} +" Push: push element into stack {{{ +function! Push(name, elem) +	exe 'let numElems = s:'.a:name.'_numElems' +	let numElems = numElems + 1 +	exe 'let s:'.a:name.'_Element_'.numElems.' = a:elem' +	exe 'let s:'.a:name.'_numElems = numElems' +endfunction +" }}} +" Pop: pops element off stack {{{ +function! Pop(name) +	exe 'let numElems = s:'.a:name.'_numElems' +	if numElems == 0 +		return '' +	else +		exe 'let ret = s:'.a:name.'_Element_'.numElems +		let numElems = numElems - 1 +		exe 'let s:'.a:name.'_numElems = numElems' +		return ret +	end +endfunction +" }}} +" MySearch: just like search(), but returns large number on failure {{{ +function! <SID>MySearch(pat, opt) +	if a:opt == 'in' +		if getline('.') =~ a:pat +			let ret = line('.') +		else +			let ret = search(a:pat, 'W') +		end +	else +		normal! $ +		let ret = search(a:pat, 'W') +	end + +	if ret == 0 +		let ret = line('$') + 1 +	end +	return ret +endfunction +" }}} +" Function: IsInSkippedRegion (lnum, regions) {{{ +" Description: finds whether a given line number is within one of the regions +"              skipped. +function! IsInSkippedRegion(lnum, regions) +	let i = 1 +	let subset = s:Strntok(a:regions, '|', i) +	while subset != '' +		let n1 = s:Strntok(subset, ',', 1) +		let n2 = s:Strntok(subset, ',', 2) +		if a:lnum >= n1 && a:lnum <= n2 +			return 1 +		end + +		let subset = s:Strntok(a:regions, '|', i) +		let i = i + 1 +	endwhile + +	return 0 +endfunction " }}} +" Function: Strntok (string, tok, n) {{{ +" extract the n^th token from s seperated by tok. +" example: Strntok('1,23,3', ',', 2) = 23 +fun! <SID>Strntok(s, tok, n) +	return matchstr( a:s.a:tok[0], '\v(\zs([^'.a:tok.']*)\ze['.a:tok.']){'.a:n.'}') +endfun " }}} + +" vim600:fdm=marker diff --git a/.vim/plugin/c.vim b/.vim/plugin/c.vim new file mode 100644 index 0000000..bb9390f --- /dev/null +++ b/.vim/plugin/c.vim @@ -0,0 +1,2678 @@ +"############################################################################################### +"   +"       Filename:  c.vim +"   +"    Description:  C/C++-IDE. Write programs by inserting complete statements,  +"                  comments, idioms, code snippets, templates and comments. +"                  Compile, link and run one-file-programs without a makefile. +"                  See also help file csupport.txt . +"   +"   GVIM Version:  7.0+ +"   +"  Configuration:  There are some personal details which should be configured  +"                   (see the files README.csupport and csupport.txt). +"   +"         Author:  Dr.-Ing. Fritz Mehner, FH Südwestfalen, 58644 Iserlohn, Germany +"          Email:  mehner@fh-swf.de +"   +"        Version:  see variable  g:C_Version  below  +"        Created:  04.11.2000 +"        License:  Copyright (c) 2000-2007, Fritz Mehner +"                  This program is free software; you can redistribute it and/or +"                  modify it under the terms of the GNU General Public License as +"                  published by the Free Software Foundation, version 2 of the +"                  License. +"                  This program is distributed in the hope that it will be +"                  useful, but WITHOUT ANY WARRANTY; without even the implied +"                  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +"                  PURPOSE. +"                  See the GNU General Public License version 2 for more details. +"       Revision:  $Id: c.vim,v 1.35 2007/11/21 09:14:16 mehner Exp $ +"         +"------------------------------------------------------------------------------ +"  +if v:version < 700 +  echohl WarningMsg | echo 'The plugin c-support.vim needs Vim version >= 7 .'| echohl None +  finish +endif +" +" Prevent duplicate loading:  +"  +if exists("g:C_Version") || &cp + finish +endif +let g:C_Version= "5.0.5"  							" version number of this script; do not change +"         +"############################################################################################### +" +"  Global variables (with default values) which can be overridden. +"           +" Platform specific items:  {{{1 +" - root directory +" - characters that must be escaped for filenames +"  +let	s:MSWIN =		has("win16") || has("win32")     || has("win64") ||  +							\ has("win95") || has("win32unix") +"  +if	s:MSWIN +	" +  let s:escfilename      = '' +  let s:plugin_dir       = $VIM.'\vimfiles\' +  let s:C_CodeSnippets   = s:plugin_dir.'c-support/codesnippets/' +  let s:C_IndentErrorLog = $HOME.'.indent.errorlog' +	let s:installation	   = 'system' +	" +	let s:C_Display        = '' +	" +else +	" +  let s:escfilename 	= ' \%#[]' +	let s:installation	= 'local' +	" +	" user / system wide installation (Linux/Unix) +	" +	if match( expand("<sfile>"), $VIM ) >= 0 +		" system wide installation  +		let s:plugin_dir  = $VIM.'/vimfiles/' +		let s:installation	= 'system' +	else +		" user installation assumed +		let s:plugin_dir  = $HOME.'/.vim/' +	endif +	" +	let s:C_CodeSnippets   = $HOME.'/.vim/c-support/codesnippets/' +	let s:C_IndentErrorLog = $HOME.'/.indent.errorlog' +	" +	let s:C_Display	= system("echo -n $DISPLAY") +	" +endif +"  Use of dictionaries  {{{1 +"  Key word completion is enabled by the filetype plugin 'c.vim' +"  g:C_Dictionary_File  must be global +"           +if !exists("g:C_Dictionary_File") +  let g:C_Dictionary_File = s:plugin_dir.'c-support/wordlists/c-c++-keywords.list,'. +        \                   s:plugin_dir.'c-support/wordlists/k+r.list,'. +        \                   s:plugin_dir.'c-support/wordlists/stl_index.list' +endif +" +"  Modul global variables (with default values) which can be overridden. {{{1 +" +if	s:MSWIN +	let s:C_CCompiler           = 'gcc.exe'  " the C   compiler +	let s:C_CplusCompiler       = 'g++.exe'  " the C++ compiler +	let s:C_ExeExtension        = '.exe'     " file extension for executables (leading point required) +	let s:C_ObjExtension        = '.obj'     " file extension for objects (leading point required) +else                           +	let s:C_CCompiler           = 'gcc'      " the C   compiler +	let s:C_CplusCompiler       = 'g++'      " the C++ compiler +	let s:C_ExeExtension        = ''         " file extension for executables (leading point required) +	let s:C_ObjExtension        = '.o'       " file extension for objects (leading point required) +endif +" +let s:C_CExtension     				= 'c'                    " C file extension; everything else is C++ +let s:C_CFlags         				= '-Wall -g -O0 -c'      " compiler flags: compile, don't optimize +let s:C_CodeCheckExeName      = 'check' +let s:C_CodeCheckOptions      = '-K13' +let s:C_LFlags         				= '-Wall -g -O0'         " compiler flags: link   , don't optimize +let s:C_Libs           				= '-lm'                  " libraries to use +let s:C_LineEndCommColDefault = 49 +let s:C_LoadMenus      				= 'yes' +let s:C_MenuHeader     				= 'yes' +let s:C_OutputGvim            = 'vim' +let s:C_Printheader           = "%<%f%h%m%<  %=%{strftime('%x %X')}     Page %N" +let s:C_Root  	       				= '&C\/C\+\+.'           " the name of the root menu of this plugin +let s:C_TypeOfH               = 'cpp' +let s:C_Wrapper               = s:plugin_dir.'c-support/scripts/wrapper.sh' +let s:C_XtermDefaults         = '-fa courier -fs 12 -geometry 80x24' +" +let s:C_GlobalTemplateFile    = s:plugin_dir.'c-support/templates/Templates' +let s:C_GlobalTemplateDir     = fnamemodify( s:C_GlobalTemplateFile, ":p:h" ).'/' +let s:C_LocalTemplateFile     = $HOME.'/.vim/c-support/templates/Templates' +let s:C_LocalTemplateDir      = fnamemodify( s:C_LocalTemplateFile, ":p:h" ).'/' +let s:C_TemplateOverwrittenMsg= 'yes' +" +let s:C_FormatDate						= '%x' +let s:C_FormatTime						= '%X' +let s:C_FormatYear						= '%Y' +" +"------------------------------------------------------------------------------ +" +"  Look for global variables (if any), to override the defaults. +"   +function! C_CheckGlobal ( name ) +  if exists('g:'.a:name) +    exe 'let s:'.a:name.'  = g:'.a:name +  endif +endfunction    " ----------  end of function C_CheckGlobal ---------- +" +call C_CheckGlobal('C_CCompiler              ') +call C_CheckGlobal('C_CExtension             ') +call C_CheckGlobal('C_CFlags                 ') +call C_CheckGlobal('C_CodeCheckExeName       ') +call C_CheckGlobal('C_CodeCheckOptions       ') +call C_CheckGlobal('C_CodeSnippets           ') +call C_CheckGlobal('C_CplusCompiler          ') +call C_CheckGlobal('C_ExeExtension           ') +call C_CheckGlobal('C_FormatDate             ') +call C_CheckGlobal('C_FormatTime             ') +call C_CheckGlobal('C_FormatYear             ') +call C_CheckGlobal('C_GlobalTemplateFile     ') +call C_CheckGlobal('C_IndentErrorLog         ') +call C_CheckGlobal('C_LFlags                 ') +call C_CheckGlobal('C_Libs                   ') +call C_CheckGlobal('C_LineEndCommColDefault  ') +call C_CheckGlobal('C_LoadMenus              ') +call C_CheckGlobal('C_LocalTemplateFile      ') +call C_CheckGlobal('C_MenuHeader             ') +call C_CheckGlobal('C_ObjExtension           ') +call C_CheckGlobal('C_OutputGvim             ') +call C_CheckGlobal('C_Printheader            ') +call C_CheckGlobal('C_Root                   ') +call C_CheckGlobal('C_TemplateOverwrittenMsg ') +call C_CheckGlobal('C_TypeOfH                ') +call C_CheckGlobal('C_XtermDefaults          ') +" +"----- some variables for internal use only ----------------------------------- +" +" +" set default geometry if not specified  +"  +if match( s:C_XtermDefaults, "-geometry\\s\\+\\d\\+x\\d\\+" ) < 0 +	let s:C_XtermDefaults	= s:C_XtermDefaults." -geometry 80x24" +endif +" +" escape the printheader +" +let s:C_Printheader  = escape( s:C_Printheader, ' %' ) +" +let s:C_HlMessage    = "" +" +" characters that must be escaped for filenames +" +let s:C_If0_Counter   = 0 +let s:C_If0_Txt		 		= "If0Label_" +" +let s:C_SplintIsExecutable	= 0 +if executable( "splint" )  +	let s:C_SplintIsExecutable	= 1 +endif +" +let s:C_CodeCheckIsExecutable	= 0 +if executable( s:C_CodeCheckExeName )  +	let s:C_CodeCheckIsExecutable	= 1 +endif +" +"------------------------------------------------------------------------------ +"  Control variables (not user configurable) +"------------------------------------------------------------------------------ +let s:Attribute                = { 'below':'', 'above':'', 'start':'', 'append':'', 'insert':'' } +let s:C_Attribute              = {} +let s:C_ExpansionLimit         = 10 +let s:C_FileVisited            = [] +" +let s:C_MacroNameRegex         = '\([a-zA-Z][a-zA-Z0-9_]*\)' +let s:C_MacroLineRegex				 = '^\s*|'.s:C_MacroNameRegex.'|\s*=\s*\(.*\)' +let s:C_ExpansionRegex				 = '|?'.s:C_MacroNameRegex.'\(:\a\)\?|' +let s:C_NonExpansionRegex			 = '|'.s:C_MacroNameRegex.'\(:\a\)\?|' +" +let s:C_TemplateNameDelimiter  = '-+_,\. ' +let s:C_TemplateLineRegex			 = '^==\s*\([a-zA-Z][0-9a-zA-Z'.s:C_TemplateNameDelimiter +let s:C_TemplateLineRegex			.= ']\+\)\s*==\s*\([a-z]\+\s*==\)\?' +" +let s:C_ExpansionCounter       = {} +let s:C_Template               = {} +let s:C_Macro                  = {'|AUTHOR|'         : 'first name surname',  +											\						'|AUTHORREF|'      : '', +											\						'|EMAIL|'          : '', +											\						'|COMPANY|'        : '', +											\						'|PROJECT|'        : '', +											\						'|COPYRIGHTHOLDER|': ''  +											\						} +let	s:C_MacroFlag								= {	':l' : 'lowercase'			,  +											\							':u' : 'uppercase'			,  +											\							':c' : 'capitalize'		,  +											\							':L' : 'legalize name'	,  +											\						} + +"------------------------------------------------------------------------------ +"  C : C_InitMenus                              {{{1 +"  Initialization of C support menus +"------------------------------------------------------------------------------ +" +function! C_InitMenus () +	" +	"=============================================================================================== +	"----- Menu : C main menu entry -------------------------------------------   {{{2 +	"=============================================================================================== +	" +	if s:C_Root != "" +		if s:C_MenuHeader == 'yes' +			exe "amenu  ".s:C_Root.'C\/C\+\+   <Esc>' +			exe "amenu  ".s:C_Root.'-Sep00-         :' +		endif +	endif +	" +	"=============================================================================================== +	"----- Menu : C-Comments --------------------------------------------------   {{{2 +	"=============================================================================================== +	" +	if s:C_MenuHeader == 'yes' +		exe "amenu  ".s:C_Root.'&Comments.&Comments<Tab>C\/C\+\+             <Esc>' +		exe "amenu  ".s:C_Root.'&Comments.-Sep00-                            :' +	endif +	exe "amenu <silent> ".s:C_Root.'&Comments.end-of-&line\ comment           <Esc><Esc><Esc>:call C_LineEndComment( )<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Comments.end-of-&line\ comment           <Esc><Esc><Esc>:call C_MultiLineEndComments( )<CR>' + +	exe "amenu <silent> ".s:C_Root.'&Comments.ad&just\ end-of-line\ com\.     <Esc><Esc>:call C_AdjustLineEndComm("a")<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Comments.ad&just\ end-of-line\ com\.     <Esc><Esc>:call C_AdjustLineEndComm("v")<CR>' + +	exe "amenu <silent> ".s:C_Root.'&Comments.&set\ end-of-line\ com\.\ col\. <Esc><Esc>:call C_GetLineEndCommCol()<CR>' +	 +	exe "amenu  ".s:C_Root.'&Comments.-SEP10-                              :' +	exe "amenu <silent> ".s:C_Root.'&Comments.code\ ->\ comment\ \/&*\ *\/   <Esc><Esc>:call C_CodeComment("a","yes")<CR><Esc>:nohlsearch<CR>j' +	exe "vmenu <silent> ".s:C_Root.'&Comments.code\ ->\ comment\ \/&*\ *\/   <Esc><Esc>:call C_CodeComment("v","yes")<CR><Esc>:nohlsearch<CR>j' +	exe "amenu <silent> ".s:C_Root.'&Comments.code\ ->\ comment\ &\/\/       <Esc><Esc>:call C_CodeComment("a","no")<CR><Esc>:nohlsearch<CR>j' +	exe "vmenu <silent> ".s:C_Root.'&Comments.code\ ->\ comment\ &\/\/       <Esc><Esc>:call C_CodeComment("v","no")<CR><Esc>:nohlsearch<CR>j' +	exe "amenu <silent> ".s:C_Root.'&Comments.c&omment\ ->\ code             <Esc><Esc>:call C_CommentCode("a")<CR><Esc>:nohlsearch<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Comments.c&omment\ ->\ code             <Esc><Esc>:call C_CommentCode("v")<CR><Esc>:nohlsearch<CR>' +	 +	exe "amenu          ".s:C_Root.'&Comments.-SEP0-                  :' +	exe "amenu <silent> ".s:C_Root.'&Comments.&frame\ comment         <Esc><Esc>:call C_InsertTemplate("comment.frame")<CR>' +	exe "amenu <silent> ".s:C_Root.'&Comments.f&unction\ description  <Esc><Esc>:call C_InsertTemplate("comment.function")<CR>' +	exe "amenu          ".s:C_Root.'&Comments.-SEP1-                  :' +	exe "amenu <silent> ".s:C_Root.'&Comments.&method\ description    <Esc><Esc>:call C_InsertTemplate("comment.method")<CR>' +	exe "amenu <silent> ".s:C_Root.'&Comments.cl&ass\ description     <Esc><Esc>:call C_InsertTemplate("comment.class")<CR>' +	exe "amenu          ".s:C_Root.'&Comments.-SEP2-                  :' +	exe "amenu <silent> ".s:C_Root.'&Comments.file\ description         <Esc><Esc>:call C_InsertTemplate("comment.file-description")<CR>' +	exe "amenu          ".s:C_Root.'&Comments.-SEP3-                  :' +	" +	"----- Submenu : C-Comments : file sections  ------------------------------------------------------------- +	" +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.file\ sections<Tab>C\/C\+\+            <Esc>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.-Sep0-                                 :' +	" +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.&Header\ File\ Includes  <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-header-includes")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.Local\ &Macros           <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-macros")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.Local\ &Type\ Def\.      <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-typedefs")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.Local\ &Data\ Types      <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-data-types")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.Local\ &Variables        <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-class-defs")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.Local\ &Prototypes       <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-local-variables")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.&Exp\.\ Function\ Def\.  <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-prototypes")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.&Local\ Function\ Def\.  <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-function-defs-exported")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.-SEP6-                   :' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.Local\ &Class\ Def\.     <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-function-defs-local")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.E&xp\.\ Class\ Impl\.    <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-class-implementations-exported")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.L&ocal\ Class\ Impl\.    <Esc><Esc>:call C_InsertTemplate("comment.file-section-cpp-class-implementations-local")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.-SEP7-                   :' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.&All\ sections,\ C       ' +				\'<Esc><Esc>:call C_Comment_C_SectionAll("c")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&C\/C\+\+-file\ sections.All\ §ions,\ C++     ' +				\'<Esc><Esc>:call C_Comment_C_SectionAll("cpp")<CR>' +	" +	" +	"----- Submenu : H-Comments : file sections  ------------------------------------------------------------- +	" +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.H-file\ sections<Tab>C\/C\+\+                  <Esc>' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.-Sep0-                         :' +	"' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.&Header\ File\ Includes    <Esc><Esc>:call C_InsertTemplate("comment.file-section-hpp-header-includes")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.Exported\ &Macros          <Esc><Esc>:call C_InsertTemplate("comment.file-section-hpp-macros")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.Exported\ &Type\ Def\.     <Esc><Esc>:call C_InsertTemplate("comment.file-section-hpp-exported-typedefs")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.Exported\ &Data\ Types     <Esc><Esc>:call C_InsertTemplate("comment.file-section-hpp-exported-data-types")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.Exported\ &Variables       <Esc><Esc>:call C_InsertTemplate("comment.file-section-hpp-exported-class-defs")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.Exported\ &Funct\.\ Decl\. <Esc><Esc>:call C_InsertTemplate("comment.file-section-hpp-exported-variables")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.-SEP4-                     :' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.E&xported\ Class\ Def\.    <Esc><Esc>:call C_InsertTemplate("comment.file-section-hpp-exported-function-declarations")<CR>' + +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.-SEP5-                     :' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.&All\ sections,\ C         ' +				\'<Esc><Esc>:call C_Comment_H_SectionAll("c")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&H-file\ sections.All\ §ions,\ C++       ' +				\'<Esc><Esc>:call C_Comment_H_SectionAll("cpp")<CR>' +	" +	exe "amenu  ".s:C_Root.'&Comments.-SEP8-                        :' +	" +	"----- Submenu : C-Comments : keyword comments  ---------------------------------------------------------- +	" +	exe "amenu  ".s:C_Root.'&Comments.&KEYWORD+comm\..keyw\.+comm\.<Tab>C\/C\+\+     <Esc>' +	exe "amenu  ".s:C_Root.'&Comments.&KEYWORD+comm\..-Sep0-            :' +" +	exe "amenu  ".s:C_Root.'&Comments.&KEYWORD+comm\..\:&BUG\:          <Esc><Esc>$<Esc>:call C_InsertTemplate("comment.keyword-bug")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&KEYWORD+comm\..\:&COMPILER\:     <Esc><Esc>$<Esc>:call C_InsertTemplate("comment.keyword-compiler")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&KEYWORD+comm\..\:&TODO\:         <Esc><Esc>$<Esc>:call C_InsertTemplate("comment.keyword-todo")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&KEYWORD+comm\..\:T&RICKY\:       <Esc><Esc>$<Esc>:call C_InsertTemplate("comment.keyword-tricky")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&KEYWORD+comm\..\:&WARNING\:      <Esc><Esc>$<Esc>:call C_InsertTemplate("comment.keyword-warning")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&KEYWORD+comm\..\:W&ORKAROUND\:   <Esc><Esc>$<Esc>:call C_InsertTemplate("comment.keyword-workaround")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.&KEYWORD+comm\..\:&new\ keyword\: <Esc><Esc>$<Esc>:call C_InsertTemplate("comment.keyword-keyword")<CR>' +	" +	"----- Submenu : C-Comments : special comments  ---------------------------------------------------------- +	" +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..special\ comm\.<Tab>C\/C\+\+         <Esc>' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..-Sep0-                :' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..&EMPTY                <Esc><Esc>$<Esc>:call C_CommentSpecial("EMPTY")                    <CR>kgJA' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..&FALL\ THROUGH        <Esc><Esc>$<Esc>:call C_CommentSpecial("FALL THROUGH")             <CR>kgJA' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..&IMPL\.\ TYPE\ CONV   <Esc><Esc>$<Esc>:call C_CommentSpecial("IMPLICIT TYPE CONVERSION") <CR>kgJA' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..&NO\ RETURN           <Esc><Esc>$<Esc>:call C_CommentSpecial("NO RETURN")                <CR>kgJA' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..NOT\ &REACHED         <Esc><Esc>$<Esc>:call C_CommentSpecial("NOT REACHED")              <CR>kgJA' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..&TO\ BE\ IMPL\.       <Esc><Esc>$<Esc>:call C_CommentSpecial("REMAINS TO BE IMPLEMENTED")<CR>kgJA' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..-SEP81-               :' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..constant\ type\ is\ &long\ (L)              <Esc><Esc>$<Esc>:call C_CommentSpecial("constant type is long")<CR>kgJA' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..constant\ type\ is\ &unsigned\ (U)          <Esc><Esc>$<Esc>:call C_CommentSpecial("constant type is unsigned")<CR>kgJA' +	exe "amenu  ".s:C_Root.'&Comments.&special\ comm\..constant\ type\ is\ unsigned\ l&ong\ (UL)   <Esc><Esc>$<Esc>:call C_CommentSpecial("constant type is unsigned long")<CR>kgJA' + +	" +	"----- Submenu : C-Comments : Tags  ---------------------------------------------------------- +	" +	exe "amenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).tags\ (plugin)<Tab>C\/C\+\+     <Esc>' +	exe "amenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).-Sep0-            :' +	" +	exe "amenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).&AUTHOR           <Esc><Esc>:call C_InsertMacroValue("AUTHOR")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).AUTHOR&REF        <Esc><Esc>:call C_InsertMacroValue("AUTHORREF")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).&COMPANY          <Esc><Esc>:call C_InsertMacroValue("COMPANY")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).C&OPYRIGHTHOLDER  <Esc><Esc>:call C_InsertMacroValue("COPYRIGHTHOLDER")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).&EMAIL            <Esc><Esc>:call C_InsertMacroValue("EMAIL")<CR>' +	exe "amenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).&PROJECT          <Esc><Esc>:call C_InsertMacroValue("PROJECT")<CR>' +                                        +	exe "imenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).&AUTHOR           <Esc><Esc>:call C_InsertMacroValue("AUTHOR")<CR>a' +	exe "imenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).AUTHOR&REF        <Esc><Esc>:call C_InsertMacroValue("AUTHORREF")<CR>a' +	exe "imenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).&COMPANY          <Esc><Esc>:call C_InsertMacroValue("COMPANY")<CR>a' +	exe "imenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).C&OPYRIGHTHOLDER  <Esc><Esc>:call C_InsertMacroValue("COPYRIGHTHOLDER")<CR>a' +	exe "imenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).&EMAIL            <Esc><Esc>:call C_InsertMacroValue("EMAIL")<CR>a' +	exe "imenu  ".s:C_Root.'&Comments.ta&gs\ (plugin).&PROJECT          <Esc><Esc>:call C_InsertMacroValue("PROJECT")<CR>a' +	" +	" +	exe "amenu  ".s:C_Root.'&Comments.-SEP9-                     :' +	" +	exe " menu  ".s:C_Root.'&Comments.&date                             a<C-R>=C_InsertDateAndTime("d")<CR>' +	exe "imenu  ".s:C_Root.'&Comments.&date                              <C-R>=C_InsertDateAndTime("d")<CR>' +	exe " menu  ".s:C_Root.'&Comments.date\ &time                       a<C-R>=C_InsertDateAndTime("dt")<CR>' +	exe "imenu  ".s:C_Root.'&Comments.date\ &time                        <C-R>=C_InsertDateAndTime("dt")<CR>' + +	exe "amenu  ".s:C_Root.'&Comments.-SEP12-                    :' +	exe "amenu <silent> ".s:C_Root.'&Comments.\/\/\ xxx\ \ \ \ \ &->\ \ \/*\ xxx\ *\/    <Esc><Esc>:call C_CommentCppToC()<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Comments.\/\/\ xxx\ \ \ \ \ &->\ \ \/*\ xxx\ *\/    <Esc><Esc>:'."'<,'>".'call C_CommentCppToC()<CR>' +	exe "amenu <silent> ".s:C_Root.'&Comments.\/*\ xxx\ *\/\ \ -&>\ \ \/\/\ xxx          <Esc><Esc>:call C_CommentCToCpp()<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Comments.\/*\ xxx\ *\/\ \ -&>\ \ \/\/\ xxx          <Esc><Esc>:'."'<,'>".'call C_CommentCToCpp()<CR>' +	" +	"=============================================================================================== +	"----- Menu : C-Statements-------------------------------------------------   {{{2 +	"=============================================================================================== +	" +	if s:C_MenuHeader == 'yes' +		exe "amenu  ".s:C_Root.'&Statements.&Statements<Tab>C\/C\+\+     <Esc>' +		exe "amenu  ".s:C_Root.'&Statements.-Sep00-                      :' +	endif +	" +	exe "amenu <silent>".s:C_Root.'&Statements.&do\ \{\ \}\ while          <Esc><Esc>:call C_InsertTemplate("statements.do-while")<CR>' +	exe "vmenu <silent>".s:C_Root.'&Statements.&do\ \{\ \}\ while          <Esc><Esc>:call C_InsertTemplate("statements.do-while", "v")<CR>' +	" +	exe "amenu <silent>".s:C_Root.'&Statements.f&or                        <Esc><Esc>:call C_InsertTemplate("statements.for")<CR>' +	" +	exe "anoremenu <silent>".s:C_Root.'&Statements.fo&r\ \{\ \}            <Esc><Esc>:call C_InsertTemplate("statements.for-block")<CR>' +	exe "vnoremenu <silent>".s:C_Root.'&Statements.fo&r\ \{\ \}            <Esc><Esc>:call C_InsertTemplate("statements.for-block", "v")<CR>' +	" +	exe "amenu <silent>".s:C_Root.'&Statements.&if                         <Esc><Esc>:call C_InsertTemplate("statements.if")<CR>' +	" +	exe "amenu <silent>".s:C_Root.'&Statements.i&f\ \{\ \}                 <Esc><Esc>:call C_InsertTemplate("statements.if-block")<CR>' +	exe "vmenu <silent>".s:C_Root.'&Statements.i&f\ \{\ \}                 <Esc><Esc>:call C_InsertTemplate("statements.if-block", "v")<CR>' + +	exe "amenu <silent>".s:C_Root.'&Statements.if\ &else                   <Esc><Esc>:call C_InsertTemplate("statements.if-else")<CR>' +	exe "vmenu <silent>".s:C_Root.'&Statements.if\ &else                   <Esc><Esc>:call C_InsertTemplate("statements.if-else", "v")<CR>' +	" +	exe "amenu <silent>".s:C_Root.'&Statements.if\ \{\ \}\ e&lse\ \{\ \}   <Esc><Esc>:call C_InsertTemplate("statements.if-block-else")<CR>' +	exe "vmenu <silent>".s:C_Root.'&Statements.if\ \{\ \}\ e&lse\ \{\ \}   <Esc><Esc>:call C_InsertTemplate("statements.if-block-else", "v")<CR>' +	" +	exe "amenu <silent>".s:C_Root.'&Statements.&while                      <Esc><Esc>:call C_InsertTemplate("statements.while")<CR>' +	" +	exe "amenu <silent>".s:C_Root.'&Statements.w&hile\ \{\ \}              <Esc><Esc>:call C_InsertTemplate("statements.while-block")<CR>' +	exe "vmenu <silent>".s:C_Root.'&Statements.w&hile\ \{\ \}              <Esc><Esc>:call C_InsertTemplate("statements.while-block", "v")<CR>' +	" +	exe "amenu <silent>".s:C_Root.'&Statements.&switch\ \{\ \}             <Esc><Esc>:call C_InsertTemplate("statements.switch")<CR>' +	exe "vmenu <silent>".s:C_Root.'&Statements.&switch\ \{\ \}             <Esc><Esc>:call C_InsertTemplate("statements.switch", "v")<CR>' +	" +	exe "amenu  ".s:C_Root.'&Statements.&case\ \.\.\.\ break               <<Esc><Esc>:call C_InsertTemplate("statements.case")<CR>' +	" +	" +	exe "amenu <silent>".s:C_Root.'&Statements.&\{\ \}                     <Esc><Esc>:call C_InsertTemplate("statements.block")<CR>' +	exe "vmenu <silent>".s:C_Root.'&Statements.&\{\ \}                   	 <Esc><Esc>:call C_InsertTemplate("statements.block", "v")<CR>' +	" +	" +	"=============================================================================================== +	"----- Menu : C-Idioms ----------------------------------------------------   {{{2 +	"=============================================================================================== +	" +	if s:C_MenuHeader == 'yes' +		exe "amenu          ".s:C_Root.'&Idioms.&Idioms<Tab>C\/C\+\+       <Esc>' +		exe "amenu          ".s:C_Root.'&Idioms.-Sep00-                   :' +	endif +	exe "amenu <silent> ".s:C_Root.'&Idioms.&function                   <Esc><Esc>:call C_InsertTemplate("idioms.function")<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Idioms.&function                   <Esc><Esc>:call C_InsertTemplate("idioms.function", "v")<CR>' +	exe "amenu <silent> ".s:C_Root.'&Idioms.s&tatic\ function           <Esc><Esc>:call C_InsertTemplate("idioms.function-static")<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Idioms.s&tatic\ function           <Esc><Esc>:call C_InsertTemplate("idioms.function-static", "v")<CR>' +	exe "amenu <silent> ".s:C_Root.'&Idioms.&main                       <Esc><Esc>:call C_InsertTemplate("idioms.main")<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Idioms.&main                       <Esc><Esc>:call C_InsertTemplate("idioms.main", "v")<CR>' + +	exe "amenu          ".s:C_Root.'&Idioms.-SEP1-                      :' +	exe "amenu          ".s:C_Root.'&Idioms.for(x=&0;\ x<n;\ x\+=1)     <Esc><Esc>:call C_CodeFor("up"  , "a")<CR>a' +	exe "amenu          ".s:C_Root.'&Idioms.for(x=&n-1;\ x>=0;\ x\-=1)  <Esc><Esc>:call C_CodeFor("down", "a")<CR>a' +	exe "vmenu          ".s:C_Root.'&Idioms.for(x=&0;\ x<n;\ x\+=1)     <Esc><Esc>:call C_CodeFor("up"  , "v")<CR>' +	exe "vmenu          ".s:C_Root.'&Idioms.for(x=&n-1;\ x>=0;\ x\-=1)  <Esc><Esc>:call C_CodeFor("down", "v")<CR>' +	 +	exe "amenu          ".s:C_Root.'&Idioms.-SEP2-                      :' +	exe "amenu <silent> ".s:C_Root.'&Idioms.&enum\+typedef              <Esc><Esc>:call C_InsertTemplate("idioms.enum")<CR>' +	exe "amenu <silent> ".s:C_Root.'&Idioms.&struct\+typedef            <Esc><Esc>:call C_InsertTemplate("idioms.struct")<CR>' +	exe "amenu <silent> ".s:C_Root.'&Idioms.&union\+typedef             <Esc><Esc>:call C_InsertTemplate("idioms.union")<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Idioms.&enum\+typedef              <Esc><Esc>:call C_InsertTemplate("idioms.enum"  , "v")<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Idioms.&struct\+typedef            <Esc><Esc>:call C_InsertTemplate("idioms.struct", "v")<CR>' +	exe "vmenu <silent> ".s:C_Root.'&Idioms.&union\+typedef             <Esc><Esc>:call C_InsertTemplate("idioms.union" , "v")<CR>' +	exe "amenu          ".s:C_Root.'&Idioms.-SEP3-                      :' +	" +	exe " noremenu          ".s:C_Root.'&Idioms.&printf                     <Esc><Esc>oprintf("\n");<Esc>2F"a' +	exe "inoremenu          ".s:C_Root.'&Idioms.&printf                                printf("\n");<Esc>2F"a' +	 +	exe " noremenu          ".s:C_Root.'&Idioms.s&canf                      <Esc><Esc>oscanf("", & );<Esc>F"i' +	exe "inoremenu          ".s:C_Root.'&Idioms.s&canf                                 scanf("", & );<Esc>F"i' +	" +	exe "amenu          ".s:C_Root.'&Idioms.-SEP4-                       :' +	exe "amenu <silent> ".s:C_Root.'&Idioms.p=ca&lloc\(n,sizeof(type)\)  <Esc><Esc>:call C_InsertTemplate("idioms.calloc")<CR>' +	exe "amenu <silent> ".s:C_Root.'&Idioms.p=m&alloc\(sizeof(type)\)    <Esc><Esc>:call C_InsertTemplate("idioms.malloc")<CR>' +	" +	exe "anoremenu <silent> ".s:C_Root.'&Idioms.si&zeof(\ \)             isizeof()<Left>' +	exe "inoremenu <silent> ".s:C_Root.'&Idioms.si&zeof(\ \)             sizeof()<Left>' +	exe "vnoremenu <silent> ".s:C_Root.'&Idioms.si&zeof(\ \)             ssizeof()<Esc>P' +	" +	exe "anoremenu <silent> ".s:C_Root.'&Idioms.asse&rt(\ \)             oassert();<Left><Left>' +	exe "vnoremenu <silent> ".s:C_Root.'&Idioms.asse&rt(\ \)             sassert();<Esc>F(p' +	exe "amenu          ".s:C_Root.'&Idioms.-SEP5-                       :' +	exe "amenu <silent> ".s:C_Root.'&Idioms.open\ &input\ file           <Esc><Esc>:call C_InsertTemplate("idioms.open-input-file")<CR>' +	exe "amenu <silent> ".s:C_Root.'&Idioms.open\ &output\ file          <Esc><Esc>:call C_InsertTemplate("idioms.open-output-file")<CR>' +	exe "amenu <silent> ".s:C_Root.'&Idioms.fscanf                       <Esc><Esc>:call C_InsertTemplate("idioms.fscanf")<CR>' +	exe "amenu <silent> ".s:C_Root.'&Idioms.fprintf                      <Esc><Esc>:call C_InsertTemplate("idioms.fprintf")<CR>' +	"                                       +	"=============================================================================================== +	"----- Menu : C-Preprocessor ----------------------------------------------   {{{2 +	"=============================================================================================== +	" +	if s:C_MenuHeader == 'yes' +		exe "amenu  ".s:C_Root.'&Preprocessor.&Preprocessor<Tab>C\/C\+\+     <Esc>' +		exe "amenu  ".s:C_Root.'&Preprocessor.-Sep00-                      :' +	endif +	" +	"----- Submenu : C-Idioms: standard library ------------------------------------------------------- +	"' +	exe "amenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..Std\.Lib\.<Tab>C\/C\+\+  <Esc>' +	exe "amenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..-Sep0-         :' +	" +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..&assert\.h     <Esc><Esc>o#include<Tab><assert.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..&ctype\.h      <Esc><Esc>o#include<Tab><ctype.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..&errno\.h      <Esc><Esc>o#include<Tab><errno.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..&float\.h      <Esc><Esc>o#include<Tab><float.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..&limits\.h     <Esc><Esc>o#include<Tab><limits.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..l&ocale\.h     <Esc><Esc>o#include<Tab><locale.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..&math\.h       <Esc><Esc>o#include<Tab><math.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..set&jmp\.h     <Esc><Esc>o#include<Tab><setjmp.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..s&ignal\.h     <Esc><Esc>o#include<Tab><signal.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..stdar&g\.h     <Esc><Esc>o#include<Tab><stdarg.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..st&ddef\.h     <Esc><Esc>o#include<Tab><stddef.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..&stdio\.h      <Esc><Esc>o#include<Tab><stdio.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..stdli&b\.h     <Esc><Esc>o#include<Tab><stdlib.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..st&ring\.h     <Esc><Esc>o#include<Tab><string.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &Std\.Lib\..&time\.h       <Esc><Esc>o#include<Tab><time.h>' +	" +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.C99<Tab>C\/C\+\+         <Esc>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.-Sep0-                :' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.&complex\.h           <Esc><Esc>o#include<Tab><complex.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.&fenv\.h              <Esc><Esc>o#include<Tab><fenv.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.&inttypes\.h          <Esc><Esc>o#include<Tab><inttypes.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.is&o646\.h            <Esc><Esc>o#include<Tab><iso646.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.&stdbool\.h           <Esc><Esc>o#include<Tab><stdbool.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.s&tdint\.h            <Esc><Esc>o#include<Tab><stdint.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.tg&math\.h            <Esc><Esc>o#include<Tab><tgmath.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.&wchar\.h             <Esc><Esc>o#include<Tab><wchar.h>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ C&99.wct&ype\.h            <Esc><Esc>o#include<Tab><wctype.h>' +	" +	exe "amenu  ".s:C_Root.'&Preprocessor.-SEP2-                        :' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &\<\.\.\.\>      <Esc><Esc>o#include<Tab><><Left>' +	exe "anoremenu  ".s:C_Root.'&Preprocessor.#include\ &\"\.\.\.\"      <Esc><Esc>o#include<Tab>""<Left>' +	exe "amenu  ".s:C_Root.'&Preprocessor.#&define                       <Esc><Esc>:call C_InsertTemplate("preprocessor.define")<CR>' +	exe "amenu  ".s:C_Root.'&Preprocessor.&#undef                        <Esc><Esc>:call C_InsertTemplate("preprocessor.undefine")<CR>' +	" +	exe "amenu  ".s:C_Root.'&Preprocessor.#&if\ #else\ #endif            <Esc><Esc>:call C_InsertTemplate("preprocessor.if-else-endif")<CR>' +	exe "amenu  ".s:C_Root.'&Preprocessor.#i&fdef\ #else\ #endif         <Esc><Esc>:call C_InsertTemplate("preprocessor.ifdef-else-endif")<CR>' +	exe "amenu  ".s:C_Root.'&Preprocessor.#if&ndef\ #else\ #endif        <Esc><Esc>:call C_InsertTemplate("preprocessor.ifndef-else-endif")<CR>' +	exe "amenu  ".s:C_Root.'&Preprocessor.#ifnd&ef\ #def\ #endif         <Esc><Esc>:call C_InsertTemplate("preprocessor.ifndef-def-endif")<CR>' +	exe "amenu  ".s:C_Root.'&Preprocessor.#if\ &0\ #endif                <Esc><Esc>:call C_PPIf0("a")<CR>2ji' +	" +	exe "vmenu  ".s:C_Root.'&Preprocessor.#&if\ #else\ #endif            <Esc><Esc>:call C_InsertTemplate("preprocessor.if-else-endif", "v")<CR>' +	exe "vmenu  ".s:C_Root.'&Preprocessor.#i&fdef\ #else\ #endif         <Esc><Esc>:call C_InsertTemplate("preprocessor.ifdef-else-endif", "v")<CR>' +	exe "vmenu  ".s:C_Root.'&Preprocessor.#if&ndef\ #else\ #endif        <Esc><Esc>:call C_InsertTemplate("preprocessor.ifndef-else-endif", "v")<CR>' +	exe "vmenu  ".s:C_Root.'&Preprocessor.#ifnd&ef\ #def\ #endif         <Esc><Esc>:call C_InsertTemplate("preprocessor.ifndef-def-endif", "v")<CR>' +	exe "vmenu  ".s:C_Root.'&Preprocessor.#if\ &0\ #endif                <Esc><Esc>:call C_PPIf0("v")<CR>' +	" +	exe "amenu  <silent> ".s:C_Root.'&Preprocessor.&remove\ #if\ 0\ #endif        <Esc><Esc>:call C_PPIf0Remove()<CR>' +	" +	"=============================================================================================== +	"----- Menu : Snippets ----------------------------------------------------   {{{2 +	"=============================================================================================== +	" +	if s:C_MenuHeader == 'yes' +		exe "amenu           ".s:C_Root.'S&nippets.S&nippets<Tab>C\/C\+\+       <Esc>' +		exe "amenu           ".s:C_Root.'S&nippets.-Sep00-                      :' +	endif +	if s:C_CodeSnippets != "" +		exe "amenu  <silent> ".s:C_Root.'S&nippets.&read\ code\ snippet   <C-C>:call C_CodeSnippet("r")<CR>' +		exe "amenu  <silent> ".s:C_Root.'S&nippets.&write\ code\ snippet  <C-C>:call C_CodeSnippet("w")<CR>' +		exe "vmenu  <silent> ".s:C_Root.'S&nippets.&write\ code\ snippet  <C-C>:call C_CodeSnippet("wv")<CR>' +		exe "amenu  <silent> ".s:C_Root.'S&nippets.&edit\ code\ snippet   <C-C>:call C_CodeSnippet("e")<CR>' +		exe " menu  <silent> ".s:C_Root.'S&nippets.-SEP1-									:' +	endif +	exe " menu  <silent> ".s:C_Root.'S&nippets.&pick\ up\ prototype   	<C-C>:call C_ProtoPick("n")<CR>' +	exe "vmenu  <silent> ".s:C_Root.'S&nippets.&pick\ up\ prototype   	<C-C>:call C_ProtoPick("v")<CR>' +	exe " menu  <silent> ".s:C_Root.'S&nippets.&insert\ prototype(s)  	<C-C>:call C_ProtoInsert()<CR>' +	exe " menu  <silent> ".s:C_Root.'S&nippets.&clear\ prototype(s)			<C-C>:call C_ProtoClear()<CR>' +	exe " menu  <silent> ".s:C_Root.'S&nippets.&show\ prototype(s)			<C-C>:call C_ProtoShow()<CR>' + +	" +	"=============================================================================================== +	"----- Menu : C++ ---------------------------------------------------------   {{{2 +	"=============================================================================================== +	" +	if s:C_MenuHeader == 'yes' +		exe "amenu  ".s:C_Root.'C&++.C&\+\+<Tab>C\/C\+\+          <Esc>' +		exe "amenu  ".s:C_Root.'C&++.-Sep00-                     :' +	endif +	exe " noremenu ".s:C_Root.'C&++.c&in                 <Esc><Esc>ocin<Tab>>> ;<Esc>i' +	exe " noremenu ".s:C_Root.'C&++.cout\ &variable      <Esc><Esc>ocout<Tab><<  << endl;<Esc>2F<hi' +	exe " noremenu ".s:C_Root.'C&++.cout\ &string        <Esc><Esc>ocout<Tab><< "\n";<Esc>2F"a' +	exe " noremenu ".s:C_Root.'C&++.<<\ &\"\"            i<< "" <Left><Left>' +	" +	exe "inoremenu ".s:C_Root.'C&++.c&in                 cin<Tab>>> ;<Esc>i' +	exe "inoremenu ".s:C_Root.'C&++.cout\ &variable      cout<Tab><<  << endl;<Esc>2F<hi' +	exe "inoremenu ".s:C_Root.'C&++.cout\ &string        cout<Tab><< "\n";<Esc>2F"a' +	exe "inoremenu ".s:C_Root.'C&++.<<\ &\"\"            << "" <Left><Left>' +	" +	"----- Submenu : C++ : output manipulators  ------------------------------------------------------- +	" +	exe "amenu ".s:C_Root.'C&++.&output\ manipulators.output\ manip\.<Tab>C\/C\+\+              <Esc>' +	exe "amenu ".s:C_Root.'C&++.&output\ manipulators.-Sep0-                     :' +	" +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &boolalpha           i<< boolalpha<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &dec                 i<< dec<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &endl                i<< endl<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &fixed               i<< fixed<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ fl&ush               i<< flush<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &hex                 i<< hex<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &internal            i<< internal<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &left                i<< left<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &oct                 i<< oct<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &right               i<< right<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ s&cientific          i<< scientific<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &setbase\(\ \)       i<< setbase(10) <Left><Left>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ se&tfill\(\ \)       i<< setfill() <Left><Left>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ setiosfla&g\(\ \)    i<< setiosflags() <Left><Left>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ set&precision\(\ \)  i<< setprecision(6) <Left><Left>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ set&w\(\ \)          i<< setw(0) <Left><Left>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ showb&ase            i<< showbase<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ showpoi&nt           i<< showpoint<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ showpos\ \(&1\)      i<< showpos<Space>' +	exe " noremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ uppercase\ \(&2\)    i<< uppercase<Space>' +	"                                 +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &boolalpha           << boolalpha<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &dec                 << dec<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &endl                << endl<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &fixed               << fixed<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ fl&ush               << flush<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &hex                 << hex<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &internal            << internal<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &left                << left<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ o&ct                 << oct<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &right               << right<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ s&cientific          << scientific<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ &setbase\(\ \)       << setbase(10) <Left><Left>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ se&tfill\(\ \)       << setfill() <Left><Left>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ setiosfla&g\(\ \)    << setiosflags() <Left><Left>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ set&precision\(\ \)  << setprecision(6) <Left><Left>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ set&w\(\ \)          << setw(0) <Left><Left>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ showb&ase            << showbase<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ showpoi&nt           << showpoint<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ showpos\ \(&1\)      << showpos<Space>' +	exe "inoremenu ".s:C_Root.'C&++.&output\ manipulators.\<\<\ uppercase\ \(&2\)    << uppercase<Space>' +	" +	"----- Submenu : C++ : ios flag bits  ------------------------------------------------------------- +	" +	exe "amenu ".s:C_Root.'C&++.ios\ flag&bits.ios\ flags<Tab>C\/C\+\+        <Esc>' +	exe "amenu ".s:C_Root.'C&++.ios\ flag&bits.-Sep0-               :' +	" +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&adjustfield      iios::adjustfield' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::bas&efield        iios::basefield' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&boolalpha        iios::boolalpha' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&dec              iios::dec' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&fixed            iios::fixed' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::floa&tfield       iios::floatfield' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&hex              iios::hex' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&internal         iios::internal' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&left             iios::left' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&oct              iios::oct' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&right            iios::right' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::s&cientific       iios::scientific' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::sho&wbase         iios::showbase' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::showpoint\ \(&1\) iios::showpoint' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::show&pos          iios::showpos' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&skipws           iios::skipws' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::u&nitbuf          iios::unitbuf' +	exe " noremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&uppercase        iios::uppercase' +	" +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&adjustfield      ios::adjustfield' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::bas&efield        ios::basefield' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&boolalpha        ios::boolalpha' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&dec              ios::dec' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&fixed            ios::fixed' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::floa&tfield       ios::floatfield' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&hex              ios::hex' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&internal         ios::internal' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&left             ios::left' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&oct              ios::oct' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&right            ios::right' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::s&cientific       ios::scientific' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::sho&wbase         ios::showbase' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::showpoint\ \(&1\) ios::showpoint' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::show&pos          ios::showpos' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&skipws           ios::skipws' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::u&nitbuf          ios::unitbuf' +	exe "inoremenu ".s:C_Root.'C&++.ios\ flag&bits.ios::&uppercase        ios::uppercase' +	" +	"----- Submenu : C++   library  (algorithm - locale) ---------------------------------------------- +	" +	exe "amenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).alg\.\.loc<Tab>C\/C\+\+   <Esc>' +	exe "amenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).-Sep0-          :' +	" +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).&algorithm      <Esc><Esc>o#include<Tab><algorithm>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).&bitset         <Esc><Esc>o#include<Tab><bitset>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).&complex        <Esc><Esc>o#include<Tab><complex>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).&deque          <Esc><Esc>o#include<Tab><deque>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).&exception      <Esc><Esc>o#include<Tab><exception>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).&fstream        <Esc><Esc>o#include<Tab><fstream>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).f&unctional     <Esc><Esc>o#include<Tab><functional>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).iomani&p        <Esc><Esc>o#include<Tab><iomanip>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).&ios            <Esc><Esc>o#include<Tab><ios>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).iosf&wd         <Esc><Esc>o#include<Tab><iosfwd>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).io&stream       <Esc><Esc>o#include<Tab><iostream>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).istrea&m        <Esc><Esc>o#include<Tab><istream>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).iterato&r       <Esc><Esc>o#include<Tab><iterator>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).&limits         <Esc><Esc>o#include<Tab><limits>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).lis&t           <Esc><Esc>o#include<Tab><list>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <alg\.\.loc>\ \(&1\).l&ocale         <Esc><Esc>o#include<Tab><locale>' +	" +	"----- Submenu : C++   library  (map - vector) ---------------------------------------------------- +	" +	exe "amenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).map\.\.vec<Tab>C\/C\+\+   <Esc>' +	exe "amenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).-Sep0-          :' + +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).&map            <Esc><Esc>o#include<Tab><map>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).memor&y         <Esc><Esc>o#include<Tab><memory>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).&new            <Esc><Esc>o#include<Tab><new>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).numeri&c        <Esc><Esc>o#include<Tab><numeric>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).&ostream        <Esc><Esc>o#include<Tab><ostream>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).&queue          <Esc><Esc>o#include<Tab><queue>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).&set            <Esc><Esc>o#include<Tab><set>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).sst&ream        <Esc><Esc>o#include<Tab><sstream>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).st&ack          <Esc><Esc>o#include<Tab><stack>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).stde&xcept      <Esc><Esc>o#include<Tab><stdexcept>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).stream&buf      <Esc><Esc>o#include<Tab><streambuf>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).str&ing         <Esc><Esc>o#include<Tab><string>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).&typeinfo       <Esc><Esc>o#include<Tab><typeinfo>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).&utility        <Esc><Esc>o#include<Tab><utility>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).&valarray       <Esc><Esc>o#include<Tab><valarray>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <map\.\.vec>\ \(&2\).v&ector         <Esc><Esc>o#include<Tab><vector>' +	" +	"----- Submenu : C     library  (cassert - ctime) ------------------------------------------------- +	" +	exe "amenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).cX<Tab>C\/C\+\+ <Esc>' +	exe "amenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).-Sep0-        :' +	" +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).c&assert      <Esc><Esc>o#include<Tab><cassert>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).c&ctype       <Esc><Esc>o#include<Tab><cctype>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).c&errno       <Esc><Esc>o#include<Tab><cerrno>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).c&float       <Esc><Esc>o#include<Tab><cfloat>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).c&limits      <Esc><Esc>o#include<Tab><climits>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).cl&ocale      <Esc><Esc>o#include<Tab><clocale>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).c&math        <Esc><Esc>o#include<Tab><cmath>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).cset&jmp      <Esc><Esc>o#include<Tab><csetjmp>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).cs&ignal      <Esc><Esc>o#include<Tab><csignal>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).cstdar&g      <Esc><Esc>o#include<Tab><cstdarg>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).cst&ddef      <Esc><Esc>o#include<Tab><cstddef>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).c&stdio       <Esc><Esc>o#include<Tab><cstdio>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).cstdli&b      <Esc><Esc>o#include<Tab><cstdlib>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).cst&ring      <Esc><Esc>o#include<Tab><cstring>' +	exe "anoremenu ".s:C_Root.'C&++.#include\ <cX>\ \(&3\).c&time        <Esc><Esc>o#include<Tab><ctime>' +	" +	"----- End Submenu : C     library  (cassert - ctime) --------------------------------------------- +	" +	exe "amenu <silent> ".s:C_Root.'C&++.-SEP2-                        :' +	exe "amenu <silent> ".s:C_Root.'C&++.&method\ implement\.          <Esc><Esc>:call C_InsertTemplate("cpp.method-implementation")<CR>' + +	exe "amenu <silent> ".s:C_Root.'C&++.&class                        <Esc><Esc>:call C_InsertTemplate("cpp.class")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.class\ (w\.\ &new)            <Esc><Esc>:call C_InsertTemplate("cpp.class-using-new")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.-SEP3-                        :' +	exe "amenu <silent> ".s:C_Root.'C&++.tem&pl\.\ method\ impl\.      <Esc><Esc>:call C_InsertTemplate("cpp.template-method-implementation")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.&templ\.\ class               <Esc><Esc>:call C_InsertTemplate("cpp.template-class")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.templ\.\ class\ (w\.\ ne&w)   <Esc><Esc>:call C_InsertTemplate("cpp.template-class-using-new")<CR>' + +	exe "amenu <silent> ".s:C_Root.'C&++.-SEP31-                       :' +	exe "amenu <silent> ".s:C_Root.'C&++.templ\.\ &function            <Esc><Esc>:call C_InsertTemplate("cpp.template-function")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.&error\ class                 <Esc><Esc>:call C_InsertTemplate("cpp.error-class")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.-SEP4-                        :' +	exe "amenu <silent> ".s:C_Root.'C&++.operator\ &<<                 <Esc><Esc>:call C_InsertTemplate("cpp.operator-in")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.operator\ &>>                 <Esc><Esc>:call C_InsertTemplate("cpp.operator-out")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.-SEP5-                        :' +	exe "amenu <silent> ".s:C_Root.'C&++.tr&y\ \.\.\ catch             <Esc><Esc>:call C_InsertTemplate("cpp.try-catch")<CR>' +	exe "vmenu <silent> ".s:C_Root.'C&++.tr&y\ \.\.\ catch             <Esc><Esc>:call C_InsertTemplate("cpp.try-catch", "v")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.catc&h                        <Esc><Esc>:call C_InsertTemplate("cpp.catch")<CR>' +	exe "vmenu <silent> ".s:C_Root.'C&++.catc&h                        <Esc><Esc>:call C_InsertTemplate("cpp.catch", "v")<CR>' + +	exe "amenu <silent> ".s:C_Root.'C&++.catch\(&\.\.\.\)              <Esc><Esc>:call C_InsertTemplate("cpp.catch-points")<CR>' +	exe "vmenu <silent> ".s:C_Root.'C&++.catch\(&\.\.\.\)              <Esc><Esc>:call C_InsertTemplate("cpp.catch-points", "v")<CR>' + +	exe "amenu <silent> ".s:C_Root.'C&++.-SEP6-                        :' +	exe "amenu <silent> ".s:C_Root.'C&++.open\ input\ file\ \ \(&4\)   <Esc><Esc>:call C_InsertTemplate("cpp.open-input-file")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.open\ output\ file\ \(&5\)    <Esc><Esc>:call C_InsertTemplate("cpp.open-output-file")<CR>' +	exe "amenu <silent> ".s:C_Root.'C&++.-SEP7-                        :' + +	exe " menu <silent> ".s:C_Root.'C&++.&using\ namespace\ std;       <Esc><Esc>ousing namespace std;<CR>' +	exe " menu <silent> ".s:C_Root.'C&++.usin&g\ namespace\ ;          <Esc><Esc>ousing namespace ;<Esc>$i' +	exe "amenu <silent> ".s:C_Root.'C&++.namespace\ &\{\ \}            <Esc><Esc>:call C_InsertTemplate("cpp.namespace")<CR>' + +	exe "imenu <silent> ".s:C_Root.'C&++.&using\ namespace\ std;       using namespace std;<CR>' +	exe "imenu <silent> ".s:C_Root.'C&++.usin&g\ namespace\ ;          using namespace ;<Esc>$i' +	exe "vmenu <silent> ".s:C_Root.'C&++.namespace\ &\{\ \}            <Esc><Esc>:call C_InsertTemplate("cpp.namespace", "v")<CR>' + +	exe "amenu <silent> ".s:C_Root.'C&++.-SEP8-              :' +	" +	"----- Submenu : RTTI  ---------------------------------------------------------------------------- +	" +	exe "amenu ".s:C_Root.'C&++.&RTTI.RTTI<Tab>C\/C\+\+          <Esc>' +	exe "amenu ".s:C_Root.'C&++.&RTTI.-Sep0-                 :' +	" +	exe " noremenu ".s:C_Root.'C&++.&RTTI.&typeid                atypeid()<Esc>hr(a' +	exe " noremenu ".s:C_Root.'C&++.&RTTI.&static_cast           astatic_cast<>()<Left>' +	exe " noremenu ".s:C_Root.'C&++.&RTTI.&const_cast            aconst_cast<>()<Left>' +	exe " noremenu ".s:C_Root.'C&++.&RTTI.&reinterpret_cast      areinterpret_cast<>()<Left>' +	exe " noremenu ".s:C_Root.'C&++.&RTTI.&dynamic_cast          adynamic_cast<>()<Left>' +	" +	exe "vnoremenu ".s:C_Root.'C&++.&RTTI.&typeid                stypeid()<Esc>hr(p' +	exe "vnoremenu ".s:C_Root.'C&++.&RTTI.&static_cast           sstatic_cast<>()<Esc>P' +	exe "vnoremenu ".s:C_Root.'C&++.&RTTI.&const_cast            sconst_cast<>()<Esc>P' +	exe "vnoremenu ".s:C_Root.'C&++.&RTTI.&reinterpret_cast      sreinterpret_cast<>()<Esc>P' +	exe "vnoremenu ".s:C_Root.'C&++.&RTTI.&dynamic_cast          sdynamic_cast<>()<Esc>P' +	" +	exe "inoremenu ".s:C_Root.'C&++.&RTTI.&typeid                typeid()<Esc>hr(a' +	exe "inoremenu ".s:C_Root.'C&++.&RTTI.&static_cast           static_cast<>()<Left>' +	exe "inoremenu ".s:C_Root.'C&++.&RTTI.&const_cast            const_cast<>()<Left>' +	exe "inoremenu ".s:C_Root.'C&++.&RTTI.&reinterpret_cast      reinterpret_cast<>()<Left>' +	exe "inoremenu ".s:C_Root.'C&++.&RTTI.&dynamic_cast          dynamic_cast<>()<Left>' +	" +	"----- End Submenu : RTTI  ------------------------------------------------------------------------ +	" +	exe "amenu  <silent>".s:C_Root.'C&++.e&xtern\ \"C\"\ \{\ \}       <Esc><Esc>:call C_InsertTemplate("cpp.extern")<CR>' +	exe "vmenu  <silent>".s:C_Root.'C&++.e&xtern\ \"C\"\ \{\ \}       <Esc><Esc>:call C_InsertTemplate("cpp.extern", "v")<CR>' +	" +	"=============================================================================================== +	"----- Menu : run  ----- --------------------------------------------------   {{{2 +	"=============================================================================================== +	" +	if s:C_MenuHeader == 'yes' +		exe "amenu  ".s:C_Root.'&Run.&Run<Tab>C\/C\+\+       <Esc>' +		exe "amenu  ".s:C_Root.'&Run.-Sep00-                 :' +	endif +	" +	exe "amenu  <silent>  ".s:C_Root.'&Run.save\ and\ &compile<Tab>\<A-F9\>    <C-C>:call C_Compile()<CR>:redraw<CR>:call C_HlMessage()<CR>' +	exe "amenu  <silent>  ".s:C_Root.'&Run.&link<Tab>\<F9\>                    <C-C>:call C_Link()<CR>:redraw<CR>:call C_HlMessage()<CR>' +	exe "amenu  <silent>  ".s:C_Root.'&Run.&run<Tab>\<C-F9\>                   <C-C>:call C_Run()<CR>' +	exe "amenu  <silent>  ".s:C_Root.'&Run.cmd\.\ line\ &arg\.<Tab>\<S-F9\>    <C-C>:call C_Arguments()<CR>' +	exe "amenu  <silent>  ".s:C_Root.'&Run.-SEP0-                              :' +	exe "amenu  <silent>  ".s:C_Root.'&Run.&make                               <C-C>:call C_Make()<CR>' +	exe "amenu  <silent>  ".s:C_Root.'&Run.cmd\.\ line\ ar&g\.\ for\ make      <C-C>:call C_MakeArguments()<CR>' +	exe "amenu  <silent>  ".s:C_Root.'&Run.-SEP1-                              :' +	if s:C_SplintIsExecutable==1 +		exe "amenu  <silent>  ".s:C_Root.'&Run.s&plint                             <C-C>:call C_SplintCheck()<CR>:redraw<CR>:call C_HlMessage()<CR>' +		exe "amenu  <silent>  ".s:C_Root.'&Run.cmd\.\ line\ arg\.\ for\ spl&int    <C-C>:call C_SplintArguments()<CR>' +		exe "amenu  <silent>  ".s:C_Root.'&Run.-SEP2-                              :' +	endif +	" +	if s:C_CodeCheckIsExecutable==1 +		exe "amenu  <silent>  ".s:C_Root.'&Run.CodeChec&k                          <C-C>:call C_CodeCheck()<CR>:redraw<CR>:call C_HlMessage()<CR>' +		exe "amenu  <silent>  ".s:C_Root.'&Run.cmd\.\ line\ arg\.\ for\ Cod&eCheck <C-C>:call C_CodeCheckArguments()<CR>' +		exe "amenu  <silent>  ".s:C_Root.'&Run.-SEP3-                              :' +	endif +	" +	exe "amenu            ".s:C_Root.'&Run.in&dent                             <C-C>:call C_Indent("a")<CR>:redraw<CR>:call C_HlMessage()<CR>' +	exe "vmenu            ".s:C_Root.'&Run.in&dent                             <C-C>:call C_Indent("v")<CR>:redraw<CR>:call C_HlMessage()<CR>' +	if	s:MSWIN +		exe "amenu  <silent>  ".s:C_Root.'&Run.&hardcopy\ to\ printer              <C-C>:call C_Hardcopy("n")<CR>' +		exe "vmenu  <silent>  ".s:C_Root.'&Run.&hardcopy\ to\ printer              <C-C>:call C_Hardcopy("v")<CR>' +	else +		exe "amenu  <silent>  ".s:C_Root.'&Run.&hardcopy\ to\ FILENAME\.ps         <C-C>:call C_Hardcopy("n")<CR>' +		exe "vmenu  <silent>  ".s:C_Root.'&Run.&hardcopy\ to\ FILENAME\.ps         <C-C>:call C_Hardcopy("v")<CR>' +	endif +	exe "imenu  <silent>  ".s:C_Root.'&Run.-SEP4-                              :' + +	exe "amenu  <silent>  ".s:C_Root.'&Run.rebuild\ &templates                   <C-C>:call C_RebuildTemplates()<CR>' +	exe "amenu  <silent>  ".s:C_Root.'&Run.&settings                             <C-C>:call C_Settings()<CR>' +	exe "imenu  <silent>  ".s:C_Root.'&Run.-SEP5-                                :' + +	if	!s:MSWIN +		exe "amenu  <silent>  ".s:C_Root.'&Run.&xterm\ size                             <C-C>:call C_XtermSize()<CR>' +	endif +	if s:C_OutputGvim == "vim"  +		exe "amenu  <silent>  ".s:C_Root.'&Run.&output:\ VIM->buffer->xterm            <C-C>:call C_Toggle_Gvim_Xterm()<CR><CR>' +	else +		if s:C_OutputGvim == "buffer"  +			exe "amenu  <silent>  ".s:C_Root.'&Run.&output:\ BUFFER->xterm->vim        <C-C>:call C_Toggle_Gvim_Xterm()<CR><CR>' +		else +			exe "amenu  <silent>  ".s:C_Root.'&Run.&output:\ XTERM->vim->buffer          <C-C>:call C_Toggle_Gvim_Xterm()<CR><CR>' +		endif +	endif +	" +	"=============================================================================================== +	"----- Menu : help  -------------------------------------------------------   {{{2 +	"=============================================================================================== +	" +	if s:C_Root != "" +		exe "menu  <silent>  ".s:C_Root.'&help\ \(plugin\)     <C-C><C-C>:call C_HelpCsupport()<CR>' +	endif + +endfunction    " ----------  end of function  C_InitMenus  ---------- +" +"=============================================================================================== +"----- Menu Functions -------------------------------------------------------------------------- +"=============================================================================================== +" +"------------------------------------------------------------------------------ +"  C_Input: Input after a highlighted prompt     {{{1 +"------------------------------------------------------------------------------ +function! C_Input ( promp, text ) +	echohl Search																					" highlight prompt +	call inputsave()																			" preserve typeahead +	let	retval=input( a:promp, a:text )										" read input +	call inputrestore()																		" restore typeahead +	echohl None																						" reset highlighting +	let retval  = substitute( retval, '^\s\+', "", "" )		" remove leading whitespaces +	let retval  = substitute( retval, '\s\+$', "", "" )		" remove trailing whitespaces +	return retval +endfunction    " ----------  end of function C_Input ---------- +" +"------------------------------------------------------------------------------ +"  C_AdjustLineEndComm: adjust line-end comments     {{{1 +"------------------------------------------------------------------------------ +function! C_AdjustLineEndComm ( mode ) range +	" +	if !exists("b:C_LineEndCommentColumn") +		let	b:C_LineEndCommentColumn	= s:C_LineEndCommColDefault +	endif + +	let save_cursor = getpos(".") + +	let	save_expandtab	= &expandtab +	exe	":set expandtab" + +	if a:mode == 'v' +		let pos0	= line("'<") +		let pos1	= line("'>") +	else +		let pos0	= line(".") +		let pos1	= pos0 +	endif + +	let	linenumber	= pos0 +	exe ":".pos0 + +	while linenumber <= pos1 +		let	line= getline(".") +		" look for a C comment +		let idx1	= 1 + match( line, '\s*\/\*.\{-}\*\/' ) +		let idx2	= 1 + match( line, '\/\*.\{-}\*\/' ) +		if idx2 == 0					 +			" look for a C++ comment +			let idx1	= 1 + match( line, '\s*\/\/.*$' ) +			let idx2	= 1 + match( line, '\/\/.*$' ) +		endif + +		let	ln	= line(".") +		call setpos(".", [ 0, ln, idx1, 0 ] ) +		let vpos1	= virtcol(".") +		call setpos(".", [ 0, ln, idx2, 0 ] ) +		let vpos2	= virtcol(".") + +		if   ! (   vpos2 == b:C_LineEndCommentColumn  +					\	|| vpos1 > b:C_LineEndCommentColumn +					\	|| idx2  == 0 ) + +			exe ":.,.retab" +			" insert some spaces +			if vpos2 < b:C_LineEndCommentColumn +				let	diff	= b:C_LineEndCommentColumn-vpos2 +				call setpos(".", [ 0, ln, vpos2, 0 ] ) +				let	@"	= ' ' +				exe "normal	".diff."P" +			endif + +			" remove some spaces +			if vpos1 < b:C_LineEndCommentColumn && vpos2 > b:C_LineEndCommentColumn +				let	diff	= vpos2 - b:C_LineEndCommentColumn +				call setpos(".", [ 0, ln, b:C_LineEndCommentColumn, 0 ] ) +				exe "normal	".diff."x" +			endif + +		endif +		let linenumber=linenumber+1 +		normal j +	endwhile +	" restore tab expansion settings and cursor position +	let &expandtab	= save_expandtab +	call setpos('.', save_cursor) + +endfunction		" ---------- end of function  C_AdjustLineEndComm  ---------- +" +"------------------------------------------------------------------------------ +"  C_GetLineEndCommCol: get line-end comment position    {{{1 +"------------------------------------------------------------------------------ +function! C_GetLineEndCommCol () +	let actcol	= virtcol(".") +	if actcol+1 == virtcol("$") +		let	b:C_LineEndCommentColumn	= C_Input( 'start line-end comment at virtual column : ', actcol ) +	else +		let	b:C_LineEndCommentColumn	= virtcol(".")  +	endif +  echomsg "line end comments will start at column  ".b:C_LineEndCommentColumn +endfunction		" ---------- end of function  C_GetLineEndCommCol  ---------- +" +"------------------------------------------------------------------------------ +"  C_LineEndComment: single line-end comment    {{{1 +"------------------------------------------------------------------------------ +function! C_LineEndComment ( ) +	if !exists("b:C_LineEndCommentColumn") +		let	b:C_LineEndCommentColumn	= s:C_LineEndCommColDefault +	endif +	" ----- trim whitespaces ----- +	exe 's/\s*$//' +	let linelength= virtcol("$") - 1 +	if linelength < b:C_LineEndCommentColumn +		let diff	= b:C_LineEndCommentColumn -1 -linelength +		exe "normal	".diff."A " +	endif +	" append at least one blank +	if linelength >= b:C_LineEndCommentColumn +		exe "normal A " +	endif +	call C_InsertTemplate('comment.end-of-line-comment') +endfunction		" ---------- end of function  C_LineEndComment  ---------- +" +"------------------------------------------------------------------------------ +"  C_MultiLineEndComments: multi line-end comments    {{{1 +"------------------------------------------------------------------------------ +function! C_MultiLineEndComments ( ) +	" +  if !exists("b:C_LineEndCommentColumn") +		let	b:C_LineEndCommentColumn	= s:C_LineEndCommColDefault +  endif +	" +	let pos0	= line("'<") +	let pos1	= line("'>") +	" +	" ----- trim whitespaces ----- +  exe pos0.','.pos1.'s/\s*$//'   +	"  +	" ----- find the longest line ----- +	let	maxlength		= 0 +	let	linenumber	= pos0 +	normal '< +	while linenumber <= pos1 +		if  getline(".") !~ "^\\s*$"  && maxlength<virtcol("$") +			let maxlength= virtcol("$") +		endif +		let linenumber=linenumber+1 +		normal j +	endwhile +	" +	if maxlength < b:C_LineEndCommentColumn +	  let maxlength = b:C_LineEndCommentColumn +	else +	  let maxlength = maxlength+1		" at least 1 blank +	endif +	" +	" ----- fill lines with blanks ----- +	let	linenumber	= pos0 +	while linenumber <= pos1 +		exe ":".linenumber +		if getline(".") !~ "^\\s*$" +			let diff	= maxlength - virtcol("$") +			exe "normal	".diff."A " +			call C_InsertTemplate('comment.end-of-line-comment') +		endif +		let linenumber=linenumber+1 +	endwhile +	" +	" ----- back to the begin of the marked block ----- +	let diff	= pos1-pos0 +	normal a +	if pos1-pos0 > 0 +		exe "normal ".diff."k" +	end +endfunction		" ---------- end of function  C_MultiLineEndComments  ---------- +" +"------------------------------------------------------------------------------ +"  C_CommentSpecial : special comments    {{{1 +"------------------------------------------------------------------------------ +function! C_CommentSpecial (special) +  	put = '	'.s:C_Com1.' '.a:special.' '.s:C_Com2 +endfunction    " ----------  end of function C_CommentSpecial ---------- +" +"------------------------------------------------------------------------------ +"  C_Comment_C_SectionAll: Section Comments    {{{1 +"------------------------------------------------------------------------------ +" +function! C_Comment_C_SectionAll ( type ) + +	call C_InsertTemplate("comment.file-section-cpp-header-includes") +	call C_InsertTemplate("comment.file-section-cpp-macros") +	call C_InsertTemplate("comment.file-section-cpp-typedefs") +	call C_InsertTemplate("comment.file-section-cpp-data-types") +	if a:type=="cpp" +		call C_InsertTemplate("comment.file-section-cpp-class-defs") +	endif +	call C_InsertTemplate("comment.file-section-cpp-local-variables") +	call C_InsertTemplate("comment.file-section-cpp-prototypes") +	call C_InsertTemplate("comment.file-section-cpp-function-defs-exported") +	call C_InsertTemplate("comment.file-section-cpp-function-defs-local") +	if a:type=="cpp" +		call C_InsertTemplate("comment.file-section-cpp-class-implementations-exported") +		call C_InsertTemplate("comment.file-section-cpp-class-implementations-local") +	endif + +endfunction    " ----------  end of function C_Comment_C_SectionAll ---------- +" +function! C_Comment_H_SectionAll ( type ) + +	call C_InsertTemplate("comment.file-section-hpp-header-includes") +	call C_InsertTemplate("comment.file-section-hpp-macros") +	call C_InsertTemplate("comment.file-section-hpp-exported-typedefs") +	call C_InsertTemplate("comment.file-section-hpp-exported-data-types") +	if a:type=="cpp" +		call C_InsertTemplate("comment.file-section-hpp-exported-class-defs") +	endif +	call C_InsertTemplate("comment.file-section-hpp-exported-variables") +	call C_InsertTemplate("comment.file-section-hpp-exported-function-declarations") + +endfunction    " ----------  end of function C_Comment_H_SectionAll ---------- +" +"---------------------------------------------------------------------- +"  C_CodeComment : Code -> Comment   {{{1 +"---------------------------------------------------------------------- +function! C_CodeComment( mode, style ) + +	if a:mode=="a" +		if a:style == 'yes'  +			silent exe ":s#^#/\* #" +			silent put = ' */' +		else +			silent exe ":s#^#//#" +		endif +	endif +	 +	if a:mode=="v" +		if a:style == 'yes'  +			silent exe ":'<,'>s/^/ \* /" +			silent exe ":'< s'^ '\/'" +			silent exe ":'>" +			silent put = ' */' +		else +			silent exe ":'<,'>s#^#//#" +		endif +	endif + +endfunction    " ----------  end of function  C_CodeComment  ---------- +" +"---------------------------------------------------------------------- +"  C_StartMultilineComment : Comment -> Code   {{{1 +"---------------------------------------------------------------------- +let s:C_StartMultilineComment	= '^\s*\/\*[\*! ]\=' + +function! C_RemoveCComment( start, end ) + +	if a:end-a:start<1 +		return 0										" lines removed +	endif +	"  +	" Is the C-comment complete ? Get length. +	"  +	let check				= getline(	a:start ) =~ s:C_StartMultilineComment +	let	linenumber	= a:start+1 +	while linenumber < a:end && getline(	linenumber ) !~ '^\s*\*\/' +		let check				= check && getline(	linenumber ) =~ '^\s*\*[ ]\=' +		let linenumber	= linenumber+1 +	endwhile +	let check = check && getline(	linenumber ) =~ '^\s*\*\/' +	" +	" remove a complete comment +	"  +	if check +		exe "silent :".a:start.'   s/'.s:C_StartMultilineComment.'//' +		let	linenumber1	= a:start+1 +		while linenumber1 < linenumber +			exe "silent :".linenumber1.' s/^\s*\*[ ]\=//' +			let linenumber1	= linenumber1+1 +		endwhile +		exe "silent :".linenumber1.'   s/^\s*\*\///' +	endif + +	return linenumber-a:start+1			" lines removed +endfunction    " ----------  end of function  C_RemoveCComment  ---------- +" +"---------------------------------------------------------------------- +"  C_CommentCode : Comment -> Code       {{{1 +"---------------------------------------------------------------------- +function! C_CommentCode(mode) +	if a:mode=="a" +		let	pos1		= line(".") +		let	pos2		= pos1 +	endif +	if a:mode=="v" +		let	pos1		= line("'<") +		let	pos2		= line("'>") +	endif + +	let	removed	= 0 +	"  +	let	linenumber=pos1 +	while linenumber <= pos2 +		" Do we have a C++ comment ? +		if getline(	linenumber ) =~ '^\s*//' +			exe "silent :".linenumber.' s#^\s*//##' +			let	removed    = 1 +		endif +		" Do we have a C   comment ? +		if removed == 0 && getline(	linenumber ) =~ s:C_StartMultilineComment +			let removed = C_RemoveCComment(linenumber,pos2) +		endif + +		if removed!=0 +			let linenumber = linenumber+removed +			let	removed    = 0 +		else +			let linenumber = linenumber+1 +		endif +	endwhile +endfunction    " ----------  end of function  C_CommentCode  ---------- +" +"---------------------------------------------------------------------- +"  C_CommentCppToC : C++ Comment -> C Comment       {{{1 +"  Removes trailing whitespaces. +"---------------------------------------------------------------------- +function! C_CommentCppToC() +		silent! exe ':s#\/\/\s*\(.*\)\s*$#/* \1 */#' +endfunction    " ----------  end of function  C_CommentCppToC  ---------- +" +"---------------------------------------------------------------------- +"  C_CommentCToCpp : C Comment -> C++ Comment       {{{1 +"  Changes the first comment in case of multiple comments: +"    xxxx;               /*  */ /*  */ +"    xxxx;               //  /*  */ +"  Removes trailing whitespaces. +"---------------------------------------------------------------------- +function! C_CommentCToCpp() +		silent! exe ':s!\/\*\s*\(.\{-}\)\*\/!\/\/ \1!' +		silent! exe ':s!\s*$!!' +endfunction    " ----------  end of function  C_CommentCToCpp  ---------- +" +"===================================================================================== +"----- Menu : Statements ----------------------------------------------------------- +"===================================================================================== +" +"------------------------------------------------------------------------------ +"  C_PPIf0 : #if 0 .. #endif        {{{1 +"------------------------------------------------------------------------------ +function! C_PPIf0 (mode) +	" +	let	s:C_If0_Counter	= 0 +	let	save_line					= line(".") +	let	actual_line				= 0 +	" +	" search for the maximum option number (if any) +	" +	normal gg +	while actual_line < search( s:C_If0_Txt."\\d\\+" ) +		let actual_line	= line(".") +	 	let actual_opt  = matchstr( getline(actual_line), s:C_If0_Txt."\\d\\+" ) +		let actual_opt  = strpart( actual_opt, strlen(s:C_If0_Txt),strlen(actual_opt)-strlen(s:C_If0_Txt)) +		if s:C_If0_Counter < actual_opt +			let	s:C_If0_Counter = actual_opt +		endif +	endwhile +	let	s:C_If0_Counter = s:C_If0_Counter+1 +	silent exe ":".save_line +	" +	if a:mode=='a' +		let zz=    "\n#if  0     ".s:C_Com1." ----- #if 0 : ".s:C_If0_Txt.s:C_If0_Counter." ----- ".s:C_Com2."\n" +		let zz= zz."\n#endif     ".s:C_Com1." ----- #if 0 : ".s:C_If0_Txt.s:C_If0_Counter." ----- ".s:C_Com2."\n\n" +		put =zz +		if v:version >= 700 +			normal 4k +		endif +	endif + +	if a:mode=='v' +		let zz=    "\n#if  0     ".s:C_Com1." ----- #if 0 : ".s:C_If0_Txt.s:C_If0_Counter." ----- ".s:C_Com2."\n" +		:'<put! =zz +		let zz=      "#endif     ".s:C_Com1." ----- #if 0 : ".s:C_If0_Txt.s:C_If0_Counter." ----- ".s:C_Com2."\n\n" +		:'>put  =zz +		:normal '< +	endif + +endfunction    " ----------  end of function C_PPIf0 ---------- +" +"------------------------------------------------------------------------------ +"  C_PPIf0Remove : remove  #if 0 .. #endif        {{{1 +"------------------------------------------------------------------------------ +function! C_PPIf0Remove () + +	let frstline	= searchpair( '^\s*#if\s\+0', '', '^\s*#endif\>.\+\<If0Label_', 'bn' ) +  if frstline<=0 +		echohl WarningMsg | echo 'no  #if 0 ... #endif  found or cursor not inside such a directive'| echohl None +    return +  endif +	let lastline	= searchpair( '^\s*#if\s\+0', '', '^\s*#endif\>.\+\<If0Label_', 'n' ) +	if lastline<=0 +		echohl WarningMsg | echo 'no  #if 0 ... #endif  found or cursor not inside such a directive'| echohl None +		return +	endif +  let actualnumber1  = matchstr( getline(frstline), s:C_If0_Txt."\\d\\+" ) +  let actualnumber2  = matchstr( getline(lastline), s:C_If0_Txt."\\d\\+" ) +	if actualnumber1 != actualnumber2 +    echohl WarningMsg | echo 'lines '.frstline.', '.lastline.': comment tags do not match'| echohl None +		return +	endif + +  silent exe ':'.lastline.','.lastline.'d' +	silent exe ':'.frstline.','.frstline.'d' +	 +endfunction    " ----------  end of function C_PPIf0Remove ---------- +" +"------------------------------------------------------------------------------- +"   C_LegalizeName : replace non-word characters by underscores +"   - multiple whitespaces +"   - multiple non-word characters +"   - multiple underscores +"------------------------------------------------------------------------------- +function! C_LegalizeName ( name ) +	let identifier = substitute(     a:name, '\s\+',  '_', 'g' ) +	let identifier = substitute( identifier, '\W\+',  '_', 'g' )  +	let identifier = substitute( identifier, '_\+', '_', 'g' ) +	return identifier +endfunction    " ----------  end of function C_LegalizeName  ---------- + +"------------------------------------------------------------------------------ +"  C_CodeSnippet : read / edit code snippet       {{{1 +"------------------------------------------------------------------------------ +function! C_CodeSnippet(mode) + +	if isdirectory(s:C_CodeSnippets) +		" +		" read snippet file, put content below current line and indent +		"  +		if a:mode == "r" +			if has("gui_running") +				let	l:snippetfile=browse(0,"read a code snippet",s:C_CodeSnippets,"") +			else +				let	l:snippetfile=input("read snippet ", s:C_CodeSnippets, "file" ) +			end +			if filereadable(l:snippetfile) +				let	linesread= line("$") +				let l:old_cpoptions	= &cpoptions " Prevent the alternate buffer from being set to this files +				setlocal cpoptions-=a +				:execute "read ".l:snippetfile +				let &cpoptions	= l:old_cpoptions		" restore previous options +				let	linesread= line("$")-linesread-1 +				if linesread>=0 && match( l:snippetfile, '\.\(ni\|noindent\)$' ) < 0  +				endif +			endif +			if line(".")==2 && getline(1)=~"^$" +				silent exe ":1,1d" +			endif +		endif +		" +		" update current buffer / split window / edit snippet file +		"  +		if a:mode == "e" +			if has("gui_running") +				let	l:snippetfile	= browse(0,"edit a code snippet",s:C_CodeSnippets,"") +			else +				let	l:snippetfile=input("edit snippet ", s:C_CodeSnippets, "file" ) +			end +			if l:snippetfile != "" +				:execute "update! | split | edit ".l:snippetfile +			endif +		endif +		" +		" write whole buffer into snippet file  +		"  +		if a:mode == "w" || a:mode == "wv" +			if has("gui_running") +				let	l:snippetfile	= browse(0,"edit a code snippet",s:C_CodeSnippets,"") +			else +				let	l:snippetfile=input("edit snippet ", s:C_CodeSnippets, "file" ) +			end +			if l:snippetfile != "" +				if filereadable(l:snippetfile) +					if confirm("File ".l:snippetfile." exists ! Overwrite ? ", "&Cancel\n&No\n&Yes") != 3 +						return +					endif +				endif +				if a:mode == "w" +					:execute ":write! ".l:snippetfile +				else +					:execute ":*write! ".l:snippetfile +				end +			endif +		endif + +	else +		echo "code snippet directory ".s:C_CodeSnippets." does not exist (please create it)" +	endif +endfunction    " ----------  end of function C_CodeSnippets  ---------- +" +"------------------------------------------------------------------------------ +"  C_CodeFor : for (idiom)       {{{1 +"------------------------------------------------------------------------------ +function! C_CodeFor( direction, mode ) +	if a:direction=="up" +		let	string	= C_Input( " loop var. [ start [ end [ incr. ]]] : ", "" ) +	else +		let	string	= C_Input( " loop var. [ start [ end [ decr. ]]] : ", "" ) +	endif +	let	pos		= 0 +	let	jmp		= 0 +	if string != "" +		" +		" use internal formatting to avoid conficts when using == below +		let	equalprg_save	= &equalprg +		set equalprg=  +		" +		" loop variable +		let loopvar		= matchstr( string, '\S\+\s*', pos ) +		let pos				= pos + strlen(loopvar) +		let loopvar		= substitute( loopvar, '\s*$', "", "" ) +		"  +		" start value +		let startval	= matchstr( string, '\S\+\s*', pos ) +		let pos				= pos + strlen(startval) +		let startval	= substitute( startval, '\s*$', "", "" ) + +		" end value +		let endval	= matchstr( string, '\S\+\s*', pos ) +		let pos				= pos + strlen(endval) +		let endval	= substitute( endval, '\s*$', "", "" ) + +		" increment +		let incval	= matchstr( string, '\S\+\s*', pos ) +		let pos			= pos + strlen(incval) +		let incval	= substitute( incval, '\s*$', "", "" ) + +		if incval=="" +			let incval	= '1' +			let	jmp		= 10 +		endif + +		if a:direction=="up" +			if endval=="" +				let endval	= 'n' +				let	jmp		= 7 +			endif +			if startval=="" +				let startval	= '0' +				let	jmp		= 4 +			endif +			let zz= "for ( ".loopvar." = ".startval."; ".loopvar." < ".endval."; ".loopvar." += ".incval." )"  +		else +			if endval=="" +				let endval	= '0' +				let	jmp		= 7 +			endif +			if startval=="" +				let startval	= 'n-1' +				let	jmp		= 4 +			endif +			let zz= "for ( ".loopvar." = ".startval."; ".loopvar." >= ".endval."; ".loopvar." -= ".incval." )"  +		endif + +		" ----- normal mode ---------------- +		if a:mode=="a"  +			put =zz +			normal 2== +			if jmp!=0 +				exe "normal ".jmp."Wh" +			else +				exe 'normal $' +			endif +		endif + +		" ----- visual mode ---------------- +		if a:mode=="v"  +			let	zz	= zz." {" +			:'<put! =zz +			let zz=    "}" +			:'>put =zz +			:'<-1 +			:exe "normal =".(line("'>")-line(".")+3)."+" +		endif +		" +		" restore formatter programm +		let &equalprg	= equalprg_save +		" +	endif +endfunction    " ----------  end of function C_CodeFor ---------- +" +"------------------------------------------------------------------------------ +"  Handle prototypes       {{{1 +"------------------------------------------------------------------------------ +" +let s:C_Prototype        = [] +let s:C_PrototypeShow    = [] +let s:C_PrototypeCounter = 0 +let s:C_CComment         = '\/\*.\{-}\*\/\s*'		" C comment with trailing whitespaces +																								"  '.\{-}'  any character, non-greedy +let s:C_CppComment       = '\/\/.*$'						" C++ comment +" +"------------------------------------------------------------------------------ +"  C_ProtoPick : pick up (normal/visual)       {{{1 +"------------------------------------------------------------------------------ +function! C_ProtoPick (mode) +	if a:mode=="n" +		" --- normal mode ------------------- +		let	pos1	= line(".") +		let	pos2	= pos1 +	else +		" --- visual mode ------------------- +		let	pos1	= line("'<") +		let	pos2	= line("'>") +	endif +	" +	" remove C/C++-comments, leading and trailing whitespaces, squeeze whitespaces +	" +	let prototyp   = '' +	let	linenumber = pos1 +	while linenumber <= pos2 +		let newline			= getline(linenumber) +		let newline 	  = substitute( newline, s:C_CppComment, "", "" ) " remove C++ comment +		let prototyp		= prototyp." ".newline +		let linenumber	= linenumber+1 +	endwhile +	" +	let prototyp  = substitute( prototyp, '^\s\+', "", "" )					" remove leading whitespaces +	let prototyp  = substitute( prototyp, s:C_CComment, "", "g" )		" remove (multiline) C comments  +	let prototyp  = substitute( prototyp, '\s\+', " ", "g" )				" squeeze whitespaces +	let prototyp  = substitute( prototyp, '\s\+$', "", "" )					" remove trailing whitespaces +	" +	" remove template keyword +	" +	let prototyp  = substitute( prototyp, '^template\s*<\s*class \w\+\s*>\s*', "", "" ) +	" +	let parlist 	= stridx( prototyp, '(' )													" start of the parameter list +	let part1   	= strpart( prototyp, 0, parlist ) +	let part2   	= strpart( prototyp, parlist ) +	" +	" remove the scope res. operator +	" +	let part1		  = substitute( part1, '<\s*\w\+\s*>', "", "g" )	 +	let part1   	= substitute( part1, '\<std\s*::', 'std##', 'g' )	" remove the scope res. operator +	let part1   	= substitute( part1, '\<\h\w*\s*::', '', 'g' )		" remove the scope res. operator +	let part1   	= substitute( part1, '\<std##', 'std::', 'g' )		" remove the scope res. operator +	let	prototyp	= part1.part2 +	" +	" remove trailing parts of the function body; add semicolon +	" +	let prototyp	= substitute( prototyp, '\s*{.*$', "", "" )  +	let prototyp	= prototyp.";\n" +	" +	" bookkeeping +	" +	let s:C_PrototypeCounter += 1 +	let s:C_Prototype        += [prototyp] +	let s:C_PrototypeShow    += ["(".s:C_PrototypeCounter.") ".bufname("%")." #  ".prototyp] +	" +	echo	s:C_PrototypeCounter.' prototype(s)' +	" +endfunction    " ---------  end of function C_ProtoPick  ---------- +" +"------------------------------------------------------------------------------ +"  C_ProtoInsert : insert       {{{1 +"------------------------------------------------------------------------------ +function! C_ProtoInsert () +	" +	" use internal formatting to avoid conficts when using == below +	let	equalprg_save	= &equalprg +	set equalprg=  +	" +	if s:C_PrototypeCounter > 0 +		for protytype in s:C_Prototype +			put =protytype +		endfor +		let	lines	= s:C_PrototypeCounter	- 1 +		silent exe "normal =".lines."-" +		call C_ProtoClear() +	else +		echo "currently no prototypes available" +	endif +	" +	" restore formatter programm +	let &equalprg	= equalprg_save +	" +endfunction    " ---------  end of function C_ProtoInsert  ---------- +" +"------------------------------------------------------------------------------ +"  C_ProtoClear : clear       {{{1 +"------------------------------------------------------------------------------ +function! C_ProtoClear () +	if s:C_PrototypeCounter > 0 +		let s:C_Prototype        = [] +		let s:C_PrototypeShow    = [] +		let s:C_PrototypeCounter = 0 +		echo 'prototypes deleted' +	else +		echo "currently no prototypes available" +	endif +endfunction    " ---------  end of function C_ProtoClear  ---------- +" +"------------------------------------------------------------------------------ +"  C_ProtoShow : show       {{{1 +"------------------------------------------------------------------------------ +function! C_ProtoShow () +	if s:C_PrototypeCounter > 0 +		for protytype in s:C_PrototypeShow +			echo protytype +		endfor +	else +		echo "currently no prototypes available" +	endif +endfunction    " ---------  end of function C_ProtoShow  ---------- +" +"------------------------------------------------------------------------------ +"  C_EscapeBlanks : C_EscapeBlanks       {{{1 +"------------------------------------------------------------------------------ +function! C_EscapeBlanks (arg) +	return  substitute( a:arg, " ", "\\ ", "g" ) +endfunction    " ---------  end of function C_EscapeBlanks  ---------- +" +"------------------------------------------------------------------------------ +"  C_Compile : C_Compile       {{{1 +"------------------------------------------------------------------------------ +"  The standard make program 'make' called by vim is set to the C or C++ compiler +"  and reset after the compilation  (set makeprg=... ). +"  The errorfile created by the compiler will now be read by gvim and +"  the commands cl, cp, cn, ... can be used. +"------------------------------------------------------------------------------ +function! C_Compile () + +	let	l:currentbuffer	= bufname("%") +	let s:C_HlMessage = "" +	exe	":cclose" +	let	Sou		= expand("%:p")											" name of the file in the current buffer +	let	Obj		= expand("%:p:r").s:C_ObjExtension	" name of the object +	let SouEsc= escape( Sou, s:escfilename ) +	let ObjEsc= escape( Obj, s:escfilename ) + +	" update : write source file if necessary +	exe	":update" +	 +	" compilation if object does not exist or object exists and is older then the source	 +	if !filereadable(Obj) || (filereadable(Obj) && (getftime(Obj) < getftime(Sou))) +		" &makeprg can be a string containing blanks +		let makeprg_saved='"'.&makeprg.'"' +		if expand("%:e") == s:C_CExtension +			exe		"set makeprg=".s:C_CCompiler +		else +			exe		"set makeprg=".s:C_CplusCompiler +		endif +		"  +		" COMPILATION +		" +		if s:MSWIN +			exe		"make ".s:C_CFlags." \"".SouEsc."\" -o \"".ObjEsc."\"" +		else +			exe		"make ".s:C_CFlags." ".SouEsc." -o ".ObjEsc +		endif +		exe	"set makeprg=".makeprg_saved +		"  +		" open error window if necessary  +		exe	":botright cwindow" +	else +		let s:C_HlMessage = " '".Obj."' is up to date " +	endif +	 +endfunction    " ----------  end of function C_Compile ---------- +" +"------------------------------------------------------------------------------ +"  C_Link : C_Link       {{{1 +"------------------------------------------------------------------------------ +"  The standard make program which is used by gvim is set to the compiler +"  (for linking) and reset after linking. +" +"  calls: C_Compile +"------------------------------------------------------------------------------ +function! C_Link () + +	call	C_Compile() + +	let s:C_HlMessage = "" +	let	Sou		= expand("%:p")						       		" name of the file in the current buffer +	let	Obj		= expand("%:p:r").s:C_ObjExtension	" name of the object file +	let	Exe		= expand("%:p:r").s:C_ExeExtension	" name of the executable +	let ObjEsc= escape( Obj, s:escfilename ) +	let ExeEsc= escape( Exe, s:escfilename ) +	 +	" no linkage if: +	"   executable exists +	"   object exists +	"   source exists +	"   executable newer then object +	"   object newer then source + +	if    filereadable(Exe)                && +      \ filereadable(Obj)                && +      \ filereadable(Sou)                && +      \ (getftime(Exe) >= getftime(Obj)) && +      \ (getftime(Obj) >= getftime(Sou)) +		let s:C_HlMessage = " '".Exe."' is up to date " +		return +	endif +	 +	" linkage if: +	"   object exists +	"   source exists +	"   object newer then source + +	if filereadable(Obj) && (getftime(Obj) >= getftime(Sou)) +		let makeprg_saved='"'.&makeprg.'"' +		if expand("%:e") == s:C_CExtension +			exe		"set makeprg=".s:C_CCompiler +		else +			exe		"set makeprg=".s:C_CplusCompiler +		endif +		let v:statusmsg=""  +		if s:MSWIN +			silent exe "make ".s:C_LFlags." ".s:C_Libs." -o \"".ExeEsc."\" \"".ObjEsc."\"" +		else +			silent exe "make ".s:C_LFlags." ".s:C_Libs." -o ".ExeEsc." ".ObjEsc +		endif +		if v:statusmsg != "" +			let s:C_HlMessage = v:statusmsg  +		endif +		exe	"set makeprg=".makeprg_saved +	endif +endfunction    " ----------  end of function C_Link ---------- +" +"------------------------------------------------------------------------------ +"  C_Run : 	C_Run       {{{1 +"  calls: C_Link +"------------------------------------------------------------------------------ +" +let s:C_OutputBufferName   = "C-Output" +let s:C_OutputBufferNumber = -1 +" +function! C_Run () +" +	let Sou  		= expand("%:p")														" name of the source file +	let Obj  		= expand("%:p:r").s:C_ObjExtension				" name of the object file +	let Exe  		= expand("%:p:r").s:C_ExeExtension				" name of the executable +	let ExeEsc  = escape( Exe, s:escfilename )						" name of the executable, escaped +	" +	let l:arguments     = exists("b:C_CmdLineArgs") ? b:C_CmdLineArgs : '' +	" +	let	l:currentbuffer	= bufname("%") +	" +	"============================================================================== +	"  run : run from the vim command line +	"============================================================================== +	if s:C_OutputGvim == "vim" +		" +		silent call C_Link() +		" +		if	executable(Exe) && getftime(Exe) >= getftime(Obj) && getftime(Obj) >= getftime(Sou) +			if s:MSWIN +				exe		"!\"".ExeEsc."\" ".l:arguments +			else +				exe		"!".ExeEsc." ".l:arguments +			endif +		else +			echomsg "file ".Exe." does not exist / is not executable" +		endif +	 +	endif +	" +	"============================================================================== +	"  run : redirect output to an output buffer +	"============================================================================== +	if s:C_OutputGvim == "buffer" +		let	l:currentbuffernr	= bufnr("%") +		" +		silent call C_Link() +		" +		if l:currentbuffer ==  bufname("%") +			" +			" +			if bufloaded(s:C_OutputBufferName) != 0 && bufwinnr(s:C_OutputBufferNumber)!=-1  +				exe bufwinnr(s:C_OutputBufferNumber) . "wincmd w" +				" buffer number may have changed, e.g. after a 'save as'  +				if bufnr("%") != s:C_OutputBufferNumber +					let s:C_OutputBufferNumber	= bufnr(s:C_OutputBufferName) +					exe ":bn ".s:C_OutputBufferNumber +				endif +			else +				silent exe ":new ".s:C_OutputBufferName +				let s:C_OutputBufferNumber=bufnr("%") +				setlocal buftype=nofile +				setlocal noswapfile +				setlocal syntax=none +				setlocal bufhidden=delete +				setlocal tabstop=8 +			endif +			" +			" run programm  +			" +			setlocal	modifiable +			if	executable(Exe) && getftime(Exe) >= getftime(Obj) && getftime(Obj) >= getftime(Sou) +				if s:MSWIN +					exe		"%!\"".ExeEsc."\" ".l:arguments +				else +					exe		"%!".ExeEsc." ".l:arguments +				endif +			endif +			setlocal	nomodifiable +			" +			if winheight(winnr()) >= line("$") +				exe bufwinnr(l:currentbuffernr) . "wincmd w"  +			endif +			" +		endif +	endif +	" +	"============================================================================== +	"  run : run in a detached xterm  (not available for MS Windows) +	"============================================================================== +	if s:C_OutputGvim == "xterm" +		" +		silent call C_Link() +		" +		if	executable(Exe) && getftime(Exe) >= getftime(Obj) && getftime(Obj) >= getftime(Sou) +			if s:MSWIN +				exe		"!\"".ExeEsc."\" ".l:arguments +			else +				silent exe '!xterm -title '.ExeEsc.' '.s:C_XtermDefaults.' -e '.s:C_Wrapper.' '.ExeEsc.' '.l:arguments.' &' +				:redraw! +			endif +		endif +	endif + +endfunction    " ----------  end of function C_Run ---------- +" +"------------------------------------------------------------------------------ +"  C_Arguments : Arguments for the executable       {{{1 +"------------------------------------------------------------------------------ +function! C_Arguments () +	let	Exe		  = expand("%:r").s:C_ExeExtension +  if Exe == "" +		redraw +		echohl WarningMsg | echo " no file name " | echohl None +		return +  endif +	let	prompt	= 'command line arguments for "'.Exe.'" : ' +	if exists("b:C_CmdLineArgs") +		let	b:C_CmdLineArgs= C_Input( prompt, b:C_CmdLineArgs ) +	else +		let	b:C_CmdLineArgs= C_Input( prompt , "" ) +	endif +endfunction    " ----------  end of function C_Arguments ---------- +" +"---------------------------------------------------------------------- +"  C_Toggle_Gvim_Xterm : change output destination       {{{1 +"---------------------------------------------------------------------- +function! C_Toggle_Gvim_Xterm () + +	if s:C_OutputGvim == "vim" +		if has("gui_running") +			exe "aunmenu  <silent>  ".s:C_Root.'&Run.&output:\ VIM->buffer->xterm' +			exe "amenu    <silent>  ".s:C_Root.'&Run.&output:\ BUFFER->xterm->vim              <C-C>:call C_Toggle_Gvim_Xterm()<CR><CR>' +		endif +		let	s:C_OutputGvim	= "buffer" +	else +		if s:C_OutputGvim == "buffer" +			if has("gui_running") +				exe "aunmenu  <silent>  ".s:C_Root.'&Run.&output:\ BUFFER->xterm->vim' +				if (!s:MSWIN)  +					exe "amenu    <silent>  ".s:C_Root.'&Run.&output:\ XTERM->vim->buffer             <C-C>:call C_Toggle_Gvim_Xterm()<CR><CR>' +				else +					exe "amenu    <silent>  ".s:C_Root.'&Run.&output:\ VIM->buffer->xterm            <C-C>:call C_Toggle_Gvim_Xterm()<CR><CR>' +				endif +			endif +			if (!s:MSWIN) && (s:C_Display != '') +				let	s:C_OutputGvim	= "xterm" +			else +				let	s:C_OutputGvim	= "vim" +			end +		else +			" ---------- output : xterm -> gvim +			if has("gui_running") +				exe "aunmenu  <silent>  ".s:C_Root.'&Run.&output:\ XTERM->vim->buffer' +				exe "amenu    <silent>  ".s:C_Root.'&Run.&output:\ VIM->buffer->xterm            <C-C>:call C_Toggle_Gvim_Xterm()<CR><CR>' +			endif +			let	s:C_OutputGvim	= "vim" +		endif +	endif +	echomsg "output destination is '".s:C_OutputGvim."'" + +endfunction    " ----------  end of function C_Toggle_Gvim_Xterm ---------- +" +"------------------------------------------------------------------------------ +"  C_XtermSize : xterm geometry       {{{1 +"------------------------------------------------------------------------------ +function! C_XtermSize () +	let regex	= '-geometry\s\+\d\+x\d\+' +	let geom	= matchstr( s:C_XtermDefaults, regex ) +	let geom	= matchstr( geom, '\d\+x\d\+' ) +	let geom	= substitute( geom, 'x', ' ', "" ) +	let	answer= C_Input("   xterm size (COLUMNS LINES) : ", geom ) +	while match(answer, '^\s*\d\+\s\+\d\+\s*$' ) < 0 +		let	answer= C_Input(" + xterm size (COLUMNS LINES) : ", geom ) +	endwhile +	let answer  = substitute( answer, '\s\+', "x", "" )						" replace inner whitespaces +	let s:C_XtermDefaults	= substitute( s:C_XtermDefaults, regex, "-geometry ".answer , "" ) +endfunction    " ----------  end of function C_XtermSize ---------- +" +"------------------------------------------------------------------------------ +"  C_MakeArguments : run make(1)       {{{1 +"------------------------------------------------------------------------------ + +let s:C_MakeCmdLineArgs   = ""     " command line arguments for Run-make; initially empty + +function! C_MakeArguments () +	let	s:C_MakeCmdLineArgs= C_Input("make command line arguments : ",s:C_MakeCmdLineArgs) +endfunction    " ----------  end of function C_MakeArguments ---------- +" +function! C_Make() +	" update : write source file if necessary +	exe	":update" +	" run make +	exe		":!make ".s:C_MakeCmdLineArgs +endfunction    " ----------  end of function C_Make ---------- +" +"------------------------------------------------------------------------------ +"  C_SplintArguments : splint command line arguments       {{{1 +"------------------------------------------------------------------------------ +function! C_SplintArguments () +	if s:C_SplintIsExecutable==0 +		let s:C_HlMessage = ' Splint is not executable or not installed! ' +	else +		let	prompt	= 'Splint command line arguments for "'.expand("%").'" : ' +		if exists("b:C_SplintCmdLineArgs") +			let	b:C_SplintCmdLineArgs= C_Input( prompt, b:C_SplintCmdLineArgs ) +		else +			let	b:C_SplintCmdLineArgs= C_Input( prompt , "" ) +		endif +	endif +endfunction    " ----------  end of function C_SplintArguments ---------- +" +"------------------------------------------------------------------------------ +"  C_SplintCheck : run splint(1)        {{{1 +"------------------------------------------------------------------------------ +function! C_SplintCheck () +	if s:C_SplintIsExecutable==0 +		let s:C_HlMessage = ' Splint is not executable or not installed! ' +		return +	endif +	let	l:currentbuffer=bufname("%") +	if &filetype != "c" && &filetype != "cpp" +		let s:C_HlMessage = ' "'.l:currentbuffer.'" seems not to be a C/C++ file ' +		return +	endif +	let s:C_HlMessage = "" +	exe	":cclose"	 +	silent exe	":update" +	let makeprg_saved='"'.&makeprg.'"' +	" Windows seems to need this: +	if	s:MSWIN +		:compiler splint +	endif +	:set makeprg=splint +	"	 +	let l:arguments  = exists("b:C_SplintCmdLineArgs") ? b:C_SplintCmdLineArgs : ' ' +	silent exe	"make ".l:arguments." ".escape(l:currentbuffer,s:escfilename) +	exe	"set makeprg=".makeprg_saved +	exe	":botright cwindow" +	" +	" message in case of success +	" +	if l:currentbuffer == bufname("%") +		let s:C_HlMessage = " Splint --- no warnings for : ".l:currentbuffer +	endif +endfunction    " ----------  end of function C_SplintCheck ---------- +" +"------------------------------------------------------------------------------ +"  C_CodeCheckArguments : CodeCheck command line arguments       {{{1 +"------------------------------------------------------------------------------ +function! C_CodeCheckArguments () +	if s:C_CodeCheckIsExecutable==0 +		let s:C_HlMessage = ' CodeCheck is not executable or not installed! ' +	else +		let	prompt	= 'CodeCheck command line arguments for "'.expand("%").'" : ' +		if exists("b:C_CodeCheckCmdLineArgs") +			let	b:C_CodeCheckCmdLineArgs= C_Input( prompt, b:C_CodeCheckCmdLineArgs ) +		else +			let	b:C_CodeCheckCmdLineArgs= C_Input( prompt , s:C_CodeCheckOptions ) +		endif +	endif +endfunction    " ----------  end of function C_CodeCheckArguments ---------- +" +"------------------------------------------------------------------------------ +"  C_CodeCheck : run CodeCheck       {{{1 +"------------------------------------------------------------------------------ +function! C_CodeCheck () +	if s:C_CodeCheckIsExecutable==0 +		let s:C_HlMessage = ' CodeCheck is not executable or not installed! ' +		return +	endif +	let	l:currentbuffer=bufname("%") +	if &filetype != "c" && &filetype != "cpp" +		let s:C_HlMessage = ' "'.l:currentbuffer.'" seems not to be a C/C++ file ' +		return +	endif +	let s:C_HlMessage = "" +	exe	":cclose"	 +	silent exe	":update" +	let makeprg_saved='"'.&makeprg.'"' +	exe	"set makeprg=".s:C_CodeCheckExeName +	"  +	" match the splint error messages (quickfix commands) +	" ignore any lines that didn't match one of the patterns +	" +	:setlocal errorformat=%f(%l)%m +	"	 +	let l:arguments  = exists("b:C_CodeCheckCmdLineArgs") ? b:C_CodeCheckCmdLineArgs : "" +	if l:arguments == "" +		let l:arguments	=	s:C_CodeCheckOptions +	endif +	exe	":make ".l:arguments." ".escape( l:currentbuffer, s:escfilename ) +	exe	':setlocal errorformat=' +	exe	"set makeprg=".makeprg_saved +	exe	":botright cwindow" +	" +	" message in case of success +	" +	if l:currentbuffer == bufname("%") +		let s:C_HlMessage = " CodeCheck --- no warnings for : ".l:currentbuffer +	endif +endfunction    " ----------  end of function C_CodeCheck ---------- +" +"------------------------------------------------------------------------------ +"  C_Indent : run indent(1)       {{{1 +"------------------------------------------------------------------------------ +" +function! C_Indent ( mode ) +	if !executable("indent")  +		let s:C_HlMessage	= ' indent is not executable or not installed! ' +		return +	endif +	let	l:currentbuffer=bufname("%") +	if &filetype != "c" && &filetype != "cpp" +		let s:C_HlMessage = ' "'.l:currentbuffer.'" seems not to be a C/C++ file ' +		return +	endif +	let s:C_HlMessage    = "" + +	if a:mode=="a" +		if C_Input("indent whole file [y/n/Esc] : ", "y" ) != "y" +			return +		endif +		exe	":update" +		if has("MSWIN") +			silent exe ":%!indent" +		else +			silent exe ":%!indent 2> ".s:C_IndentErrorLog +		endif +		let s:C_HlMessage = ' File "'.l:currentbuffer.'" reformatted.' +	endif + +	if a:mode=="v" +		if has("MSWIN") +			silent exe ":'<,'>!indent" +		else +			silent exe ":'<,'>!indent 2> ".s:C_IndentErrorLog +		endif +		let s:C_HlMessage = ' File "'.l:currentbuffer.'" (lines '.line("'<").'-'.line("'>").') reformatted. ' +	endif + +	if v:shell_error != 0 +		let s:C_HlMessage = ' Indent reported an error when processing file "'.l:currentbuffer.'". ' +	endif + +endfunction    " ----------  end of function C_Indent ---------- +" +"------------------------------------------------------------------------------ +"  C_HlMessage : indent message     {{{1 +"------------------------------------------------------------------------------ +function! C_HlMessage () +	echohl Search  +	echo s:C_HlMessage +	echohl None +endfunction    " ----------  end of function C_HlMessage ---------- +" +"------------------------------------------------------------------------------ +"  C_Settings : settings     {{{1 +"------------------------------------------------------------------------------ +function! C_Settings () +	let	txt =     " C/C++-Support settings\n\n" +	let txt = txt.'                   author :  "'.s:C_Macro['|AUTHOR|']."\"\n" +	let txt = txt.'                 initials :  "'.s:C_Macro['|AUTHORREF|']."\"\n" +	let txt = txt.'                    email :  "'.s:C_Macro['|EMAIL|']."\"\n" +	let txt = txt.'                  company :  "'.s:C_Macro['|COMPANY|']."\"\n" +	let txt = txt.'                  project :  "'.s:C_Macro['|PROJECT|']."\"\n" +	let txt = txt.'         copyright holder :  "'.s:C_Macro['|COPYRIGHTHOLDER|']."\"\n" +	let txt = txt.'         C / C++ compiler :  '.s:C_CCompiler.' / '.s:C_CplusCompiler."\n" +	let txt = txt.'         C file extension :  "'.s:C_CExtension.'"  (everything else is C++)'."\n" +	let txt = txt.'    extension for objects :  "'.s:C_ObjExtension."\"\n" +	let txt = txt.'extension for executables :  "'.s:C_ExeExtension."\"\n" +	let txt = txt.'           compiler flags :  "'.s:C_CFlags."\"\n" +	let txt = txt.'             linker flags :  "'.s:C_LFlags."\"\n" +	let txt = txt.'                libraries :  "'.s:C_Libs."\"\n" +	let txt = txt.'   code snippet directory :  '.s:C_CodeSnippets."\n" +	if s:installation == 'system' +		let txt = txt.'global template directory :  '.s:C_GlobalTemplateDir."\n" +		if filereadable( s:C_LocalTemplateFile ) +			let txt = txt.' local template directory :  '.s:C_LocalTemplateDir."\n" +		endif +	else +		let txt = txt.' local template directory :  '.s:C_GlobalTemplateDir."\n" +	endif +	if	!s:MSWIN +		let txt = txt.'           xterm defaults :  '.s:C_XtermDefaults."\n" +	endif +	" ----- dictionaries ------------------------ +	if g:C_Dictionary_File != "" +		let ausgabe= substitute( g:C_Dictionary_File, ",", ",\n                           + ", "g" ) +		let txt = txt."       dictionary file(s) :  ".ausgabe."\n" +	endif +	let txt = txt.'     current output dest. :  '.s:C_OutputGvim."\n" +	" ----- splint ------------------------------ +	if s:C_SplintIsExecutable==1 +		if exists("b:C_SplintCmdLineArgs") +			let ausgabe = b:C_SplintCmdLineArgs +		else +			let ausgabe = "" +		endif +		let txt = txt."        splint options(s) :  ".ausgabe."\n" +	endif +	" ----- code check -------------------------- +	if s:C_CodeCheckIsExecutable==1 +		if exists("b:C_CodeCheckCmdLineArgs") +			let ausgabe = b:C_CodeCheckCmdLineArgs +		else +			let ausgabe = s:C_CodeCheckOptions +		endif +		let txt = txt."CodeCheck (TM) options(s) :  ".ausgabe."\n" +	endif +	let txt = txt."\n" +	let	txt = txt."__________________________________________________________________________\n" +	let	txt = txt." C/C++-Support, Version ".g:C_Version." / Dr.-Ing. Fritz Mehner / mehner@fh-swf.de\n\n" +	echo txt +endfunction    " ----------  end of function C_Settings ---------- +" +"------------------------------------------------------------------------------ +"  C_Hardcopy : hardcopy     {{{1 +"    MSWIN : a printer dialog is displayed +"    other : print PostScript to file +"------------------------------------------------------------------------------ +function! C_Hardcopy (arg1) +	let Sou	= expand("%")	 +  if Sou == "" +		redraw +		echohl WarningMsg | echo " no file name " | echohl None +		return +  endif +	let	Sou		= escape(Sou,s:escfilename)		" name of the file in the current buffer +	let	old_printheader=&printheader +	exe  ':set printheader='.s:C_Printheader +	" ----- normal mode ---------------- +	if a:arg1=="n" +		silent exe	"hardcopy > ".Sou.".ps"		 +		if	!s:MSWIN +			echo "file \"".Sou."\" printed to \"".Sou.".ps\"" +		endif +	endif +	" ----- visual mode ---------------- +	if a:arg1=="v" +		silent exe	"*hardcopy > ".Sou.".ps"		 +		if	!s:MSWIN +			echo "file \"".Sou."\" (lines ".line("'<")."-".line("'>").") printed to \"".Sou.".ps\"" +		endif +	endif +	exe  ':set printheader='.escape( old_printheader, ' %' ) +endfunction    " ----------  end of function C_Hardcopy ---------- +" +"------------------------------------------------------------------------------ +"  C_HelpCsupport : help csupport     {{{1 +"------------------------------------------------------------------------------ +function! C_HelpCsupport () +	try +		:help csupport +	catch +		exe ':helptags '.s:plugin_dir.'doc' +		:help csupport +	endtry +endfunction    " ----------  end of function C_HelpCsupport ---------- + +"------------------------------------------------------------------------------ +"  C_CreateGuiMenus     {{{1 +"------------------------------------------------------------------------------ +let s:C_MenuVisible = 0								" state variable controlling the C-menus +" +function! C_CreateGuiMenus () +	if s:C_MenuVisible != 1 +		aunmenu <silent> &Tools.Load\ C\ Support +		amenu   <silent> 40.1000 &Tools.-SEP100- :  +		amenu   <silent> 40.1030 &Tools.Unload\ C\ Support <C-C>:call C_RemoveGuiMenus()<CR> +		call C_InitMenus() +		let s:C_MenuVisible = 1 +	endif +endfunction    " ----------  end of function C_CreateGuiMenus  ---------- + +"------------------------------------------------------------------------------ +"  C_ToolMenu     {{{1 +"------------------------------------------------------------------------------ +function! C_ToolMenu () +	amenu   <silent> 40.1000 &Tools.-SEP100- :  +	amenu   <silent> 40.1030 &Tools.Load\ C\ Support <C-C>:call C_CreateGuiMenus()<CR> +endfunction    " ----------  end of function C_ToolMenu  ---------- + +"------------------------------------------------------------------------------ +"  C_RemoveGuiMenus     {{{1 +"------------------------------------------------------------------------------ +function! C_RemoveGuiMenus () +	if s:C_MenuVisible == 1 +		if s:C_Root == "" +			aunmenu <silent> Comments +			aunmenu <silent> Statements +			aunmenu <silent> Preprocessor +			aunmenu <silent> Idioms +			aunmenu <silent> Snippets +			aunmenu <silent> C++ +			aunmenu <silent> Run +		else +			exe "aunmenu <silent> ".s:C_Root +		endif +		" +		aunmenu <silent> &Tools.Unload\ C\ Support +		call C_ToolMenu() +		" +		let s:C_MenuVisible = 0 +	endif +endfunction    " ----------  end of function C_RemoveGuiMenus  ---------- + +"------------------------------------------------------------------------------ +"  C_RebuildTemplates +"  rebuild commands and the menu from the (changed) template file +"------------------------------------------------------------------------------ +function! C_RebuildTemplates () +    let s:C_Template     = {} +    let s:C_FileVisited  = [] +    call C_ReadTemplates(s:C_GlobalTemplateFile) +    echomsg "templates rebuilt from '".s:C_GlobalTemplateFile."'" +		" +		if s:installation == 'system' && filereadable( s:C_LocalTemplateFile ) +			call C_ReadTemplates( s:C_LocalTemplateFile )  +			echomsg " and from '".s:C_LocalTemplateFile."'" +		endif +endfunction    " ----------  end of function C_RebuildTemplates  ---------- + +"------------------------------------------------------------------------------ +"  C_ReadTemplates +"  read the template file(s), build the macro and the template dictionary +" +"------------------------------------------------------------------------------ +function! C_ReadTemplates ( templatefile ) + +  if !filereadable( a:templatefile ) +    echohl WarningMsg +    echomsg "C/C++ template file '".a:templatefile."' does not exist or is not readable" +    echohl None +    return +  endif + +	let	skipmacros	= 0 +  let s:C_FileVisited  += [a:templatefile] + +  "------------------------------------------------------------------------------ +  "  read template file, start with an empty template dictionary +  "------------------------------------------------------------------------------ + +  let item  = '' +  for line in readfile( a:templatefile ) +		" if not a comment : +    if line !~ '^\$' +      " +      " macros and file includes +      " + +      let string  = matchlist( line, s:C_MacroLineRegex ) +      if !empty(string) && skipmacros == 0 +        let key = '|'.string[1].'|' +        let val = string[2] +        let val = substitute( val, '\s\+$', '', '' ) +        let val = substitute( val, "[\"\']$", '', '' ) +        let val = substitute( val, "^[\"\']", '', '' ) +        " +        if key == '|includefile|' && count( s:C_FileVisited, val ) == 0 +					let path   = fnamemodify( a:templatefile, ":p:h" ) +          call C_ReadTemplates( path.'/'.val )    " recursive call +        else +          let s:C_Macro[key] = val +        endif +        continue                                            " next line +      endif +      " +      " template header +      " +      let name  = matchstr( line, s:C_TemplateLineRegex ) +      " +      if name != '' +        let part  = split( name, '\s*==\s*') +        let item  = part[0] +        if has_key( s:C_Template, item ) && s:C_TemplateOverwrittenMsg == 'yes' +          echomsg "existing C/C++ template '".item."' overwritten" +        endif +        let s:C_Template[item] = '' +				let skipmacros	= 1 +        " +        let s:C_Attribute[item] = 'below' +        if has_key( s:Attribute, get( part, 1, 'NONE' ) ) +          let s:C_Attribute[item] = part[1] +        endif +      else +        if item != '' +          let s:C_Template[item] = s:C_Template[item].line."\n" +        endif +      endif +    endif +  endfor + +	call C_SetSmallCommentStyle() +endfunction    " ----------  end of function C_ReadTemplates  ---------- + +"------------------------------------------------------------------------------ +"  C_InsertTemplate +"  insert a template from the template dictionary +"  do macro expansion +"------------------------------------------------------------------------------ +function! C_InsertTemplate ( key, ... ) + +	if !has_key( s:C_Template, a:key ) +		echomsg "Template '".a:key."' not found. Please check your template file in '".s:C_GlobalTemplateDir."'" +		return +	endif + +  "------------------------------------------------------------------------------ +  "  insert the user macros +  "------------------------------------------------------------------------------ + +	" use internal formatting to avoid conficts when using == below +	" +	let	equalprg_save	= &equalprg +	set equalprg=  + +  let mode  = s:C_Attribute[a:key] + +	" remove <SPLIT> and insert the complete macro +	" +	if a:0 == 0 +		let val = C_ExpandUserMacros (a:key) +		if val	== "" +			return +		endif +		let val	= C_ExpandSingleMacro( val, '<SPLIT>', '' ) + +		if mode == 'below' +			let pos1  = line(".")+1 +			put  =val +			let pos2  = line(".") +			" proper indenting  +			exe ":".pos1 +			let ins	= pos2-pos1+1 +			exe "normal ".ins."==" +		endif + +		if mode == 'above' +			let pos1  = line(".") +			put! =val +			let pos2  = line(".") +			" proper indenting  +			exe ":".pos1 +			let ins	= pos2-pos1+1 +			exe "normal ".ins."==" +		endif + +		if mode == 'start' +			normal gg +			let pos1  = 1 +			put! =val +			let pos2  = line(".") +			" proper indenting  +			exe ":".pos1 +			let ins	= pos2-pos1+1 +			exe "normal ".ins."==" +		endif + +		if mode == 'append' +			let pos1  = line(".") +			put =val +			let pos2  = line(".")-1 +			exe ":".pos1 +			:join! +		endif + +		if mode == 'insert' +			let val   = substitute( val, '\n$', '', '' ) +			let pos1  = line(".") +			let pos2  = pos1 + count( split(val,'\zs'), "\n" )  +			exe "normal a".val +		endif +		" +	else +		" +		" =====  visual mode  =============================== +		" +		if  a:1 == 'v' +			let val = C_ExpandUserMacros (a:key) +			if val	== "" +				return +			endif + +			let part	= split( val, '<SPLIT>' ) +			if len(part) < 2 +				let part	= [ "" ] + part +				echomsg 'SPLIT missing in template '.a:key +			endif + +			if mode == 'below' + +				:'<put! =part[0] +				:'>put  =part[1] + +				let pos1  = line("'<") - len(split(part[0], '\n' )) +				let pos2  = line("'>") + len(split(part[1], '\n' )) +				""			echo part[0] part[1] pos1 pos2 +				"			" proper indenting  +				exe ":".pos1 +				let ins	= pos2-pos1+1 +				exe "normal ".ins."==" +			endif + +			" +		endif +	endif + +	" restore formatter programm +	let &equalprg	= equalprg_save + +  "------------------------------------------------------------------------------ +  "  position the cursor +  "------------------------------------------------------------------------------ +  exe ":".pos1 +  let mtch = search( '<CURSOR>', "c", pos2 ) +  if mtch != 0 +    if  matchend( getline(mtch) ,'<CURSOR>') == match( getline(mtch) ,"$" ) +      normal 8x +      :startinsert! +    else +      normal 8x +      :startinsert +    endif +	else +		" to the end of the block; needed for repeated inserts +		if mode == 'below' +			exe ":".pos2 +		endif +  endif + +endfunction    " ----------  end of function C_InsertTemplate  ---------- + +"------------------------------------------------------------------------------ +"  C_ExpandUserMacros +"------------------------------------------------------------------------------ +function! C_ExpandUserMacros ( key ) + +  let template 								= s:C_Template[ a:key ] +	let	s:C_ExpansionCounter		= {}										" reset the expansion counter + +  "------------------------------------------------------------------------------ +  "  renew the predefined macros and expand them +	"  can be replaced, with e.g. |?DATE| +  "------------------------------------------------------------------------------ +	let	s:C_Macro['|BASENAME|']	= toupper(expand("%:t:r")) +  let s:C_Macro['|DATE|']  		= C_InsertDateAndTime('d') +  let s:C_Macro['|FILENAME|'] = expand("%:t") +  let s:C_Macro['|PATH|']  		= expand("%:p:h") +  let s:C_Macro['|SUFFIX|'] 	= expand("%:e") +  let s:C_Macro['|TIME|']  		= C_InsertDateAndTime('t') +  let s:C_Macro['|YEAR|']  		= C_InsertDateAndTime('y') + +  "------------------------------------------------------------------------------ +  "  look for replacements +  "------------------------------------------------------------------------------ +	while match( template, s:C_ExpansionRegex ) != -1 +		let macro				= matchstr( template, s:C_ExpansionRegex ) +		let replacement	= substitute( macro, '?', '', '' ) +		let template		= substitute( template, macro, replacement, "g" ) + +		let match	= matchlist( macro, s:C_ExpansionRegex ) + +		if match[1] != '' +			let macroname	= '|'.match[1].'|' +			" +			" notify flag action, if any +			let flagaction	= '' +			if has_key( s:C_MacroFlag, match[2] ) +				let flagaction	= ' (-> '.s:C_MacroFlag[ match[2] ].')' +			endif +			" +			" ask for a replacement +			if has_key( s:C_Macro, macroname ) +				let	name	= C_Input( match[1].flagaction.' : ', C_ApplyFlag( s:C_Macro[macroname], match[2] ) ) +			else +				let	name	= C_Input( match[1].flagaction.' : ', '' ) +			endif +			if name == "" +				return "" +			endif +			" +			" keep the modified name +			let s:C_Macro[macroname]  			= C_ApplyFlag( name, match[2] ) +		endif +	endwhile + +  "------------------------------------------------------------------------------ +  "  do the actual macro expansion +	"  loop over the macros found in the template +  "------------------------------------------------------------------------------ +	while match( template, s:C_NonExpansionRegex ) != -1 + +		let macro			= matchstr( template, s:C_NonExpansionRegex ) +		let match			= matchlist( macro, s:C_NonExpansionRegex ) + +		if match[1] != '' +			let macroname	= '|'.match[1].'|' + +			if has_key( s:C_Macro, macroname )  +				"------------------------------------------------------------------------------- +				"   check for recursion +				"------------------------------------------------------------------------------- +				if has_key( s:C_ExpansionCounter, macroname ) +					let	s:C_ExpansionCounter[macroname]	+= 1 +				else +					let	s:C_ExpansionCounter[macroname]	= 0 +				endif +				if s:C_ExpansionCounter[macroname]	>= s:C_ExpansionLimit +					echomsg " recursion terminated for recursive macro ".macroname +					return template +				endif +				"------------------------------------------------------------------------------- +				"   replace +				"------------------------------------------------------------------------------- +				let replacement = C_ApplyFlag( s:C_Macro[macroname], match[2] ) +				let template 		= substitute( template, macro, replacement, "g" ) +			else +				" +				" macro not yet defined +				let s:C_Macro['|'.match[1].'|']  		= '' +			endif +		endif + +	endwhile + +  return template +endfunction    " ----------  end of function C_ExpandUserMacros  ---------- + +"------------------------------------------------------------------------------ +"  C_ApplyFlag +"------------------------------------------------------------------------------ +function! C_ApplyFlag ( val, flag ) +	" +	" l : lowercase +	if a:flag == ':l' +		return  tolower(a:val) +	end +	" +	" u : uppercase +	if a:flag == ':u' +		return  toupper(a:val) +	end +	" +	" c : capitalize +	if a:flag == ':c' +		return  toupper(a:val[0]).a:val[1:] +	end +	" +	" L : legalized name +	if a:flag == ':L' +		return  C_LegalizeName(a:val) +	end +	" +	" flag not valid +	return a:val			 +endfunction    " ----------  end of function C_ApplyFlag  ---------- +" +"------------------------------------------------------------------------------ +"  C_ExpandSingleMacro +"------------------------------------------------------------------------------ +function! C_ExpandSingleMacro ( val, macroname, replacement ) +  return substitute( a:val, escape(a:macroname, '$' ), a:replacement, "g" ) +endfunction    " ----------  end of function C_ExpandSingleMacro  ---------- + +"------------------------------------------------------------------------------ +"  C_SetSmallCommentStyle +"------------------------------------------------------------------------------ +function! C_SetSmallCommentStyle () +	if has_key( s:C_Template, 'comment.end-of-line-comment' )  +		if match( s:C_Template['comment.end-of-line-comment'], '^\s*/\*' ) != -1 +			let s:C_Com1          = '/*'     " C-style : comment start  +			let s:C_Com2          = '*/'     " C-style : comment end +		else +			let s:C_Com1          = '//'     " C++style : comment start  +			let s:C_Com2          = ''       " C++style : comment end +		endif +	endif +endfunction    " ----------  end of function C_SetSmallCommentStyle  ---------- + +"------------------------------------------------------------------------------ +"  C_InsertMacroValue +"------------------------------------------------------------------------------ +function! C_InsertMacroValue ( key ) +	if col(".") > 1 +		exe 'normal a'.s:C_Macro['|'.a:key.'|'] +	else +		exe 'normal i'.s:C_Macro['|'.a:key.'|'] +	end +endfunction    " ----------  end of function C_InsertMacroValue  ---------- + +"------------------------------------------------------------------------------ +"  date and time +"------------------------------------------------------------------------------ +function! C_InsertDateAndTime ( format ) +	if a:format == 'd' +		return strftime( s:C_FormatDate ) +	end +	if a:format == 't' +		return strftime( s:C_FormatTime ) +	end +	if a:format == 'dt' +		return strftime( s:C_FormatDate ).' '.strftime( s:C_FormatTime ) +	end +	if a:format == 'y' +		return strftime( s:C_FormatYear ) +	end +endfunction    " ----------  end of function C_InsertDateAndTime  ---------- + +"------------------------------------------------------------------------------ +"  show / hide the c-support menus +"  define key mappings (gVim only)  +"------------------------------------------------------------------------------ +" +if has("gui_running") +	" +	call C_ToolMenu() +	" +	if s:C_LoadMenus == 'yes' +		call C_CreateGuiMenus() +	endif +	" +	nmap  <unique>  <silent>  <Leader>lcs   :call C_CreateGuiMenus()<CR> +	nmap  <unique>  <silent>  <Leader>ucs   :call C_RemoveGuiMenus()<CR> +	" +endif + +"------------------------------------------------------------------------------ +"  Automated header insertion +"  Local settings for the quickfix window +"------------------------------------------------------------------------------ +if has("autocmd") +	" +	"  Automated header insertion (suffixes from the gcc manual) +	" +	autocmd BufNewFile  * if (&filetype=='cpp' || &filetype=='c') |  +				\     call C_InsertTemplate("comment.file-description") | endif +	" +	"  *.h has filetype 'cpp' by default; this can be changed to 'c' : +	" +	if s:C_TypeOfH=='c'  +		autocmd BufNewFile,BufEnter  *.h  :set filetype=c +	endif +	" +	" C/C++ source code files which should not be preprocessed. +	" +	autocmd BufNewFile,BufRead  *.i  :set filetype=c +	autocmd BufNewFile,BufRead  *.ii :set filetype=cpp +	" +	" Wrap error descriptions in the quickfix window. +	" +	autocmd BufReadPost quickfix  setlocal wrap | setlocal linebreak  +	" +endif " has("autocmd") +" +"------------------------------------------------------------------------------ +"  READ THE TEMPLATE FILES +"------------------------------------------------------------------------------ +call C_ReadTemplates(s:C_GlobalTemplateFile) +if s:installation == 'system' && filereadable( s:C_LocalTemplateFile ) +	call C_ReadTemplates( s:C_LocalTemplateFile )  +endif + +" +"===================================================================================== +" vim: tabstop=2 shiftwidth=2 foldmethod=marker  diff --git a/.vim/plugin/filebrowser.vim b/.vim/plugin/filebrowser.vim new file mode 100644 index 0000000..e9de049 --- /dev/null +++ b/.vim/plugin/filebrowser.vim @@ -0,0 +1,251 @@ +" filebrowser.vim: utility file for vim 6.2+ +" +" Copyright: Srinath Avadhanula <srinath AT fastmail DOT fm> +" 	Parts of this file are taken from explorer.vim which is a plugin file +" 	distributed with vim under the Vim charityware license. +" License: distributed under the Vim charityware license. +" +" Settings: +" FB_CallBackFunction: the function name which gets called when the user +" 		presses <cr> on a file-name in the file browser. +" FB_AllowRegexp: A filename has to match this regexp to be displayed. +" FB_RejectRegexp: If a filename matches this regexp, then its not displayed. +" 		(Both these regexps are '' by default which means no filtering is +" 		done). + +" line continuation used here. +let s:save_cpo = &cpo +set cpo&vim + +"====================================================================== +" Globally visible functions (API) +"====================================================================== +" FB_OpenFileBrowser: opens a new buffer and displays the file list {{{ +" Description:  +function! FB_OpenFileBrowser(dir) +	if !isdirectory(a:dir) +		return +	endif +	if exists('s:FB_BufferNumber') +		if bufwinnr(s:FB_BufferNumber) != -1 +			execute bufwinnr(s:FB_BufferNumber).' wincmd w' +			return +		endif +		execute 'aboveleft split #'.s:FB_BufferNumber +	else +		aboveleft split __Choose_File__ +		let s:FB_BufferNumber = bufnr('%') +	endif +	call FB_DisplayFiles(a:dir) +endfunction " }}} +" FB_DisplayFiles: displays the files in a given directory {{{ +" Description:  +" 	Call this function only when the cursor is in a temporary buffer +function! FB_DisplayFiles(dir) +	if !isdirectory(a:dir) +		return +	endif +	call s:FB_SetSilentSettings() +	" make this a "scratch" buffer +	call s:FB_SetScratchSettings() + +	let allowRegexp = s:FB_GetVar('FB_AllowRegexp', '') +	let rejectRegexp = s:FB_GetVar('FB_RejectRegexp', '') + +	" change to the directory to make processing simpler. +	execute "lcd ".a:dir +	" delete everything in the buffer. +	" IMPORTANT: we need to be in a scratch buffer +	0,$ d_ + +	let allFilenames = glob('*') +	let dispFiles = "" +	let subDirs = "../\n" + +	let i = 1 +	while 1 +		let filename = s:FB_Strntok(allFilenames, "\n", i) +		if filename == '' +			break +		endif +		if isdirectory(filename) +			let subDirs = subDirs.filename."/\n" +		else +			if allowRegexp != '' && filename !~ allowRegexp +			elseif rejectRegexp != '' && filename =~ rejectRegexp +			else +				let dispFiles = dispFiles.filename."\n" +			endif +		endif +		let i = i + 1 +	endwhile +	0put!=dispFiles +	0put!=subDirs +	" delte the last empty line resulting from the put +	$ d_ + +	call s:FB_SetHighlighting() +	call s:FB_DisplayHelp() +	call s:FB_SetMaps() + +	" goto the first file/directory +	0 +	call search('^"=', 'w') +	normal! j:<bs> + +	set nomodified nomodifiable + +	call s:FB_ResetSilentSettings() +endfunction " }}} +" FB_SetVar: sets script local variables from outside this script {{{ +" Description:  +function! FB_SetVar(varname, value) +	let s:{a:varname} = a:value +endfunction " }}} + +" FB_SetHighlighting: sets syntax highlighting for the buffer {{{ +" Description: +" Origin: from explorer.vim in vim +function! <SID>FB_SetHighlighting() +	" Set up syntax highlighting +	" Something wrong with the evaluation of the conditional though... +	if has("syntax") && exists("g:syntax_on") && !has("syntax_items") +		syn match browseSynopsis    "^\"[ -].*" +		syn match browseDirectory   "[^\"].*/ " +		syn match browseDirectory   "[^\"].*/$" +		syn match browseCurDir      "^\"= .*$" +		syn match browseSortBy      "^\" Sorted by .*$"  contains=browseSuffixInfo +		syn match browseSuffixInfo  "(.*)$"  contained +		syn match browseFilter      "^\" Not Showing:.*$" +		syn match browseFiletime    "«\d\+$" + +		"hi def link browseSynopsis    PreProc +		hi def link browseSynopsis    Special +		hi def link browseDirectory   Directory +		hi def link browseCurDir      Statement +		hi def link browseSortBy      String +		hi def link browseSuffixInfo  Type +		hi def link browseFilter      String +		hi def link browseFiletime    Ignore +		hi def link browseSuffixes    Type +	endif +endfunction " }}} +" FB_SetMaps: sets buffer local maps {{{ +" Description:  +function! <SID>FB_SetMaps() +	nnoremap <buffer> <silent> q :bdelete<cr> +	nnoremap <buffer> <silent> C :call FB_DisplayFiles(getcwd())<CR> +	nnoremap <buffer> <silent> <esc> :bdelete<cr> +	nnoremap <buffer> <silent> <CR> :call <SID>FB_EditEntry()<CR> +	nnoremap <buffer> <silent> ? :call <SID>FB_ToggleHelp()<CR> + +	" lock the user in this window +	nnoremap <buffer> <C-w> <nop> +endfunction " }}} +" FB_SetSilentSettings: some settings which make things silent {{{ +" Description:  +" Origin: from explorer.vim distributed with vim. +function! <SID>FB_SetSilentSettings() +	let s:save_report=&report +	let s:save_showcmd = &sc +	set report=10000 noshowcmd +endfunction  +" FB_ResetSilentSettings: reset settings set by FB_SetSilentSettings +" Description:  +function! <SID>FB_ResetSilentSettings() +	let &report=s:save_report +	let &showcmd = s:save_showcmd +endfunction " }}} +" FB_SetScratchSettings: makes the present buffer a scratch buffer {{{ +" Description:  +function! <SID>FB_SetScratchSettings() +	" Turn off the swapfile, set the buffer type so that it won't get +	" written, and so that it will get deleted when it gets hidden. +	setlocal noreadonly modifiable +	setlocal noswapfile +	setlocal buftype=nowrite +	setlocal bufhidden=delete +	" Don't wrap around long lines +	setlocal nowrap +endfunction  + +" }}} +" FB_ToggleHelp: toggles verbosity of help {{{ +" Description:  +function! <SID>FB_ToggleHelp() +	let s:FB_VerboseHelp = 1 - s:FB_GetVar('FB_VerboseHelp', 0) + +	call FB_DisplayFiles('.') +endfunction " }}} +" FB_DisplayHelp: displays a helpful header {{{ +" Description:  +function! <SID>FB_DisplayHelp() +	let verboseHelp = s:FB_GetVar('FB_VerboseHelp', 0) +	if verboseHelp +		let txt =  +			\  "\" <cr>: on file, choose the file and quit\n" +			\ ."\"       on dir, enter directory\n" +			\ ."\" q/<esc>: quit without choosing\n" +			\ ."\" C: change directory to getcwd()\n" +			\ ."\" ?: toggle help verbosity\n" +			\ ."\"= ".getcwd() +	else +		let txt = "\" ?: toggle help verbosity\n" +			\ ."\"= ".getcwd() +	endif +	0put!=txt +endfunction " }}} + +" Handles various actions in the file-browser +" FB_EditEntry: handles the user pressing <enter> on a line {{{ +" Description:  +function! <SID>FB_EditEntry() +	let line = getline('.') + +	if isdirectory(line) +		call FB_DisplayFiles(line) +	endif + +	" If the user has a call back function defined on choosing a file, handle +	" it. +	let cbf = s:FB_GetVar('FB_CallBackFunction', '') +	if cbf != '' && line !~ '^" ' && filereadable(line)  +		let fname = fnamemodify(line, ':p') +		bdelete + +		let arguments = s:FB_GetVar('FB_CallBackFunctionArgs', '') +		if arguments != '' +			let arguments = ','.arguments +		endif +		call Tex_Debug('arguments = '.arguments, 'fb') +		call Tex_Debug("call ".cbf."('".fname."'".arguments.')', 'fb') +		exec "call ".cbf."('".fname."'".arguments.')' +	endif +endfunction " }}} + +"  FB_Strntok (string, tok, n) {{{ +" extract the n^th token from s seperated by tok. +" example: FB_Strntok('1,23,3', ',', 2) = 23 +fun! <SID>FB_Strntok(s, tok, n) +	return matchstr( a:s.a:tok[0], '\v(\zs([^'.a:tok.']*)\ze['.a:tok.']){'.a:n.'}') +endfun " }}} +" FB_GetVar: gets the most local value of a variable {{{ +function! <SID>FB_GetVar(name, default) +	if exists('s:'.a:name) +		return s:{a:name} +	elseif exists('w:'.a:name) +		return w:{a:name} +	elseif exists('b:'.a:name) +		return b:{a:name} +	elseif exists('g:'.a:name) +		return g:{a:name} +	else +		return a:default +	endif +endfunction + +" }}} + +let &cpo = s:save_cpo + +" vim:fdm=marker:ff=unix:noet:ts=4:sw=4:nowrap diff --git a/.vim/plugin/imaps.vim b/.vim/plugin/imaps.vim new file mode 100644 index 0000000..d871aa1 --- /dev/null +++ b/.vim/plugin/imaps.vim @@ -0,0 +1,831 @@ +"        File: imaps.vim +"     Authors: Srinath Avadhanula <srinath AT fastmail.fm> +"              Benji Fisher <benji AT member.AMS.org> +"               +"         WWW: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/vim-latex/vimfiles/plugin/imaps.vim?only_with_tag=MAIN +" +" Description: insert mode template expander with cursor placement +"              while preserving filetype indentation. +" +"     $Id: imaps.vim 997 2006-03-20 09:45:45Z srinathava $ +" +" Documentation: {{{ +" +" Motivation: +" this script provides a way to generate insert mode mappings which do not +" suffer from some of the problem of mappings and abbreviations while allowing +" cursor placement after the expansion. It can alternatively be thought of as +" a template expander.  +" +" Consider an example. If you do +" +" imap lhs something +" +" then a mapping is set up. However, there will be the following problems: +" 1. the 'ttimeout' option will generally limit how easily you can type the +"    lhs. if you type the left hand side too slowly, then the mapping will not +"    be activated. +" 2. if you mistype one of the letters of the lhs, then the mapping is +"    deactivated as soon as you backspace to correct the mistake. +" +" If, in order to take care of the above problems, you do instead +" +" iab lhs something +" +" then the timeout problem is solved and so is the problem of mistyping. +" however, abbreviations are only expanded after typing a non-word character. +" which causes problems of cursor placement after the expansion and invariably +" spurious spaces are inserted. +"  +" Usage Example: +" this script attempts to solve all these problems by providing an emulation +" of imaps wchich does not suffer from its attendant problems. Because maps +" are activated without having to press additional characters, therefore +" cursor placement is possible. furthermore, file-type specific indentation is +" preserved, because the rhs is expanded as if the rhs is typed in literally +" by the user. +"   +" The script already provides some default mappings. each "mapping" is of the +" form: +" +" call IMAP (lhs, rhs, ft) +"  +" Some characters in the RHS have special meaning which help in cursor +" placement. +" +" Example One: +" +" 	call IMAP ("bit`", "\\begin{itemize}\<cr>\\item <++>\<cr>\\end{itemize}<++>", "tex") +"  +" This effectively sets up the map for "bit`" whenever you edit a latex file. +" When you type in this sequence of letters, the following text is inserted: +"  +" \begin{itemize} +" \item * +" \end{itemize}<++> +" +" where * shows the cursor position. The cursor position after inserting the +" text is decided by the position of the first "place-holder". Place holders +" are special characters which decide cursor placement and movement. In the +" example above, the place holder characters are <+ and +>. After you have typed +" in the item, press <C-j> and you will be taken to the next set of <++>'s. +" Therefore by placing the <++> characters appropriately, you can minimize the +" use of movement keys. +" +" NOTE: Set g:Imap_UsePlaceHolders to 0 to disable placeholders altogether. +" Set  +" 	g:Imap_PlaceHolderStart and g:Imap_PlaceHolderEnd +" to something else if you want different place holder characters. +" Also, b:Imap_PlaceHolderStart and b:Imap_PlaceHolderEnd override the values +" of g:Imap_PlaceHolderStart and g:Imap_PlaceHolderEnd respectively. This is +" useful for setting buffer specific place hoders. +"  +" Example Two: +" You can use the <C-r> command to insert dynamic elements such as dates. +"	call IMAP ('date`', "\<c-r>=strftime('%b %d %Y')\<cr>", '') +" +" sets up the map for date` to insert the current date. +" +"--------------------------------------%<-------------------------------------- +" Bonus: This script also provides a command Snip which puts tearoff strings, +" '----%<----' above and below the visually selected range of lines. The +" length of the string is chosen to be equal to the longest line in the range. +" Recommended Usage: +"   '<,'>Snip +"--------------------------------------%<-------------------------------------- +" }}} + +" line continuation used here. +let s:save_cpo = &cpo +set cpo&vim + +" ============================================================================== +" Script Options / Variables +" ==============================================================================  +" Options {{{ +if !exists('g:Imap_StickyPlaceHolders') +	let g:Imap_StickyPlaceHolders = 1 +endif +if !exists('g:Imap_DeleteEmptyPlaceHolders') +	let g:Imap_DeleteEmptyPlaceHolders = 1 +endif +" }}} +" Variables {{{ +" s:LHS_{ft}_{char} will be generated automatically.  It will look like +" s:LHS_tex_o = 'fo\|foo\|boo' and contain all mapped sequences ending in "o". +" s:Map_{ft}_{lhs} will be generated automatically.  It will look like +" s:Map_c_foo = 'for(<++>; <++>; <++>)', the mapping for "foo". +" +" }}} + +" ============================================================================== +" functions for easy insert mode mappings. +" ============================================================================== +" IMAP: Adds a "fake" insert mode mapping. {{{ +"       For example, doing +"           IMAP('abc', 'def' ft)  +"       will mean that if the letters abc are pressed in insert mode, then +"       they will be replaced by def. If ft != '', then the "mapping" will be +"       specific to the files of type ft.  +" +"       Using IMAP has a few advantages over simply doing: +"           imap abc def +"       1. with imap, if you begin typing abc, the cursor will not advance and +"          long as there is a possible completion, the letters a, b, c will be +"          displayed on on top of the other. using this function avoids that. +"       2. with imap, if a backspace or arrow key is pressed before completing +"          the word, then the mapping is lost. this function allows movement.  +"          (this ofcourse means that this function is only limited to +"          left-hand-sides which do not have movement keys or unprintable +"          characters) +"       It works by only mapping the last character of the left-hand side. +"       when this character is typed in, then a reverse lookup is done and if +"       the previous characters consititute the left hand side of the mapping, +"       the previously typed characters and erased and the right hand side is +"       inserted + +" IMAP: set up a filetype specific mapping. +" Description: +"   "maps" the lhs to rhs in files of type 'ft'. If supplied with 2 +"   additional arguments, then those are assumed to be the placeholder +"   characters in rhs. If unspecified, then the placeholder characters +"   are assumed to be '<+' and '+>' These placeholder characters in +"   a:rhs are replaced with the users setting of +"   [bg]:Imap_PlaceHolderStart and [bg]:Imap_PlaceHolderEnd settings. +" +function! IMAP(lhs, rhs, ft, ...) + +	" Find the place holders to save for IMAP_PutTextWithMovement() . +	if a:0 < 2 +		let phs = '<+' +		let phe = '+>' +	else +		let phs = a:1 +		let phe = a:2 +	endif + +	let hash = s:Hash(a:lhs) +	let s:Map_{a:ft}_{hash} = a:rhs +	let s:phs_{a:ft}_{hash} = phs +	let s:phe_{a:ft}_{hash} = phe + +	" Add a:lhs to the list of left-hand sides that end with lastLHSChar: +	let lastLHSChar = a:lhs[strlen(a:lhs)-1] +	let hash = s:Hash(lastLHSChar) +	if !exists("s:LHS_" . a:ft . "_" . hash) +		let s:LHS_{a:ft}_{hash} = escape(a:lhs, '\') +	else +		let s:LHS_{a:ft}_{hash} = escape(a:lhs, '\') .'\|'.  s:LHS_{a:ft}_{hash} +	endif + +	" map only the last character of the left-hand side. +	if lastLHSChar == ' ' +		let lastLHSChar = '<space>' +	end +	exe 'inoremap <silent>' +				\ escape(lastLHSChar, '|') +				\ '<C-r>=<SID>LookupCharacter("' . +				\ escape(lastLHSChar, '\|"') . +				\ '")<CR>' +endfunction + +" }}} +" IMAP_list:  list the rhs and place holders corresponding to a:lhs {{{ +" +" Added mainly for debugging purposes, but maybe worth keeping. +function! IMAP_list(lhs) +	let char = a:lhs[strlen(a:lhs)-1] +	let charHash = s:Hash(char) +	if exists("s:LHS_" . &ft ."_". charHash) && a:lhs =~ s:LHS_{&ft}_{charHash} +		let ft = &ft +	elseif exists("s:LHS__" . charHash) && a:lhs =~ s:LHS__{charHash} +		let ft = "" +	else +		return "" +	endif +	let hash = s:Hash(a:lhs) +	return "rhs = " . s:Map_{ft}_{hash} . " place holders = " . +				\ s:phs_{ft}_{hash} . " and " . s:phe_{ft}_{hash} +endfunction +" }}} +" LookupCharacter: inserts mapping corresponding to this character {{{ +" +" This function extracts from s:LHS_{&ft}_{a:char} or s:LHS__{a:char} +" the longest lhs matching the current text.  Then it replaces lhs with the +" corresponding rhs saved in s:Map_{ft}_{lhs} . +" The place-holder variables are passed to IMAP_PutTextWithMovement() . +function! s:LookupCharacter(char) +	if IMAP_GetVal('Imap_FreezeImap', 0) == 1 +		return a:char +	endif +	let charHash = s:Hash(a:char) + +	" The line so far, including the character that triggered this function: +	let text = strpart(getline("."), 0, col(".")-1) . a:char +	" Prefer a local map to a global one, even if the local map is shorter. +	" Is this what we want?  Do we care? +	" Use '\V' (very no-magic) so that only '\' is special, and it was already +	" escaped when building up s:LHS_{&ft}_{charHash} . +	if exists("s:LHS_" . &ft . "_" . charHash) +				\ && text =~ "\\C\\V\\(" . s:LHS_{&ft}_{charHash} . "\\)\\$" +		let ft = &ft +	elseif exists("s:LHS__" . charHash) +				\ && text =~ "\\C\\V\\(" . s:LHS__{charHash} . "\\)\\$" +		let ft = "" +	else +		" If this is a character which could have been used to trigger an +		" abbreviation, check if an abbreviation exists. +		if a:char !~ '\k' +			let lastword = matchstr(getline('.'), '\k\+$', '') +			call IMAP_Debug('getting lastword = ['.lastword.']', 'imap') +			if lastword != '' +				" An extremeley wierd way to get around the fact that vim +				" doesn't have the equivalent of the :mapcheck() function for +				" abbreviations. +				let _a = @a +				exec "redir @a | silent! iab ".lastword." | redir END" +				let abbreviationRHS = matchstr(@a."\n", "\n".'i\s\+'.lastword.'\s\+@\?\zs.*\ze'."\n") + +				call IMAP_Debug('getting abbreviationRHS = ['.abbreviationRHS.']', 'imap') + +				if @a =~ "No abbreviation found" || abbreviationRHS == "" +					let @a = _a +					return a:char +				endif + +				let @a = _a +				let abbreviationRHS = escape(abbreviationRHS, '\<"') +				exec 'let abbreviationRHS = "'.abbreviationRHS.'"' + +				let lhs = lastword.a:char +				let rhs = abbreviationRHS.a:char +				let phs = IMAP_GetPlaceHolderStart() +				let phe = IMAP_GetPlaceHolderEnd() +			else +				return a:char +			endif +		else +			return a:char +		endif +	endif +	" Find the longest left-hand side that matches the line so far. +	" matchstr() returns the match that starts first. This automatically +	" ensures that the longest LHS is used for the mapping. +	if !exists('lhs') || !exists('rhs') +		let lhs = matchstr(text, "\\C\\V\\(" . s:LHS_{ft}_{charHash} . "\\)\\$") +		let hash = s:Hash(lhs) +		let rhs = s:Map_{ft}_{hash} +		let phs = s:phs_{ft}_{hash}  +		let phe = s:phe_{ft}_{hash} +	endif + +	if strlen(lhs) == 0 +		return a:char +	endif +	" enough back-spaces to erase the left-hand side; -1 for the last +	" character typed: +	let bs = substitute(strpart(lhs, 1), ".", "\<bs>", "g") +	return bs . IMAP_PutTextWithMovement(rhs, phs, phe) +endfunction + +" }}} +" IMAP_PutTextWithMovement: returns the string with movement appended {{{ +" Description: +"   If a:str contains "placeholders", then appends movement commands to +"   str in a way that the user moves to the first placeholder and enters +"   insert or select mode. If supplied with 2 additional arguments, then +"   they are assumed to be the placeholder specs. Otherwise, they are +"   assumed to be '<+' and '+>'. These placeholder chars are replaced +"   with the users settings of [bg]:Imap_PlaceHolderStart and +"   [bg]:Imap_PlaceHolderEnd. +function! IMAP_PutTextWithMovement(str, ...) + +	" The placeholders used in the particular input string. These can be +	" different from what the user wants to use. +	if a:0 < 2 +		let phs = '<+' +		let phe = '+>' +	else +		let phs = escape(a:1, '\') +		let phe = escape(a:2, '\') +	endif + +	let text = a:str + +	" The user's placeholder settings. +	let phsUser = IMAP_GetPlaceHolderStart() +	let pheUser = IMAP_GetPlaceHolderEnd() + +	" Problem:  depending on the setting of the 'encoding' option, a character +	" such as "\xab" may not match itself.  We try to get around this by +	" changing the encoding of all our strings.  At the end, we have to +	" convert text back. +	let phsEnc     = s:Iconv(phs, "encode") +	let pheEnc     = s:Iconv(phe, "encode") +	let phsUserEnc = s:Iconv(phsUser, "encode") +	let pheUserEnc = s:Iconv(pheUser, "encode") +	let textEnc    = s:Iconv(text, "encode") +	if textEnc != text +		let textEncoded = 1 +	else +		let textEncoded = 0 +	endif + +	let pattern = '\V\(\.\{-}\)' .phs. '\(\.\{-}\)' .phe. '\(\.\*\)' +	" If there are no placeholders, just return the text. +	if textEnc !~ pattern +		call IMAP_Debug('Not getting '.phs.' and '.phe.' in '.textEnc, 'imap') +		return text +	endif +	" Break text up into "initial <+template+> final"; any piece may be empty. +	let initialEnc  = substitute(textEnc, pattern, '\1', '') +	let templateEnc = substitute(textEnc, pattern, '\2', '') +	let finalEnc    = substitute(textEnc, pattern, '\3', '') + +	" If the user does not want to use placeholders, then remove all but the +	" first placeholder. +	" Otherwise, replace all occurences of the placeholders here with the +	" user's choice of placeholder settings. +	if exists('g:Imap_UsePlaceHolders') && !g:Imap_UsePlaceHolders +		let finalEnc = substitute(finalEnc, '\V'.phs.'\.\{-}'.phe, '', 'g') +	else +		let finalEnc = substitute(finalEnc, '\V'.phs.'\(\.\{-}\)'.phe, +					\ phsUserEnc.'\1'.pheUserEnc, 'g') +	endif + +	" The substitutions are done, so convert back, if necessary. +	if textEncoded +		let initial = s:Iconv(initialEnc, "decode") +		let template = s:Iconv(templateEnc, "decode") +		let final = s:Iconv(finalEnc, "decode") +	else +		let initial = initialEnc +		let template = templateEnc +		let final = finalEnc +	endif + +	" Build up the text to insert: +	" 1. the initial text plus an extra character; +	" 2. go to Normal mode with <C-\><C-N>, so it works even if 'insertmode' +	" is set, and mark the position; +	" 3. replace the extra character with tamplate and final; +	" 4. back to Normal mode and restore the cursor position; +	" 5. call IMAP_Jumpfunc(). +	let template = phsUser . template . pheUser +	" Old trick:  insert and delete a character to get the same behavior at +	" start, middle, or end of line and on empty lines. +	let text = initial . "X\<C-\>\<C-N>:call IMAP_Mark('set')\<CR>\"_s" +	let text = text . template . final +	let text = text . "\<C-\>\<C-N>:call IMAP_Mark('go')\<CR>" +	let text = text . "i\<C-r>=IMAP_Jumpfunc('', 1)\<CR>" + +	call IMAP_Debug('IMAP_PutTextWithMovement: text = ['.text.']', 'imap') +	return text +endfunction + +" }}} +" IMAP_Jumpfunc: takes user to next <+place-holder+> {{{ +" Author: Luc Hermitte +" Arguments: +" direction: flag for the search() function. If set to '', search forwards, +"            if 'b', then search backwards. See the {flags} argument of the +"            |search()| function for valid values. +" inclusive: In vim, the search() function is 'exclusive', i.e we always goto +"            next cursor match even if there is a match starting from the +"            current cursor position. Setting this argument to 1 makes +"            IMAP_Jumpfunc() also respect a match at the current cursor +"            position. 'inclusive'ness is necessary for IMAP() because a +"            placeholder string can occur at the very beginning of a map which +"            we want to select. +"            We use a non-zero value only in special conditions. Most mappings +"            should use a zero value. +function! IMAP_Jumpfunc(direction, inclusive) + +	" The user's placeholder settings. +	let phsUser = IMAP_GetPlaceHolderStart() +	let pheUser = IMAP_GetPlaceHolderEnd() + +	let searchString = '' +	" If this is not an inclusive search or if it is inclusive, but the +	" current cursor position does not contain a placeholder character, then +	" search for the placeholder characters. +	if !a:inclusive || strpart(getline('.'), col('.')-1) !~ '\V\^'.phsUser +		let searchString = '\V'.phsUser.'\_.\{-}'.pheUser +	endif + +	" If we didn't find any placeholders return quietly. +	if searchString != '' && !search(searchString, a:direction) +		return '' +	endif + +	" Open any closed folds and make this part of the text visible. +	silent! foldopen! + +	" Calculate if we have an empty placeholder or if it contains some +	" description. +	let template =  +		\ matchstr(strpart(getline('.'), col('.')-1), +		\          '\V\^'.phsUser.'\zs\.\{-}\ze\('.pheUser.'\|\$\)') +	let placeHolderEmpty = !strlen(template) + +	" If we are selecting in exclusive mode, then we need to move one step to +	" the right +	let extramove = '' +	if &selection == 'exclusive' +		let extramove = 'l' +	endif + +	" Select till the end placeholder character. +	let movement = "\<C-o>v/\\V".pheUser."/e\<CR>".extramove + +	" First remember what the search pattern was. s:RemoveLastHistoryItem will +	" reset @/ to this pattern so we do not create new highlighting. +	let g:Tex_LastSearchPattern = @/ + +	" Now either goto insert mode or select mode. +	if placeHolderEmpty && g:Imap_DeleteEmptyPlaceHolders +		" delete the empty placeholder into the blackhole. +		return movement."\"_c\<C-o>:".s:RemoveLastHistoryItem."\<CR>" +	else +		return movement."\<C-\>\<C-N>:".s:RemoveLastHistoryItem."\<CR>gv\<C-g>" +	endif +	 +endfunction + +" }}} +" Maps for IMAP_Jumpfunc {{{ +" +" These mappings use <Plug> and thus provide for easy user customization. When +" the user wants to map some other key to jump forward, he can do for +" instance: +"   nmap ,f   <plug>IMAP_JumpForward +" etc. + +" jumping forward and back in insert mode. +imap <silent> <Plug>IMAP_JumpForward    <c-r>=IMAP_Jumpfunc('', 0)<CR> +imap <silent> <Plug>IMAP_JumpBack       <c-r>=IMAP_Jumpfunc('b', 0)<CR> + +" jumping in normal mode +nmap <silent> <Plug>IMAP_JumpForward        i<c-r>=IMAP_Jumpfunc('', 0)<CR> +nmap <silent> <Plug>IMAP_JumpBack           i<c-r>=IMAP_Jumpfunc('b', 0)<CR> + +" deleting the present selection and then jumping forward. +vmap <silent> <Plug>IMAP_DeleteAndJumpForward       "_<Del>i<c-r>=IMAP_Jumpfunc('', 0)<CR> +vmap <silent> <Plug>IMAP_DeleteAndJumpBack          "_<Del>i<c-r>=IMAP_Jumpfunc('b', 0)<CR> + +" jumping forward without deleting present selection. +vmap <silent> <Plug>IMAP_JumpForward       <C-\><C-N>i<c-r>=IMAP_Jumpfunc('', 0)<CR> +vmap <silent> <Plug>IMAP_JumpBack          <C-\><C-N>`<i<c-r>=IMAP_Jumpfunc('b', 0)<CR> + +" }}} +" Default maps for IMAP_Jumpfunc {{{ +" map only if there is no mapping already. allows for user customization. +" NOTE: Default mappings for jumping to the previous placeholder are not +"       provided. It is assumed that if the user will create such mappings +"       hself if e so desires. +if !hasmapto('<Plug>IMAP_JumpForward', 'i') +    imap <C-J> <Plug>IMAP_JumpForward +endif +if !hasmapto('<Plug>IMAP_JumpForward', 'n') +    nmap <C-J> <Plug>IMAP_JumpForward +endif +if exists('g:Imap_StickyPlaceHolders') && g:Imap_StickyPlaceHolders +	if !hasmapto('<Plug>IMAP_JumpForward', 'v') +		vmap <C-J> <Plug>IMAP_JumpForward +	endif +else +	if !hasmapto('<Plug>IMAP_DeleteAndJumpForward', 'v') +		vmap <C-J> <Plug>IMAP_DeleteAndJumpForward +	endif +endif +" }}} + +nmap <silent> <script> <plug><+SelectRegion+> `<v`> + +" ==============================================================================  +" enclosing selected region. +" ==============================================================================  +" VEnclose: encloses the visually selected region with given arguments {{{ +" Description: allows for differing action based on visual line wise +"              selection or visual characterwise selection. preserves the +"              marks and search history. +function! VEnclose(vstart, vend, VStart, VEnd) + +	" its characterwise if +	" 1. characterwise selection and valid values for vstart and vend. +	" OR +	" 2. linewise selection and invalid values for VStart and VEnd +	if (visualmode() == 'v' && (a:vstart != '' || a:vend != '')) || (a:VStart == '' && a:VEnd == '') + +		let newline = "" +		let _r = @r + +		let normcmd = "normal! \<C-\>\<C-n>`<v`>\"_s" + +		exe "normal! \<C-\>\<C-n>`<v`>\"ry" +		if @r =~ "\n$" +			let newline = "\n" +			let @r = substitute(@r, "\n$", '', '') +		endif + +		" In exclusive selection, we need to select an extra character. +		if &selection == 'exclusive' +			let movement = 8 +		else +			let movement = 7 +		endif +		let normcmd = normcmd. +			\ a:vstart."!!mark!!".a:vend.newline. +			\ "\<C-\>\<C-N>?!!mark!!\<CR>v".movement."l\"_s\<C-r>r\<C-\>\<C-n>" + +		" this little if statement is because till very recently, vim used to +		" report col("'>") > length of selected line when `> is $. on some +		" systems it reports a -ve number. +		if col("'>") < 0 || col("'>") > strlen(getline("'>")) +			let lastcol = strlen(getline("'>")) +		else +			let lastcol = col("'>") +		endif +		if lastcol - col("'<") != 0 +			let len = lastcol - col("'<") +		else +			let len = '' +		endif + +		" the next normal! is for restoring the marks. +		let normcmd = normcmd."`<v".len."l\<C-\>\<C-N>" + +		" First remember what the search pattern was. s:RemoveLastHistoryItem +		" will reset @/ to this pattern so we do not create new highlighting. +		let g:Tex_LastSearchPattern = @/ + +		silent! exe normcmd +		" this is to restore the r register. +		let @r = _r +		" and finally, this is to restore the search history. +		execute s:RemoveLastHistoryItem + +	else + +		exec 'normal! `<O'.a:VStart."\<C-\>\<C-n>" +		exec 'normal! `>o'.a:VEnd."\<C-\>\<C-n>" +		if &indentexpr != '' +			silent! normal! `<kV`>j= +		endif +		silent! normal! `> +	endif +endfunction  + +" }}} +" ExecMap: adds the ability to correct an normal/visual mode mapping.  {{{ +" Author: Hari Krishna Dara <hari_vim@yahoo.com> +" Reads a normal mode mapping at the command line and executes it with the +" given prefix. Press <BS> to correct and <Esc> to cancel. +function! ExecMap(prefix, mode) +	" Temporarily remove the mapping, otherwise it will interfere with the +	" mapcheck call below: +	let myMap = maparg(a:prefix, a:mode) +	exec a:mode."unmap ".a:prefix + +	" Generate a line with spaces to clear the previous message. +	let i = 1 +	let clearLine = "\r" +	while i < &columns +		let clearLine = clearLine . ' ' +		let i = i + 1 +	endwhile + +	let mapCmd = a:prefix +	let foundMap = 0 +	let breakLoop = 0 +	echon "\rEnter Map: " . mapCmd +	while !breakLoop +		let char = getchar() +		if char !~ '^\d\+$' +			if char == "\<BS>" +				let mapCmd = strpart(mapCmd, 0, strlen(mapCmd) - 1) +			endif +		else " It is the ascii code. +			let char = nr2char(char) +			if char == "\<Esc>" +				let breakLoop = 1 +			else +				let mapCmd = mapCmd . char +				if maparg(mapCmd, a:mode) != "" +					let foundMap = 1 +					let breakLoop = 1 +				elseif mapcheck(mapCmd, a:mode) == "" +					let mapCmd = strpart(mapCmd, 0, strlen(mapCmd) - 1) +				endif +			endif +		endif +		echon clearLine +		echon "\rEnter Map: " . mapCmd +	endwhile +	if foundMap +		if a:mode == 'v' +			" use a plug to select the region instead of using something like +			" `<v`> to avoid problems caused by some of the characters in +			" '`<v`>' being mapped. +			let gotoc = "\<plug><+SelectRegion+>" +		else +			let gotoc = '' +		endif +		exec "normal ".gotoc.mapCmd +	endif +	exec a:mode.'noremap '.a:prefix.' '.myMap +endfunction + +" }}} + +" ==============================================================================  +" helper functions +" ==============================================================================  +" Strntok: extract the n^th token from a list {{{ +" example: Strntok('1,23,3', ',', 2) = 23 +fun! <SID>Strntok(s, tok, n) +	return matchstr( a:s.a:tok[0], '\v(\zs([^'.a:tok.']*)\ze['.a:tok.']){'.a:n.'}') +endfun + +" }}} +" s:RemoveLastHistoryItem: removes last search item from search history {{{ +" Description: Execute this string to clean up the search history. +let s:RemoveLastHistoryItem = ':call histdel("/", -1)|let @/=g:Tex_LastSearchPattern' + +" }}} +" s:Hash: Return a version of a string that can be used as part of a variable" {{{ +" name. +" 	Converts every non alphanumeric character into _{ascii}_ where {ascii} is +" 	the ASCII code for that character... +fun! s:Hash(text) +	return substitute(a:text, '\([^[:alnum:]]\)', +				\ '\="_".char2nr(submatch(1))."_"', 'g') +endfun +"" }}} +" IMAP_GetPlaceHolderStart and IMAP_GetPlaceHolderEnd:  "{{{ +" return the buffer local placeholder variables, or the global one, or the default. +function! IMAP_GetPlaceHolderStart() +	if exists("b:Imap_PlaceHolderStart") && strlen(b:Imap_PlaceHolderEnd) +		return b:Imap_PlaceHolderStart +	elseif exists("g:Imap_PlaceHolderStart") && strlen(g:Imap_PlaceHolderEnd) +		return g:Imap_PlaceHolderStart +	else +		return "<+" +endfun +function! IMAP_GetPlaceHolderEnd() +	if exists("b:Imap_PlaceHolderEnd") && strlen(b:Imap_PlaceHolderEnd) +		return b:Imap_PlaceHolderEnd +	elseif exists("g:Imap_PlaceHolderEnd") && strlen(g:Imap_PlaceHolderEnd) +		return g:Imap_PlaceHolderEnd +	else +		return "+>" +endfun +" }}} +" s:Iconv:  a wrapper for iconv()" {{{ +" Problem:  after +" 	let text = "\xab" +" (or using the raw 8-bit ASCII character in a file with 'fenc' set to +" "latin1") if 'encoding' is set to utf-8, then text does not match itself: +" 	echo text =~ text +" returns 0. +" Solution:  When this happens, a re-encoded version of text does match text: +" 	echo iconv(text, "latin1", "utf8") =~ text +" returns 1.  In this case, convert text to utf-8 with iconv(). +" TODO:  Is it better to use &encoding instead of "utf8"?  Internally, vim +" uses utf-8, and can convert between latin1 and utf-8 even when compiled with +" -iconv, so let's try using utf-8. +" Arguments: +" 	a:text = text to be encoded or decoded +" 	a:mode = "encode" (latin1 to utf8) or "decode" (utf8 to latin1) +" Caution:  do not encode and then decode without checking whether the text +" has changed, becuase of the :if clause in encoding! +function! s:Iconv(text, mode) +	if a:mode == "decode" +		return iconv(a:text, "utf8", "latin1") +	endif +	if a:text =~ '\V\^' . escape(a:text, '\') . '\$' +		return a:text +	endif +	let textEnc = iconv(a:text, "latin1", "utf8") +	if textEnc !~ '\V\^' . escape(a:text, '\') . '\$' +		call IMAP_Debug('Encoding problems with text '.a:text.' ', 'imap') +	endif +	return textEnc +endfun +"" }}} +" IMAP_Debug: interface to Tex_Debug if available, otherwise emulate it {{{ +" Description:  +" Do not want a memory leak! Set this to zero so that imaps always +" starts out in a non-debugging mode. +if !exists('g:Imap_Debug') +	let g:Imap_Debug = 0 +endif +function! IMAP_Debug(string, pattern) +	if !g:Imap_Debug +		return +	endif +	if exists('*Tex_Debug') +		call Tex_Debug(a:string, a:pattern) +	else +		if !exists('s:debug_'.a:pattern) +			let s:debug_{a:pattern} = a:string +		else +			let s:debug_{a:pattern} = s:debug_{a:pattern}.a:string +		endif +	endif +endfunction " }}} +" IMAP_DebugClear: interface to Tex_DebugClear if avaialable, otherwise emulate it {{{ +" Description:  +function! IMAP_DebugClear(pattern) +	if exists('*Tex_DebugClear') +		call Tex_DebugClear(a:pattern) +	else	 +		let s:debug_{a:pattern} = '' +	endif +endfunction " }}} +" IMAP_PrintDebug: interface to Tex_DebugPrint if avaialable, otherwise emulate it {{{ +" Description:  +function! IMAP_PrintDebug(pattern) +	if exists('*Tex_PrintDebug') +		call Tex_PrintDebug(a:pattern) +	else +		if exists('s:debug_'.a:pattern) +			echo s:debug_{a:pattern} +		endif +	endif +endfunction " }}} +" IMAP_Mark:  Save the cursor position (if a:action == 'set') in a" {{{ +" script-local variable; restore this position if a:action == 'go'. +let s:Mark = "(0,0)" +let s:initBlanks = '' +function! IMAP_Mark(action) +	if a:action == 'set' +		let s:Mark = "(" . line(".") . "," . col(".") . ")" +		let s:initBlanks = matchstr(getline('.'), '^\s*') +	elseif a:action == 'go' +		execute "call cursor" s:Mark +		let blanksNow = matchstr(getline('.'), '^\s*') +		if strlen(blanksNow) > strlen(s:initBlanks) +			execute 'silent! normal! '.(strlen(blanksNow) - strlen(s:initBlanks)).'l' +		elseif strlen(blanksNow) < strlen(s:initBlanks) +			execute 'silent! normal! '.(strlen(s:initBlanks) - strlen(blanksNow)).'h' +		endif +	endif +endfunction	"" }}} +" IMAP_GetVal: gets the value of a variable {{{ +" Description: first checks window local, then buffer local etc. +function! IMAP_GetVal(name, ...) +	if a:0 > 0 +		let default = a:1 +	else +		let default = '' +	endif +	if exists('w:'.a:name) +		return w:{a:name} +	elseif exists('b:'.a:name) +		return b:{a:name} +	elseif exists('g:'.a:name) +		return g:{a:name} +	else +		return default +	endif +endfunction " }}} + +" ==============================================================================  +" A bonus function: Snip() +" ==============================================================================  +" Snip: puts a scissor string above and below block of text {{{ +" Desciption: +"-------------------------------------%<------------------------------------- +"   this puts a the string "--------%<---------" above and below the visually +"   selected block of lines. the length of the 'tearoff' string depends on the +"   maximum string length in the selected range. this is an aesthetically more +"   pleasing alternative instead of hardcoding a length. +"-------------------------------------%<------------------------------------- +function! <SID>Snip() range +	let i = a:firstline +	let maxlen = -2 +	" find out the maximum virtual length of each line. +	while i <= a:lastline +		exe i +		let length = virtcol('$') +		let maxlen = (length > maxlen ? length : maxlen) +		let i = i + 1 +	endwhile +	let maxlen = (maxlen > &tw && &tw != 0 ? &tw : maxlen) +	let half = maxlen/2 +	exe a:lastline +	" put a string below +	exe "norm! o\<esc>".(half - 1)."a-\<esc>A%<\<esc>".(half - 1)."a-" +	" and above. its necessary to put the string below the block of lines +	" first because that way the first line number doesnt change... +	exe a:firstline +	exe "norm! O\<esc>".(half - 1)."a-\<esc>A%<\<esc>".(half - 1)."a-" +endfunction + +com! -nargs=0 -range Snip :<line1>,<line2>call <SID>Snip() +" }}} + +let &cpo = s:save_cpo + +" vim:ft=vim:ts=4:sw=4:noet:fdm=marker:commentstring=\"\ %s:nowrap diff --git a/.vim/plugin/libList.vim b/.vim/plugin/libList.vim new file mode 100644 index 0000000..7d72c3e --- /dev/null +++ b/.vim/plugin/libList.vim @@ -0,0 +1,249 @@ +" File: libList.vim +" Last Change: 2001 Dec 10 +" Maintainer: Gontran BAERTS <gbcreation@free.fr> +" Version: 0.1 +" +" Please don't hesitate to correct my english :) +" Send corrections to <gbcreation@free.fr> +" +"----------------------------------------------------------------------------- +" Description: libList.vim is a set of functions to work with lists or one +" level arrays. +" +"----------------------------------------------------------------------------- +" To Enable: Normally, this file will reside in your plugins directory and be +" automatically sourced. +" +"----------------------------------------------------------------------------- +" Usage: Lists are strings variable with values separated by g:listSep +" character (comma" by default). You may redefine g:listSep variable as you +" wish. +" +" Here are available functions : +" +" - AddListItem( array, newItem, index ) : +"		Add item "newItem" to array "array" at "index" position +" - GetListItem( array, index ) : +"		Return item at "index" position in array "array" +" - GetListMatchItem( array, pattern ) : +"		Return item matching "pattern" in array "array" +" - GetListCount( array ) : +"		Return the number of items in array "array" +" - RemoveListItem( array, index ) : +"		Remove item at "index" position from array "array" +" - ReplaceListItem( array, index, item ) : +"		Remove item at "index" position by "item" in array "array" +" - ExchangeListItems( array, item1Index, item2Index ) : +" 		Exchange item "item1Index" with item "item2Index" in array "array" +" - QuickSortList( array, beg, end ) : +" 		Return array "array" with items between "beg" and "end" sorted +" +" Example: +" let mylist="" +" echo GetListCount( mylist ) " --> 0 +" let mylist = AddListItem( mylist, "One", 0 ) " mylist == "One" +" let mylist = AddListItem( mylist, "Three", 1 ) " mylist == "One,Three" +" let mylist = AddListItem( mylist, "Two", 1 ) " mylist == "One,Two,Three" +" echo GetListCount( mylist ) " --> 3 +" echo GetListItem( mylist, 2 ) " --> Three +" echo GetListMatchItem( mylist, "w" ) " --> two +" echo GetListMatchItem( mylist, "e" ) " --> One +" let mylist = RemoveListItem( mylist, 2 ) " mylist == "One,Two" +" echo GetListCount( mylist ) " --> 2 +" let mylist = ReplaceListItem( mylist, 0, "Three" ) " mylist == "Three,Two" +" let mylist = ExchangeListItems( mylist, 0, 1 ) " mylist == "Two,Three" +" let mylist = AddListItem( mylist, "One", 0 ) " mylist == "One,Two,Three" +" let mylist = QuickSortList( mylist, 0, GetListCount(mylist)-1 ) +" " mylist == "One,Three,Two" +" +"----------------------------------------------------------------------------- +" Updates: +" in version 0.1 +" - First version + +" Has this already been loaded ? +if exists("loaded_libList") +       finish +endif +let loaded_libList=1 + +"** +" Separator: +" You may change the separator character et any time. +"** +let g:listSep = "," + +"** +"AddListItem: +"	Add new item at given position. +"	First item index is 0 (zero). +"Parameters: +" - array : Array/List (string of values) which receives the new item. +" - newItem : String containing the item value to add. +" - index : Integer indicating the position at which the new item is added. +" 			It must be greater than or equals to 0 (zero). +"Return: +"String containing array values, including newItem. +"** +function AddListItem( array, newItem, index ) +	if a:index == 0 +		if a:array == "" +			return a:newItem +		endif +		return a:newItem . g:listSep . a:array +	endif +	return substitute( a:array, '\(\%(^\|' . g:listSep . '\)[^' . g:listSep . ']\+\)\{' . a:index . '\}', '\0' . g:listSep . a:newItem , "" ) +endfunction + +"** +"GetListItem: +"	Get item at given position. +"Parameters: +" - array : Array/List (string of values). +" - index : Integer indicating the position of item to return. +" 			It must be greater than or equals to 0 (zero). +"Return: +"String representing the item. +"** +function GetListItem( array, index ) +	if a:index == 0 +		return matchstr( a:array, '^[^' . g:listSep . ']\+' ) +	else +		return matchstr( a:array, "[^" . g:listSep . "]\\+", matchend( a:array, '\(\%(^\|' . g:listSep . '\)[^' . g:listSep . ']\+\)\{' . a:index . '\}' . g:listSep ) ) +	endif +endfunction + +"** +"GetListMatchItem: +"	Get the first item matching given pattern. +"Parameters: +" - array : Array/List (string of values). +" - pattern : Regular expression to match with items. +"			  Avoid to use ^, $ and listSep characters in pattern, unless you +"			  know what you do. +"Return: +"String representing the first item that matches the pattern. +"** +function GetListMatchItem( array, pattern ) +	return matchstr( a:array, '[^' . g:listSep . ']*' . a:pattern . '[^' . g:listSep . ']*' ) +endfunction + +"** +"ReplaceListItem: +"	Replace item at given position by a new one. +"Parameters: +" - array : Array/List (string of values). +" - index : Integer indicating the position of item to replace. +" 			It must be greater than or equals to 0 (zero). +" - item : String containing the new value of the replaced item. +"Return: +"String containing array values. +"** +function ReplaceListItem( array, index, item ) +	if a:index == 0 +		return substitute( a:array, '^[^' .g:listSep. ']\+', a:item, "" ) +	else +		return substitute( a:array, '\(\%(\%(^\|' . g:listSep . '\)[^' . g:listSep . ']\+\)\{' . a:index . '\}\)' . g:listSep . '[^' . g:listSep . ']\+', '\1' . g:listSep . a:item , "" ) +	endif +endfunction + +"** +"RemoveListItem: +"	Remove item at given position. +"Parameters: +" - array : Array/List (string of values) from which remove an item. +" - index : Integer indicating the position of item to remove. +" 			It must be greater than or equals to 0 (zero). +"Return: +"String containing array values, except the removed one. +"** +function RemoveListItem( array, index ) +	if a:index == 0 +		return substitute( a:array, '^[^' .g:listSep. ']\+\(' . g:listSep . '\|$\)', "", "" ) +	else +		return substitute( a:array, '\(\%(\%(^\|' . g:listSep . '\)[^' . g:listSep . ']\+\)\{' . a:index . '\}\)' . g:listSep . '[^' . g:listSep . ']\+', '\1', "" ) +	endif +endfunction + +"** +"ExchangeListItems: +"	Exchange item at position item1Index with item at position item2Index. +"Parameters: +" - array : Array/List (string of values). +" - item1index : Integer indicating the position of the first item to exchange. +" 				 It must be greater than or equals to 0 (zero). +" - item2index : Integer indicating the position of the second item to +"				 exchange. It must be greater than or equals to 0 (zero). +"Return: +"String containing array values. +"** +function ExchangeListItems( array, item1Index, item2Index ) +	let item1 = GetListItem( a:array, a:item1Index ) +	let array = ReplaceListItem( a:array, a:item1Index, GetListItem( a:array, a:item2Index ) ) +	return ReplaceListItem( array, a:item2Index, item1 ) +endfunction + +"** +"GetListCount: +"	Number of items in array. +"Parameters: +" - array : Array/List (string of values). +"Return: +"Integer representing the number of items in array. +"Index of last item is GetListCount(array)-1. +"** +function GetListCount( array ) +	if a:array == "" | return 0 | endif +	let pos = 0 +	let cnt = 0 +	while pos != -1 +		let pos = matchend( a:array, g:listSep, pos ) +		let cnt = cnt + 1 +	endwhile +	return cnt +endfunction + +"** +"QuickSortList: +"	Sort array. +"Parameters: +" - array : Array/List (string of values). +" - beg : Min index of the range of items to sort. +" - end : Max index of the range of items to sort. +"Return: +"String containing array values with indicated range of items sorted. +"** +function QuickSortList( array, beg, end ) +	let array = a:array +	let pivot = GetListItem( array, a:beg ) +	let l = a:beg +	let r = a:end +	while l < r +		while GetListItem( array, r ) > pivot +			let r = r - 1 +		endwhile +		if l != r +			let array = ReplaceListItem( array, l, GetListItem( array, r ) ) +			let array = ReplaceListItem( array, r, pivot ) +			let l = l + 1 +		endif + +		while GetListItem( array, l ) < pivot +			let l = l + 1 +		endwhile +		if l != r +			let array = ReplaceListItem( array, r, GetListItem( array, l ) ) +			let array = ReplaceListItem( array, l, pivot ) +			let r = r - 1 +		endif +	endwhile +	if a:beg < l-1 +		let array = QuickSortList( array, a:beg, l-1 ) +	endif +	if a:end > l+1 +		let array = QuickSortList( array, l+1, a:end ) +	endif +	return array +endfunction + + diff --git a/.vim/plugin/minibufexpl.vim b/.vim/plugin/minibufexpl.vim new file mode 100644 index 0000000..4e78063 --- /dev/null +++ b/.vim/plugin/minibufexpl.vim @@ -0,0 +1,1838 @@ +" Mini Buffer Explorer <minibufexpl.vim> +" +" HINT: Type zR if you don't know how to use folds +" +" Script Info and Documentation  {{{ +"============================================================================= +"    Copyright: Copyright (C) 2002 & 2003 Bindu Wavell  +"               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, +"               minibufexplorer.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. +" +" Name Of File: minibufexpl.vim +"  Description: Mini Buffer Explorer Vim Plugin +"   Maintainer: Bindu Wavell <bindu@wavell.net> +"          URL: http://vim.sourceforge.net/scripts/script.php?script_id=159 +"  Last Change: Sunday, June 21, 2004 +"      Version: 6.3.2 +"               Derived from Jeff Lanzarotta's bufexplorer.vim version 6.0.7 +"               Jeff can be reached at (jefflanzarotta@yahoo.com) and the +"               original plugin can be found at: +"               http://lanzarotta.tripod.com/vim/plugin/6/bufexplorer.vim.zip +" +"        Usage: Normally, this file should reside in the plugins +"               directory and be automatically sourced. If not, you must +"               manually source this file using ':source minibufexplorer.vim'. +" +"               You may use the default keymappings of +" +"                 <Leader>mbe - Opens MiniBufExplorer +" +"               or you may want to add something like the following +"               key mapping to your _vimrc/.vimrc file. +" +"                 map <Leader>b :MiniBufExplorer<cr> +" +"               However, in most cases you won't need any key-bindings at all. +" +"               <Leader> is usually backslash so type "\mbe" (quickly) to open  +"               the -MiniBufExplorer- window. +" +"               Other keymappings include: <Leader>mbc to close the Explorer +"               window,  <Leader>mbu to force the Explorer to Update and +"               <Leader>mbt to toggle the Explorer window; it will open if +"               closed or close if open. Each of these key bindings can be +"               overridden (see the notes on <Leader>mbe above.) +"  +"               You can map these additional commands as follows: +" +"                 map <Leader>c :CMiniBufExplorer<cr> +"                 map <Leader>u :UMiniBufExplorer<cr> +"                 map <Leader>t :TMiniBufExplorer<cr> +" +"               NOTE: you can change the key binding used in these mappings +"                     so that they fit with your configuration of vim. +" +"               You can also call each of these features by typing the +"               following in command mode: +" +"                 :MiniBufExplorer    " Open and/or goto Explorer +"                 :CMiniBufExplorer   " Close the Explorer if it's open +"                 :UMiniBufExplorer   " Update Explorer without navigating +"                 :TMiniBufExplorer   " Toggle the Explorer window open and  +"                                       closed. +" +"               To control where the new split window goes relative to the  +"               current window, use the setting: +" +"                 let g:miniBufExplSplitBelow=0  " Put new window above +"                                                " current or on the +"                                                " left for vertical split +"                 let g:miniBufExplSplitBelow=1  " Put new window below +"                                                " current or on the +"                                                " right for vertical split +" +"               The default for this is read from the &splitbelow VIM option. +" +"               By default we are now (as of 6.0.2) forcing the -MiniBufExplorer- +"               window to open up at the edge of the screen. You can turn this  +"               off by setting the following variable in your .vimrc: +" +"                 let g:miniBufExplSplitToEdge = 0 +" +"               If you would like a vertical explorer you can assign the column +"               width (in characters) you want for your explorer window with the +"               following .vimrc variable (this was introduced in 6.3.0): +" +"                 let g:miniBufExplVSplit = 20   " column width in chars +" +"               IN HORIZONTAL MODE: +"               It is now (as of 6.1.1) possible to set a maximum height for +"               the -MiniBufExplorer- window. You can set the max height by +"               letting the following variable in your .vimrc: +" +"                 let g:miniBufExplMaxSize = <max lines: defualt 0> +"                +"               setting this to 0 will mean the window gets as big as +"               needed to fit all your buffers.  +" +"               NOTE: This was g:miniBufExplMaxHeight before 6.3.0; the old +"               setting is backwards compatible if you don't use MaxSize. +" +"               As of 6.2.2 it is possible to set a minimum height for the  +"               -MiniBufExplorer- window. You can set the min height by +"               letting the following variable in your .vimrc: +" +"                 let g:miniBufExplMinSize = <min height: default 1> +" +"               NOTE: This was g:miniBufExplMinHeight before 6.3.0; the old +"               setting is backwards compatible if you don't use MinSize. +" +"               IN VERTICAL MODE: (as of 6.3.0) +"               By default the vertical explorer has a fixed width. If you put: +" +"                 let g:miniBufExplMaxSize = <max width: default 0>  +" +"               into your .vimrc then MBE will attempt to set the width of the +"               MBE window to be as wide as your widest tab. The width will not +"               exceed MaxSize even if you have wider tabs.  +" +"               Accepting the default value of 0 for this will give you a fixed +"               width MBE window. +" +"               You can specify a MinSize for the vertical explorer window by +"               putting the following in your .vimrc: +" +"                 let g:miniBufExplMinSize = <min width: default 1> +" +"               This will have no effect unless you also specivy MaxSize. +" +"               By default we are now (as of 6.0.1) turning on the MoreThanOne +"               option. This stops the -MiniBufExplorer- from opening  +"               automatically until more than one eligible buffer is available. +"               You can turn this feature off by setting the following variable +"               in your .vimrc: +"                  +"                 let g:miniBufExplorerMoreThanOne=1 +" +"               (The following enhancement is as of 6.2.2) +"               Setting this to 0 will cause the MBE window to be loaded even +"               if no buffers are available. Setting it to 1 causes the MBE +"               window to be loaded as soon as an eligible buffer is read. You +"               can also set it to larger numbers. So if you set it to 4 for +"               example the MBE window wouldn't auto-open until 4 eligibles +"               buffers had been loaded. This is nice for folks that don't  +"               want an MBE window unless they are editing more than two or +"               three buffers. +" +"               To enable the optional mapping of Control + Vim Direction Keys  +"               [hjkl] to window movement commands, you can put the following into  +"               your .vimrc: +" +"                 let g:miniBufExplMapWindowNavVim = 1 +" +"               To enable the optional mapping of Control + Arrow Keys to window  +"               movement commands, you can put the following into your .vimrc: +" +"                 let g:miniBufExplMapWindowNavArrows = 1 +" +"               To enable the optional mapping of <C-TAB> and <C-S-TAB> to a  +"               function that will bring up the next or previous buffer in the +"               current window, you can put the following into your .vimrc: +" +"                 let g:miniBufExplMapCTabSwitchBufs = 1 +" +"               To enable the optional mapping of <C-TAB> and <C-S-TAB> to mappings +"               that will move to the next and previous (respectively) window, you +"               can put the following into your .vimrc: +" +"                 let g:miniBufExplMapCTabSwitchWindows = 1 +" +" +"               NOTE: If you set the ...TabSwitchBufs AND ...TabSwitchWindows,  +"                     ...TabSwitchBufs will be enabled and ...TabSwitchWindows  +"                     will not. +"                +"               As of MBE 6.3.0, you can put the following into your .vimrc: +"                +"                 let g:miniBufExplUseSingleClick = 1 +" +"               If you would like to single click on tabs rather than double +"               clicking on them to goto the selected buffer.  +" +"               NOTE: If you use the single click option in taglist.vim you may  +"                     need to get an updated version that includes a patch I  +"                     provided to allow both explorers to provide single click  +"                     buffer selection. +" +"               It is possible to customize the the highlighting for the tabs in  +"               the MBE by configuring the following highlighting groups: +" +"                 MBENormal         - for buffers that have NOT CHANGED and +"                                     are NOT VISIBLE. +"                 MBEChanged        - for buffers that HAVE CHANGED and are +"                                     NOT VISIBLE +"                 MBEVisibleNormal  - buffers that have NOT CHANGED and are +"                                     VISIBLE +"                 MBEVisibleChanged - buffers that have CHANGED and are VISIBLE +" +"               You can either link to an existing highlighting group by +"               adding a command like: +" +"                 hi link MBEVisibleChanged Error +" +"               to your .vimrc or you can specify exact foreground and background +"               colors using the following syntax: +" +"                 hi MBEChanged guibg=darkblue ctermbg=darkblue termbg=white +" +"               NOTE: If you set a colorscheme in your .vimrc you should do it +"                     BEFORE updating the MBE highlighting groups. +" +"               If you use other explorers like TagList you can (As of 6.2.8) put: +" +"                 let g:miniBufExplModSelTarget = 1 +"  +"               into your .vimrc in order to force MBE to try to place selected  +"               buffers into a window that does not have a nonmodifiable buffer. +"               The upshot of this should be that if you go into MBE and select +"               a buffer, the buffer should not show up in a window that is  +"               hosting an explorer. +" +"               There is a VIM bug that can cause buffers to show up without  +"               their highlighting. The following setting will cause MBE to +"               try and turn highlighting back on (introduced in 6.3.1): +" +"                 let g:miniBufExplForceSyntaxEnable = 1 +" +"               MBE has had a basic debugging capability for quite some time. +"               However, it has not been very friendly in the past. As of 6.0.8,  +"               you can put one of each of the following into your .vimrc: +" +"                 let g:miniBufExplorerDebugLevel = 0  " MBE serious errors output +"                 let g:miniBufExplorerDebugLevel = 4  " MBE all errors output +"                 let g:miniBufExplorerDebugLevel = 10 " MBE reports everything +" +"               You can also set a DebugMode to cause output to be target as +"               follows (default is mode 3): +" +"                 let g:miniBufExplorerDebugMode  = 0  " Errors will show up in  +"                                                      " a vim window +"                 let g:miniBufExplorerDebugMode  = 1  " Uses VIM's echo function +"                                                      " to display on the screen +"                 let g:miniBufExplorerDebugMode  = 2  " Writes to a file +"                                                      " MiniBufExplorer.DBG +"                 let g:miniBufExplorerDebugMode  = 3  " Store output in global: +"                                                 " g:miniBufExplorerDebugOutput +" +"               Or if you are able to start VIM, you might just perform these +"               at a command prompt right before you do the operation that is +"               failing. +" +"      History: Moved to end of file +"       +" Known Issues: When debugging is turned on and set to output to a window, there +"               are some cases where the window is opened more than once, there +"               are other cases where an old debug window can be lost. +"  +"               Several MBE commands can break the window history so <C-W>[pnw] +"               might not take you to the expected window. +" +"         Todo: Add the ability to specify a regexp for eligible buffers +"               allowing the ability to filter out certain buffers that  +"               you don't want to control from MBE +" +"============================================================================= +" }}} + +" Startup Check +" +" Has this plugin already been loaded? {{{ +" +if exists('loaded_minibufexplorer') +  finish +endif +let loaded_minibufexplorer = 1 +" }}} + +" Mappings and Commands +" +" MBE Keyboard Mappings {{{ +" If we don't already have keyboard mappings for MBE then create them  +"  +if !hasmapto('<Plug>MiniBufExplorer') +  map <unique> <Leader>mbe <Plug>MiniBufExplorer +endif +if !hasmapto('<Plug>CMiniBufExplorer') +  map <unique> <Leader>mbc <Plug>CMiniBufExplorer +endif +if !hasmapto('<Plug>UMiniBufExplorer') +  map <unique> <Leader>mbu <Plug>UMiniBufExplorer +endif +if !hasmapto('<Plug>TMiniBufExplorer') +  map <unique> <Leader>mbt <Plug>TMiniBufExplorer +endif + +" }}} +" MBE <Script> internal map {{{ +"  +noremap <unique> <script> <Plug>MiniBufExplorer  :call <SID>StartExplorer(1, -1)<CR>:<BS> +noremap <unique> <script> <Plug>CMiniBufExplorer :call <SID>StopExplorer(1)<CR>:<BS> +noremap <unique> <script> <Plug>UMiniBufExplorer :call <SID>AutoUpdate(-1)<CR>:<BS> +noremap <unique> <script> <Plug>TMiniBufExplorer :call <SID>ToggleExplorer()<CR>:<BS> + +" }}} +" MBE commands {{{ +"  +if !exists(':MiniBufExplorer') +  command! MiniBufExplorer  call <SID>StartExplorer(1, -1) +endif +if !exists(':CMiniBufExplorer') +  command! CMiniBufExplorer  call <SID>StopExplorer(1) +endif +if !exists(':UMiniBufExplorer') +  command! UMiniBufExplorer  call <SID>AutoUpdate(-1) +endif +if !exists(':TMiniBufExplorer') +  command! TMiniBufExplorer  call <SID>ToggleExplorer() +endif +if !exists(':MBEbn') +  command! MBEbn call <SID>CycleBuffer(1) +endif +if !exists(':MBEbp') +  command! MBEbp call <SID>CycleBuffer(0) +endif " }}} + +" Global Configuration Variables +" +" Debug Level {{{ +" +" 0 = no logging +" 1=5 = errors ; 1 is the most important +" 5-9 = info ; 5 is the most important +" 10 = Entry/Exit +if !exists('g:miniBufExplorerDebugLevel') +  let g:miniBufExplorerDebugLevel = 0  +endif + +" }}} +" Debug Mode {{{ +" +" 0 = debug to a window +" 1 = use vim's echo facility +" 2 = write to a file named MiniBufExplorer.DBG +"     in the directory where vim was started +"     THIS IS VERY SLOW +" 3 = Write into g:miniBufExplorerDebugOutput +"     global variable [This is the default] +if !exists('g:miniBufExplorerDebugMode') +  let g:miniBufExplorerDebugMode = 3  +endif  + +" }}} +" Allow auto update? {{{ +" +" We start out with this off for startup, but once vim is running we  +" turn this on. +if !exists('g:miniBufExplorerAutoUpdate') +  let g:miniBufExplorerAutoUpdate = 0 +endif + +" }}} +" MoreThanOne? {{{ +" Display Mini Buf Explorer when there are 'More Than One' eligible buffers  +" +if !exists('g:miniBufExplorerMoreThanOne') +  let g:miniBufExplorerMoreThanOne = 2 +endif  + +" }}} +" Split below/above/left/right? {{{ +" When opening a new -MiniBufExplorer- window, split the new windows below or  +" above the current window?  1 = below, 0 = above. +" +if !exists('g:miniBufExplSplitBelow') +  let g:miniBufExplSplitBelow = &splitbelow +endif  + +" }}} +" Split to edge? {{{ +" When opening a new -MiniBufExplorer- window, split the new windows to the +" full edge? 1 = yes, 0 = no. +" +if !exists('g:miniBufExplSplitToEdge') +  let g:miniBufExplSplitToEdge = 1 +endif  + +" }}} +" MaxHeight (depreciated) {{{ +" When sizing the -MiniBufExplorer- window, assign a maximum window height. +" 0 = size to fit all buffers, otherwise the value is number of lines for +" buffer. [Depreciated use g:miniBufExplMaxSize] +" +if !exists('g:miniBufExplMaxHeight') +  let g:miniBufExplMaxHeight = 0 +endif  + +" }}} +" MaxSize {{{ +" Same as MaxHeight but also works for vertical splits if specified with a +" vertical split then vertical resizing will be performed. If left at 0  +" then the number of columns in g:miniBufExplVSplit will be used as a +" static window width. +if !exists('g:miniBufExplMaxSize') +  let g:miniBufExplMaxSize = g:miniBufExplMaxHeight +endif + +" }}} +" MinHeight (depreciated) {{{ +" When sizing the -MiniBufExplorer- window, assign a minumum window height. +" the value is minimum number of lines for buffer. Setting this to zero can +" cause strange height behavior. The default value is 1 [Depreciated use +" g:miniBufExplMinSize] +" +if !exists('g:miniBufExplMinHeight') +  let g:miniBufExplMinHeight = 1 +endif + +" }}} +" MinSize {{{ +" Same as MinHeight but also works for vertical splits. For vertical splits,  +" this is ignored unless g:miniBufExplMax(Size|Height) are specified. +if !exists('g:miniBufExplMinSize') +  let g:miniBufExplMinSize = g:miniBufExplMinHeight +endif + +" }}} +" Horizontal or Vertical explorer? {{{ +" For folks that like vertical explorers, I'm caving in and providing for +" veritcal splits. If this is set to 0 then the current horizontal  +" splitting logic will be run. If however you want a vertical split, +" assign the width (in characters) you wish to assign to the MBE window. +" +if !exists('g:miniBufExplVSplit') +  let g:miniBufExplVSplit = 0 +endif + +" }}} +" TabWrap? {{{ +" By default line wrap is used (possibly breaking a tab name between two +" lines.) Turning this option on (setting it to 1) can take more screen +" space, but will make sure that each tab is on one and only one line. +" +if !exists('g:miniBufExplTabWrap') +  let g:miniBufExplTabWrap = 0 +endif + +" }}} +" Extended window navigation commands? {{{ +" Global flag to turn extended window navigation commands on or off +" enabled = 1, dissabled = 0 +" +if !exists('g:miniBufExplMapWindowNav') +  " This is for backwards compatibility and may be removed in a +  " later release, please use the ...NavVim and/or ...NavArrows  +  " settings. +  let g:miniBufExplMapWindowNav = 0 +endif +if !exists('g:miniBufExplMapWindowNavVim') +  let g:miniBufExplMapWindowNavVim = 0 +endif +if !exists('g:miniBufExplMapWindowNavArrows') +  let g:miniBufExplMapWindowNavArrows = 0 +endif +if !exists('g:miniBufExplMapCTabSwitchBufs') +  let g:miniBufExplMapCTabSwitchBufs = 0 +endif +" Notice: that if CTabSwitchBufs is turned on then +" we turn off CTabSwitchWindows. +if g:miniBufExplMapCTabSwitchBufs == 1 || !exists('g:miniBufExplMapCTabSwitchWindows') +  let g:miniBufExplMapCTabSwitchWindows = 0 +endif  + +" +" If we have enabled control + vim direction key remapping +" then perform the remapping +" +" Notice: I left g:miniBufExplMapWindowNav in for backward +" compatibility. Eventually this mapping will be removed so +" please use the newer g:miniBufExplMapWindowNavVim setting. +if g:miniBufExplMapWindowNavVim || g:miniBufExplMapWindowNav +  noremap <C-J> <C-W>j +  noremap <C-K> <C-W>k +  noremap <C-H> <C-W>h +  noremap <C-L> <C-W>l +endif + +" +" If we have enabled control + arrow key remapping +" then perform the remapping +" +if g:miniBufExplMapWindowNavArrows +  noremap <C-Down>  <C-W>j +  noremap <C-Up>    <C-W>k +  noremap <C-Left>  <C-W>h +  noremap <C-Right> <C-W>l +endif + +" If we have enabled <C-TAB> and <C-S-TAB> to switch buffers +" in the current window then perform the remapping +" +if g:miniBufExplMapCTabSwitchBufs +  noremap <C-TAB>   :call <SID>CycleBuffer(1)<CR>:<BS> +  noremap <C-S-TAB> :call <SID>CycleBuffer(0)<CR>:<BS> +endif + +" +" If we have enabled <C-TAB> and <C-S-TAB> to switch windows +" then perform the remapping +" +if g:miniBufExplMapCTabSwitchWindows +  noremap <C-TAB>   <C-W>w +  noremap <C-S-TAB> <C-W>W +endif + +" }}} +" Modifiable Select Target {{{ +" +if !exists('g:miniBufExplModSelTarget') +  let g:miniBufExplModSelTarget = 0 +endif + +"}}} +" Force Syntax Enable {{{ +" +if !exists('g:miniBufExplForceSyntaxEnable') +  let g:miniBufExplForceSyntaxEnable = 0 +endif + +" }}} +" Single/Double Click? {{{ +" flag that can be set to 1 in a users .vimrc to allow  +" single click switching of tabs. By default we use +" double click for tab selection. +" +if !exists('g:miniBufExplUseSingleClick') +  let g:miniBufExplUseSingleClick = 0 +endif  + +" +" attempt to perform single click mapping, it would be much +" nicer if we could nnoremap <buffer> ... however vim does +" not fire the <buffer> <leftmouse> when you use the mouse +" to enter a buffer. +" +if g:miniBufExplUseSingleClick == 1 +  let s:clickmap = ':if bufname("%") == "-MiniBufExplorer-" <bar> call <SID>MBEClick() <bar> endif <CR>' +  if maparg('<LEFTMOUSE>', 'n') == ''  +    " no mapping for leftmouse +    exec ':nnoremap <silent> <LEFTMOUSE> <LEFTMOUSE>' . s:clickmap +  else +    " we have a mapping +    let  g:miniBufExplDoneClickSave = 1 +    let  s:m = ':nnoremap <silent> <LEFTMOUSE> <LEFTMOUSE>' +    let  s:m = s:m . substitute(substitute(maparg('<LEFTMOUSE>', 'n'), '|', '<bar>', 'g'), '\c^<LEFTMOUSE>', '', '') +    let  s:m = s:m . s:clickmap +    exec s:m +  endif +endif " }}} + +" Variables used internally +" +" Script/Global variables {{{ +" Global used to store the buffer list so we don't update the +" UI unless the list has changed. +if !exists('g:miniBufExplBufList') +  let g:miniBufExplBufList = '' +endif + +" Variable used as a mutex so that we don't do lots +" of AutoUpdates at the same time. +if !exists('g:miniBufExplInAutoUpdate') +  let g:miniBufExplInAutoUpdate = 0 +endif + +" In debug mode 3 this variable will hold the debug output +if !exists('g:miniBufExplorerDebugOutput') +  let g:miniBufExplorerDebugOutput = '' +endif + +" In debug mode 3 this variable will hold the debug output +if !exists('g:miniBufExplForceDisplay') +  let g:miniBufExplForceDisplay = 0 +endif + +" Variable used to pass maxTabWidth info between functions +let s:maxTabWidth = 0  + +" Variable used to count debug output lines +let s:debugIndex = 0  + +   +" }}} +" Setup an autocommand group and some autocommands {{{ +" that keep our explorer updated automatically. +" +augroup MiniBufExplorer +autocmd MiniBufExplorer BufDelete   * call <SID>DEBUG('-=> BufDelete AutoCmd', 10) |call <SID>AutoUpdate(expand('<abuf>')) +autocmd MiniBufExplorer BufEnter    * call <SID>DEBUG('-=> BufEnter  AutoCmd', 10) |call <SID>AutoUpdate(-1) +autocmd MiniBufExplorer VimEnter    * call <SID>DEBUG('-=> VimEnter  AutoCmd', 10) |let g:miniBufExplorerAutoUpdate = 1 |call <SID>AutoUpdate(-1) +" }}} + +" Functions +" +" StartExplorer - Sets up our explorer and causes it to be displayed {{{ +" +function! <SID>StartExplorer(sticky, delBufNum) +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Entering StartExplorer()'   ,10) +  call <SID>DEBUG('===========================',10) + +  if a:sticky == 1 +    let g:miniBufExplorerAutoUpdate = 1 +  endif + +  " Store the current buffer +  let l:curBuf = bufnr('%') + +  " Prevent a report of our actions from showing up. +  let l:save_rep = &report +  let l:save_sc  = &showcmd +  let &report    = 10000 +  set noshowcmd  + +  call <SID>FindCreateWindow('-MiniBufExplorer-', -1, 1, 1) + +  " Make sure we are in our window +  if bufname('%') != '-MiniBufExplorer-' +    call <SID>DEBUG('StartExplorer called in invalid window',1) +    let &report  = l:save_rep +    let &showcmd = l:save_sc +    return +  endif + +  " !!! We may want to make the following optional -- Bindu +  " New windows don't cause all windows to be resized to equal sizes +  set noequalalways +  " !!! We may want to make the following optional -- Bindu +  " We don't want the mouse to change focus without a click +  set nomousefocus + +  " If folks turn numbering and columns on by default we will turn  +  " them off for the MBE window +  setlocal foldcolumn=0 +  setlocal nonumber +  +  if has("syntax") +    syn clear +    syn match MBENormal             '\[[^\]]*\]' +    syn match MBEChanged            '\[[^\]]*\]+' +    syn match MBEVisibleNormal      '\[[^\]]*\]\*+\=' +    syn match MBEVisibleChanged     '\[[^\]]*\]\*+' +     +    if !exists("g:did_minibufexplorer_syntax_inits") +      let g:did_minibufexplorer_syntax_inits = 1 +      hi def link MBENormal         Comment +      hi def link MBEChanged        String +      hi def link MBEVisibleNormal  Special +      hi def link MBEVisibleChanged Special +    endif +  endif + +  " If you press return in the -MiniBufExplorer- then try +  " to open the selected buffer in the previous window. +  nnoremap <buffer> <CR> :call <SID>MBESelectBuffer()<CR>:<BS> +  " If you DoubleClick in the -MiniBufExplorer- then try +  " to open the selected buffer in the previous window. +  nnoremap <buffer> <2-LEFTMOUSE> :call <SID>MBEDoubleClick()<CR>:<BS> +  " If you press d in the -MiniBufExplorer- then try to +  " delete the selected buffer. +  nnoremap <buffer> d :call <SID>MBEDeleteBuffer()<CR>:<BS> +  " If you press w in the -MiniBufExplorer- then switch back +  " to the previous window. +  nnoremap <buffer> p :wincmd p<CR>:<BS> +  " The following allow us to use regular movement keys to  +  " scroll in a wrapped single line buffer +  nnoremap <buffer> j gj +  nnoremap <buffer> k gk +  nnoremap <buffer> <down> gj +  nnoremap <buffer> <up> gk +  " The following allows for quicker moving between buffer +  " names in the [MBE] window it also saves the last-pattern +  " and restores it. +  nnoremap <buffer> <TAB>   :call search('\[[0-9]*:[^\]]*\]')<CR>:<BS> +  nnoremap <buffer> <S-TAB> :call search('\[[0-9]*:[^\]]*\]','b')<CR>:<BS> +  +  call <SID>DisplayBuffers(a:delBufNum) + +  if (l:curBuf != -1) +    call search('\['.l:curBuf.':'.expand('#'.l:curBuf.':t').'\]') +  else +    call <SID>DEBUG('No current buffer to search for',9) +  endif + +  let &report  = l:save_rep +  let &showcmd = l:save_sc + +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Completed StartExplorer()'  ,10) +  call <SID>DEBUG('===========================',10) + +endfunction  + +" }}} +" StopExplorer - Looks for our explorer and closes the window if it is open {{{ +" +function! <SID>StopExplorer(sticky) +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Entering StopExplorer()'    ,10) +  call <SID>DEBUG('===========================',10) + +  if a:sticky == 1 +    let g:miniBufExplorerAutoUpdate = 0 +  endif + +  let l:winNum = <SID>FindWindow('-MiniBufExplorer-', 1) + +  if l:winNum != -1  +    exec l:winNum.' wincmd w' +    silent! close +    wincmd p +  endif + +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Completed StopExplorer()'   ,10) +  call <SID>DEBUG('===========================',10) + +endfunction + +" }}} +" ToggleExplorer - Looks for our explorer and opens/closes the window {{{ +" +function! <SID>ToggleExplorer() +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Entering ToggleExplorer()'  ,10) +  call <SID>DEBUG('===========================',10) + +  let g:miniBufExplorerAutoUpdate = 0 + +  let l:winNum = <SID>FindWindow('-MiniBufExplorer-', 1) + +  if l:winNum != -1  +    call <SID>StopExplorer(1) +  else +    call <SID>StartExplorer(1, -1) +    wincmd p +  endif + +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Completed ToggleExplorer()' ,10) +  call <SID>DEBUG('===========================',10) + +endfunction + +" }}} +" FindWindow - Return the window number of a named buffer {{{ +" If none is found then returns -1.  +" +function! <SID>FindWindow(bufName, doDebug) +  if a:doDebug +    call <SID>DEBUG('Entering FindWindow()',10) +  endif + +  " Try to find an existing window that contains  +  " our buffer. +  let l:bufNum = bufnr(a:bufName) +  if l:bufNum != -1 +    if a:doDebug +      call <SID>DEBUG('Found buffer ('.a:bufName.'): '.l:bufNum,9) +    endif +    let l:winNum = bufwinnr(l:bufNum) +  else +    let l:winNum = -1 +  endif + +  return l:winNum + +endfunction + +" }}} +" FindCreateWindow - Attempts to find a window for a named buffer. {{{ +" +" If it is found then moves there. Otherwise creates a new window and  +" configures it and moves there. +" +" forceEdge, -1 use defaults, 0 below, 1 above +" isExplorer, 0 no, 1 yes  +" doDebug, 0 no, 1 yes +" +function! <SID>FindCreateWindow(bufName, forceEdge, isExplorer, doDebug) +  if a:doDebug +    call <SID>DEBUG('Entering FindCreateWindow('.a:bufName.')',10) +  endif + +  " Save the user's split setting. +  let l:saveSplitBelow = &splitbelow + +  " Set to our new values. +  let &splitbelow = g:miniBufExplSplitBelow + +  " Try to find an existing explorer window +  let l:winNum = <SID>FindWindow(a:bufName, a:doDebug) + +  " If found goto the existing window, otherwise  +  " split open a new window. +  if l:winNum != -1 +    if a:doDebug +      call <SID>DEBUG('Found window ('.a:bufName.'): '.l:winNum,9) +    endif +    exec l:winNum.' wincmd w' +    let l:winFound = 1 +  else + +    if g:miniBufExplSplitToEdge == 1 || a:forceEdge >= 0 + +        let l:edge = &splitbelow +        if a:forceEdge >= 0 +            let l:edge = a:forceEdge +        endif + +        if l:edge +            if g:miniBufExplVSplit == 0 +              exec 'bo sp '.a:bufName +            else +              exec 'bo vsp '.a:bufName +            endif +        else +            if g:miniBufExplVSplit == 0 +              exec 'to sp '.a:bufName +            else +              exec 'to vsp '.a:bufName +            endif +        endif +    else +        if g:miniBufExplVSplit == 0 +          exec 'sp '.a:bufName +        else +          " &splitbelow doesn't affect vertical splits +          " so we have to do this explicitly.. ugh. +          if &splitbelow +            exec 'rightb vsp '.a:bufName +          else +            exec 'vsp '.a:bufName +          endif +        endif +    endif + +    let g:miniBufExplForceDisplay = 1 + +    " Try to find an existing explorer window +    let l:winNum = <SID>FindWindow(a:bufName, a:doDebug) +    if l:winNum != -1 +      if a:doDebug +        call <SID>DEBUG('Created and then found window ('.a:bufName.'): '.l:winNum,9) +      endif +      exec l:winNum.' wincmd w' +    else +      if a:doDebug +        call <SID>DEBUG('FindCreateWindow failed to create window ('.a:bufName.').',1) +      endif +      return +    endif + +    if a:isExplorer +      " Turn off the swapfile, set the buffer type so that it won't get written, +      " and so that it will get deleted when it gets hidden and turn on word wrap. +      setlocal noswapfile +      setlocal buftype=nofile +      setlocal bufhidden=delete +      if g:miniBufExplVSplit == 0 +        setlocal wrap +      else +        setlocal nowrap +        exec('setlocal winwidth='.g:miniBufExplMinSize) +      endif +    endif + +    if a:doDebug +      call <SID>DEBUG('Window ('.a:bufName.') created: '.winnr(),9) +    endif + +  endif + +  " Restore the user's split setting. +  let &splitbelow = l:saveSplitBelow + +endfunction + +" }}} +" DisplayBuffers - Wrapper for getting MBE window shown {{{ +" +" Makes sure we are in our explorer, then erases the current buffer and turns  +" it into a mini buffer explorer window. +" +function! <SID>DisplayBuffers(delBufNum) +  call <SID>DEBUG('Entering DisplayBuffers()',10) +   +  " Make sure we are in our window +  if bufname('%') != '-MiniBufExplorer-' +    call <SID>DEBUG('DisplayBuffers called in invalid window',1) +    return +  endif + +  " We need to be able to modify the buffer +  setlocal modifiable + +  call <SID>ShowBuffers(a:delBufNum) +  call <SID>ResizeWindow() +   +  normal! zz +   +  " Prevent the buffer from being modified. +  setlocal nomodifiable +  set nobuflisted + +endfunction + +" }}} +" Resize Window - Set width/height of MBE window {{{ +"  +" Makes sure we are in our explorer, then sets the height/width for our explorer  +" window so that we can fit all of our information without taking extra lines. +" +function! <SID>ResizeWindow() +  call <SID>DEBUG('Entering ResizeWindow()',10) + +  " Make sure we are in our window +  if bufname('%') != '-MiniBufExplorer-' +    call <SID>DEBUG('ResizeWindow called in invalid window',1) +    return +  endif + +  let l:width  = winwidth('.') + +  " Horizontal Resize +  if g:miniBufExplVSplit == 0 + +    if g:miniBufExplTabWrap == 0 +      let l:length = strlen(getline('.')) +      let l:height = 0 +      if (l:width == 0) +        let l:height = winheight('.') +      else +        let l:height = (l:length / l:width)  +        " handle truncation from div +        if (l:length % l:width) != 0 +          let l:height = l:height + 1 +        endif +      endif +    else +      exec("setlocal textwidth=".l:width) +      normal gg +      normal gq} +      normal G +      let l:height = line('.') +      normal gg +    endif +   +    " enforce max window height +    if g:miniBufExplMaxSize != 0 +      if g:miniBufExplMaxSize < l:height +        let l:height = g:miniBufExplMaxSize +      endif +    endif +   +    " enfore min window height +    if l:height < g:miniBufExplMinSize || l:height == 0 +      let l:height = g:miniBufExplMinSize +    endif +   +    call <SID>DEBUG('ResizeWindow to '.l:height.' lines',9) +   +    exec('resize '.l:height) +   +  " Vertical Resize +  else  + +    if g:miniBufExplMaxSize != 0 +      let l:newWidth = s:maxTabWidth +      if l:newWidth > g:miniBufExplMaxSize  +          let l:newWidth = g:miniBufExplMaxSize +      endif +      if l:newWidth < g:miniBufExplMinSize +          let l:newWidth = g:miniBufExplMinSize +      endif +    else +      let l:newWidth = g:miniBufExplVSplit +    endif + +    if l:width != l:newWidth +      call <SID>DEBUG('ResizeWindow to '.l:newWidth.' columns',9) +      exec('vertical resize '.l:newWidth) +    endif + +  endif +   +endfunction + +" }}} +" ShowBuffers - Clear current buffer and put the MBE text into it {{{ +"  +" Makes sure we are in our explorer, then adds a list of all modifiable  +" buffers to the current buffer. Special marks are added for buffers that  +" are in one or more windows (*) and buffers that have been modified (+) +" +function! <SID>ShowBuffers(delBufNum) +  call <SID>DEBUG('Entering ShowBuffers()',10) + +  let l:ListChanged = <SID>BuildBufferList(a:delBufNum, 1) + +  if (l:ListChanged == 1 || g:miniBufExplForceDisplay) +    let l:save_rep = &report +    let l:save_sc = &showcmd +    let &report = 10000 +    set noshowcmd  + +    " Delete all lines in buffer. +    1,$d _ +   +    " Goto the end of the buffer put the buffer list  +    " and then delete the extra trailing blank line +    $ +    put! =g:miniBufExplBufList +    $ d _ + +    let g:miniBufExplForceDisplay = 0 + +    let &report  = l:save_rep +    let &showcmd = l:save_sc +  else +    call <SID>DEBUG('Buffer list not update since there was no change',9) +  endif +   +endfunction + +" }}} +" Max - Returns the max of two numbers {{{ +" +function! <SID>Max(argOne, argTwo) +  if a:argOne > a:argTwo +    return a:argOne +  else +    return a:argTwo +  endif +endfunction + +" }}} +" BuildBufferList - Build the text for the MBE window {{{ +"  +" Creates the buffer list string and returns 1 if it is different than +" last time this was called and 0 otherwise. +" +function! <SID>BuildBufferList(delBufNum, updateBufList) +  call <SID>DEBUG('Entering BuildBufferList()',10) + +  let l:NBuffers = bufnr('$')     " Get the number of the last buffer. +  let l:i = 0                     " Set the buffer index to zero. + +  let l:fileNames = '' +  let l:maxTabWidth = 0 + +  " Loop through every buffer less than the total number of buffers. +  while(l:i <= l:NBuffers) +    let l:i = l:i + 1 +    +    " If we have a delBufNum and it is the current +    " buffer then ignore the current buffer.  +    " Otherwise, continue. +    if (a:delBufNum == -1 || l:i != a:delBufNum) +      " Make sure the buffer in question is listed. +      if(getbufvar(l:i, '&buflisted') == 1) +        " Get the name of the buffer. +        let l:BufName = bufname(l:i) +        " Check to see if the buffer is a blank or not. If the buffer does have +        " a name, process it. +        if(strlen(l:BufName)) +          " Only show modifiable buffers (The idea is that we don't  +          " want to show Explorers) +          if (getbufvar(l:i, '&modifiable') == 1 && BufName != '-MiniBufExplorer-') +             +            " Get filename & Remove []'s & ()'s +            let l:shortBufName = fnamemodify(l:BufName, ":t")                   +            let l:shortBufName = substitute(l:shortBufName, '[][()]', '', 'g')  +            let l:tab = '['.l:i.':'.l:shortBufName.']' + +            " If the buffer is open in a window mark it +            if bufwinnr(l:i) != -1 +              let l:tab = l:tab . '*' +            endif + +            " If the buffer is modified then mark it +            if(getbufvar(l:i, '&modified') == 1) +              let l:tab = l:tab . '+' +            endif + +            let l:maxTabWidth = <SID>Max(strlen(l:tab), l:maxTabWidth) +            let l:fileNames = l:fileNames.l:tab + +            " If horizontal and tab wrap is turned on we need to add spaces +            if g:miniBufExplVSplit == 0 +              if g:miniBufExplTabWrap != 0 +                let l:fileNames = l:fileNames.' ' +              endif +            " If not horizontal we need a newline +            else +              let l:fileNames = l:fileNames . "\n" +            endif +          endif +        endif +      endif +    endif +  endwhile + +  if (g:miniBufExplBufList != l:fileNames) +    if (a:updateBufList) +      let g:miniBufExplBufList = l:fileNames +      let s:maxTabWidth = l:maxTabWidth +    endif +    return 1 +  else +    return 0 +  endif + +endfunction + +" }}} +" HasEligibleBuffers - Are there enough MBE eligible buffers to open the MBE window? {{{ +"  +" Returns 1 if there are any buffers that can be displayed in a  +" mini buffer explorer. Otherwise returns 0. If delBufNum is +" any non -1 value then don't include that buffer in the list +" of eligible buffers. +" +function! <SID>HasEligibleBuffers(delBufNum) +  call <SID>DEBUG('Entering HasEligibleBuffers()',10) + +  let l:save_rep = &report +  let l:save_sc = &showcmd +  let &report = 10000 +  set noshowcmd  +   +  let l:NBuffers = bufnr('$')     " Get the number of the last buffer. +  let l:i        = 0              " Set the buffer index to zero. +  let l:found    = 0              " No buffer found + +  if (g:miniBufExplorerMoreThanOne > 1) +    call <SID>DEBUG('More Than One mode turned on',6) +  endif +  let l:needed = g:miniBufExplorerMoreThanOne + +  " Loop through every buffer less than the total number of buffers. +  while(l:i <= l:NBuffers && l:found < l:needed) +    let l:i = l:i + 1 +    +    " If we have a delBufNum and it is the current +    " buffer then ignore the current buffer.  +    " Otherwise, continue. +    if (a:delBufNum == -1 || l:i != a:delBufNum) +      " Make sure the buffer in question is listed. +      if (getbufvar(l:i, '&buflisted') == 1) +        " Get the name of the buffer. +        let l:BufName = bufname(l:i) +        " Check to see if the buffer is a blank or not. If the buffer does have +        " a name, process it. +        if (strlen(l:BufName)) +          " Only show modifiable buffers (The idea is that we don't  +          " want to show Explorers) +          if ((getbufvar(l:i, '&modifiable') == 1) && (BufName != '-MiniBufExplorer-')) +             +              let l:found = l:found + 1 +   +          endif +        endif +      endif +    endif +  endwhile + +  let &report  = l:save_rep +  let &showcmd = l:save_sc + +  call <SID>DEBUG('HasEligibleBuffers found '.l:found.' eligible buffers of '.l:needed.' needed',6) + +  return (l:found >= l:needed) +   +endfunction + +" }}} +" Auto Update - Function called by auto commands for auto updating the MBE {{{ +" +" IF auto update is turned on        AND +"    we are in a real buffer         AND +"    we have enough eligible buffers THEN +" Update our explorer and get back to the current window +" +" If we get a buffer number for a buffer that  +" is being deleted, we need to make sure and  +" remove the buffer from the list of eligible  +" buffers in case we are down to one eligible +" buffer, in which case we will want to close +" the MBE window. +" +function! <SID>AutoUpdate(delBufNum) +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Entering AutoUpdate('.a:delBufNum.') : '.bufnr('%').' : '.bufname('%'),10) +  call <SID>DEBUG('===========================',10) + +  if (g:miniBufExplInAutoUpdate == 1) +    call <SID>DEBUG('AutoUpdate recursion stopped',9) +    call <SID>DEBUG('===========================',10) +    call <SID>DEBUG('Terminated AutoUpdate()'    ,10) +    call <SID>DEBUG('===========================',10) +    return +  else +    let g:miniBufExplInAutoUpdate = 1 +  endif + +  " Don't bother autoupdating the MBE window +  if (bufname('%') == '-MiniBufExplorer-') +    " If this is the only buffer left then toggle the buffer +    if (winbufnr(2) == -1) +        call <SID>CycleBuffer(1) +        call <SID>DEBUG('AutoUpdate does not run for cycled windows', 9) +    else +      call <SID>DEBUG('AutoUpdate does not run for the MBE window', 9) +    endif + +    call <SID>DEBUG('===========================',10) +    call <SID>DEBUG('Terminated AutoUpdate()'    ,10) +    call <SID>DEBUG('===========================',10) + +    let g:miniBufExplInAutoUpdate = 0 +    return + +  endif + +  if (a:delBufNum != -1) +    call <SID>DEBUG('AutoUpdate will make sure that buffer '.a:delBufNum.' is not included in the buffer list.', 5) +  endif +   +  " Only allow updates when the AutoUpdate flag is set +  " this allows us to stop updates on startup. +  if g:miniBufExplorerAutoUpdate == 1 +    " Only show MiniBufExplorer if we have a real buffer +    if ((g:miniBufExplorerMoreThanOne == 0) || (bufnr('%') != -1 && bufname('%') != "")) +      if <SID>HasEligibleBuffers(a:delBufNum) == 1 +        " if we don't have a window then create one +        let l:bufnr = <SID>FindWindow('-MiniBufExplorer-', 0) +        if (l:bufnr == -1) +          call <SID>DEBUG('About to call StartExplorer (Create MBE)', 9) +          call <SID>StartExplorer(0, a:delBufNum) +        else +        " otherwise only update the window if the contents have +        " changed +          let l:ListChanged = <SID>BuildBufferList(a:delBufNum, 0) +          if (l:ListChanged) +            call <SID>DEBUG('About to call StartExplorer (Update MBE)', 9)  +            call <SID>StartExplorer(0, a:delBufNum) +          endif +        endif + +        " go back to the working buffer +        if (bufname('%') == '-MiniBufExplorer-') +          wincmd p +        endif +      else +        call <SID>DEBUG('Failed in eligible check', 9) +        call <SID>StopExplorer(0) +      endif + +	  " VIM sometimes turns syntax highlighting off, +	  " we can force it on, but this may cause weird +	  " behavior so this is an optional hack to force +	  " syntax back on when we enter a buffer +	  if g:miniBufExplForceSyntaxEnable +		call <SID>DEBUG('Enable Syntax', 9) +		exec 'syntax enable' +	  endif + +    else +      call <SID>DEBUG('No buffers loaded...',9) +    endif +  else +    call <SID>DEBUG('AutoUpdates are turned off, terminating',9) +  endif + +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Completed AutoUpdate()'     ,10) +  call <SID>DEBUG('===========================',10) + +  let g:miniBufExplInAutoUpdate = 0 + +endfunction + +" }}} +" GetSelectedBuffer - From the MBE window, return the bufnum for buf under cursor {{{ +"  +" If we are in our explorer window then return the buffer number +" for the buffer under the cursor. +" +function! <SID>GetSelectedBuffer() +  call <SID>DEBUG('Entering GetSelectedBuffer()',10) + +  " Make sure we are in our window +  if bufname('%') != '-MiniBufExplorer-' +    call <SID>DEBUG('GetSelectedBuffer called in invalid window',1) +    return -1 +  endif + +  let l:save_reg = @" +  let @" = "" +  normal ""yi[ +  if @" != "" +    let l:retv = substitute(@",'\([0-9]*\):.*', '\1', '') + 0 +    let @" = l:save_reg +    return l:retv +  else +    let @" = l:save_reg +    return -1 +  endif + +endfunction + +" }}} +" MBESelectBuffer - From the MBE window, open buffer under the cursor {{{ +"  +" If we are in our explorer, then we attempt to open the buffer under the +" cursor in the previous window. +" +function! <SID>MBESelectBuffer() +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Entering MBESelectBuffer()' ,10) +  call <SID>DEBUG('===========================',10) + +  " Make sure we are in our window +  if bufname('%') != '-MiniBufExplorer-' +    call <SID>DEBUG('MBESelectBuffer called in invalid window',1) +    return  +  endif + +  let l:save_rep = &report +  let l:save_sc  = &showcmd +  let &report    = 10000 +  set noshowcmd  +   +  let l:bufnr  = <SID>GetSelectedBuffer() +  let l:resize = 0 + +  if(l:bufnr != -1)             " If the buffer exists. + +    let l:saveAutoUpdate = g:miniBufExplorerAutoUpdate +    let g:miniBufExplorerAutoUpdate = 0 +    " Switch to the previous window +    wincmd p + +    " If we are in the buffer explorer or in a nonmodifiable buffer with +    " g:miniBufExplModSelTarget set then try another window (a few times) +    if bufname('%') == '-MiniBufExplorer-' || (g:miniBufExplModSelTarget == 1 && getbufvar(bufnr('%'), '&modifiable') == 0) +      wincmd w +      if bufname('%') == '-MiniBufExplorer-' || (g:miniBufExplModSelTarget == 1 && getbufvar(bufnr('%'), '&modifiable') == 0) +        wincmd w +        if bufname('%') == '-MiniBufExplorer-' || (g:miniBufExplModSelTarget == 1 && getbufvar(bufnr('%'), '&modifiable') == 0) +          wincmd w +          " The following handles the case where -MiniBufExplorer- +          " is the only window left. We need to resize so we don't +          " end up with a 1 or two line buffer. +          if bufname('%') == '-MiniBufExplorer-' +            let l:resize = 1 +          endif +        endif +      endif +    endif + +    exec('b! '.l:bufnr) +    if (l:resize) +      resize +    endif +    let g:miniBufExplorerAutoUpdate = l:saveAutoUpdate +    call <SID>AutoUpdate(-1) + +  endif + +  let &report  = l:save_rep +  let &showcmd = l:save_sc + +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Completed MBESelectBuffer()',10) +  call <SID>DEBUG('===========================',10) + +endfunction + +" }}} +" MBEDeleteBuffer - From the MBE window, delete selected buffer from list {{{ +"  +" After making sure that we are in our explorer, This will delete the buffer  +" under the cursor. If the buffer under the cursor is being displayed in a +" window, this routine will attempt to get different buffers into the  +" windows that will be affected so that windows don't get removed. +" +function! <SID>MBEDeleteBuffer() +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Entering MBEDeleteBuffer()' ,10) +  call <SID>DEBUG('===========================',10) + +  " Make sure we are in our window +  if bufname('%') != '-MiniBufExplorer-' +    call <SID>DEBUG('MBEDeleteBuffer called in invalid window',1) +    return  +  endif + +  let l:curLine    = line('.') +  let l:curCol     = virtcol('.') +  let l:selBuf     = <SID>GetSelectedBuffer() +  let l:selBufName = bufname(l:selBuf) + +  if l:selBufName == 'MiniBufExplorer.DBG' && g:miniBufExplorerDebugLevel > 0 +    call <SID>DEBUG('MBEDeleteBuffer will not delete the debug window, when debugging is turned on.',1) +    return +  endif + +  let l:save_rep = &report +  let l:save_sc  = &showcmd +  let &report    = 10000 +  set noshowcmd  +   +   +  if l:selBuf != -1  + +    " Don't want auto updates while we are processing a delete +    " request. +    let l:saveAutoUpdate = g:miniBufExplorerAutoUpdate +    let g:miniBufExplorerAutoUpdate = 0 + +    " Save previous window so that if we show a buffer after +    " deleting. The show will come up in the correct window. +    wincmd p +    let l:prevWin    = winnr() +    let l:prevWinBuf = winbufnr(winnr()) + +    call <SID>DEBUG('Previous window: '.l:prevWin.' buffer in window: '.l:prevWinBuf,5) +    call <SID>DEBUG('Selected buffer is <'.l:selBufName.'>['.l:selBuf.']',5) + +    " If buffer is being displayed in a window then  +    " move window to a different buffer before  +    " deleting this one.  +    let l:winNum = (bufwinnr(l:selBufName) + 0) +    " while we have windows that contain our buffer +    while l:winNum != -1  +        call <SID>DEBUG('Buffer '.l:selBuf.' is being displayed in window: '.l:winNum,5) + +        " move to window that contains our selected buffer +        exec l:winNum.' wincmd w' + +        call <SID>DEBUG('We are now in window: '.winnr().' which contains buffer: '.bufnr('%').' and should contain buffer: '.l:selBuf,5) + +        let l:origBuf = bufnr('%') +        call <SID>CycleBuffer(1) +        let l:curBuf  = bufnr('%') + +        call <SID>DEBUG('Window now contains buffer: '.bufnr('%').' which should not be: '.l:selBuf,5) + +        if l:origBuf == l:curBuf +            " we wrapped so we are going to have to delete a buffer  +            " that is in an open window. +            let l:winNum = -1 +        else +            " see if we have anymore windows with our selected buffer +            let l:winNum = (bufwinnr(l:selBufName) + 0) +        endif +    endwhile + +    " Attempt to restore previous window +    call <SID>DEBUG('Restoring previous window to: '.l:prevWin,5) +    exec l:prevWin.' wincmd w' + +    " Try to get back to the -MiniBufExplorer- window  +    let l:winNum = bufwinnr(bufnr('-MiniBufExplorer-')) +    if l:winNum != -1 +        exec l:winNum.' wincmd w' +        call <SID>DEBUG('Got to -MiniBufExplorer- window: '.winnr(),5) +    else +        call <SID>DEBUG('Unable to get to -MiniBufExplorer- window',1) +    endif +   +    " Delete the buffer selected. +    call <SID>DEBUG('About to delete buffer: '.l:selBuf,5) +    exec('silent! bd '.l:selBuf) + +    let g:miniBufExplorerAutoUpdate = l:saveAutoUpdate  +    call <SID>DisplayBuffers(-1) +    call cursor(l:curLine, l:curCol) + +  endif + +  let &report  = l:save_rep +  let &showcmd = l:save_sc + +  call <SID>DEBUG('===========================',10) +  call <SID>DEBUG('Completed MBEDeleteBuffer()',10) +  call <SID>DEBUG('===========================',10) + +endfunction + +" }}} +" MBEClick - Handle mouse double click {{{ +" +function! s:MBEClick() +  call <SID>DEBUG('Entering MBEClick()',10) +  call <SID>MBESelectBuffer() +endfunction + +" +" MBEDoubleClick - Double click with the mouse. +" +function! s:MBEDoubleClick() +  call <SID>DEBUG('Entering MBEDoubleClick()',10) +  call <SID>MBESelectBuffer() +endfunction + +" }}} +" CycleBuffer - Cycle Through Buffers {{{ +" +" Move to next or previous buffer in the current window. If there  +" are no more modifiable buffers then stay on the current buffer. +" can be called with no parameters in which case the buffers are +" cycled forward. Otherwise a single argument is accepted, if  +" it's 0 then the buffers are cycled backwards, otherwise they +" are cycled forward. +" +function! <SID>CycleBuffer(forward) + +  " The following hack handles the case where we only have one +  " window open and it is too small +  let l:saveAutoUpdate = g:miniBufExplorerAutoUpdate +  if (winbufnr(2) == -1) +    resize +    let g:miniBufExplorerAutoUpdate = 0 +  endif +   +  " Change buffer (keeping track of before and after buffers) +  let l:origBuf = bufnr('%') +  if (a:forward == 1) +    bn! +  else +    bp! +  endif +  let l:curBuf  = bufnr('%') + +  " Skip any non-modifiable buffers, but don't cycle forever +  " This should stop us from stopping in any of the [Explorers] +  while getbufvar(l:curBuf, '&modifiable') == 0 && l:origBuf != l:curBuf +    if (a:forward == 1) +        bn! +    else +        bp! +    endif +    let l:curBuf = bufnr('%') +  endwhile + +  let g:miniBufExplorerAutoUpdate = l:saveAutoUpdate +  if (l:saveAutoUpdate == 1) +    call <SID>AutoUpdate(-1) +  endif + +endfunction + +" }}} +" DEBUG - Display debug output when debugging is turned on {{{ +" +" Thanks to Charles E. Campbell, Jr. PhD <cec@NgrOyphSon.gPsfAc.nMasa.gov>  +" for Decho.vim which was the inspiration for this enhanced debugging  +" capability. +" +function! <SID>DEBUG(msg, level) + +  if g:miniBufExplorerDebugLevel >= a:level + +    " Prevent a report of our actions from showing up. +    let l:save_rep    = &report +    let l:save_sc     = &showcmd +    let &report       = 10000 +    set noshowcmd  + +    " Debug output to a buffer +    if g:miniBufExplorerDebugMode == 0 +        " Save the current window number so we can come back here +        let l:prevWin     = winnr() +        wincmd p +        let l:prevPrevWin = winnr() +        wincmd p + +        " Get into the debug window or create it if needed +        call <SID>FindCreateWindow('MiniBufExplorer.DBG', 1, 0, 0) +     +        " Make sure we really got to our window, if not we  +        " will display a confirm dialog and turn debugging +        " off so that we won't break things even more. +        if bufname('%') != 'MiniBufExplorer.DBG' +            call confirm('Error in window debugging code. Dissabling MiniBufExplorer debugging.', 'OK') +            let g:miniBufExplorerDebugLevel = 0 +        endif + +        " Write Message to DBG buffer +        let res=append("$",s:debugIndex.':'.a:level.':'.a:msg) +        norm G +        "set nomodified + +        " Return to original window +        exec l:prevPrevWin.' wincmd w' +        exec l:prevWin.' wincmd w' +    " Debug output using VIM's echo facility +    elseif g:miniBufExplorerDebugMode == 1 +      echo s:debugIndex.':'.a:level.':'.a:msg +    " Debug output to a file -- VERY SLOW!!! +    " should be OK on UNIX and Win32 (not the 95/98 variants) +    elseif g:miniBufExplorerDebugMode == 2 +        if has('system') || has('fork') +            if has('win32') && !has('win95') +                let l:result = system("cmd /c 'echo ".s:debugIndex.':'.a:level.':'.a:msg." >> MiniBufExplorer.DBG'") +            endif +            if has('unix') +                let l:result = system("echo '".s:debugIndex.':'.a:level.':'.a:msg." >> MiniBufExplorer.DBG'") +            endif +        else +            call confirm('Error in file writing version of the debugging code, vim not compiled with system or fork. Dissabling MiniBufExplorer debugging.', 'OK') +            let g:miniBufExplorerDebugLevel = 0 +        endif +    elseif g:miniBufExplorerDebugMode == 3 +        let g:miniBufExplorerDebugOutput = g:miniBufExplorerDebugOutput."\n".s:debugIndex.':'.a:level.':'.a:msg +    endif +    let s:debugIndex = s:debugIndex + 1 + +    let &report  = l:save_rep +    let &showcmd = l:save_sc + +  endif + +endfunc " }}} + +" MBE Script History {{{ +"============================================================================= +" +"      History: 6.3.2 o For some reason there was still a call to StopExplorer +"                       with 2 params. Very old bug. I know I fixed before,  +"                       any way many thanks to Jason Mills for reporting this! +"               6.3.1 o Include folds in source so that it's easier to  +"                       navigate. +"                     o Added g:miniBufExplForceSyntaxEnable setting for folks +"                       that want a :syntax enable to be called when we enter  +"                       buffers. This can resolve issues caused by a vim bug +"                       where buffers show up without highlighting when another  +"                       buffer has been closed, quit, wiped or deleted. +"               6.3.0 o Added an option to allow single click (rather than +"                       the default double click) to select buffers in the +"                       MBE window. This feature was requested by AW Law +"                       and was inspired by taglist.vim. Note that you will  +"                       need the latest version of taglist.vim if you want to  +"                       use MBE and taglist both with singleclick turned on. +"                       Also thanks to AW Law for pointing out that you can +"                       make an Explorer not be listed in a standard :ls. +"                     o Added the ability to have your tabs show up in a +"                       vertical window rather than the standard horizontal +"                       one. Just let g:miniBufExplVSplit = <width> in your +"                       .vimrc and your will get this functionality. +"                     o If you use the vertical explorer and you want it to +"                       autosize then let g:miniBufExplMaxSize = <max width> +"                       in your .vimrc. You may use the MinSize letting in +"                       addition to the MaxLetting if you don't want a super +"                       thin window. +"                     o g:miniBufExplMaxHeight was renamed g:miniBufExplMaxSize +"                       g:miniBufExplMinHeight was renamed g:miniBufExplMinSize +"                       the old settings are backwards compatible if you don't +"                       use the new settings, but they are depreciated. +"               6.2.8 o Add an option to stop MBE from targeting non-modifiable +"                       buffers when switching buffers. Thanks to AW Law for +"                       the inspiration for this. This may not work if a user +"                       has lots of explorer/help windows open. +"               6.2.7 o Very minor bug fix for people who want to set +"                       loaded_minibufexplorer in their .vimrc in order to +"                       stop MBE from loading. 99.99% of users do not need +"                       this update. +"               6.2.6 o Moved history to end of source file +"                     o Updated highlighting documentation +"                     o Created global commands MBEbn and MBEbp that can be  +"                       used in mappings if folks want to cycle buffers while  +"                       skipping non-eligible buffers. +"               6.2.5 o Added <Leader>mbt key mapping which will toggle +"                       the MBE window. I map this to F3 in my .vimrc +"                       with "map <F3> :TMiniBufExplorer<CR>" which  +"                       means I can easily close the MBE window when I'm  +"                       not using it and get it back when I want it. +"                     o Changed default debug mode to 3 (write to global +"                       g:miniBufExplorerDebugOutput) +"                     o Made a pass through the documentation to clarify  +"                       serveral issues and provide more complete docs +"                       for mappings and commands. +"               6.2.4 o Because of the autocommand switch (see 6.2.0) it  +"                       was possible to remove the restriction on the +"                       :set hidden option. It is now possible to use +"                       this option with MBE. +"               6.2.3 o Added miniBufExplTabWrap option. It is turned  +"                       off by default. When turned on spaces are added +"                       between tabs and gq} is issued to perform line +"                       formatting. This won't work very well if filenames +"                       contain spaces. It would be pretty easy to write +"                       my own formatter, but I'm too lazy, so if someone +"                       really needs that feature I'll add it :) +"               6.2.2 o Changed the way the g:miniBufExplorerMoreThanOne +"                       global is handled. You can set this to the number +"                       of eligible buffers you want to be loaded before +"                       the MBE window is loaded. Setting it to 0 causes +"                       the MBE window to be opened even if there are no +"                       buffers. Setting it to 4 causes the window to stay +"                       closed until the 4th eligible buffer is loaded. +"                     o Added a MinHeight option. This is nice if you want +"                       the MBE window to always take the same amount of +"                       space. For example set MaxSize and MinSize to 2 +"                       and set MoreThanOne to 0 and you will always have +"                       a 2 row (plus the ruler :) MBE window. +"                       NOTE: in 6.3.0 we started using MinSize instead of +"                       Minheight. This will still work if MinSize is not +"                       specified, but it is depreciated. Use MinSize instead. +"                     o I now setlocal foldcomun=0 and nonumber in the MBE  +"                       window. This is for those of you that like to have +"                       these options turned on locally. I'm assuming noone +"                       outthere wants foldcolumns and line numbers in the +"                       MBE window? :) +"                     o Fixed a bug where an empty MBE window was taking half +"                       of the screen (partly why the MinHeight option was  +"                       added.) +"               6.2.1 o If MBE is the only window (because of :bd for example) +"                       and there are still eligible buffers then one of them +"                       will be displayed. +"                     o The <Leader>mbe mapping now highlights the buffer from +"                       the current window. +"                     o The delete ('d') binding in the MBE window now restors +"                       the cursor position, which can help if you want to  +"                       delete several buffers in a row that are not at the +"                       beginning of the buffer list. +"                     o Added a new key binding ('p') in the MBE window to  +"                       switch to the previous window (last edit window) +"               6.2.0 o Major overhaul of autocommand and list updating code, +"                       we now have much better handling of :bd (which is the  +"                       most requested feature.) As well as resolving other +"                       issues where the buffer list would not be updated +"                       automatically. The old version tried to trap specific +"                       events, this one just updates frequently, but it keeps +"                       track and only changes the screen if there has been +"                       a change. +"                     o Added g:miniBufExplMaxHeight variable so you can keep +"                       the -MiniBufExplorer- window small when you have lots +"                       of buffers (or buffers with long names :) +"                       NOTE: in 6.3.0 we started using MaxSize instead of +"                       MaxHeight. This will still work if MaxSize is not +"                       specified, but it is depreciated. Use MaxSize instead. +"                     o Improvement to internal syntax highlighting code +"                       I renamed the syntax group names. Anyone who has  +"                       figured out how to use them already shouldn't have +"                       any trouble with the new Nameing :) +"                     o Added debug mode 3 which writes to a global variable +"                       this is fast and doesn't mess with the buffer/window +"                       lists. +"               6.1.0 o <Leader>mbc was failing because I was calling one of +"                       my own functions with the wrong number of args. :( +"                       Thanks to Gerry Patterson for finding this! +"                       This code is very stable (although it has some +"                       idiocyncracies.) +"               6.0.9 o Double clicking tabs was overwriting the cliboard  +"                       register on MS Windows.  Thanks to Shoeb Bhinderwala  +"                       for reporting this issue. +"               6.0.8 o Apparently some VIM builds are having a hard time with +"                       line continuation in scripts so the few that were here +"                       have been removed. +"                     o Generalized FindExplorer and FindCreateExplorer so +"                       that they can be used for the debug window. Renaming +"                       to FindWindow and FindCreateWindow. +"                     o Updated debugging code so that debug output is put into +"                       a buffer which can then be written to disk or emailed +"                       to me when someone is having a major issue. Can also +"                       write directly to a file (VERY SLOWLY) on UNIX or Win32 +"                       (not 95 or 98 at the moment) or use VIM's echo function  +"                       to display the output to the screen. +"                     o Several people have had issues when the hidden option  +"                       is turned on. So I have put in several checks to make +"                       sure folks know this if they try to use MBE with this +"                       option set. +"               6.0.7 o Handling BufDelete autocmd so that the UI updates  +"                       properly when using :bd (rather than going through  +"                       the MBE UI.) +"                     o The AutoUpdate code will now close the MBE window when  +"                       there is a single eligible buffer available. +"                       This has the usefull side effect of stopping the MBE +"                       window from blocking the VIM session open when you close  +"                       the last buffer. +"                     o Added functions, commands and maps to close & update +"                       the MBE window (<leader>mbc and <leader>mbu.) +"                     o Made MBE open/close state be sticky if set through +"                       StartExplorer(1) or StopExplorer(1), which are  +"                       called from the standard mappings. So if you close +"                       the mbe window with \mbc it won't be automatically  +"                       opened again unless you do a \mbe (or restart VIM). +"                     o Removed spaces between "tabs" (even more mini :) +"                     o Simplified MBE tab processing  +"               6.0.6 o Fixed register overwrite bug found by Sébastien Pierre +"               6.0.5 o Fixed an issue with window sizing when we run out of  +"                       buffers.   +"                     o Fixed some weird commenting bugs.   +"                     o Added more optional fancy window/buffer navigation: +"                     o You can turn on the capability to use control and the  +"                       arrow keys to move between windows. +"                     o You can turn on the ability to use <C-TAB> and  +"                       <C-S-TAB> to open the next and previous (respectively)  +"                       buffer in the current window. +"                     o You can turn on the ability to use <C-TAB> and  +"                       <C-S-TAB> to switch windows (forward and backwards  +"                       respectively.) +"               6.0.4 o Added optional fancy window navigation:  +"                     o Holding down control and pressing a vim direction  +"                       [hjkl] will switch windows in the indicated direction. +"               6.0.3 o Changed buffer name to -MiniBufExplorer- to resolve +"                       Issue in filename pattern matching on Windows. +"               6.0.2 o 2 Changes requested by Suresh Govindachar: +"                     o Added SplitToEdge option and set it on by default +"                     o Added tab and shift-tab mappings in [MBE] window +"               6.0.1 o Added MoreThanOne option and set it on by default +"                       MiniBufExplorer will not automatically open until +"                       more than one eligible buffers are opened. This +"                       reduces cluter when you are only working on a +"                       single file.  +"                       NOTE: See change log for 6.2.2 for more details about  +"                             this feature +"               6.0.0 o Initial Release on November 20, 2001 +" +"============================================================================= +" }}} +" vim:ft=vim:fdm=marker:ff=unix:nowrap:tabstop=4:shiftwidth=4:softtabstop=4:smarttab:shiftround:expandtab diff --git a/.vim/plugin/openssl.vim b/.vim/plugin/openssl.vim new file mode 100644 index 0000000..2e2db44 --- /dev/null +++ b/.vim/plugin/openssl.vim @@ -0,0 +1,201 @@ +" openssl.vim version 3.2 2008 Noah Spurrier <noah@noah.org> +" +" == Edit OpenSSL encrypted files and turn Vim into a Password Safe! == +" +" This plugin enables reading and writing of files encrypted using OpenSSL. +" The file must have the extension of one of the ciphers used by OpenSSL. For +" example: +" +"    .des3 .aes .bf .bfa .idea .cast .rc2 .rc4 .rc5 (.bfa is base64 ASCII +"    encoded blowfish.) +" +" This will turn off the swap file and the .viminfo log. The `openssl` command +" line tool must be in the path. +" +" == Install == +" +" Put this in your plugin directory and Vim will automatically load it: +" +"    ~/.vim/plugin/openssl.vim +" +" You can start by editing an empty unencrypted file. Give it one of the +" extensions above. When you write the file you will be asked to give it a new +" password. +" +" == Simple Vim Password Safe == +" +" If you edit any file named '.auth.bfa' (that's the full name, not just the +" extension) then this plugin will add folding features and an automatic quit +" timeout. +" +" Vim will quit automatically after 5 minutes of no typing activity (unless +" the file has been changed). +" +" This plugin will fold on wiki-style headlines in the following format: +" +"     == This is a headline == +"  +" Any notes under the headline will be inside the fold until the next headline +" is reached. The SPACE key will toggle a fold open and closed. The q key will +" quit Vim. Create the following example file named ~/.auth.bfa: +" +"     == Colo server == +" +"     username: maryjane password: esydpm +" +"     == Office server == +" +"     username: peter password: 4m4z1ng +" +" Then create this bash alias: +" +"     alias auth='view ~/.auth.bfa' +" +" Now you can view your password safe by typing 'auth'. When Vim starts all +" the password information will be hidden under the headlines. To view the +" password information put the cursor on the headline and press SPACE. When +" you write an encrypted file a backup will automatically be made. +" +" This plugin can also make a backup of an encrypted file before writing +" changes. This helps guard against the situation where you may edit a file +" and write changes with the wrong password. You can still go back to the +" previous backup version. The backup file will have the same name as the +" original file with .bak before the original extension. For example: +" +"     .auth.bfa  -->  .auth.bak.bfa +" +" To turn on backups put the following global definition in your .vimrc file: +"  +"     let g:openssl_backup = 1 +" +" Thanks to Tom Purl for the original des3 tip. +" +" I release all copyright claims. This code is in the public domain. +" Permission is granted to use, copy modify, distribute, and sell this +" software for any purpose. I make no guarantee about the suitability of this +" software for any purpose and I am not liable for any damages resulting from +" its use. Further, I am under no obligation to maintain or extend this +" software. It is provided on an 'as is' basis without any expressed or +" implied warranty. +" +" $Id: openssl.vim 189 2008-01-28 20:44:44Z root $ + +augroup openssl_encrypted +if exists("openssl_encrypted_loaded") +    finish +endif +let openssl_encrypted_loaded = 1 +autocmd! + +function! s:OpenSSLReadPre() +    set cmdheight=3 +    set viminfo= +    set noswapfile +    set shell=/bin/sh +    set bin +endfunction + +function! s:OpenSSLReadPost() +    let l:cipher = expand("%:e") +    if l:cipher == "aes" +        let l:cipher = "aes-256-cbc" +    endif +    if l:cipher == "bfa" +        let l:cipher = "bf" +        let l:expr = "0,$!openssl " . l:cipher . " -d -a -salt" +    else +        let l:expr = "0,$!openssl " . l:cipher . " -d -salt" +    endif + +    silent! execute l:expr +    if v:shell_error +        silent! 0,$y +        silent! undo +        echo "COULD NOT DECRYPT USING EXPRESSION: " . expr +        echo "Note that your version of openssl may not have the given cipher engine built-in" +        echo "even though the engine may be documented in the openssl man pages." +        echo "ERROR FROM OPENSSL:" +        echo @" +        echo "COULD NOT DECRYPT" +        return +    endif +    set nobin +    set cmdheight& +    set shell& +    execute ":doautocmd BufReadPost ".expand("%:r") +    redraw! +endfunction + +function! s:OpenSSLWritePre() +    set cmdheight=3 +    set shell=/bin/sh +    set bin + +    if !exists("g:openssl_backup") +        let g:openssl_backup=0 +    endif +    if (g:openssl_backup) +        silent! execute '!cp % %:r.bak.%:e' +    endif + +    let l:cipher = expand("<afile>:e")  +    if l:cipher == "aes" +        let l:cipher = "aes-256-cbc" +    endif +    if l:cipher == "bfa" +        let l:cipher = "bf" +        let l:expr = "0,$!openssl " . l:cipher . " -e -a -salt" +    else +        let l:expr = "0,$!openssl " . l:cipher . " -e -salt" +    endif + +    silent! execute l:expr +    if v:shell_error +        silent! 0,$y +        silent! undo +        echo "COULD NOT ENCRYPT USING EXPRESSION: " . expr +        echo "Note that your version of openssl may not have the given cipher engine built in" +        echo "even though the engine may be documented in the openssl man pages." +        echo "ERROR FROM OPENSSL:" +        echo @" +        echo "COULD NOT ENCRYPT" +        return +    endif +endfunction + +function! s:OpenSSLWritePost() +    silent! undo +    set nobin +    set shell& +    set cmdheight& +    redraw! +endfunction + +autocmd BufReadPre,FileReadPre     *.des3,*.des,*.bf,*.bfa,*.aes,*.idea,*.cast,*.rc2,*.rc4,*.rc5,*.desx call s:OpenSSLReadPre() +autocmd BufReadPost,FileReadPost   *.des3,*.des,*.bf,*.bfa,*.aes,*.idea,*.cast,*.rc2,*.rc4,*.rc5,*.desx call s:OpenSSLReadPost() +autocmd BufWritePre,FileWritePre   *.des3,*.des,*.bf,*.bfa,*.aes,*.idea,*.cast,*.rc2,*.rc4,*.rc5,*.desx call s:OpenSSLWritePre() +autocmd BufWritePost,FileWritePost *.des3,*.des,*.bf,*.bfa,*.aes,*.idea,*.cast,*.rc2,*.rc4,*.rc5,*.desx call s:OpenSSLWritePost() + +" The following implements a simple password safe for any file named +" '.auth.bfa'. The file is encrypted with Blowfish and base64 encoded. +" Folding is supported for == headlines == style lines. + +function! HeadlineDelimiterExpression(lnum) +    if a:lnum == 1 +        return ">1" +    endif +    return (getline(a:lnum)=~"^\\s*==.*==\\s*$") ? ">1" : "=" +endfunction +autocmd BufReadPost,FileReadPost   .auth.bfa set foldexpr=HeadlineDelimiterExpression(v:lnum) +autocmd BufReadPost,FileReadPost   .auth.bfa set foldlevel=0 +autocmd BufReadPost,FileReadPost   .auth.bfa set foldcolumn=0 +autocmd BufReadPost,FileReadPost   .auth.bfa set foldmethod=expr +autocmd BufReadPost,FileReadPost   .auth.bfa set foldtext=getline(v:foldstart) +autocmd BufReadPost,FileReadPost   .auth.bfa nnoremap <silent><space> :exe 'silent! normal! za'.(foldlevel('.')?'':'l')<CR> +autocmd BufReadPost,FileReadPost   .auth.bfa nnoremap <silent>q :q<CR> +autocmd BufReadPost,FileReadPost   .auth.bfa highlight Folded ctermbg=red ctermfg=black +autocmd BufReadPost,FileReadPost   .auth.bfa set updatetime=300000 +autocmd CursorHold                 .auth.bfa quit + +augroup END + diff --git a/.vim/plugin/remoteOpen.vim b/.vim/plugin/remoteOpen.vim new file mode 100644 index 0000000..cb550ff --- /dev/null +++ b/.vim/plugin/remoteOpen.vim @@ -0,0 +1,163 @@ +" File: remoteOpen.vim +" Author: Srinath Avadhanula <srinath AT fastmail DOT fm> +" $Id: remoteOpen.vim 997 2006-03-20 09:45:45Z srinathava $ +"  +" Description: +" Often times, an external program needs to open a file in gvim from the +" command line. However, it will not know if the file is already opened in a +" previous vim session. It is not sufficient to simply specify  +" +" gvim --remote-silent <filename>  +" +" because this simply opens up <filename> in the first remote gvim session it +" sees. This script provides a command RemoteOpen which is meant to be used +" from the command line as follows: +" +" gvim -c ":RemoteOpen +<lnum> <filename>" +" +" where <lnum> is the line-number you wish <filename> to open to.  What will +" happen is that a new gvim will start up and enquire from all previous +" sessions if <filename> is already open in any of them. If it is, then it +" will edit the file in that session and bring it to the foreground and itself +" quit. Otherwise, it will not quit and instead open up the file for editing +" at <lnum>. +" +" This was mainly created to be used with Yap (the dvi previewer in miktex), +" so you can specify the program for "inverse search" as specified above. +" This ensures that the inverse search uses the correct gvim each time. +" +" Ofcourse, this requires vim with +clientserver. If not, then RemoteOpen just +" opens in the present session. + +" Enclose <args> in single quotes so it can be passed as a function argument. +com -nargs=1 RemoteOpen :call RemoteOpen('<args>') +com -nargs=? RemoteInsert :call RemoteInsert('<args>') + +" RemoteOpen: open a file remotely (if possible) {{{ +" Description: checks all open vim windows to see if this file has been opened +"              anywhere and if so, opens it there instead of in this session. +function! RemoteOpen(arglist) + +	" First construct line number and filename from argument. a:arglist is of +	" the form: +	"    +10 c:\path\to\file +	" or just +	" 	 c:\path\to\file +	if a:arglist =~ '^\s*+\d\+' +		let linenum = matchstr(a:arglist, '^\s*+\zs\d\+\ze') +		let filename = matchstr(a:arglist, '^\s*+\d\+\s*\zs.*\ze') +	else +		let linenum = 1 +		let filename = matchstr(a:arglist, '^\s*\zs.*\ze') +	endif +	let filename = escape(filename, ' ') +	call Tex_Debug("linenum = ".linenum.', filename = '.filename, "ropen") + +	" If there is no clientserver functionality, then just open in the present +	" session and return +	if !has('clientserver') +		call Tex_Debug("-clientserver, opening locally and returning", "ropen") +		exec "e ".filename +		exec linenum +		normal! zv +		return +	endif + +	" Otherwise, loop through all available servers +	let servers = serverlist() +	" If there are no servers, open file locally. +	if servers == '' +		call Tex_Debug("no open servers, opening locally", "ropen") +		exec "e ".filename +		exec linenum +		let g:Remote_Server = 1 +		normal! zv +		return +	endif + +	let i = 1 +	let server = s:Strntok(servers, "\n", i)  +	let targetServer = v:servername + +	while server != '' +		" Find out if there was any server which was used by remoteOpen before +		" this. If a new gvim session was ever started via remoteOpen, then +		" g:Remote_Server will be set. +		if remote_expr(server, 'exists("g:Remote_Server")') +			let targetServer = server +		endif + +		" Ask each server if that file is being edited by them. +		let bufnum = remote_expr(server, "bufnr('".filename."')") +		" If it is... +		if bufnum != -1 +			" ask the server to edit that file and come to the foreground. +			" set a variable g:Remote_Server to indicate that this server +			" session has at least one file opened via RemoteOpen +			let targetServer = server +			break +		end +		 +		let i = i + 1 +		let server = s:Strntok(servers, "\n", i)  +	endwhile + +	" If none of the servers have the file open, then open this file in the +	" first server. This has the advantage if yap tries to make vim open +	" multiple vims, then at least they will all be opened by the same gvim +	" server. +	call remote_send(targetServer,  +		\ "\<C-\>\<C-n>". +		\ ":let g:Remote_Server = 1\<CR>". +		\ ":drop ".filename."\<CR>". +		\ ":".linenum."\<CR>zv" +		\ ) +	call remote_foreground(targetServer) +	" quit this vim session +	if v:servername != targetServer +		q +	endif +endfunction " }}} +" RemoteInsert: inserts a \cite'ation remotely (if possible) {{{ +" Description: +function! RemoteInsert(...) + +	let citation =  matchstr(argv(0), "\\[InsText('.cite{\\zs.\\{-}\\ze}');\\]") +	if citation == "" +		q +	endif + +	" Otherwise, loop through all available servers +	let servers = serverlist() + +	let i = 1 +	let server = s:Strntok(servers, "\n", i)  +	let targetServer = v:servername + +	while server != '' +		if remote_expr(server, 'exists("g:Remote_WaitingForCite")') +			call remote_send(server, citation . "\<CR>") +			call remote_foreground(server) +			if v:servername != server +				q +			else +				return +			endif +		endif + +		let i = i + 1 +		let server = s:Strntok(servers, "\n", i)  +	endwhile + +	q + +endfunction " }}} +" Strntok: extract the n^th token from a list {{{ +" example: Strntok('1,23,3', ',', 2) = 23 +fun! <SID>Strntok(s, tok, n) +	return matchstr( a:s.a:tok[0], '\v(\zs([^'.a:tok.']*)\ze['.a:tok.']){'.a:n.'}') +endfun + +" }}} + +" vim:ft=vim:ts=4:sw=4:noet:fdm=marker:commentstring=\"\ %s:nowrap diff --git a/.vim/plugin/taglist.vim b/.vim/plugin/taglist.vim new file mode 100644 index 0000000..59901f6 --- /dev/null +++ b/.vim/plugin/taglist.vim @@ -0,0 +1,4546 @@ +" File: taglist.vim +" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com) +" Version: 4.5 +" Last Modified: September 21, 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(<f-args>) +    command! -nargs=+ -complete=dir TlistAddFilesRecursive +                \ call s:Tlist_Add_Files_Recursive(<f-args>) +    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(<f-args>) +    command! -nargs=* -complete=buffer TlistShowTag +                \ echo Tlist_Get_Tagname_By_Line(<f-args>) +    command! -nargs=* -complete=file TlistSessionLoad +                \ call s:Tlist_Session_Load(<q-args>) +    command! -nargs=* -complete=file TlistSessionSave +                \ call s:Tlist_Session_Save(<q-args>) +    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(<q-args>) +    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 <SID>xx <SID>xx +    let s:tlist_sid = substitute(maparg('<SID>xx'), '<SNR>\(\d\+_\)xx$', +                                \ '\1', '') +    unmap <SID>xx + +    exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_* source ' . +                \ escape(expand('<sfile>'), ' ') +    exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Window_* source ' . +                \ escape(expand('<sfile>'), ' ') +    exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Menu_* source ' . +                \ escape(expand('<sfile>'), ' ') +    exe 'autocmd FuncUndefined Tlist_* source ' . +                \ escape(expand('<sfile>'), ' ') +    exe 'autocmd FuncUndefined TagList_* source ' . +                \ escape(expand('<sfile>'), ' ') + +    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>;<flag>:<name>;<flag>:<name>;... +" +" 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 <F1> to display help text') +    else +        " Add the extensive help +        call append(0, '" <enter> : Jump to tag definition') +        call append(1, '" o : Jump to tag definition in new window') +        call append(2, '" p : Preview the tag definition') +        call append(3, '" <space> : Display tag prototype') +        call append(4, '" u : Update tag list') +        call append(5, '" s : Select sort field') +        call append(6, '" d : Remove file from taglist') +        call append(7, '" x : Zoom-out/Zoom-in taglist window') +        call append(8, '" + : Open a fold') +        call append(9, '" - : Close a fold') +        call append(10, '" * : Open all folds') +        call append(11, '" = : Close all folds') +        call append(12, '" [[ : 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, '" <F1> : 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: +    " +    "       <language_name>;flag1:name1;flag2:name2;flag3:name3 +    " + +    " Extract the file type to pass to ctags. This may be different from the +    " file type detected by Vim +    let pos = stridx(settings, ';') +    if pos == -1 +        call s:Tlist_Warning_Msg(msg) +        return 0 +    endif +    let ctags_ftype = strpart(settings, 0, pos) +    if ctags_ftype == '' +        call s:Tlist_Warning_Msg(msg) +        return 0 +    endif +    " Make sure a valid filetype is supplied. If the user didn't specify a +    " valid filetype, then the ctags option settings may be treated as the +    " filetype +    if ctags_ftype =~ ':' +        call s:Tlist_Warning_Msg(msg) +        return 0 +    endif + +    " Remove the file type from settings +    let settings = strpart(settings, pos + 1) +    if settings == '' +        call s:Tlist_Warning_Msg(msg) +        return 0 +    endif + +    " Process all the specified ctags flags. The format is +    " flag1:name1;flag2:name2;flag3:name3 +    let ctags_flags = '' +    let cnt = 0 +    while settings != '' +        " Extract the flag +        let pos = stridx(settings, ':') +        if pos == -1 +            call s:Tlist_Warning_Msg(msg) +            return 0 +        endif +        let flag = strpart(settings, 0, pos) +        if flag == '' +            call s:Tlist_Warning_Msg(msg) +            return 0 +        endif +        " Remove the flag from settings +        let settings = strpart(settings, pos + 1) + +        " Extract the tag type name +        let pos = stridx(settings, ';') +        if pos == -1 +            call s:Tlist_Warning_Msg(msg) +            return 0 +        endif +        let name = strpart(settings, 0, pos) +        if name == '' +            call s:Tlist_Warning_Msg(msg) +            return 0 +        endif +        let settings = strpart(settings, pos + 1) + +        let cnt = cnt + 1 + +        let s:tlist_{a:ftype}_{cnt}_name = flag +        let s:tlist_{a:ftype}_{cnt}_fullname = name +        let ctags_flags = ctags_flags . flag +    endwhile + +    let s:tlist_{a:ftype}_ctags_args = '--language-force=' . ctags_ftype . +                            \ ' --' . ctags_ftype . '-types=' . ctags_flags +    let s:tlist_{a:ftype}_count = cnt +    let s:tlist_{a:ftype}_ctags_flags = ctags_flags + +    " Save the filetype name +    let s:tlist_ftype_{s:tlist_ftype_count}_name = a:ftype +    let s:tlist_ftype_count = s:tlist_ftype_count + 1 + +    return 1 +endfunction + +" Tlist_Detect_Filetype +" Determine the filetype for the specified file using the filetypedetect +" autocmd. +function! s:Tlist_Detect_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) +    let buf_ft = getbufvar(a:bnum, '&filetype') + +    if bufloaded(a:bnum) +        " For loaded buffers, the 'filetype' is already determined +        return buf_ft +    endif + +    " For unloaded buffers, if the 'filetype' option is set, return it +    if buf_ft != '' +        return buf_ft +    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_Detect_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 <buffer> <silent> <CR> +                \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR> +    nnoremap <buffer> <silent> o +                \ :call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR> +    nnoremap <buffer> <silent> p +                \ :call <SID>Tlist_Window_Jump_To_Tag('preview')<CR> +    nnoremap <buffer> <silent> P +                \ :call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR> +    if v:version >= 700 +    nnoremap <buffer> <silent> t +                \ :call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR> +    nnoremap <buffer> <silent> <C-t> +                \ :call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR> +    endif +    nnoremap <buffer> <silent> <2-LeftMouse> +                \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR> +    nnoremap <buffer> <silent> s +                \ :call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR> +    nnoremap <buffer> <silent> + :silent! foldopen<CR> +    nnoremap <buffer> <silent> - :silent! foldclose<CR> +    nnoremap <buffer> <silent> * :silent! %foldopen!<CR> +    nnoremap <buffer> <silent> = :silent! %foldclose<CR> +    nnoremap <buffer> <silent> <kPlus> :silent! foldopen<CR> +    nnoremap <buffer> <silent> <kMinus> :silent! foldclose<CR> +    nnoremap <buffer> <silent> <kMultiply> :silent! %foldopen!<CR> +    nnoremap <buffer> <silent> <Space> :call <SID>Tlist_Window_Show_Info()<CR> +    nnoremap <buffer> <silent> u :call <SID>Tlist_Window_Update_File()<CR> +    nnoremap <buffer> <silent> d :call <SID>Tlist_Remove_File(-1, 1)<CR> +    nnoremap <buffer> <silent> x :call <SID>Tlist_Window_Zoom()<CR> +    nnoremap <buffer> <silent> [[ :call <SID>Tlist_Window_Move_To_File(-1)<CR> +    nnoremap <buffer> <silent> <BS> :call <SID>Tlist_Window_Move_To_File(-1)<CR> +    nnoremap <buffer> <silent> ]] :call <SID>Tlist_Window_Move_To_File(1)<CR> +    nnoremap <buffer> <silent> <Tab> :call <SID>Tlist_Window_Move_To_File(1)<CR> +    nnoremap <buffer> <silent> <F1> :call <SID>Tlist_Window_Toggle_Help_Text()<CR> +    nnoremap <buffer> <silent> q :close<CR> + +    " Insert mode mappings +    inoremap <buffer> <silent> <CR> +                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR> +    " Windows needs return +    inoremap <buffer> <silent> <Return> +                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR> +    inoremap <buffer> <silent> o +                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR> +    inoremap <buffer> <silent> p +                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('preview')<CR> +    inoremap <buffer> <silent> P +                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR> +    if v:version >= 700 +    inoremap <buffer> <silent> t +                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR> +    inoremap <buffer> <silent> <C-t> +                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR> +    endif +    inoremap <buffer> <silent> <2-LeftMouse> +                \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR> +    inoremap <buffer> <silent> s +                \ <C-o>:call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR> +    inoremap <buffer> <silent> +             <C-o>:silent! foldopen<CR> +    inoremap <buffer> <silent> -             <C-o>:silent! foldclose<CR> +    inoremap <buffer> <silent> *             <C-o>:silent! %foldopen!<CR> +    inoremap <buffer> <silent> =             <C-o>:silent! %foldclose<CR> +    inoremap <buffer> <silent> <kPlus>       <C-o>:silent! foldopen<CR> +    inoremap <buffer> <silent> <kMinus>      <C-o>:silent! foldclose<CR> +    inoremap <buffer> <silent> <kMultiply>   <C-o>:silent! %foldopen!<CR> +    inoremap <buffer> <silent> <Space>       <C-o>:call +                                    \ <SID>Tlist_Window_Show_Info()<CR> +    inoremap <buffer> <silent> u +                            \ <C-o>:call <SID>Tlist_Window_Update_File()<CR> +    inoremap <buffer> <silent> d    <C-o>:call <SID>Tlist_Remove_File(-1, 1)<CR> +    inoremap <buffer> <silent> x    <C-o>:call <SID>Tlist_Window_Zoom()<CR> +    inoremap <buffer> <silent> [[   <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR> +    inoremap <buffer> <silent> <BS> <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR> +    inoremap <buffer> <silent> ]]   <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR> +    inoremap <buffer> <silent> <Tab> <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR> +    inoremap <buffer> <silent> <F1>  <C-o>:call <SID>Tlist_Window_Toggle_Help_Text()<CR> +    inoremap <buffer> <silent> q    <C-o>:close<CR> + +    " Map single left mouse click if the user wants this functionality +    if g:Tlist_Use_SingleClick == 1 +        " Contributed by Bindu Wavell +        " attempt to perform single click mapping, it would be much +        " nicer if we could nnoremap <buffer> ... however vim does +        " not fire the <buffer> <leftmouse> when you use the mouse +        " to enter a buffer. +        let clickmap = ':if bufname("%") =~ "__Tag_List__" <bar> ' . +                    \ 'call <SID>Tlist_Window_Jump_To_Tag("useopen") ' . +                    \ '<bar> endif <CR>' +        if maparg('<leftmouse>', 'n') == '' +            " no mapping for leftmouse +            exe ':nnoremap <silent> <leftmouse> <leftmouse>' . clickmap +        else +            " we have a mapping +            let mapcmd = ':nnoremap <silent> <leftmouse> <leftmouse>' +            let mapcmd = mapcmd . substitute(substitute( +                        \ maparg('<leftmouse>', 'n'), '|', '<bar>', 'g'), +                        \ '\c^<leftmouse>', '', '') +            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('<abuf>')) +        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 +        if v:version >= 700 +            autocmd TabEnter * silent call s:Tlist_Refresh_Folds() +        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('<LeftMouse>') +            nunmap <LeftMouse> +        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_name<TAB>file_name<TAB>ex_cmd;"<TAB>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:<num>\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:<num>\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 = s:Tlist_Get_Buffer_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_Detect_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 = s:Tlist_Get_Buffer_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 +        let ft = s:Tlist_Get_Buffer_Filetype('%') +        call Tlist_Update_File(filename, ft) +    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 <filename> ' . +                                \ '<line_number>' +        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 <filename> <line_number>' +        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 <filename>') +        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 <filename>') +        return +    endif + +    let sessionfile = a:1 + +    if s:tlist_file_count == 0 +        " There is nothing to save +        call s:Tlist_Warning_Msg('Warning: Taglist is empty. Nothing to save.') +        return +    endif + +    if filereadable(sessionfile) +        let ans = input('Do you want to overwrite ' . sessionfile . ' (Y/N)?') +        if ans !=? 'y' +            return +        endif + +        echo "\n" +    endif + +    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 txt = escape(s:tlist_{i}_{ttype}, '"\') +                let txt = substitute(txt, "\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('<afile>: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') +        let ft = s:Tlist_Get_Buffer_Filetype(buf_num) +        if !s:Tlist_Skip_File(filename, ft) +            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 + +" Tlist_Refresh_Folds +" Remove and create the folds for all the files displayed in the taglist +" window. Used after entering a tab. If this is not done, then the folds +" are not properly created for taglist windows displayed in multiple tabs. +function! s:Tlist_Refresh_Folds() +    let winnum = bufwinnr(g:TagList_title) +    if winnum == -1 +        return +    endif + +    let save_wnum = winnr() +    exe winnum . 'wincmd w' + +    " First remove all the existing folds +    normal! zE + +    " Create the folds for each in the tag list +    let fidx = 0 +    while fidx < s:tlist_file_count +        let ftype = s:tlist_{fidx}_filetype + +        " Create the folds for each tag type in a file +        let j = 1 +        while j <= s:tlist_{ftype}_count +            let ttype = s:tlist_{ftype}_{j}_name +            if s:tlist_{fidx}_{ttype}_count +                let s = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset +                let e = s + s:tlist_{fidx}_{ttype}_count +                exe s . ',' . e . 'fold' +            endif +            let j = j + 1 +        endwhile + +        exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold' +        exe 'silent! ' . s:tlist_{fidx}_start . ',' . +                    \ s:tlist_{fidx}_end . 'foldopen!' +        let fidx = fidx + 1 +    endwhile + +    exe save_wnum . 'wincmd w' +endfunction + +function! s:Tlist_Menu_Add_Base_Menu() +    call s:Tlist_Log_Msg('Adding the base menu') + +    " Add the menu +    anoremenu <silent> T&ags.Refresh\ menu :call <SID>Tlist_Menu_Refresh()<CR> +    anoremenu <silent> T&ags.Sort\ menu\ by.Name +                    \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR> +    anoremenu <silent> T&ags.Sort\ menu\ by.Order +                    \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR> +    anoremenu T&ags.-SEP1-           : + +    if &mousemodel =~ 'popup' +        anoremenu <silent> PopUp.T&ags.Refresh\ menu +                    \ :call <SID>Tlist_Menu_Refresh()<CR> +        anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Name +                  \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR> +        anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Order +                  \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR> +        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 <silent> 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 <SID>Tlist_Menu_Jump_To_Tag(' . +                            \ tidx . ')<CR>|' + +                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 <silent> 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 <SID>Tlist_Menu_Jump_To_Tag(' . tidx +                        \ . ')<CR>|' + +            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 = s:Tlist_Get_Buffer_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 . ' <Nop>' +        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 = s:Tlist_Get_Buffer_Filetype(bufnum) +    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 + | 
