24c78d478e36

vim: a ton of stuff
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Wed, 09 Jun 2010 17:00:10 -0400
parents 797e80047af1
children 52be542a43c1 309b770e8a8d
branches/tags (none)
files vim/.vimrc vim/autoload/repeat.vim vim/bundle/nerdcommenter/.gitignore vim/bundle/nerdcommenter/Rakefile vim/bundle/nerdcommenter/doc/NERD_commenter.txt vim/bundle/nerdcommenter/plugin/NERD_commenter.vim vim/bundle/yankring/doc/yankring.txt vim/bundle/yankring/plugin/yankring.vim

Changes

--- a/vim/.vimrc	Wed Jun 09 16:15:51 2010 -0400
+++ b/vim/.vimrc	Wed Jun 09 17:00:10 2010 -0400
@@ -19,11 +19,12 @@
 set wildmode=list:longest
 set visualbell
 set cursorline
+set ttyfast
 
 " Backups
-set nobackup
-set nowritebackup
-set directory=$HOME/.vim/tmp//,.
+set backupdir=~/tmp,/tmp " backups (~)
+set directory=~/tmp,/tmp " swap files
+set backup               " enable backups
 
 " Leader
 let mapleader = ","
@@ -40,7 +41,8 @@
 set incsearch
 set showmatch
 set hlsearch
-map <leader>c :let @/=''<CR>
+set gdefault
+map <leader><space> :let @/=''<CR>
 
 " Soft/hard wrapping
 set wrap
@@ -85,7 +87,8 @@
 map <D-k> :resize +10<CR>
 map <D-l> :vertical resize +10<CR>
 
-" Use F1 to fold/unfold
+" Folding
+set foldlevelstart=1
 nnoremap <F1> za
 vnoremap <F1> za
 
@@ -126,3 +129,6 @@
 if has("gui_running")
     highlight SpellBad term=underline gui=undercurl guisp=Orange
 endif
+
+" Yankring
+nnoremap <silent> <F3> :YRShow<CR>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/autoload/repeat.vim	Wed Jun 09 17:00:10 2010 -0400
@@ -0,0 +1,72 @@
+" repeat.vim - Let the repeat command repeat plugin maps
+" Maintainer:   Tim Pope
+" Version:      1.0
+
+" Installation:
+" Place in either ~/.vim/plugin/repeat.vim (to load at start up) or
+" ~/.vim/autoload/repeat.vim (to load automatically as needed).
+"
+" Developers:
+" Basic usage is as follows:
+"
+"   silent! call repeat#set("\<Plug>MappingToRepeatCommand",3)
+"
+" The first argument is the mapping that will be invoked when the |.| key is
+" pressed.  Typically, it will be the same as the mapping the user invoked.
+" This sequence will be stuffed into the input queue literally.  Thus you must
+" encode special keys by prefixing them with a backslash inside double quotes.
+"
+" The second argument is the default count.  This is the number that will be
+" prefixed to the mapping if no explicit numeric argument was given.  The
+" value of the v:count variable is usually correct and it will be used if the
+" second parameter is omitted.  If your mapping doesn't accept a numeric
+" argument and you never want to receive one, pass a value of -1.
+"
+" Make sure to call the repeat#set function _after_ making changes to the
+" file.
+
+if exists("g:loaded_repeat") || &cp || v:version < 700
+    finish
+endif
+let g:loaded_repeat = 1
+
+let g:repeat_tick = -1
+
+function! repeat#set(sequence,...)
+    silent exe "norm! \"=''\<CR>p"
+    let g:repeat_sequence = a:sequence
+    let g:repeat_count = a:0 ? a:1 : v:count
+    let g:repeat_tick = b:changedtick
+endfunction
+
+function! s:repeat(count)
+    if g:repeat_tick == b:changedtick
+        let c = g:repeat_count
+        let s = g:repeat_sequence
+        let cnt = c == -1 ? "" : (a:count ? a:count : (c ? c : ''))
+        call feedkeys(cnt . s)
+    else
+        call feedkeys((a:count ? a:count : '') . '.', 'n')
+    endif
+endfunction
+
+function! s:wrap(command,count)
+    let preserve = (g:repeat_tick == b:changedtick)
+    exe 'norm! '.(a:count ? a:count : '').a:command
+    if preserve
+        let g:repeat_tick = b:changedtick
+    endif
+endfunction
+
+nnoremap <silent> .     :<C-U>call <SID>repeat(v:count)<CR>
+nnoremap <silent> u     :<C-U>call <SID>wrap('u',v:count)<CR>
+nnoremap <silent> U     :<C-U>call <SID>wrap('U',v:count)<CR>
+nnoremap <silent> <C-R> :<C-U>call <SID>wrap("\<Lt>C-R>",v:count)<CR>
+
+augroup repeatPlugin
+    autocmd!
+    autocmd BufLeave,BufWritePre,BufReadPre * let g:repeat_tick = (g:repeat_tick == b:changedtick || g:repeat_tick == 0) ? 0 : -1
+    autocmd BufEnter,BufWritePost * if g:repeat_tick == 0|let g:repeat_tick = b:changedtick|endif
+augroup END
+
+" vim:set ft=vim et sw=4 sts=4:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/bundle/nerdcommenter/.gitignore	Wed Jun 09 17:00:10 2010 -0400
@@ -0,0 +1,2 @@
+*~
+*.swp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/bundle/nerdcommenter/Rakefile	Wed Jun 09 17:00:10 2010 -0400
@@ -0,0 +1,18 @@
+desc "Copy the vim/doc files into ~/.vim"
+task :deploy_local do
+  run "cp plugin/NERD_commenter.vim ~/.vim/plugin"
+  run "cp doc/NERD_commenter.txt ~/.vim/doc"
+end
+
+
+desc "Create a zip archive for release to vim.org"
+task :zip do
+  abort "NERD_commenter.zip already exists, aborting" if File.exist?("NERD_commenter.zip")
+  run "zip NERD_commenter.zip plugin/NERD_commenter.vim doc/NERD_commenter.txt"
+end
+
+def run(cmd)
+  puts "Executing: #{cmd}"
+  system cmd
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/bundle/nerdcommenter/doc/NERD_commenter.txt	Wed Jun 09 17:00:10 2010 -0400
@@ -0,0 +1,991 @@
+*NERD_commenter.txt*         Plugin for commenting code
+
+
+                        NERD COMMENTER REFERENCE MANUAL~
+
+
+
+
+
+==============================================================================
+CONTENTS                                               *NERDCommenterContents*
+
+    1.Intro...................................|NERDCommenter|
+    2.Functionality provided..................|NERDComFunctionality|
+        2.1 Functionality Summary.............|NERDComFunctionalitySummary|
+        2.2 Functionality Details.............|NERDComFunctionalityDetails|
+            2.2.1 Comment map.................|NERDComComment|
+            2.2.2 Nested comment map..........|NERDComNestedComment|
+            2.2.3 Toggle comment map..........|NERDComToggleComment|
+            2.2.4 Minimal comment map.........|NERDComMinimalComment|
+            2.2.5 Invert comment map..........|NERDComInvertComment|
+            2.2.6 Sexy comment map............|NERDComSexyComment|
+            2.2.7 Yank comment map............|NERDComYankComment|
+            2.2.8 Comment to EOL map..........|NERDComEOLComment|
+            2.2.9 Append com to line map......|NERDComAppendComment|
+            2.2.10 Insert comment map.........|NERDComInsertComment|
+            2.2.11 Use alternate delims map...|NERDComAltDelim|
+            2.2.12 Comment aligned maps.......|NERDComAlignedComment|
+            2.2.13 Uncomment line map.........|NERDComUncommentLine|
+        2.3 Supported filetypes...............|NERDComFiletypes|
+        2.4 Sexy Comments.....................|NERDComSexyComments|
+        2.5 The NERDComment function..........|NERDComNERDComment|
+    3.Options.................................|NERDComOptions|
+        3.1 Options summary...................|NERDComOptionsSummary|
+        3.2 Options details...................|NERDComOptionsDetails|
+        3.3 Default delimiter Options.........|NERDComDefaultDelims|
+    4. Customising key mappings...............|NERDComMappings|
+    5. Issues with the script.................|NERDComIssues|
+        5.1 Delimiter detection heuristics....|NERDComHeuristics|
+        5.2 Nesting issues....................|NERDComNesting|
+    6.About..     ............................|NERDComAbout|
+    7.Changelog...............................|NERDComChangelog|
+    8.Credits.................................|NERDComCredits|
+    9.License.................................|NERDComLicense|
+
+==============================================================================
+1. Intro                                                       *NERDCommenter*
+
+The NERD commenter provides many different commenting operations and styles
+which are invoked via key mappings and a menu. These operations are available
+for most filetypes.
+
+There are also options that allow to tweak the commenting engine to your
+taste.
+
+==============================================================================
+2. Functionality provided                               *NERDComFunctionality*
+
+------------------------------------------------------------------------------
+2.1 Functionality summary                        *NERDComFunctionalitySummary*
+
+The following key mappings are provided by default (there is also a menu
+with items corresponding to all the mappings below):
+
+[count],cc |NERDComComment|
+Comment out the current line or text selected in visual mode.
+
+
+[count],cn |NERDComNestedComment|
+Same as ,cc but forces nesting.
+
+
+[count],c<space> |NERDComToggleComment|
+Toggles the comment state of the selected line(s). If the topmost selected
+line is commented, all selected lines are uncommented and vice versa.
+
+
+[count],cm |NERDComMinimalComment|
+Comments the given lines using only one set of multipart delimiters.
+
+
+[count],ci |NERDComInvertComment|
+Toggles the comment state of the selected line(s) individually.
+
+
+[count],cs |NERDComSexyComment|
+Comments out the selected lines ``sexily''
+
+
+[count],cy |NERDComYankComment|
+Same as ,cc except that the commented line(s) are yanked first.
+
+
+,c$ |NERDComEOLComment|
+Comments the current line from the cursor to the end of line.
+
+
+,cA |NERDComAppendComment|
+Adds comment delimiters to the end of line and goes into insert mode between
+them.
+
+
+|NERDComInsertComment|
+Adds comment delimiters at the current cursor position and inserts between.
+Disabled by default.
+
+
+,ca |NERDComAltDelim|
+Switches to the alternative set of delimiters.
+
+
+[count],cl
+[count],cb    |NERDComAlignedComment|
+Same as |NERDComComment| except that the delimiters are aligned down the
+left side (,cl) or both sides (,cb).
+
+
+[count],cu |NERDComUncommentLine|
+Uncomments the selected line(s).
+
+------------------------------------------------------------------------------
+2.2 Functionality details                        *NERDComFunctionalityDetails*
+
+------------------------------------------------------------------------------
+2.2.1 Comment map                                             *NERDComComment*
+
+Default mapping: [count],cc
+Mapped to: <plug>NERDCommenterComment
+Applicable modes: normal visual visual-line visual-block.
+
+
+Comments out the current line. If multiple lines are selected in visual-line
+mode, they are all commented out.  If some text is selected in visual or
+visual-block mode then the script will try to comment out the exact text that
+is selected using multi-part delimiters if they are available.
+
+If a [count] is given in normal mode, the mapping works as though that many
+lines were selected in visual-line mode.
+
+------------------------------------------------------------------------------
+2.2.2 Nested comment map                                *NERDComNestedComment*
+
+Default mapping: [count],cn
+Mapped to: <plug>NERDCommenterNest
+Applicable modes: normal visual visual-line visual-block.
+
+Performs nested commenting.  Works the same as ,cc except that if a line is
+already commented then it will be commented again.
+
+If |'NERDUsePlaceHolders'| is set then the previous comment delimiters will
+be replaced by place-holder delimiters if needed.  Otherwise the nested
+comment will only be added if the current commenting delimiters have no right
+delimiter (to avoid syntax errors)
+
+If a [count] is given in normal mode, the mapping works as though that many
+lines were selected in visual-line mode.
+
+Related options:
+|'NERDDefaultNesting'|
+
+------------------------------------------------------------------------------
+2.2.3 Toggle comment map                                *NERDComToggleComment*
+
+Default mapping: [count],c<space>
+Mapped to: <plug>NERDCommenterToggle
+Applicable modes: normal visual-line.
+
+Toggles commenting of the lines selected. The behaviour of this mapping
+depends on whether the first line selected is commented or not.  If so, all
+selected lines are uncommented and vice versa.
+
+With this mapping, a line is only considered to be commented if it starts with
+a left delimiter.
+
+If a [count] is given in normal mode, the mapping works as though that many
+lines were selected in visual-line mode.
+
+------------------------------------------------------------------------------
+2.2.4 Minimal comment map                              *NERDComMinimalComment*
+
+Default mapping: [count],cm
+Mapped to: <plug>NERDCommenterMinimal
+Applicable modes: normal visual-line.
+
+Comments the selected lines using one set of multipart delimiters if possible.
+
+For example: if you are programming in c and you select 5 lines and press ,cm
+then a '/*' will be placed at the start of the top line and a '*/' will be
+placed at the end of the last line.
+
+Sets of multipart comment delimiters that are between the top and bottom
+selected lines are replaced with place holders (see |'NERDLPlace'|) if
+|'NERDUsePlaceHolders'| is set for the current filetype. If it is not, then
+the comment will be aborted if place holders are required to prevent illegal
+syntax.
+
+If a [count] is given in normal mode, the mapping works as though that many
+lines were selected in visual-line mode.
+
+------------------------------------------------------------------------------
+2.2.5 Invert comment map                                *NERDComInvertComment*
+
+Default mapping: ,ci
+Mapped to: <plug>NERDCommenterInvert
+Applicable modes: normal visual-line.
+
+Inverts the commented state of each selected line. If the a selected line is
+commented then it is uncommented and vice versa. Each line is examined and
+commented/uncommented individually.
+
+With this mapping, a line is only considered to be commented if it starts with
+a left delimiter.
+
+If a [count] is given in normal mode, the mapping works as though that many
+lines were selected in visual-line mode.
+
+------------------------------------------------------------------------------
+2.2.6 Sexy comment map                                    *NERDComSexyComment*
+
+Default mapping: [count],cs
+Mapped to: <plug>NERDCommenterSexy
+Applicable modes: normal, visual-line.
+
+Comments the selected line(s) ``sexily''... see |NERDComSexyComments| for
+a description of what sexy comments are. Can only be done on filetypes for
+which there is at least one set of multipart comment delimiters specified.
+
+Sexy comments cannot be nested and lines inside a sexy comment cannot be
+commented again.
+
+If a [count] is given in normal mode, the mapping works as though that many
+lines were selected in visual-line mode.
+
+Related options:
+|'NERDCompactSexyComs'|
+
+------------------------------------------------------------------------------
+2.2.7 Yank comment map                                    *NERDComYankComment*
+
+Default mapping: [count],cy
+Mapped to: <plug>NERDCommenterYank
+Applicable modes: normal visual visual-line visual-block.
+
+Same as ,cc except that it yanks the line(s) that are commented first.
+
+------------------------------------------------------------------------------
+2.2.8 Comment to EOL map                                   *NERDComEOLComment*
+
+Default mapping: ,c$
+Mapped to: <plug>NERDCommenterToEOL
+Applicable modes: normal.
+
+Comments the current line from the current cursor position up to the end of
+the line.
+
+------------------------------------------------------------------------------
+2.2.9 Append com to line map                            *NERDComAppendComment*
+
+Default mapping: ,cA
+Mapped to: <plug>NERDCommenterAppend
+Applicable modes: normal.
+
+Appends comment delimiters to the end of the current line and goes
+to insert mode between the new delimiters.
+
+------------------------------------------------------------------------------
+2.2.10 Insert comment map                               *NERDComInsertComment*
+
+Default mapping: disabled by default.
+Map it to: <plug>NERDCommenterInInsert
+Applicable modes: insert.
+
+Adds comment delimiters at the current cursor position and inserts
+between them.
+
+NOTE: prior to version 2.1.17 this was mapped to ctrl-c. To restore this
+mapping add >
+    let NERDComInsertMap='<c-c>'
+<
+to your vimrc.
+
+------------------------------------------------------------------------------
+2.2.11 Use alternate delims map                              *NERDComAltDelim*
+
+Default mapping: ,ca
+Mapped to: <plug>NERDCommenterAltDelims
+Applicable modes: normal.
+
+Changes to the alternative commenting style if one is available. For example,
+if the user is editing a c++ file using // comments and they hit ,ca
+then they will be switched over to /**/ comments.
+
+See also |NERDComDefaultDelims|
+
+------------------------------------------------------------------------------
+2.2.12 Comment aligned maps                            *NERDComAlignedComment*
+
+Default mappings: [count],cl   [count],cb
+Mapped to: <plug>NERDCommenterAlignLeft
+           <plug>NERDCommenterAlignBoth
+Applicable modes: normal visual-line.
+
+Same as ,cc except that the comment delimiters are aligned on the left side or
+both sides respectively. These comments are always nested if the line(s) are
+already commented.
+
+If a [count] is given in normal mode, the mapping works as though that many
+lines were selected in visual-line mode.
+
+------------------------------------------------------------------------------
+2.2.13 Uncomment line map                               *NERDComUncommentLine*
+
+Default mapping: [count],cu
+Mapped to: <plug>NERDCommenterUncomment
+Applicable modes: normal visual visual-line visual-block.
+
+Uncomments the current line. If multiple lines are selected in
+visual mode then they are all uncommented.
+
+When uncommenting, if the line contains multiple sets of delimiters then the
+``outtermost'' pair of delimiters will be removed.
+
+The script uses a set of heurisics to distinguish ``real'' delimiters from
+``fake'' ones when uncommenting. See |NERDComIssues| for details.
+
+If a [count] is given in normal mode, the mapping works as though that many
+lines were selected in visual-line mode.
+
+Related  options:
+|'NERDRemoveAltComs'|
+|'NERDRemoveExtraSpaces'|
+
+------------------------------------------------------------------------------
+2.3 Supported filetypes                                     *NERDComFiletypes*
+
+Filetypes that can be commented by this plugin:
+abaqus abc acedb ada ahdl amiga aml ampl ant apache apachestyle asm68k asm asn
+aspvbs atlas autohotkey autoit automake ave awk basic b bc bdf bib bindzone
+bst btm caos catalog c cfg cg ch changelog cl clean clipper cmake conf config
+context cpp crontab cs csc csp css cterm cupl csv cvs dcl debchangelog
+debcontrol debsources def diff django docbk dns dosbatch dosini dot dracula
+dsl dtd dtml dylan ecd eiffel elf elmfilt erlang eruby eterm expect exports
+fetchmail fgl focexec form fortran foxpro fstab fvwm fx gdb gdmo geek
+gentoo-package-keywords' gentoo-package-mask' gentoo-package-use' gnuplot
+gtkrc haskell hb h help hercules hog html htmldjango htmlos ia64 icon idlang
+idl indent inform inittab ishd iss ist jam java javascript jess jgraph
+jproperties jproperties jsp kconfig kix kscript lace lex lftp lifelines lilo
+lisp lite lotos lout lprolog lscript lss lua lynx m4 mail make maple masm
+master matlab mel mf mib mma model moduala.  modula2 modula3 monk mush muttrc
+named nasm nastran natural ncf netdict netrw nqc nroff nsis objc ocaml occam
+omlet omnimark openroad opl ora otl ox pascal passwd pcap pccts perl pfmain
+php phtml pic pike pilrc pine plaintex plm plsql po postscr pov povini ppd
+ppwiz procmail progress prolog psf ptcap python python qf radiance ratpoison r
+rc readline rebol registry remind rexx robots rpl rtf ruby sa samba sas sass
+sather scheme scilab screen scsh sdl sed selectbuf sgml sgmldecl sgmllnx sh
+sicad simula sinda skill slang sl slrnrc sm smarty smil smith sml snnsnet
+snnspat snnsres snobol4 spec specman spice sql sqlforms sqlj sqr squid st stp
+strace svn systemverilog tads taglist tags tak tasm tcl terminfo tex text
+plaintex texinfo texmf tf tidy tli trasys tsalt tsscl tssgm uc uil vb verilog
+verilog_systemverilog vgrindefs vhdl vim viminfo virata vo_base vrml vsejcl
+webmacro wget winbatch wml wvdial xdefaults xf86conf xhtml xkb xmath xml
+xmodmap xpm2 xpm xslt yacc yaml z8a
+
+If a language is not in the list of hardcoded supported filetypes then the
+&commentstring vim option is used.
+
+------------------------------------------------------------------------------
+2.4 Sexy Comments                                        *NERDComSexyComments*
+These are comments that use one set of multipart comment delimiters as well as
+one other marker symbol. For example: >
+    /*
+     * This is a c style sexy comment
+     * So there!
+     */
+
+    /* This is a c style sexy comment
+     * So there!
+     * But this one is ``compact'' style */
+<
+Here the multipart delimiters are /* and */ and the marker is *.
+
+------------------------------------------------------------------------------
+2.5 The NERDComment function                             *NERDComNERDComment*
+
+All of the NERD commenter mappings and menu items invoke a single function
+which delegates the commenting work to other functions. This function is
+public and has the prototype: >
+    function! NERDComment(isVisual, type)
+<
+The arguments to this function are simple:
+    - isVisual: if you wish to do any kind of visual comment then set this to
+      1 and the function will use the '< and '> marks to find the comment
+      boundries. If set to 0 then the function will operate on the current
+      line.
+    - type: is used to specify what type of commenting operation is to be
+      performed, and it can be one of the following: "sexy", "invert",
+      "minimal", "toggle", "alignLeft", "alignBoth", "norm", "nested",
+      "toEOL", "append", "insert", "uncomment", "yank"
+
+For example, if you typed >
+    :call NERDComment(1, 'sexy')
+<
+then the script would do a sexy comment on the last visual selection.
+
+
+==============================================================================
+3. Options                                                    *NERDComOptions*
+
+------------------------------------------------------------------------------
+3.1 Options summary                                    *NERDComOptionsSummary*
+
+|'loaded_nerd_comments'|              Turns off the script.
+|'NERDAllowAnyVisualDelims'|          Allows multipart alternative delims to
+                                      be used when commenting in
+                                      visual/visual-block mode.
+|'NERDBlockComIgnoreEmpty'|           Forces right delims to be placed when
+                                      doing visual-block comments.
+|'NERDCommentWholeLinesInVMode'|      Changes behaviour of visual comments.
+|'NERDCreateDefaultMappings'|         Turn the default mappings on/off.
+|'NERDDefaultNesting'|                Tells the script to use nested comments
+                                      by default.
+|'NERDMenuMode'|                      Specifies how the NERD commenter menu
+                                      will appear (if at all).
+|'NERDLPlace'|                        Specifies what to use as the left
+                                      delimiter placeholder when nesting
+                                      comments.
+|'NERDUsePlaceHolders'|               Specifies which filetypes may use
+                                      placeholders when nesting comments.
+|'NERDRemoveAltComs'|                 Tells the script whether to remove
+                                      alternative comment delimiters when
+                                      uncommenting.
+|'NERDRemoveExtraSpaces'|             Tells the script to always remove the
+                                      extra spaces when uncommenting
+                                      (regardless of whether NERDSpaceDelims
+                                      is set)
+|'NERDRPlace'|                        Specifies what to use as the right
+                                      delimiter placeholder when nesting
+                                      comments.
+|'NERDSpaceDelims'|                   Specifies whether to add extra spaces
+                                      around delimiters when commenting, and
+                                      whether to remove them when
+                                      uncommenting.
+|'NERDCompactSexyComs'|               Specifies whether to use the compact
+                                      style sexy comments.
+
+------------------------------------------------------------------------------
+3.3 Options details                                    *NERDComOptionsDetails*
+
+To enable any of the below options you should put the given line in your
+~/.vimrc
+
+                                                       *'loaded_nerd_comments'*
+If this script is driving you insane you can turn it off by setting this
+option >
+    let loaded_nerd_comments=1
+<
+------------------------------------------------------------------------------
+                                                    *'NERDAllowAnyVisualDelims'*
+Values: 0 or 1.
+Default: 1.
+
+If set to 1 then, when doing a visual or visual-block comment (but not a
+visual-line comment), the script will choose the right delimiters to use for
+the comment. This means either using the current delimiters if they are
+multipart or using the alternative delimiters if THEY are multipart.  For
+example if we are editing the following java code: >
+    float foo = 1221;
+    float bar = 324;
+    System.out.println(foo * bar);
+<
+If we are using // comments and select the "foo" and "bar" in visual-block
+mode, as shown left below (where '|'s are used to represent the visual-block
+boundary), and comment it then the script will use the alternative delims as
+shown on the right: >
+
+    float |foo| = 1221;                   float /*foo*/ = 1221;
+    float |bar| = 324;                    float /*bar*/ = 324;
+    System.out.println(foo * bar);        System.out.println(foo * bar);
+<
+------------------------------------------------------------------------------
+                                                     *'NERDBlockComIgnoreEmpty'*
+Values: 0 or 1.
+Default: 1.
+
+This option  affects visual-block mode commenting. If this option is turned
+on, lines that begin outside the right boundary of the selection block will be
+ignored.
+
+For example, if you are commenting this chunk of c code in visual-block mode
+(where the '|'s are used to represent the visual-block boundary) >
+    #include <sys/types.h>
+    #include <unistd.h>
+    #include <stdio.h>
+   |int| main(){
+   |   | printf("SUCK THIS\n");
+   |   | while(1){
+   |   |     fork();
+   |   | }
+   |}  |
+<
+If NERDBlockComIgnoreEmpty=0 then this code will become: >
+    #include <sys/types.h>
+    #include <unistd.h>
+    #include <stdio.h>
+    /*int*/ main(){
+    /*   */ printf("SUCK THIS\n");
+    /*   */ while(1){
+    /*   */     fork();
+    /*   */ }
+    /*}  */
+<
+Otherwise, the code block would become: >
+    #include <sys/types.h>
+    #include <unistd.h>
+    #include <stdio.h>
+    /*int*/ main(){
+    printf("SUCK THIS\n");
+    while(1){
+        fork();
+    }
+    /*}  */
+<
+------------------------------------------------------------------------------
+                                                *'NERDCommentWholeLinesInVMode'*
+Values: 0, 1 or 2.
+Default: 0.
+
+By default the script tries to comment out exactly what is selected in visual
+mode (v). For example if you select and comment the following c code (using |
+to represent the visual boundary): >
+    in|t foo = 3;
+    int bar =| 9;
+    int baz = foo + bar;
+<
+This will result in: >
+    in/*t foo = 3;*/
+    /*int bar =*/ 9;
+    int baz = foo + bar;
+<
+But some people prefer it if the whole lines are commented like: >
+    /*int foo = 3;*/
+    /*int bar = 9;*/
+    int baz = foo + bar;
+<
+If you prefer the second option then stick this line in your vimrc: >
+    let NERDCommentWholeLinesInVMode=1
+<
+
+If the filetype you are editing only has no multipart delimiters (for example
+a shell script) and you hadnt set this option then the above would become >
+    in#t foo = 3;
+    #int bar = 9;
+<
+(where # is the comment delimiter) as this is the closest the script can
+come to commenting out exactly what was selected. If you prefer for whole
+lines to be commented out when there is no multipart delimiters but the EXACT
+text that was selected to be commented out if there IS multipart delimiters
+then stick the following line in your vimrc: >
+    let NERDCommentWholeLinesInVMode=2
+<
+
+Note that this option does not affect the behaviour of commenting in
+|visual-block| mode.
+
+------------------------------------------------------------------------------
+                                                *'NERDCreateDefaultMappings'*
+Values: 0 or 1.
+Default: 1.
+
+If set to 0, none of the default mappings will be created.
+
+See also |NERDComMappings|.
+
+------------------------------------------------------------------------------
+                                                           *'NERDRemoveAltComs'*
+Values: 0 or 1.
+Default: 1.
+
+When uncommenting a line (for a filetype with an alternative commenting style)
+this option tells the script whether to look for, and remove, comment
+delimiters of the alternative style.
+
+For example, if you are editing a c++ file using // style comments and you go
+,cu on this line: >
+    /* This is a c++ comment baby! */
+<
+It will not be uncommented if the NERDRemoveAltComs is set to 0.
+
+------------------------------------------------------------------------------
+                                                       *'NERDRemoveExtraSpaces'*
+Values: 0 or 1.
+Default: 1.
+
+By default, the NERD commenter will remove spaces around comment delimiters if
+either:
+1. |'NERDSpaceDelims'| is set to 1.
+2. NERDRemoveExtraSpaces is set to 1.
+
+This means that if we have the following lines in a c code file: >
+    /* int foo = 5; */
+    /* int bar = 10; */
+    int baz = foo + bar
+<
+If either of the above conditions hold then if these lines are uncommented
+they will become: >
+    int foo = 5;
+    int bar = 10;
+    int baz = foo + bar
+<
+Otherwise they would become: >
+     int foo = 5;
+     int bar = 10;
+    int baz = foo + bar
+<
+If you want the spaces to be removed only if |'NERDSpaceDelims'| is set then
+set NERDRemoveExtraSpaces to 0.
+
+------------------------------------------------------------------------------
+                                                                  *'NERDLPlace'*
+                                                                  *'NERDRPlace'*
+Values: arbitrary string.
+Default:
+    NERDLPlace: "[>"
+    NERDRPlace: "<]"
+
+These options are used to control the strings used as place-holder delimiters.
+Place holder delimiters are used when performing nested commenting when the
+filetype supports commenting styles with both left and right delimiters.
+To set these options use lines like: >
+    let NERDLPlace="FOO"
+    let NERDRPlace="BAR"
+<
+Following the above example, if we have line of c code: >
+    /* int horse */
+<
+and we comment it with ,cn it will be changed to: >
+    /*FOO int horse BAR*/
+<
+When we uncomment this line it will go back to what it was.
+
+------------------------------------------------------------------------------
+                                                                *'NERDMenuMode'*
+Values: 0, 1, 2, 3.
+Default: 3
+
+This option can take 4 values:
+    "0": Turns the menu off.
+    "1": Turns the 'comment' menu on with no menu shortcut.
+    "2": Turns the 'comment 'menu on with <alt>-c as the shortcut.
+    "3": Turns the 'Plugin -> comment' menu on with <alt>-c as the shortcut.
+
+------------------------------------------------------------------------------
+                                                         *'NERDUsePlaceHolders'*
+Values: 0 or 1.
+Default 1.
+
+This option is used to specify whether place-holder delimiters should be used
+when creating a nested comment.
+
+------------------------------------------------------------------------------
+                                                             *'NERDSpaceDelims'*
+Values: 0 or 1.
+Default 0.
+
+Some people prefer a space after the left delimiter and before the right
+delimiter like this: >
+    /* int foo=2; */
+<
+as opposed to this: >
+    /*int foo=2;*/
+<
+If you want spaces to be added then set NERDSpaceDelims to 1 in your vimrc.
+
+See also |'NERDRemoveExtraSpaces'|.
+
+------------------------------------------------------------------------------
+                                                         *'NERDCompactSexyComs'*
+Values: 0 or 1.
+Default 0.
+
+Some people may want their sexy comments to be like this: >
+    /* Hi There!
+     * This is a sexy comment
+     * in c */
+<
+As opposed to like this: >
+    /*
+     * Hi There!
+     * This is a sexy comment
+     * in c
+     */
+<
+If this option is set to 1 then the top style will be used.
+
+------------------------------------------------------------------------------
+                                                          *'NERDDefaultNesting'*
+Values: 0 or 1.
+Default 1.
+
+When this option is set to 1, comments are nested automatically. That is, if
+you hit ,cc on a line that is already commented it will be commented again
+
+------------------------------------------------------------------------------
+3.3 Default delimiter customisation                     *NERDComDefaultDelims*
+
+If you want the NERD commenter to use the alternative delimiters for a
+specific filetype by default then put a line of this form into your vimrc: >
+    let NERD_<filetype>_alt_style=1
+<
+Example: java uses // style comments by default, but you want it to default to
+/* */ style comments instead. You would put this line in your vimrc: >
+    let NERD_java_alt_style=1
+<
+
+See |NERDComAltDelim| for switching commenting styles at runtime.
+
+==============================================================================
+4. Key mapping customisation                                *NERDComMappings*
+
+To change a mapping just map another key combo to the internal <plug> mapping.
+For example, to remap the |NERDComComment| mapping to ",omg" you would put
+this line in your vimrc: >
+    map ,omg <plug>NERDCommenterComment
+<
+This will stop the corresponding default mappings from being created.
+
+See the help for the mapping in question to see which <plug> mapping to
+map to.
+
+See also |'NERDCreateDefaultMappings'|.
+
+==============================================================================
+5. Issues with the script                                      *NERDComIssues*
+
+
+------------------------------------------------------------------------------
+5.1 Delimiter detection heuristics                         *NERDComHeuristics*
+
+Heuristics are used to distinguish the real comment delimiters
+
+Because we have comment mappings that place delimiters in the middle of lines,
+removing comment delimiters is a bit tricky. This is because if comment
+delimiters appear in a line doesnt mean they really ARE delimiters. For
+example, Java uses // comments but the line >
+    System.out.println("//");
+<
+clearly contains no real comment delimiters.
+
+To distinguish between ``real'' comment delimiters and ``fake'' ones we use a
+set of heuristics. For example, one such heuristic states that any comment
+delimiter that has an odd number of non-escaped " characters both preceding
+and following it on the line is not a comment because it is probably part of a
+string. These heuristics, while usually pretty accurate, will not work for all
+cases.
+
+------------------------------------------------------------------------------
+5.2 Nesting issues                                            *NERDComNesting*
+
+If we have some line of code like this: >
+    /*int foo */ = /*5 + 9;*/
+<
+This will not be uncommented legally. The NERD commenter will remove the
+"outter most" delimiters so the line will become: >
+    int foo */ = /*5 + 9;
+<
+which almost certainly will not be what you want. Nested sets of comments will
+uncomment fine though. Eg: >
+    /*int/* foo =*/ 5 + 9;*/
+<
+will become: >
+    int/* foo =*/ 5 + 9;
+<
+(Note that in the above examples I have deliberately not used place holders
+for simplicity)
+
+==============================================================================
+6. About                                                        *NERDComAbout*
+
+The author of the NERD commenter is Martyzillatron --- the half robot, half
+dinosaur bastard son of Megatron and Godzilla. He enjoys destroying
+metropolises and eating tourist busses.
+
+Drop him a line at martin_grenfell at msn.com. He would love to hear from you.
+its a lonely life being the worlds premier terror machine. How would you feel
+if your face looked like a toaster and a t-rex put together? :(
+
+The latest stable versions can be found at
+    http://www.vim.org/scripts/script.php?script_id=1218
+
+The latest dev versions are on github
+    http://github.com/scrooloose/nerdcommenter
+
+==============================================================================
+8. Changelog                                                *NERDComChangelog*
+
+2.2.2
+    - remove the NERDShutup option and the message is suppresses, this makes
+      the plugin silently rely on &commentstring for unknown filetypes.
+    - add support for dhcpd, limits, ntp, resolv, rgb, sysctl, udevconf and
+      udevrules. Thanks to Thilo Six.
+    - match filetypes case insensitively
+    - add support for mp (metapost), thanks to Andrey Skvortsov.
+    - add support for htmlcheetah, thanks to Simon Hengel.
+    - add support for javacc, thanks to Matt Tolton.
+    - make <%# %> the default delims for eruby, thanks to tpope.
+    - add support for javascript.jquery, thanks to Ivan Devat.
+    - add support for cucumber and pdf. Fix sass and railslog delims,
+      thanks to tpope
+
+2.2.1
+    - add support for newlisp and clojure, thanks to Matthew Lee Hinman.
+    - fix automake comments, thanks to Elias Pipping
+    - make haml comments default to -# with / as the alternative delimiter,
+      thanks to tpope
+    - add support for actionscript and processing thanks to Edwin Benavides
+    - add support for ps1 (powershell), thanks to Jason Mills
+    - add support for hostsaccess, thanks to Thomas Rowe
+    - add support for CVScommit
+    - add support for asciidoc, git and gitrebase. Thanks to Simon Ruderich.
+    - use # for gitcommit comments, thanks to Simon Ruderich.
+    - add support for mako and genshi, thanks to Keitheis.
+    - add support for conkyrc, thanks to David
+    - add support for SVNannotate, thanks to Miguel Jaque Barbero.
+    - add support for sieve, thanks to Stefan Walk
+    - add support for objj, thanks to Adam Thorsen.
+
+2.2.0
+    - rewrote the mappings system to be more "standard".
+      - removed all the mapping options. Now, mappings to <plug> mappings are
+        used
+      - see :help NERDComMappings, and :help NERDCreateDefaultMappings for
+        more info
+    - remove "prepend comments" and "right aligned comments".
+    - add support for applescript, calbire, man, SVNcommit, potwiki, txt2tags and SVNinfo.
+      Thanks to nicothakis, timberke, sgronblo, mntnoe, Bernhard Grotz, John
+      O'Shea, François and Giacomo Mariani respectively.
+    - bugfix for haskell delimiters. Thanks to mntnoe.
+2.1.18
+    - add support for llvm. Thanks to nicothakis.
+    - add support for xquery. Thanks to Phillip Kovalev.
+2.1.17
+    - fixed haskell delimiters (hackily). Thanks to Elias Pipping.
+    - add support for mailcap. Thanks to Pascal Brueckner.
+    - add support for stata. Thanks to Jerónimo Carballo.
+    - applied a patch from ewfalor to fix an error in the help file with the
+      NERDMapleader doc
+    - disable the insert mode ctrl-c mapping by default, see :help
+      NERDComInsertComment if you wish to restore it
+
+==============================================================================
+8. Credits                                                    *NERDComCredits*
+
+Thanks to the follow people for suggestions and patches:
+
+Nick Brettell
+Matthew Hawkins
+Mathieu Clabaut
+Greg Searle
+Nguyen
+Litchi
+Jorge Scandaliaris
+Shufeng Zheng
+Martin Stubenschrott
+Markus Erlmann
+Brent Rice
+Richard Willis
+Igor Prischepoff
+Harry
+David Bourgeois
+Eike Von Seggern
+Torsten Blix
+Alexander Bosecke
+Stefano Zacchiroli
+Norick Chen
+Joseph Barker
+Gary Church
+Tim Carey-Smith
+Markus Klinik
+Anders
+Seth Mason
+James Hales
+Heptite
+Cheng Fang
+Yongwei Wu
+David Miani
+Jeremy Hinegardner
+Marco
+Ingo Karkat
+Zhang Shuhan
+tpope
+Ben Schmidt
+David Fishburn
+Erik Falor
+JaGoTerr
+Elias Pipping
+mntnoe
+Mark S.
+
+
+Thanks to the following people for sending me new filetypes to support:
+
+The hackers                         The filetypes~
+Sam R                               verilog
+Jonathan                            Derque context, plaintext and mail
+Vigil                               fetchmail
+Michael Brunner                     kconfig
+Antono Vasiljev                     netdict
+Melissa Reid                        omlet
+Ilia N Ternovich                    quickfix
+John O'Shea                         RTF, SVNcommitlog and vcscommit, SVNCommit
+Anders                              occam
+Mark Woodward                       csv
+fREW                                gentoo-package-mask,
+                                    gentoo-package-keywords,
+                                    gentoo-package-use, and vo_base
+Alexey                              verilog_systemverilog, systemverilog
+Lizendir                            fstab
+Michael Böhler                      autoit, autohotkey and docbk
+Aaron Small                         cmake
+Ramiro                              htmldjango and django
+Stefano Zacchiroli                  debcontrol, debchangelog, mkd
+Alex Tarkovsky                      ebuild and eclass
+Jorge Rodrigues                     gams
+Rainer Müller                       Objective C
+Jason Mills                         Groovy, ps1
+Normandie Azucena                   vera
+Florian Apolloner                   ldif
+David Fishburn                      lookupfile
+Niels Aan de Brugh                  rst
+Don Hatlestad                       ahk
+Christophe Benz                     Desktop and xsd
+Eyolf Østrem                        lilypond, bbx and lytex
+Ingo Karkat                         dosbatch
+Nicolas Weber                       markdown, objcpp
+tinoucas                            gentoo-conf-d
+Greg Weber                          D, haml
+Bruce Sherrod                       velocity
+timberke                            cobol, calibre
+Aaron Schaefer                      factor
+Mr X                                asterisk, mplayerconf
+Kuchma Michael                      plsql
+Brett Warneke                       spectre
+Pipp                                lhaskell
+Renald Buter                        scala
+Vladimir Lomov                      asymptote
+Marco                               mrxvtrc, aap
+nicothakis                          SVNAnnotate, CVSAnnotate, SVKAnnotate,
+                                    SVNdiff, gitAnnotate, gitdiff, dtrace
+                                    llvm, applescript
+Chen Xing                           Wikipedia
+Jacobo Diaz                         dakota, patran
+Li Jin                              gentoo-env-d, gentoo-init-d,
+                                    gentoo-make-conf, grub, modconf, sudoers
+SpookeyPeanut                       rib
+Greg Jandl                          pyrex/cython
+Christophe Benz                     services, gitcommit
+A Pontus                            vimperator
+Stromnov                            slice, bzr
+Martin Kustermann                   pamconf
+Indriði Einarsson                   mason
+Chris                               map
+Krzysztof A. Adamski                group
+Pascal Brueckner                    mailcap
+Jerónimo Carballo                   stata
+Phillip Kovalev                     xquery
+Bernhard Grotz                      potwiki
+sgronblo                            man
+François                            txt2tags
+Giacomo Mariani                     SVNinfo
+Matthew Lee Hinman                  newlisp, clojure
+Elias Pipping                       automake
+Edwin Benavides                     actionscript, processing
+Thomas Rowe                         hostsaccess
+Simon Ruderich                      asciidoc, git, gitcommit, gitrebase
+Keitheis                            mako, genshi
+David                               conkyrc
+Miguel Jaque Barbero                SVNannotate
+Stefan Walk                         sieve
+Adam Thorsen                        objj
+Thilo Six                           dhcpd, limits, ntp, resolv, rgb, sysctl,
+                                    udevconf, udevrules
+Andrey Skvortsov                    mp
+Simon Hengel                        htmlcheetah
+Matt Tolton                         javacc
+Ivan Devat                          javascript.jquery
+tpope                               cucumber,pdf
+==============================================================================
+9. License                                                    *NERDComLicense*
+
+The NERD commenter is released under the wtfpl.
+See http://sam.zoy.org/wtfpl/COPYING.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/bundle/nerdcommenter/plugin/NERD_commenter.vim	Wed Jun 09 17:00:10 2010 -0400
@@ -0,0 +1,3146 @@
+" ============================================================================
+" File:        NERD_commenter.vim
+" Description: vim global plugin that provides easy code commenting
+" Maintainer:  Martin Grenfell <martin_grenfell at msn dot com>
+" Version:     2.2.2
+" Last Change: 30th March, 2008
+" License:     This program is free software. It comes without any warranty,
+"              to the extent permitted by applicable law. You can redistribute
+"              it and/or modify it under the terms of the Do What The Fuck You
+"              Want To Public License, Version 2, as published by Sam Hocevar.
+"              See http://sam.zoy.org/wtfpl/COPYING for more details.
+"
+" ============================================================================
+
+" Section: script init stuff {{{1
+if exists("loaded_nerd_comments")
+    finish
+endif
+if v:version < 700
+    echoerr "NERDCommenter: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!"
+    finish
+endif
+let loaded_nerd_comments = 1
+
+" Function: s:InitVariable() function {{{2
+" This function is used to initialise a given variable to a given value. The
+" variable is only initialised if it does not exist prior
+"
+" Args:
+"   -var: the name of the var to be initialised
+"   -value: the value to initialise var to
+"
+" Returns:
+"   1 if the var is set, 0 otherwise
+function s:InitVariable(var, value)
+    if !exists(a:var)
+        exec 'let ' . a:var . ' = ' . "'" . a:value . "'"
+        return 1
+    endif
+    return 0
+endfunction
+
+" Section: space string init{{{2
+" When putting spaces after the left delim and before the right we use
+" s:spaceStr for the space char. This way we can make it add anything after
+" the left and before the right by modifying this variable
+let s:spaceStr = ' '
+let s:lenSpaceStr = strlen(s:spaceStr)
+
+" Section: variable init calls {{{2
+call s:InitVariable("g:NERDAllowAnyVisualDelims", 1)
+call s:InitVariable("g:NERDBlockComIgnoreEmpty", 0)
+call s:InitVariable("g:NERDCommentWholeLinesInVMode", 0)
+call s:InitVariable("g:NERDCompactSexyComs", 0)
+call s:InitVariable("g:NERDCreateDefaultMappings", 1)
+call s:InitVariable("g:NERDDefaultNesting", 1)
+call s:InitVariable("g:NERDMenuMode", 3)
+call s:InitVariable("g:NERDLPlace", "[>")
+call s:InitVariable("g:NERDUsePlaceHolders", 1)
+call s:InitVariable("g:NERDRemoveAltComs", 1)
+call s:InitVariable("g:NERDRemoveExtraSpaces", 1)
+call s:InitVariable("g:NERDRPlace", "<]")
+call s:InitVariable("g:NERDSpaceDelims", 0)
+call s:InitVariable("g:NERDDelimiterRequests", 1)
+
+
+
+let s:NERDFileNameEscape="[]#*$%'\" ?`!&();<>\\"
+
+" Section: Comment mapping functions, autocommands and commands {{{1
+" ============================================================================
+" Section: Comment enabler autocommands {{{2
+" ============================================================================
+
+augroup commentEnablers
+
+    "if the user enters a buffer or reads a buffer then we gotta set up
+    "the comment delimiters for that new filetype
+    autocmd BufEnter,BufRead * :call s:SetUpForNewFiletype(&filetype, 0)
+
+    "if the filetype of a buffer changes, force the script to reset the
+    "delims for the buffer
+    autocmd Filetype * :call s:SetUpForNewFiletype(&filetype, 1)
+augroup END
+
+
+" Function: s:SetUpForNewFiletype(filetype) function {{{2
+" This function is responsible for setting up buffer scoped variables for the
+" given filetype.
+"
+" These variables include the comment delimiters for the given filetype and calls
+" MapDelimiters or MapDelimitersWithAlternative passing in these delimiters.
+"
+" Args:
+"   -filetype: the filetype to set delimiters for
+"   -forceReset: 1 if the delimiters should be reset if they have already be
+"    set for this buffer.
+"
+function s:SetUpForNewFiletype(filetype, forceReset)
+    "if we have already set the delimiters for this buffer then dont go thru
+    "it again
+    if !a:forceReset && exists("b:NERDLeft") && b:NERDLeft != ''
+        return
+    endif
+
+    let b:NERDSexyComMarker = ''
+
+    "check the filetype against all known filetypes to see if we have
+    "hardcoded the comment delimiters to use
+    if a:filetype ==? ""
+        call s:MapDelimiters('', '')
+    elseif a:filetype ==? "aap"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "abc"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "acedb"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "actionscript"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "ada"
+        call s:MapDelimitersWithAlternative('--','', '--  ', '')
+    elseif a:filetype ==? "ahdl"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "ahk"
+        call s:MapDelimitersWithAlternative(';', '', '/*', '*/')
+    elseif a:filetype ==? "amiga"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "aml"
+        call s:MapDelimiters('/*', '')
+    elseif a:filetype ==? "ampl"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "apache"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "apachestyle"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "asciidoc"
+        call s:MapDelimiters('//', '')
+    elseif a:filetype ==? "applescript"
+        call s:MapDelimitersWithAlternative('--', '', '(*', '*)')
+    elseif a:filetype ==? "asm68k"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "asm"
+        call s:MapDelimitersWithAlternative(';', '', '#', '')
+    elseif a:filetype ==? "asn"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "aspvbs"
+        call s:MapDelimiters('''', '')
+    elseif a:filetype ==? "asterisk"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "asy"
+        call s:MapDelimiters('//', '')
+    elseif a:filetype ==? "atlas"
+        call s:MapDelimiters('C','$')
+    elseif a:filetype ==? "autohotkey"
+        call s:MapDelimiters(';','')
+    elseif a:filetype ==? "autoit"
+        call s:MapDelimiters(';','')
+    elseif a:filetype ==? "ave"
+        call s:MapDelimiters("'",'')
+    elseif a:filetype ==? "awk"
+        call s:MapDelimiters('#','')
+    elseif a:filetype ==? "basic"
+        call s:MapDelimitersWithAlternative("'",'', 'REM ', '')
+    elseif a:filetype ==? "bbx"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "bc"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "bib"
+        call s:MapDelimiters('%','')
+    elseif a:filetype ==? "bindzone"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "bst"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "btm"
+        call s:MapDelimiters('::', '')
+    elseif a:filetype ==? "caos"
+        call s:MapDelimiters('*', '')
+    elseif a:filetype ==? "calibre"
+        call s:MapDelimiters('//','')
+    elseif a:filetype ==? "catalog"
+        call s:MapDelimiters('--','--')
+    elseif a:filetype ==? "c"
+        call s:MapDelimitersWithAlternative('/*','*/', '//', '')
+    elseif a:filetype ==? "cfg"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "cg"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "ch"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "cl"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "clean"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "clipper"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "clojure"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "cmake"
+        call s:MapDelimiters('#','')
+    elseif a:filetype ==? "conkyrc"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "cpp"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "crontab"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "cs"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "csp"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "cterm"
+        call s:MapDelimiters('*', '')
+    elseif a:filetype ==? "cucumber"
+        call s:MapDelimiters('#','')
+    elseif a:filetype ==? "cvs"
+        call s:MapDelimiters('CVS:','')
+    elseif a:filetype ==? "d"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "dcl"
+        call s:MapDelimiters('$!', '')
+    elseif a:filetype ==? "dakota"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "debcontrol"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "debsources"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "def"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "desktop"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "dhcpd"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "diff"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "django"
+        call s:MapDelimitersWithAlternative('<!--','-->', '{#', '#}')
+    elseif a:filetype ==? "docbk"
+        call s:MapDelimiters('<!--', '-->')
+    elseif a:filetype ==? "dns"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "dosbatch"
+        call s:MapDelimitersWithAlternative('REM ','', '::', '')
+    elseif a:filetype ==? "dosini"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "dot"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "dracula"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "dsl"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "dtml"
+        call s:MapDelimiters('<dtml-comment>','</dtml-comment>')
+    elseif a:filetype ==? "dylan"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? 'ebuild'
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "ecd"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? 'eclass'
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "eiffel"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "elf"
+        call s:MapDelimiters("'", '')
+    elseif a:filetype ==? "elmfilt"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "erlang"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "eruby"
+        call s:MapDelimitersWithAlternative('<%#', '%>', '<!--', '-->')
+    elseif a:filetype ==? "expect"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "exports"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "factor"
+        call s:MapDelimitersWithAlternative('! ', '', '!# ', '')
+    elseif a:filetype ==? "fgl"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "focexec"
+        call s:MapDelimiters('-*', '')
+    elseif a:filetype ==? "form"
+        call s:MapDelimiters('*', '')
+    elseif a:filetype ==? "foxpro"
+        call s:MapDelimiters('*', '')
+    elseif a:filetype ==? "fstab"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "fvwm"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "fx"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "gams"
+        call s:MapDelimiters('*', '')
+    elseif a:filetype ==? "gdb"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "gdmo"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "geek"
+        call s:MapDelimiters('GEEK_COMMENT:', '')
+    elseif a:filetype ==? "genshi"
+        call s:MapDelimitersWithAlternative('<!--','-->', '{#', '#}')
+    elseif a:filetype ==? "gentoo-conf-d"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "gentoo-env-d"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "gentoo-init-d"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "gentoo-make-conf"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? 'gentoo-package-keywords'
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? 'gentoo-package-mask'
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? 'gentoo-package-use'
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? 'gitcommit'
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? 'gitconfig'
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? 'gitrebase'
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "gnuplot"
+        call s:MapDelimiters('#','')
+    elseif a:filetype ==? "groovy"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "gtkrc"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "haskell"
+        call s:MapDelimitersWithAlternative('{-','-}', '--', '')
+    elseif a:filetype ==? "hb"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "h"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "haml"
+        call s:MapDelimitersWithAlternative('-#', '', '/', '')
+    elseif a:filetype ==? "hercules"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "hog"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "hostsaccess"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "htmlcheetah"
+        call s:MapDelimiters('##','')
+    elseif a:filetype ==? "htmldjango"
+        call s:MapDelimitersWithAlternative('<!--','-->', '{#', '#}')
+    elseif a:filetype ==? "htmlos"
+        call s:MapDelimiters('#','/#')
+    elseif a:filetype ==? "ia64"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "icon"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "idlang"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "idl"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "inform"
+        call s:MapDelimiters('!', '')
+    elseif a:filetype ==? "inittab"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "ishd"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "iss"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "ist"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "java"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "javacc"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "javascript"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype == "javascript.jquery"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "jess"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "jgraph"
+        call s:MapDelimiters('(*','*)')
+    elseif a:filetype ==? "jproperties"
+        call s:MapDelimiters('#','')
+    elseif a:filetype ==? "jsp"
+        call s:MapDelimiters('<%--', '--%>')
+    elseif a:filetype ==? "kix"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "kscript"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "lace"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "ldif"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "lilo"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "lilypond"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "liquid"
+        call s:MapDelimiters('{%', '%}')
+    elseif a:filetype ==? "lisp"
+        call s:MapDelimitersWithAlternative(';','', '#|', '|#')
+    elseif a:filetype ==? "llvm"
+        call s:MapDelimiters(';','')
+    elseif a:filetype ==? "lotos"
+        call s:MapDelimiters('(*','*)')
+    elseif a:filetype ==? "lout"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "lprolog"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "lscript"
+        call s:MapDelimiters("'", '')
+    elseif a:filetype ==? "lss"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "lua"
+        call s:MapDelimitersWithAlternative('--','', '--[[', ']]')
+    elseif a:filetype ==? "lynx"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "lytex"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "mail"
+        call s:MapDelimiters('> ','')
+    elseif a:filetype ==? "mako"
+        call s:MapDelimiters('##', '')
+    elseif a:filetype ==? "man"
+        call s:MapDelimiters('."', '')
+    elseif a:filetype ==? "map"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "maple"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "markdown"
+        call s:MapDelimiters('<!--', '-->')
+    elseif a:filetype ==? "masm"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "mason"
+        call s:MapDelimiters('<% #', '%>')
+    elseif a:filetype ==? "master"
+        call s:MapDelimiters('$', '')
+    elseif a:filetype ==? "matlab"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "mel"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "mib"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "mkd"
+        call s:MapDelimiters('>', '')
+    elseif a:filetype ==? "mma"
+        call s:MapDelimiters('(*','*)')
+    elseif a:filetype ==? "model"
+        call s:MapDelimiters('$','$')
+    elseif a:filetype =~ "moduala."
+        call s:MapDelimiters('(*','*)')
+    elseif a:filetype ==? "modula2"
+        call s:MapDelimiters('(*','*)')
+    elseif a:filetype ==? "modula3"
+        call s:MapDelimiters('(*','*)')
+    elseif a:filetype ==? "monk"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "mush"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "named"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "nasm"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "nastran"
+        call s:MapDelimiters('$', '')
+    elseif a:filetype ==? "natural"
+        call s:MapDelimiters('/*', '')
+    elseif a:filetype ==? "ncf"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "newlisp"
+        call s:MapDelimiters(';','')
+    elseif a:filetype ==? "nroff"
+        call s:MapDelimiters('\"', '')
+    elseif a:filetype ==? "nsis"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "ntp"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "objc"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "objcpp"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "objj"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "ocaml"
+        call s:MapDelimiters('(*','*)')
+    elseif a:filetype ==? "occam"
+        call s:MapDelimiters('--','')
+    elseif a:filetype ==? "omlet"
+        call s:MapDelimiters('(*','*)')
+    elseif a:filetype ==? "omnimark"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "openroad"
+        call s:MapDelimiters('//', '')
+    elseif a:filetype ==? "opl"
+        call s:MapDelimiters("REM", "")
+    elseif a:filetype ==? "ora"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "ox"
+        call s:MapDelimiters('//', '')
+    elseif a:filetype ==? "pascal"
+        call s:MapDelimitersWithAlternative('{','}', '(*', '*)')
+    elseif a:filetype ==? "patran"
+        call s:MapDelimitersWithAlternative('$','','/*', '*/')
+    elseif a:filetype ==? "pcap"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "pccts"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "pdf"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "pfmain"
+        call s:MapDelimiters('//', '')
+    elseif a:filetype ==? "php"
+        call s:MapDelimitersWithAlternative('//','','/*', '*/')
+    elseif a:filetype ==? "pic"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "pike"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "pilrc"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "pine"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "plm"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "plsql"
+        call s:MapDelimitersWithAlternative('--', '', '/*', '*/')
+    elseif a:filetype ==? "po"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "postscr"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "pov"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "povini"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "ppd"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "ppwiz"
+        call s:MapDelimiters(';;', '')
+    elseif a:filetype ==? "processing"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "prolog"
+        call s:MapDelimitersWithAlternative('%','','/*','*/')
+    elseif a:filetype ==? "ps1"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "psf"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "ptcap"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "python"
+        call s:MapDelimiters('#','')
+    elseif a:filetype ==? "radiance"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "ratpoison"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "r"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "rc"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "rebol"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "registry"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "remind"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "resolv"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "rgb"
+        call s:MapDelimiters('!', '')
+    elseif a:filetype ==? "rib"
+        call s:MapDelimiters('#','')
+    elseif a:filetype ==? "robots"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "sa"
+        call s:MapDelimiters('--','')
+    elseif a:filetype ==? "samba"
+        call s:MapDelimitersWithAlternative(';','', '#', '')
+    elseif a:filetype ==? "sass"
+        call s:MapDelimitersWithAlternative('//','', '/*', '')
+    elseif a:filetype ==? "sather"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "scala"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "scilab"
+        call s:MapDelimiters('//', '')
+    elseif a:filetype ==? "scsh"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "sed"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "sgmldecl"
+        call s:MapDelimiters('--','--')
+    elseif a:filetype ==? "sgmllnx"
+        call s:MapDelimiters('<!--','-->')
+    elseif a:filetype ==? "sicad"
+        call s:MapDelimiters('*', '')
+    elseif a:filetype ==? "simula"
+        call s:MapDelimitersWithAlternative('%', '', '--', '')
+    elseif a:filetype ==? "sinda"
+        call s:MapDelimiters('$', '')
+    elseif a:filetype ==? "skill"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "slang"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "slice"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "slrnrc"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "sm"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "smarty"
+        call s:MapDelimiters('{*', '*}')
+    elseif a:filetype ==? "smil"
+        call s:MapDelimiters('<!','>')
+    elseif a:filetype ==? "smith"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "sml"
+        call s:MapDelimiters('(*','*)')
+    elseif a:filetype ==? "snnsnet"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "snnspat"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "snnsres"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "snobol4"
+        call s:MapDelimiters('*', '')
+    elseif a:filetype ==? "spec"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "specman"
+        call s:MapDelimiters('//', '')
+    elseif a:filetype ==? "spectre"
+        call s:MapDelimitersWithAlternative('//', '', '*', '')
+    elseif a:filetype ==? "spice"
+        call s:MapDelimiters('$', '')
+    elseif a:filetype ==? "sql"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "sqlforms"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "sqlj"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "sqr"
+        call s:MapDelimiters('!', '')
+    elseif a:filetype ==? "squid"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "st"
+        call s:MapDelimiters('"','')
+    elseif a:filetype ==? "stp"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "systemverilog"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "tads"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "tags"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "tak"
+        call s:MapDelimiters('$', '')
+    elseif a:filetype ==? "tasm"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "tcl"
+        call s:MapDelimiters('#','')
+    elseif a:filetype ==? "texinfo"
+        call s:MapDelimiters("@c ", "")
+    elseif a:filetype ==? "texmf"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "tf"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "tidy"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "tli"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "trasys"
+        call s:MapDelimiters("$", "")
+    elseif a:filetype ==? "tsalt"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "tsscl"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "tssgm"
+        call s:MapDelimiters("comment = '","'")
+    elseif a:filetype ==? "txt2tags"
+        call s:MapDelimiters('%','')
+    elseif a:filetype ==? "uc"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "uil"
+        call s:MapDelimiters('!', '')
+    elseif a:filetype ==? "vb"
+        call s:MapDelimiters("'","")
+    elseif a:filetype ==? "velocity"
+        call s:MapDelimitersWithAlternative("##","", '#*', '*#')
+    elseif a:filetype ==? "vera"
+        call s:MapDelimitersWithAlternative('/*','*/','//','')
+    elseif a:filetype ==? "verilog"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "verilog_systemverilog"
+        call s:MapDelimitersWithAlternative('//','', '/*','*/')
+    elseif a:filetype ==? "vgrindefs"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "vhdl"
+        call s:MapDelimiters('--', '')
+    elseif a:filetype ==? "vimperator"
+        call s:MapDelimiters('"','')
+    elseif a:filetype ==? "virata"
+        call s:MapDelimiters('%', '')
+    elseif a:filetype ==? "vrml"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "vsejcl"
+        call s:MapDelimiters('/*', '')
+    elseif a:filetype ==? "webmacro"
+        call s:MapDelimiters('##', '')
+    elseif a:filetype ==? "wget"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "Wikipedia"
+        call s:MapDelimiters('<!--','-->')
+    elseif a:filetype ==? "winbatch"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "wml"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "wvdial"
+        call s:MapDelimiters(';', '')
+    elseif a:filetype ==? "xdefaults"
+        call s:MapDelimiters('!', '')
+    elseif a:filetype ==? "xkb"
+        call s:MapDelimiters('//', '')
+    elseif a:filetype ==? "xmath"
+        call s:MapDelimiters('#', '')
+    elseif a:filetype ==? "xpm2"
+        call s:MapDelimiters('!', '')
+    elseif a:filetype ==? "xquery"
+        call s:MapDelimiters('(:',':)')
+    elseif a:filetype ==? "z8a"
+        call s:MapDelimiters(';', '')
+
+    else
+
+        "extract the delims from &commentstring
+        let left= substitute(&commentstring, '\([^ \t]*\)\s*%s.*', '\1', '')
+        let right= substitute(&commentstring, '.*%s\s*\(.*\)', '\1', 'g')
+        call s:MapDelimiters(left,right)
+
+    endif
+endfunction
+
+" Function: s:MapDelimiters(left, right) function {{{2
+" This function is a wrapper for s:MapDelimiters(left, right, leftAlt, rightAlt, useAlt) and is called when there
+" is no alternative comment delimiters for the current filetype
+"
+" Args:
+"   -left: the left comment delimiter
+"   -right: the right comment delimiter
+function s:MapDelimiters(left, right)
+    call s:MapDelimitersWithAlternative(a:left, a:right, "", "")
+endfunction
+
+" Function: s:MapDelimitersWithAlternative(left, right, leftAlt, rightAlt) function {{{2
+" this function sets up the comment delimiter buffer variables
+"
+" Args:
+"   -left:  the string defining the comment start delimiter
+"   -right: the string defining the comment end delimiter
+"   -leftAlt:  the string for the alternative comment style defining the comment start delimiter
+"   -rightAlt: the string for the alternative comment style defining the comment end delimiter
+function s:MapDelimitersWithAlternative(left, right, leftAlt, rightAlt)
+    if !exists('g:NERD_' . &filetype . '_alt_style')
+        let b:NERDLeft = a:left
+        let b:NERDRight = a:right
+        let b:NERDLeftAlt = a:leftAlt
+        let b:NERDRightAlt = a:rightAlt
+    else
+        let b:NERDLeft = a:leftAlt
+        let b:NERDRight = a:rightAlt
+        let b:NERDLeftAlt = a:left
+        let b:NERDRightAlt = a:right
+    endif
+endfunction
+
+" Function: s:SwitchToAlternativeDelimiters(printMsgs) function {{{2
+" This function is used to swap the delimiters that are being used to the
+" alternative delimiters for that filetype. For example, if a c++ file is
+" being edited and // comments are being used, after this function is called
+" /**/ comments will be used.
+"
+" Args:
+"   -printMsgs: if this is 1 then a message is echoed to the user telling them
+"    if this function changed the delimiters or not
+function s:SwitchToAlternativeDelimiters(printMsgs)
+    "if both of the alternative delimiters are empty then there is no
+    "alternative comment style so bail out
+    if b:NERDLeftAlt == "" && b:NERDRightAlt == ""
+        if a:printMsgs
+            call s:NerdEcho("Cannot use alternative delimiters, none are specified", 0)
+        endif
+        return 0
+    endif
+
+    "save the current delimiters
+    let tempLeft = b:NERDLeft
+    let tempRight = b:NERDRight
+
+    "swap current delimiters for alternative
+    let b:NERDLeft = b:NERDLeftAlt
+    let b:NERDRight = b:NERDRightAlt
+
+    "set the previously current delimiters to be the new alternative ones
+    let b:NERDLeftAlt = tempLeft
+    let b:NERDRightAlt = tempRight
+
+    "tell the user what comment delimiters they are now using
+    if a:printMsgs
+        let leftNoEsc = b:NERDLeft
+        let rightNoEsc = b:NERDRight
+        call s:NerdEcho("Now using " . leftNoEsc . " " . rightNoEsc . " to delimit comments", 1)
+    endif
+
+    return 1
+endfunction
+
+" Section: Comment delimiter add/removal functions {{{1
+" ============================================================================
+" Function: s:AppendCommentToLine(){{{2
+" This function appends comment delimiters at the EOL and places the cursor in
+" position to start typing the comment
+function s:AppendCommentToLine()
+    let left = s:GetLeft(0,1,0)
+    let right = s:GetRight(0,1,0)
+
+    " get the len of the right delim
+    let lenRight = strlen(right)
+
+    let isLineEmpty = strlen(getline(".")) == 0
+    let insOrApp = (isLineEmpty==1 ? 'i' : 'A')
+
+    "stick the delimiters down at the end of the line. We have to format the
+    "comment with spaces as appropriate
+    execute ":normal! " . insOrApp . (isLineEmpty ? '' : ' ') . left . right . " "
+
+    " if there is a right delimiter then we gotta move the cursor left
+    " by the len of the right delimiter so we insert between the delimiters
+    if lenRight > 0
+        let leftMoveAmount = lenRight
+        execute ":normal! " . leftMoveAmount . "h"
+    endif
+    startinsert
+endfunction
+
+" Function: s:CommentBlock(top, bottom, lSide, rSide, forceNested ) {{{2
+" This function is used to comment out a region of code. This region is
+" specified as a bounding box by arguments to the function.
+"
+" Args:
+"   -top: the line number for the top line of code in the region
+"   -bottom: the line number for the bottom line of code in the region
+"   -lSide: the column number for the left most column in the region
+"   -rSide: the column number for the right most column in the region
+"   -forceNested: a flag indicating whether comments should be nested
+function s:CommentBlock(top, bottom, lSide, rSide, forceNested )
+    " we need to create local copies of these arguments so we can modify them
+    let top = a:top
+    let bottom = a:bottom
+    let lSide = a:lSide
+    let rSide = a:rSide
+
+    "if the top or bottom line starts with tabs we have to adjust the left and
+    "right boundaries so that they are set as though the tabs were spaces
+    let topline = getline(top)
+    let bottomline = getline(bottom)
+    if s:HasLeadingTabs(topline, bottomline)
+
+        "find out how many tabs are in the top line and adjust the left
+        "boundary accordingly
+        let numTabs = s:NumberOfLeadingTabs(topline)
+        if lSide < numTabs
+            let lSide = &ts * lSide
+        else
+            let lSide = (lSide - numTabs) + (&ts * numTabs)
+        endif
+
+        "find out how many tabs are in the bottom line and adjust the right
+        "boundary accordingly
+        let numTabs = s:NumberOfLeadingTabs(bottomline)
+        let rSide = (rSide - numTabs) + (&ts * numTabs)
+    endif
+
+    "we must check that bottom IS actually below top, if it is not then we
+    "swap top and bottom. Similarly for left and right.
+    if bottom < top
+        let temp = top
+        let top = bottom
+        let bottom = top
+    endif
+    if rSide < lSide
+        let temp = lSide
+        let lSide = rSide
+        let rSide = temp
+    endif
+
+    "if the current delimiters arent multipart then we will switch to the
+    "alternative delims (if THEY are) as the comment will be better and more
+    "accurate with multipart delims
+    let switchedDelims = 0
+    if !s:Multipart() && g:NERDAllowAnyVisualDelims && s:AltMultipart()
+        let switchedDelims = 1
+        call s:SwitchToAlternativeDelimiters(0)
+    endif
+
+    "start the commenting from the top and keep commenting till we reach the
+    "bottom
+    let currentLine=top
+    while currentLine <= bottom
+
+        "check if we are allowed to comment this line
+        if s:CanCommentLine(a:forceNested, currentLine)
+
+            "convert the leading tabs into spaces
+            let theLine = getline(currentLine)
+            let lineHasLeadTabs = s:HasLeadingTabs(theLine)
+            if lineHasLeadTabs
+                let theLine = s:ConvertLeadingTabsToSpaces(theLine)
+            endif
+
+            "dont comment lines that begin after the right boundary of the
+            "block unless the user has specified to do so
+            if theLine !~ '^ \{' . rSide . '\}' || !g:NERDBlockComIgnoreEmpty
+
+                "attempt to place the cursor in on the left of the boundary box,
+                "then check if we were successful, if not then we cant comment this
+                "line
+                call setline(currentLine, theLine)
+                if s:CanPlaceCursor(currentLine, lSide)
+
+                    let leftSpaced = s:GetLeft(0,1,0)
+                    let rightSpaced = s:GetRight(0,1,0)
+
+                    "stick the left delimiter down
+                    let theLine = strpart(theLine, 0, lSide-1) . leftSpaced . strpart(theLine, lSide-1)
+
+                    if s:Multipart()
+                        "stick the right delimiter down
+                        let theLine = strpart(theLine, 0, rSide+strlen(leftSpaced)) . rightSpaced . strpart(theLine, rSide+strlen(leftSpaced))
+
+                        let firstLeftDelim = s:FindDelimiterIndex(b:NERDLeft, theLine)
+                        let lastRightDelim = s:LastIndexOfDelim(b:NERDRight, theLine)
+
+                        if firstLeftDelim != -1 && lastRightDelim != -1
+                            let searchStr = strpart(theLine, 0, lastRightDelim)
+                            let searchStr = strpart(searchStr, firstLeftDelim+strlen(b:NERDLeft))
+
+                            "replace the outter most delims in searchStr with
+                            "place-holders
+                            let theLineWithPlaceHolders = s:ReplaceDelims(b:NERDLeft, b:NERDRight, g:NERDLPlace, g:NERDRPlace, searchStr)
+
+                            "add the right delimiter onto the line
+                            let theLine = strpart(theLine, 0, firstLeftDelim+strlen(b:NERDLeft)) . theLineWithPlaceHolders . strpart(theLine, lastRightDelim)
+                        endif
+                    endif
+                endif
+            endif
+
+            "restore tabs if needed
+            if lineHasLeadTabs
+                let theLine = s:ConvertLeadingSpacesToTabs(theLine)
+            endif
+
+            call setline(currentLine, theLine)
+        endif
+
+        let currentLine = currentLine + 1
+    endwhile
+
+    "if we switched delims then we gotta go back to what they were before
+    if switchedDelims == 1
+        call s:SwitchToAlternativeDelimiters(0)
+    endif
+endfunction
+
+" Function: s:CommentLines(forceNested, alignLeft, alignRight, firstLine, lastLine) {{{2
+" This function comments a range of lines.
+"
+" Args:
+"   -forceNested: a flag indicating whether the called is requesting the comment
+"    to be nested if need be
+"   -align: should be "left" or "both" or "none"
+"   -firstLine/lastLine: the top and bottom lines to comment
+function s:CommentLines(forceNested, align, firstLine, lastLine)
+    " we need to get the left and right indexes of the leftmost char in the
+    " block of of lines and the right most char so that we can do alignment of
+    " the delimiters if the user has specified
+    let leftAlignIndx = s:LeftMostIndx(a:forceNested, 0, a:firstLine, a:lastLine)
+    let rightAlignIndx = s:RightMostIndx(a:forceNested, 0, a:firstLine, a:lastLine)
+
+    " gotta add the length of the left delimiter onto the rightAlignIndx cos
+    " we'll be adding a left delim to the line
+    let rightAlignIndx = rightAlignIndx + strlen(s:GetLeft(0,1,0))
+
+    " now we actually comment the lines. Do it line by line
+    let currentLine = a:firstLine
+    while currentLine <= a:lastLine
+
+        " get the next line, check commentability and convert spaces to tabs
+        let theLine = getline(currentLine)
+        let lineHasLeadingTabs = s:HasLeadingTabs(theLine)
+        let theLine = s:ConvertLeadingTabsToSpaces(theLine)
+        if s:CanCommentLine(a:forceNested, currentLine)
+            "if the user has specified forceNesting then we check to see if we
+            "need to switch delimiters for place-holders
+            if a:forceNested && g:NERDUsePlaceHolders
+                let theLine = s:SwapOutterMultiPartDelimsForPlaceHolders(theLine)
+            endif
+
+            " find out if the line is commented using normal delims and/or
+            " alternate ones
+            let isCommented = s:IsCommented(b:NERDLeft, b:NERDRight, theLine) || s:IsCommented(b:NERDLeftAlt, b:NERDRightAlt, theLine)
+
+            " check if we can comment this line
+            if !isCommented || g:NERDUsePlaceHolders || s:Multipart()
+                if a:align == "left" || a:align == "both"
+                    let theLine = s:AddLeftDelimAligned(s:GetLeft(0,1,0), theLine, leftAlignIndx)
+                else
+                    let theLine = s:AddLeftDelim(s:GetLeft(0,1,0), theLine)
+                endif
+                if a:align == "both"
+                    let theLine = s:AddRightDelimAligned(s:GetRight(0,1,0), theLine, rightAlignIndx)
+                else
+                    let theLine = s:AddRightDelim(s:GetRight(0,1,0), theLine)
+                endif
+            endif
+        endif
+
+        " restore leading tabs if appropriate
+        if lineHasLeadingTabs
+            let theLine = s:ConvertLeadingSpacesToTabs(theLine)
+        endif
+
+        " we are done with this line
+        call setline(currentLine, theLine)
+        let currentLine = currentLine + 1
+    endwhile
+
+endfunction
+
+" Function: s:CommentLinesMinimal(firstLine, lastLine) {{{2
+" This function comments a range of lines in a minimal style. I
+"
+" Args:
+"   -firstLine/lastLine: the top and bottom lines to comment
+function s:CommentLinesMinimal(firstLine, lastLine)
+    "check that minimal comments can be done on this filetype
+    if !s:HasMultipartDelims()
+        throw 'NERDCommenter.Delimiters exception: Minimal comments can only be used for filetypes that have multipart delimiters'
+    endif
+
+    "if we need to use place holders for the comment, make sure they are
+    "enabled for this filetype
+    if !g:NERDUsePlaceHolders && s:DoesBlockHaveMultipartDelim(a:firstLine, a:lastLine)
+        throw 'NERDCommenter.Settings exception: Placeoholders are required but disabled.'
+    endif
+
+    "get the left and right delims to smack on
+    let left = s:GetSexyComLeft(g:NERDSpaceDelims,0)
+    let right = s:GetSexyComRight(g:NERDSpaceDelims,0)
+
+    "make sure all multipart delims on the lines are replaced with
+    "placeholders to prevent illegal syntax
+    let currentLine = a:firstLine
+    while(currentLine <= a:lastLine)
+        let theLine = getline(currentLine)
+        let theLine = s:ReplaceDelims(left, right, g:NERDLPlace, g:NERDRPlace, theLine)
+        call setline(currentLine, theLine)
+        let currentLine = currentLine + 1
+    endwhile
+
+    "add the delim to the top line
+    let theLine = getline(a:firstLine)
+    let lineHasLeadingTabs = s:HasLeadingTabs(theLine)
+    let theLine = s:ConvertLeadingTabsToSpaces(theLine)
+    let theLine = s:AddLeftDelim(left, theLine)
+    if lineHasLeadingTabs
+        let theLine = s:ConvertLeadingSpacesToTabs(theLine)
+    endif
+    call setline(a:firstLine, theLine)
+
+    "add the delim to the bottom line
+    let theLine = getline(a:lastLine)
+    let lineHasLeadingTabs = s:HasLeadingTabs(theLine)
+    let theLine = s:ConvertLeadingTabsToSpaces(theLine)
+    let theLine = s:AddRightDelim(right, theLine)
+    if lineHasLeadingTabs
+        let theLine = s:ConvertLeadingSpacesToTabs(theLine)
+    endif
+    call setline(a:lastLine, theLine)
+endfunction
+
+" Function: s:CommentLinesSexy(topline, bottomline) function {{{2
+" This function is used to comment lines in the 'Sexy' style. eg in c:
+" /*
+"  * This is a sexy comment
+"  */
+" Args:
+"   -topline: the line num of the top line in the sexy comment
+"   -bottomline: the line num of the bottom line in the sexy comment
+function s:CommentLinesSexy(topline, bottomline)
+    let left = s:GetSexyComLeft(0, 0)
+    let right = s:GetSexyComRight(0, 0)
+
+    "check if we can do a sexy comment with the available delimiters
+    if left == -1 || right == -1
+        throw 'NERDCommenter.Delimiters exception: cannot perform sexy comments with available delimiters.'
+    endif
+
+    "make sure the lines arent already commented sexually
+    if !s:CanSexyCommentLines(a:topline, a:bottomline)
+        throw 'NERDCommenter.Nesting exception: cannot nest sexy comments'
+    endif
+
+
+    let sexyComMarker = s:GetSexyComMarker(0,0)
+    let sexyComMarkerSpaced = s:GetSexyComMarker(1,0)
+
+
+    " we jam the comment as far to the right as possible
+    let leftAlignIndx = s:LeftMostIndx(1, 1, a:topline, a:bottomline)
+
+    "check if we should use the compact style i.e that the left/right
+    "delimiters should appear on the first and last lines of the code and not
+    "on separate lines above/below the first/last lines of code
+    if g:NERDCompactSexyComs
+        let spaceString = (g:NERDSpaceDelims ? s:spaceStr : '')
+
+        "comment the top line
+        let theLine = getline(a:topline)
+        let lineHasTabs = s:HasLeadingTabs(theLine)
+        if lineHasTabs
+            let theLine = s:ConvertLeadingTabsToSpaces(theLine)
+        endif
+        let theLine = s:SwapOutterMultiPartDelimsForPlaceHolders(theLine)
+        let theLine = s:AddLeftDelimAligned(left . spaceString, theLine, leftAlignIndx)
+        if lineHasTabs
+            let theLine = s:ConvertLeadingSpacesToTabs(theLine)
+        endif
+        call setline(a:topline, theLine)
+
+        "comment the bottom line
+        if a:bottomline != a:topline
+            let theLine = getline(a:bottomline)
+            let lineHasTabs = s:HasLeadingTabs(theLine)
+            if lineHasTabs
+                let theLine = s:ConvertLeadingTabsToSpaces(theLine)
+            endif
+            let theLine = s:SwapOutterMultiPartDelimsForPlaceHolders(theLine)
+        endif
+        let theLine = s:AddRightDelim(spaceString . right, theLine)
+        if lineHasTabs
+            let theLine = s:ConvertLeadingSpacesToTabs(theLine)
+        endif
+        call setline(a:bottomline, theLine)
+    else
+
+        " add the left delimiter one line above the lines that are to be commented
+        call cursor(a:topline, 1)
+        execute 'normal! O'
+        let theLine = repeat(' ', leftAlignIndx) . left
+
+        " Make sure tabs are respected
+        if !&expandtab
+           let theLine = s:ConvertLeadingSpacesToTabs(theLine)
+        endif
+        call setline(a:topline, theLine)
+
+        " add the right delimiter after bottom line (we have to add 1 cos we moved
+        " the lines down when we added the left delim
+        call cursor(a:bottomline+1, 1)
+        execute 'normal! o'
+        let theLine = repeat(' ', leftAlignIndx) . repeat(' ', strlen(left)-strlen(sexyComMarker)) . right
+
+        " Make sure tabs are respected
+        if !&expandtab
+           let theLine = s:ConvertLeadingSpacesToTabs(theLine)
+        endif
+        call setline(a:bottomline+2, theLine)
+
+    endif
+
+    " go thru each line adding the sexyComMarker marker to the start of each
+    " line in the appropriate place to align them with the comment delims
+    let currentLine = a:topline+1
+    while currentLine <= a:bottomline + !g:NERDCompactSexyComs
+        " get the line and convert the tabs to spaces
+        let theLine = getline(currentLine)
+        let lineHasTabs = s:HasLeadingTabs(theLine)
+        if lineHasTabs
+            let theLine = s:ConvertLeadingTabsToSpaces(theLine)
+        endif
+
+        let theLine = s:SwapOutterMultiPartDelimsForPlaceHolders(theLine)
+
+        " add the sexyComMarker
+        let theLine = repeat(' ', leftAlignIndx) . repeat(' ', strlen(left)-strlen(sexyComMarker)) . sexyComMarkerSpaced . strpart(theLine, leftAlignIndx)
+
+        if lineHasTabs
+            let theLine = s:ConvertLeadingSpacesToTabs(theLine)
+        endif
+
+
+        " set the line and move onto the next one
+        call setline(currentLine, theLine)
+        let currentLine = currentLine + 1
+    endwhile
+
+endfunction
+
+" Function: s:CommentLinesToggle(forceNested, firstLine, lastLine) {{{2
+" Applies "toggle" commenting to the given range of lines
+"
+" Args:
+"   -forceNested: a flag indicating whether the called is requesting the comment
+"    to be nested if need be
+"   -firstLine/lastLine: the top and bottom lines to comment
+function s:CommentLinesToggle(forceNested, firstLine, lastLine)
+    let currentLine = a:firstLine
+    while currentLine <= a:lastLine
+
+        " get the next line, check commentability and convert spaces to tabs
+        let theLine = getline(currentLine)
+        let lineHasLeadingTabs = s:HasLeadingTabs(theLine)
+        let theLine = s:ConvertLeadingTabsToSpaces(theLine)
+        if s:CanToggleCommentLine(a:forceNested, currentLine)
+
+            "if the user has specified forceNesting then we check to see if we
+            "need to switch delimiters for place-holders
+            if g:NERDUsePlaceHolders
+                let theLine = s:SwapOutterMultiPartDelimsForPlaceHolders(theLine)
+            endif
+
+            let theLine = s:AddLeftDelim(s:GetLeft(0, 1, 0), theLine)
+            let theLine = s:AddRightDelim(s:GetRight(0, 1, 0), theLine)
+        endif
+
+        " restore leading tabs if appropriate
+        if lineHasLeadingTabs
+            let theLine = s:ConvertLeadingSpacesToTabs(theLine)
+        endif
+
+        " we are done with this line
+        call setline(currentLine, theLine)
+        let currentLine = currentLine + 1
+    endwhile
+
+endfunction
+
+" Function: s:CommentRegion(topline, topCol, bottomLine, bottomCol) function {{{2
+" This function comments chunks of text selected in visual mode.
+" It will comment exactly the text that they have selected.
+" Args:
+"   -topLine: the line num of the top line in the sexy comment
+"   -topCol: top left col for this comment
+"   -bottomline: the line num of the bottom line in the sexy comment
+"   -bottomCol: the bottom right col for this comment
+"   -forceNested: whether the caller wants comments to be nested if the
+"    line(s) are already commented
+function s:CommentRegion(topLine, topCol, bottomLine, bottomCol, forceNested)
+
+    "switch delims (if we can) if the current set isnt multipart
+    let switchedDelims = 0
+    if !s:Multipart() && s:AltMultipart() && !g:NERDAllowAnyVisualDelims
+        let switchedDelims = 1
+        call s:SwitchToAlternativeDelimiters(0)
+    endif
+
+    "if there is only one line in the comment then just do it
+    if a:topLine == a:bottomLine
+        call s:CommentBlock(a:topLine, a:bottomLine, a:topCol, a:bottomCol, a:forceNested)
+
+    "there are multiple lines in the comment
+    else
+        "comment the top line
+        call s:CommentBlock(a:topLine, a:topLine, a:topCol, strlen(getline(a:topLine)), a:forceNested)
+
+        "comment out all the lines in the middle of the comment
+        let topOfRange = a:topLine+1
+        let bottomOfRange = a:bottomLine-1
+        if topOfRange <= bottomOfRange
+            call s:CommentLines(a:forceNested, "none", topOfRange, bottomOfRange)
+        endif
+
+        "comment the bottom line
+        let bottom = getline(a:bottomLine)
+        let numLeadingSpacesTabs = strlen(substitute(bottom, '^\([ \t]*\).*$', '\1', ''))
+        call s:CommentBlock(a:bottomLine, a:bottomLine, numLeadingSpacesTabs+1, a:bottomCol, a:forceNested)
+
+    endif
+
+    "stick the cursor back on the char it was on before the comment
+    call cursor(a:topLine, a:topCol + strlen(b:NERDLeft) + g:NERDSpaceDelims)
+
+    "if we switched delims then we gotta go back to what they were before
+    if switchedDelims == 1
+        call s:SwitchToAlternativeDelimiters(0)
+    endif
+
+endfunction
+
+" Function: s:InvertComment(firstLine, lastLine) function {{{2
+" Inverts the comments on the lines between and including the given line
+" numbers i.e all commented lines are uncommented and vice versa
+" Args:
+"   -firstLine: the top of the range of lines to be inverted
+"   -lastLine: the bottom of the range of lines to be inverted
+function s:InvertComment(firstLine, lastLine)
+
+    " go thru all lines in the given range
+    let currentLine = a:firstLine
+    while currentLine <= a:lastLine
+        let theLine = getline(currentLine)
+
+        let sexyComBounds = s:FindBoundingLinesOfSexyCom(currentLine)
+
+        " if the line is commented normally, uncomment it
+        if s:IsCommentedFromStartOfLine(b:NERDLeft, theLine) || s:IsCommentedFromStartOfLine(b:NERDLeftAlt, theLine)
+            call s:UncommentLines(currentLine, currentLine)
+            let currentLine = currentLine + 1
+
+        " check if the line is commented sexually
+        elseif !empty(sexyComBounds)
+            let numLinesBeforeSexyComRemoved = s:NumLinesInBuf()
+            call s:UncommentLinesSexy(sexyComBounds[0], sexyComBounds[1])
+
+            "move to the line after last line of the sexy comment
+            let numLinesAfterSexyComRemoved = s:NumLinesInBuf()
+            let currentLine = bottomBound - (numLinesBeforeSexyComRemoved - numLinesAfterSexyComRemoved) + 1
+
+        " the line isnt commented
+        else
+            call s:CommentLinesToggle(1, currentLine, currentLine)
+            let currentLine = currentLine + 1
+        endif
+
+    endwhile
+endfunction
+
+" Function: NERDComment(isVisual, type) function {{{2
+" This function is a Wrapper for the main commenting functions
+"
+" Args:
+"   -isVisual: a flag indicating whether the comment is requested in visual
+"    mode or not
+"   -type: the type of commenting requested. Can be 'sexy', 'invert',
+"    'minimal', 'toggle', 'alignLeft', 'alignBoth', 'norm',
+"    'nested', 'toEOL', 'append', 'insert', 'uncomment', 'yank'
+function! NERDComment(isVisual, type) range
+    " we want case sensitivity when commenting
+    let oldIgnoreCase = &ignorecase
+    set noignorecase
+
+    if a:isVisual
+        let firstLine = line("'<")
+        let lastLine = line("'>")
+        let firstCol = col("'<")
+        let lastCol = col("'>") - (&selection == 'exclusive' ? 1 : 0)
+    else
+        let firstLine = a:firstline
+        let lastLine = a:lastline
+    endif
+
+    let countWasGiven = (a:isVisual == 0 && firstLine != lastLine)
+
+    let forceNested = (a:type == 'nested' || g:NERDDefaultNesting)
+
+    if a:type == 'norm' || a:type == 'nested'
+        if a:isVisual && visualmode() == ""
+            call s:CommentBlock(firstLine, lastLine, firstCol, lastCol, forceNested)
+        elseif a:isVisual && visualmode() == "v" && (g:NERDCommentWholeLinesInVMode==0 || (g:NERDCommentWholeLinesInVMode==2 && s:HasMultipartDelims()))
+            call s:CommentRegion(firstLine, firstCol, lastLine, lastCol, forceNested)
+        else
+            call s:CommentLines(forceNested, "none", firstLine, lastLine)
+        endif
+
+    elseif a:type == 'alignLeft' || a:type == 'alignBoth'
+        let align = "none"
+        if a:type == "alignLeft"
+            let align = "left"
+        elseif a:type == "alignBoth"
+            let align = "both"
+        endif
+        call s:CommentLines(forceNested, align, firstLine, lastLine)
+
+    elseif a:type == 'invert'
+        call s:InvertComment(firstLine, lastLine)
+
+    elseif a:type == 'sexy'
+        try
+            call s:CommentLinesSexy(firstLine, lastLine)
+        catch /NERDCommenter.Delimiters/
+            call s:CommentLines(forceNested, "none", firstLine, lastLine)
+        catch /NERDCommenter.Nesting/
+            call s:NerdEcho("Sexy comment aborted. Nested sexy cannot be nested", 0)
+        endtry
+
+    elseif a:type == 'toggle'
+        let theLine = getline(firstLine)
+
+        if s:IsInSexyComment(firstLine) || s:IsCommentedFromStartOfLine(b:NERDLeft, theLine) || s:IsCommentedFromStartOfLine(b:NERDLeftAlt, theLine)
+            call s:UncommentLines(firstLine, lastLine)
+        else
+            call s:CommentLinesToggle(forceNested, firstLine, lastLine)
+        endif
+
+    elseif a:type == 'minimal'
+        try
+            call s:CommentLinesMinimal(firstLine, lastLine)
+        catch /NERDCommenter.Delimiters/
+            call s:NerdEcho("Minimal comments can only be used for filetypes that have multipart delimiters.", 0)
+        catch /NERDCommenter.Settings/
+            call s:NerdEcho("Place holders are required but disabled.", 0)
+        endtry
+
+    elseif a:type == 'toEOL'
+        call s:SaveScreenState()
+        call s:CommentBlock(firstLine, firstLine, col("."), col("$")-1, 1)
+        call s:RestoreScreenState()
+
+    elseif a:type == 'append'
+        call s:AppendCommentToLine()
+
+    elseif a:type == 'insert'
+        call s:PlaceDelimitersAndInsBetween()
+
+    elseif a:type == 'uncomment'
+        call s:UncommentLines(firstLine, lastLine)
+
+    elseif a:type == 'yank'
+        if a:isVisual
+            normal! gvy
+        elseif countWasGiven
+            execute firstLine .','. lastLine .'yank'
+        else
+            normal! yy
+        endif
+        execute firstLine .','. lastLine .'call NERDComment('. a:isVisual .', "norm")'
+    endif
+
+    let &ignorecase = oldIgnoreCase
+endfunction
+
+" Function: s:PlaceDelimitersAndInsBetween() function {{{2
+" This is function is called to place comment delimiters down and place the
+" cursor between them
+function s:PlaceDelimitersAndInsBetween()
+    " get the left and right delimiters without any escape chars in them
+    let left = s:GetLeft(0, 1, 0)
+    let right = s:GetRight(0, 1, 0)
+
+    let theLine = getline(".")
+    let lineHasLeadTabs = s:HasLeadingTabs(theLine) || (theLine =~ '^ *$' && !&expandtab)
+
+    "convert tabs to spaces and adjust the cursors column to take this into
+    "account
+    let untabbedCol = s:UntabbedCol(theLine, col("."))
+    call setline(line("."), s:ConvertLeadingTabsToSpaces(theLine))
+    call cursor(line("."), untabbedCol)
+
+    " get the len of the right delim
+    let lenRight = strlen(right)
+
+    let isDelimOnEOL = col(".") >= strlen(getline("."))
+
+    " if the cursor is in the first col then we gotta insert rather than
+    " append the comment delimiters here
+    let insOrApp = (col(".")==1 ? 'i' : 'a')
+
+    " place the delimiters down. We do it differently depending on whether
+    " there is a left AND right delimiter
+    if lenRight > 0
+        execute ":normal! " . insOrApp . left . right
+        execute ":normal! " . lenRight . "h"
+    else
+        execute ":normal! " . insOrApp . left
+
+        " if we are tacking the delim on the EOL then we gotta add a space
+        " after it cos when we go out of insert mode the cursor will move back
+        " one and the user wont be in position to type the comment.
+        if isDelimOnEOL
+            execute 'normal! a '
+        endif
+    endif
+    normal! l
+
+    "if needed convert spaces back to tabs and adjust the cursors col
+    "accordingly
+    if lineHasLeadTabs
+        let tabbedCol = s:TabbedCol(getline("."), col("."))
+        call setline(line("."), s:ConvertLeadingSpacesToTabs(getline(".")))
+        call cursor(line("."), tabbedCol)
+    endif
+
+    startinsert
+endfunction
+
+" Function: s:RemoveDelimiters(left, right, line) {{{2
+" this function is called to remove the first left comment delimiter and the
+" last right delimiter of the given line.
+"
+" The args left and right must be strings. If there is no right delimiter (as
+" is the case for e.g vim file comments) them the arg right should be ""
+"
+" Args:
+"   -left: the left comment delimiter
+"   -right: the right comment delimiter
+"   -line: the line to remove the delimiters from
+function s:RemoveDelimiters(left, right, line)
+
+    let l:left = a:left
+    let l:right = a:right
+    let lenLeft = strlen(left)
+    let lenRight = strlen(right)
+
+    let delimsSpaced = (g:NERDSpaceDelims || g:NERDRemoveExtraSpaces)
+
+    let line = a:line
+
+    "look for the left delimiter, if we find it, remove it.
+    let leftIndx = s:FindDelimiterIndex(a:left, line)
+    if leftIndx != -1
+        let line = strpart(line, 0, leftIndx) . strpart(line, leftIndx+lenLeft)
+
+        "if the user has specified that there is a space after the left delim
+        "then check for the space and remove it if it is there
+        if delimsSpaced && strpart(line, leftIndx, s:lenSpaceStr) == s:spaceStr
+            let line = strpart(line, 0, leftIndx) . strpart(line, leftIndx+s:lenSpaceStr)
+        endif
+    endif
+
+    "look for the right delimiter, if we find it, remove it
+    let rightIndx = s:FindDelimiterIndex(a:right, line)
+    if rightIndx != -1
+        let line = strpart(line, 0, rightIndx) . strpart(line, rightIndx+lenRight)
+
+        "if the user has specified that there is a space before the right delim
+        "then check for the space and remove it if it is there
+        if delimsSpaced && strpart(line, rightIndx-s:lenSpaceStr, s:lenSpaceStr) == s:spaceStr && s:Multipart()
+            let line = strpart(line, 0, rightIndx-s:lenSpaceStr) . strpart(line, rightIndx)
+        endif
+    endif
+
+    return line
+endfunction
+
+" Function: s:UncommentLines(topLine, bottomLine) {{{2
+" This function uncomments the given lines
+"
+" Args:
+" topLine: the top line of the visual selection to uncomment
+" bottomLine: the bottom line of the visual selection to uncomment
+function s:UncommentLines(topLine, bottomLine)
+    "make local copies of a:firstline and a:lastline and, if need be, swap
+    "them around if the top line is below the bottom
+    let l:firstline = a:topLine
+    let l:lastline = a:bottomLine
+    if firstline > lastline
+        let firstline = lastline
+        let lastline = a:topLine
+    endif
+
+    "go thru each line uncommenting each line removing sexy comments
+    let currentLine = firstline
+    while currentLine <= lastline
+
+        "check the current line to see if it is part of a sexy comment
+        let sexyComBounds = s:FindBoundingLinesOfSexyCom(currentLine)
+        if !empty(sexyComBounds)
+
+            "we need to store the num lines in the buf before the comment is
+            "removed so we know how many lines were removed when the sexy com
+            "was removed
+            let numLinesBeforeSexyComRemoved = s:NumLinesInBuf()
+
+            call s:UncommentLinesSexy(sexyComBounds[0], sexyComBounds[1])
+
+            "move to the line after last line of the sexy comment
+            let numLinesAfterSexyComRemoved = s:NumLinesInBuf()
+            let numLinesRemoved = numLinesBeforeSexyComRemoved - numLinesAfterSexyComRemoved
+            let currentLine = sexyComBounds[1] - numLinesRemoved + 1
+            let lastline = lastline - numLinesRemoved
+
+        "no sexy com was detected so uncomment the line as normal
+        else
+            call s:UncommentLinesNormal(currentLine, currentLine)
+            let currentLine = currentLine + 1
+        endif
+    endwhile
+
+endfunction
+
+" Function: s:UncommentLinesSexy(topline, bottomline) {{{2
+" This function removes all the comment characters associated with the sexy
+" comment spanning the given lines
+" Args:
+"   -topline/bottomline: the top/bottom lines of the sexy comment
+function s:UncommentLinesSexy(topline, bottomline)
+    let left = s:GetSexyComLeft(0,1)
+    let right = s:GetSexyComRight(0,1)
+
+
+    "check if it is even possible for sexy comments to exist with the
+    "available delimiters
+    if left == -1 || right == -1
+        throw 'NERDCommenter.Delimiters exception: cannot uncomment sexy comments with available delimiters.'
+    endif
+
+    let leftUnEsc = s:GetSexyComLeft(0,0)
+    let rightUnEsc = s:GetSexyComRight(0,0)
+
+    let sexyComMarker = s:GetSexyComMarker(0, 1)
+    let sexyComMarkerUnEsc = s:GetSexyComMarker(0, 0)
+
+    "the markerOffset is how far right we need to move the sexyComMarker to
+    "line it up with the end of the left delim
+    let markerOffset = strlen(leftUnEsc)-strlen(sexyComMarkerUnEsc)
+
+    " go thru the intermediate lines of the sexy comment and remove the
+    " sexy comment markers (eg the '*'s on the start of line in a c sexy
+    " comment)
+    let currentLine = a:topline+1
+    while currentLine < a:bottomline
+        let theLine = getline(currentLine)
+
+        " remove the sexy comment marker from the line. We also remove the
+        " space after it if there is one and if appropriate options are set
+        let sexyComMarkerIndx = stridx(theLine, sexyComMarkerUnEsc)
+        if strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc), s:lenSpaceStr) == s:spaceStr  && g:NERDSpaceDelims
+            let theLine = strpart(theLine, 0, sexyComMarkerIndx - markerOffset) . strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc)+s:lenSpaceStr)
+        else
+            let theLine = strpart(theLine, 0, sexyComMarkerIndx - markerOffset) . strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc))
+        endif
+
+        let theLine = s:SwapOutterPlaceHoldersForMultiPartDelims(theLine)
+
+        let theLine = s:ConvertLeadingWhiteSpace(theLine)
+
+        " move onto the next line
+        call setline(currentLine, theLine)
+        let currentLine = currentLine + 1
+    endwhile
+
+    " gotta make a copy of a:bottomline cos we modify the position of the
+    " last line  it if we remove the topline
+    let bottomline = a:bottomline
+
+    " get the first line so we can remove the left delim from it
+    let theLine = getline(a:topline)
+
+    " if the first line contains only the left delim then just delete it
+    if theLine =~ '^[ \t]*' . left . '[ \t]*$' && !g:NERDCompactSexyComs
+        call cursor(a:topline, 1)
+        normal! dd
+        let bottomline = bottomline - 1
+
+    " topline contains more than just the left delim
+    else
+
+        " remove the delim. If there is a space after it
+        " then remove this too if appropriate
+        let delimIndx = stridx(theLine, leftUnEsc)
+        if strpart(theLine, delimIndx+strlen(leftUnEsc), s:lenSpaceStr) == s:spaceStr && g:NERDSpaceDelims
+            let theLine = strpart(theLine, 0, delimIndx) . strpart(theLine, delimIndx+strlen(leftUnEsc)+s:lenSpaceStr)
+        else
+            let theLine = strpart(theLine, 0, delimIndx) . strpart(theLine, delimIndx+strlen(leftUnEsc))
+        endif
+        let theLine = s:SwapOutterPlaceHoldersForMultiPartDelims(theLine)
+        call setline(a:topline, theLine)
+    endif
+
+    " get the last line so we can remove the right delim
+    let theLine = getline(bottomline)
+
+    " if the bottomline contains only the right delim then just delete it
+    if theLine =~ '^[ \t]*' . right . '[ \t]*$'
+        call cursor(bottomline, 1)
+        normal! dd
+
+    " the last line contains more than the right delim
+    else
+        " remove the right delim. If there is a space after it and
+        " if the appropriate options are set then remove this too.
+        let delimIndx = s:LastIndexOfDelim(rightUnEsc, theLine)
+        if strpart(theLine, delimIndx+strlen(leftUnEsc), s:lenSpaceStr) == s:spaceStr  && g:NERDSpaceDelims
+            let theLine = strpart(theLine, 0, delimIndx) . strpart(theLine, delimIndx+strlen(rightUnEsc)+s:lenSpaceStr)
+        else
+            let theLine = strpart(theLine, 0, delimIndx) . strpart(theLine, delimIndx+strlen(rightUnEsc))
+        endif
+
+        " if the last line also starts with a sexy comment marker then we
+        " remove this as well
+        if theLine =~ '^[ \t]*' . sexyComMarker
+
+            " remove the sexyComMarker. If there is a space after it then
+            " remove that too
+            let sexyComMarkerIndx = stridx(theLine, sexyComMarkerUnEsc)
+            if strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc), s:lenSpaceStr) == s:spaceStr  && g:NERDSpaceDelims
+                let theLine = strpart(theLine, 0, sexyComMarkerIndx - markerOffset ) . strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc)+s:lenSpaceStr)
+            else
+                let theLine = strpart(theLine, 0, sexyComMarkerIndx - markerOffset ) . strpart(theLine, sexyComMarkerIndx+strlen(sexyComMarkerUnEsc))
+            endif
+        endif
+
+        let theLine = s:SwapOutterPlaceHoldersForMultiPartDelims(theLine)
+        call setline(bottomline, theLine)
+    endif
+endfunction
+
+" Function: s:UncommentLineNormal(line) {{{2
+" uncomments the given line and returns the result
+" Args:
+"   -line: the line to uncomment
+function s:UncommentLineNormal(line)
+    let line = a:line
+
+    "get the comment status on the line so we know how it is commented
+    let lineCommentStatus =  s:IsCommentedOuttermost(b:NERDLeft, b:NERDRight, b:NERDLeftAlt, b:NERDRightAlt, line)
+
+    "it is commented with b:NERDLeft and b:NERDRight so remove these delims
+    if lineCommentStatus == 1
+        let line = s:RemoveDelimiters(b:NERDLeft, b:NERDRight, line)
+
+    "it is commented with b:NERDLeftAlt and b:NERDRightAlt so remove these delims
+    elseif lineCommentStatus == 2 && g:NERDRemoveAltComs
+        let line = s:RemoveDelimiters(b:NERDLeftAlt, b:NERDRightAlt, line)
+
+    "it is not properly commented with any delims so we check if it has
+    "any random left or right delims on it and remove the outtermost ones
+    else
+        "get the positions of all delim types on the line
+        let indxLeft = s:FindDelimiterIndex(b:NERDLeft, line)
+        let indxLeftAlt = s:FindDelimiterIndex(b:NERDLeftAlt, line)
+        let indxRight = s:FindDelimiterIndex(b:NERDRight, line)
+        let indxRightAlt = s:FindDelimiterIndex(b:NERDRightAlt, line)
+
+        "remove the outter most left comment delim
+        if indxLeft != -1 && (indxLeft < indxLeftAlt || indxLeftAlt == -1)
+            let line = s:RemoveDelimiters(b:NERDLeft, '', line)
+        elseif indxLeftAlt != -1
+            let line = s:RemoveDelimiters(b:NERDLeftAlt, '', line)
+        endif
+
+        "remove the outter most right comment delim
+        if indxRight != -1 && (indxRight < indxRightAlt || indxRightAlt == -1)
+            let line = s:RemoveDelimiters('', b:NERDRight, line)
+        elseif indxRightAlt != -1
+            let line = s:RemoveDelimiters('', b:NERDRightAlt, line)
+        endif
+    endif
+
+
+    let indxLeft = s:FindDelimiterIndex(b:NERDLeft, line)
+    let indxLeftAlt = s:FindDelimiterIndex(b:NERDLeftAlt, line)
+    let indxLeftPlace = s:FindDelimiterIndex(g:NERDLPlace, line)
+
+    let indxRightPlace = s:FindDelimiterIndex(g:NERDRPlace, line)
+    let indxRightAlt = s:FindDelimiterIndex(b:NERDRightAlt, line)
+    let indxRightPlace = s:FindDelimiterIndex(g:NERDRPlace, line)
+
+    let right = b:NERDRight
+    let left = b:NERDLeft
+    if !s:Multipart()
+        let right = b:NERDRightAlt
+        let left = b:NERDLeftAlt
+    endif
+
+
+    "if there are place-holders on the line then we check to see if they are
+    "the outtermost delimiters on the line. If so then we replace them with
+    "real delimiters
+    if indxLeftPlace != -1
+        if (indxLeftPlace < indxLeft || indxLeft==-1) && (indxLeftPlace < indxLeftAlt || indxLeftAlt==-1)
+            let line = s:ReplaceDelims(g:NERDLPlace, g:NERDRPlace, left, right, line)
+        endif
+    elseif indxRightPlace != -1
+        if (indxRightPlace < indxLeft || indxLeft==-1) && (indxLeftPlace < indxLeftAlt || indxLeftAlt==-1)
+            let line = s:ReplaceDelims(g:NERDLPlace, g:NERDRPlace, left, right, line)
+        endif
+
+    endif
+
+    let line = s:ConvertLeadingWhiteSpace(line)
+
+    return line
+endfunction
+
+" Function: s:UncommentLinesNormal(topline, bottomline) {{{2
+" This function is called to uncomment lines that arent a sexy comment
+" Args:
+"   -topline/bottomline: the top/bottom line numbers of the comment
+function s:UncommentLinesNormal(topline, bottomline)
+    let currentLine = a:topline
+    while currentLine <= a:bottomline
+        let line = getline(currentLine)
+        call setline(currentLine, s:UncommentLineNormal(line))
+        let currentLine = currentLine + 1
+    endwhile
+endfunction
+
+
+" Section: Other helper functions {{{1
+" ============================================================================
+
+" Function: s:AddLeftDelim(delim, theLine) {{{2
+" Args:
+function s:AddLeftDelim(delim, theLine)
+    return substitute(a:theLine, '^\([ \t]*\)', '\1' . a:delim, '')
+endfunction
+
+" Function: s:AddLeftDelimAligned(delim, theLine) {{{2
+" Args:
+function s:AddLeftDelimAligned(delim, theLine, alignIndx)
+
+    "if the line is not long enough then bung some extra spaces on the front
+    "so we can align the delim properly
+    let theLine = a:theLine
+    if strlen(theLine) < a:alignIndx
+        let theLine = repeat(' ', a:alignIndx - strlen(theLine))
+    endif
+
+    return strpart(theLine, 0, a:alignIndx) . a:delim . strpart(theLine, a:alignIndx)
+endfunction
+
+" Function: s:AddRightDelim(delim, theLine) {{{2
+" Args:
+function s:AddRightDelim(delim, theLine)
+    if a:delim == ''
+        return a:theLine
+    else
+        return substitute(a:theLine, '$', a:delim, '')
+    endif
+endfunction
+
+" Function: s:AddRightDelimAligned(delim, theLine, alignIndx) {{{2
+" Args:
+function s:AddRightDelimAligned(delim, theLine, alignIndx)
+    if a:delim == ""
+        return a:theLine
+    else
+
+        " when we align the right delim we are just adding spaces
+        " so we get a string containing the needed spaces (it
+        " could be empty)
+        let extraSpaces = ''
+        let extraSpaces = repeat(' ', a:alignIndx-strlen(a:theLine))
+
+        " add the right delim
+        return substitute(a:theLine, '$', extraSpaces . a:delim, '')
+    endif
+endfunction
+
+" Function: s:AltMultipart() {{{2
+" returns 1 if the alternative delims are multipart
+function s:AltMultipart()
+    return b:NERDRightAlt != ''
+endfunction
+
+" Function: s:CanCommentLine(forceNested, line) {{{2
+"This function is used to determine whether the given line can be commented.
+"It returns 1 if it can be and 0 otherwise
+"
+" Args:
+"   -forceNested: a flag indicating whether the caller wants comments to be nested
+"    if the current line is already commented
+"   -lineNum: the line num of the line to check for commentability
+function s:CanCommentLine(forceNested, lineNum)
+    let theLine = getline(a:lineNum)
+
+    " make sure we don't comment lines that are just spaces or tabs or empty.
+    if theLine =~ "^[ \t]*$"
+        return 0
+    endif
+
+    "if the line is part of a sexy comment then just flag it...
+    if s:IsInSexyComment(a:lineNum)
+        return 0
+    endif
+
+    let isCommented = s:IsCommentedNormOrSexy(a:lineNum)
+
+    "if the line isnt commented return true
+    if !isCommented
+        return 1
+    endif
+
+    "if the line is commented but nesting is allowed then return true
+    if a:forceNested && (!s:Multipart() || g:NERDUsePlaceHolders)
+        return 1
+    endif
+
+    return 0
+endfunction
+
+" Function: s:CanPlaceCursor(line, col) {{{2
+" returns 1 if the cursor can be placed exactly in the given position
+function s:CanPlaceCursor(line, col)
+    let c = col(".")
+    let l = line(".")
+    call cursor(a:line, a:col)
+    let success = (line(".") == a:line && col(".") == a:col)
+    call cursor(l,c)
+    return success
+endfunction
+
+" Function: s:CanSexyCommentLines(topline, bottomline) {{{2
+" Return: 1 if the given lines can be commented sexually, 0 otherwise
+function s:CanSexyCommentLines(topline, bottomline)
+    " see if the selected regions have any sexy comments
+    let currentLine = a:topline
+    while(currentLine <= a:bottomline)
+        if s:IsInSexyComment(currentLine)
+            return 0
+        endif
+        let currentLine = currentLine + 1
+    endwhile
+    return 1
+endfunction
+" Function: s:CanToggleCommentLine(forceNested, line) {{{2
+"This function is used to determine whether the given line can be toggle commented.
+"It returns 1 if it can be and 0 otherwise
+"
+" Args:
+"   -lineNum: the line num of the line to check for commentability
+function s:CanToggleCommentLine(forceNested, lineNum)
+    let theLine = getline(a:lineNum)
+    if (s:IsCommentedFromStartOfLine(b:NERDLeft, theLine) || s:IsCommentedFromStartOfLine(b:NERDLeftAlt, theLine)) && !a:forceNested
+        return 0
+    endif
+
+    " make sure we don't comment lines that are just spaces or tabs or empty.
+    if theLine =~ "^[ \t]*$"
+        return 0
+    endif
+
+    "if the line is part of a sexy comment then just flag it...
+    if s:IsInSexyComment(a:lineNum)
+        return 0
+    endif
+
+    return 1
+endfunction
+
+" Function: s:ConvertLeadingSpacesToTabs(line) {{{2
+" This function takes a line and converts all leading tabs on that line into
+" spaces
+"
+" Args:
+"   -line: the line whose leading tabs will be converted
+function s:ConvertLeadingSpacesToTabs(line)
+    let toReturn  = a:line
+    while toReturn =~ '^\t*' . s:TabSpace() . '\(.*\)$'
+        let toReturn = substitute(toReturn, '^\(\t*\)' . s:TabSpace() . '\(.*\)$'  ,  '\1\t\2' , "")
+    endwhile
+
+    return toReturn
+endfunction
+
+
+" Function: s:ConvertLeadingTabsToSpaces(line) {{{2
+" This function takes a line and converts all leading spaces on that line into
+" tabs
+"
+" Args:
+"   -line: the line whose leading spaces will be converted
+function s:ConvertLeadingTabsToSpaces(line)
+    let toReturn  = a:line
+    while toReturn =~ '^\( *\)\t'
+        let toReturn = substitute(toReturn, '^\( *\)\t',  '\1' . s:TabSpace() , "")
+    endwhile
+
+    return toReturn
+endfunction
+
+" Function: s:ConvertLeadingWhiteSpace(line) {{{2
+" Converts the leading white space to tabs/spaces depending on &ts
+"
+" Args:
+"   -line: the line to convert
+function s:ConvertLeadingWhiteSpace(line)
+    let toReturn = a:line
+    while toReturn =~ '^ *\t'
+        let toReturn = substitute(toReturn, '^ *\zs\t\ze', s:TabSpace(), "g")
+    endwhile
+
+    if !&expandtab
+        let toReturn = s:ConvertLeadingSpacesToTabs(toReturn)
+    endif
+
+    return toReturn
+endfunction
+
+
+" Function: s:CountNonESCedOccurances(str, searchstr, escChar) {{{2
+" This function counts the number of substrings contained in another string.
+" These substrings are only counted if they are not escaped with escChar
+" Args:
+"   -str: the string to look for searchstr in
+"   -searchstr: the substring to search for in str
+"   -escChar: the escape character which, when preceding an instance of
+"    searchstr, will cause it not to be counted
+function s:CountNonESCedOccurances(str, searchstr, escChar)
+    "get the index of the first occurrence of searchstr
+    let indx = stridx(a:str, a:searchstr)
+
+    "if there is an instance of searchstr in str process it
+    if indx != -1
+        "get the remainder of str after this instance of searchstr is removed
+        let lensearchstr = strlen(a:searchstr)
+        let strLeft = strpart(a:str, indx+lensearchstr)
+
+        "if this instance of searchstr is not escaped, add one to the count
+        "and recurse. If it is escaped, just recurse
+        if !s:IsEscaped(a:str, indx, a:escChar)
+            return 1 + s:CountNonESCedOccurances(strLeft, a:searchstr, a:escChar)
+        else
+            return s:CountNonESCedOccurances(strLeft, a:searchstr, a:escChar)
+        endif
+    endif
+endfunction
+" Function: s:DoesBlockHaveDelim(delim, top, bottom) {{{2
+" Returns 1 if the given block of lines has a delimiter (a:delim) in it
+" Args:
+"   -delim: the comment delimiter to check the block for
+"   -top: the top line number of the block
+"   -bottom: the bottom line number of the block
+function s:DoesBlockHaveDelim(delim, top, bottom)
+    let currentLine = a:top
+    while currentLine < a:bottom
+        let theline = getline(currentLine)
+        if s:FindDelimiterIndex(a:delim, theline) != -1
+            return 1
+        endif
+        let currentLine = currentLine + 1
+    endwhile
+    return 0
+endfunction
+
+" Function: s:DoesBlockHaveMultipartDelim(top, bottom) {{{2
+" Returns 1 if the given block has a >= 1 multipart delimiter in it
+" Args:
+"   -top: the top line number of the block
+"   -bottom: the bottom line number of the block
+function s:DoesBlockHaveMultipartDelim(top, bottom)
+    if s:HasMultipartDelims()
+        if s:Multipart()
+            return s:DoesBlockHaveDelim(b:NERDLeft, a:top, a:bottom) || s:DoesBlockHaveDelim(b:NERDRight, a:top, a:bottom)
+        else
+            return s:DoesBlockHaveDelim(b:NERDLeftAlt, a:top, a:bottom) || s:DoesBlockHaveDelim(b:NERDRightAlt, a:top, a:bottom)
+        endif
+    endif
+    return 0
+endfunction
+
+
+" Function: s:Esc(str) {{{2
+" Escapes all the tricky chars in the given string
+function s:Esc(str)
+    let charsToEsc = '*/\."&$+'
+    return escape(a:str, charsToEsc)
+endfunction
+
+" Function: s:FindDelimiterIndex(delimiter, line) {{{2
+" This function is used to get the string index of the input comment delimiter
+" on the input line. If no valid comment delimiter is found in the line then
+" -1 is returned
+" Args:
+"   -delimiter: the delimiter we are looking to find the index of
+"   -line: the line we are looking for delimiter on
+function s:FindDelimiterIndex(delimiter, line)
+
+    "make sure the delimiter isnt empty otherwise we go into an infinite loop.
+    if a:delimiter == ""
+        return -1
+    endif
+
+
+    let l:delimiter = a:delimiter
+    let lenDel = strlen(l:delimiter)
+
+    "get the index of the first occurrence of the delimiter
+    let delIndx = stridx(a:line, l:delimiter)
+
+    "keep looping thru the line till we either find a real comment delimiter
+    "or run off the EOL
+    while delIndx != -1
+
+        "if we are not off the EOL get the str before the possible delimiter
+        "in question and check if it really is a delimiter. If it is, return
+        "its position
+        if delIndx != -1
+            if s:IsDelimValid(l:delimiter, delIndx, a:line)
+                return delIndx
+            endif
+        endif
+
+        "we have not yet found a real comment delimiter so move past the
+        "current one we are lookin at
+        let restOfLine = strpart(a:line, delIndx + lenDel)
+        let distToNextDelim = stridx(restOfLine , l:delimiter)
+
+        "if distToNextDelim is -1 then there is no more potential delimiters
+        "on the line so set delIndx to -1. Otherwise, move along the line by
+        "distToNextDelim
+        if distToNextDelim == -1
+            let delIndx = -1
+        else
+            let delIndx = delIndx + lenDel + distToNextDelim
+        endif
+    endwhile
+
+    "there is no comment delimiter on this line
+    return -1
+endfunction
+
+" Function: s:FindBoundingLinesOfSexyCom(lineNum) {{{2
+" This function takes in a line number and tests whether this line number is
+" the top/bottom/middle line of a sexy comment. If it is then the top/bottom
+" lines of the sexy comment are returned
+" Args:
+"   -lineNum: the line number that is to be tested whether it is the
+"    top/bottom/middle line of a sexy com
+" Returns:
+"   A string that has the top/bottom lines of the sexy comment encoded in it.
+"   The format is 'topline,bottomline'. If a:lineNum turns out not to be the
+"   top/bottom/middle of a sexy comment then -1 is returned
+function s:FindBoundingLinesOfSexyCom(lineNum)
+
+    "find which delimiters to look for as the start/end delims of the comment
+    let left = ''
+    let right = ''
+    if s:Multipart()
+        let left = s:GetLeft(0,0,1)
+        let right = s:GetRight(0,0,1)
+    elseif s:AltMultipart()
+        let left = s:GetLeft(1,0,1)
+        let right = s:GetRight(1,0,1)
+    else
+        return []
+    endif
+
+    let sexyComMarker = s:GetSexyComMarker(0, 1)
+
+    "initialise the top/bottom line numbers of the sexy comment to -1
+    let top = -1
+    let bottom = -1
+
+    let currentLine = a:lineNum
+    while top == -1 || bottom == -1
+        let theLine = getline(currentLine)
+
+        "check if the current line is the top of the sexy comment
+        if currentLine <= a:lineNum && theLine =~ '^[ \t]*' . left && theLine !~ '.*' . right && currentLine < s:NumLinesInBuf()
+            let top = currentLine
+            let currentLine = a:lineNum
+
+        "check if the current line is the bottom of the sexy comment
+        elseif theLine =~ '^[ \t]*' . right && theLine !~ '.*' . left && currentLine > 1
+            let bottom = currentLine
+
+        "the right delimiter is on the same line as the last sexyComMarker
+        elseif theLine =~ '^[ \t]*' . sexyComMarker . '.*' . right
+            let bottom = currentLine
+
+        "we have not found the top or bottom line so we assume currentLine is an
+        "intermediate line and look to prove otherwise
+        else
+
+            "if the line doesnt start with a sexyComMarker then it is not a sexy
+            "comment
+            if theLine !~ '^[ \t]*' . sexyComMarker
+                return []
+            endif
+
+        endif
+
+        "if top is -1 then we havent found the top yet so keep looking up
+        if top == -1
+            let currentLine = currentLine - 1
+        "if we have found the top line then go down looking for the bottom
+        else
+            let currentLine = currentLine + 1
+        endif
+
+    endwhile
+
+    return [top, bottom]
+endfunction
+
+
+" Function: s:GetLeft(alt, space, esc) {{{2
+" returns the left/left-alternative delimiter
+" Args:
+"   -alt: specifies whether to get left or left-alternative delim
+"   -space: specifies whether the delim should be spaced or not
+"    (the space string will only be added if NERDSpaceDelims is set)
+"   -esc: specifies whether the tricky chars in the delim should be ESCed
+function s:GetLeft(alt, space, esc)
+    let delim = b:NERDLeft
+
+    if a:alt
+        if b:NERDLeftAlt == ''
+            return ''
+        else
+            let delim = b:NERDLeftAlt
+        endif
+    endif
+    if delim == ''
+        return ''
+    endif
+
+    if a:space && g:NERDSpaceDelims
+        let delim = delim . s:spaceStr
+    endif
+
+    if a:esc
+        let delim = s:Esc(delim)
+    endif
+
+    return delim
+endfunction
+
+" Function: s:GetRight(alt, space, esc) {{{2
+" returns the right/right-alternative delimiter
+" Args:
+"   -alt: specifies whether to get right or right-alternative delim
+"   -space: specifies whether the delim should be spaced or not
+"   (the space string will only be added if NERDSpaceDelims is set)
+"   -esc: specifies whether the tricky chars in the delim should be ESCed
+function s:GetRight(alt, space, esc)
+    let delim = b:NERDRight
+
+    if a:alt
+        if !s:AltMultipart()
+            return ''
+        else
+            let delim = b:NERDRightAlt
+        endif
+    endif
+    if delim == ''
+        return ''
+    endif
+
+    if a:space && g:NERDSpaceDelims
+        let delim = s:spaceStr . delim
+    endif
+
+    if a:esc
+        let delim = s:Esc(delim)
+    endif
+
+    return delim
+endfunction
+
+
+" Function: s:GetSexyComMarker() {{{2
+" Returns the sexy comment marker for the current filetype.
+"
+" C style sexy comments are assumed if possible. If not then the sexy comment
+" marker is the last char of the delimiter pair that has both left and right
+" delims and has the longest left delim
+"
+" Args:
+"   -space: specifies whether the marker is to have a space string after it
+"    (the space string will only be added if NERDSpaceDelims is set)
+"   -esc: specifies whether the tricky chars in the marker are to be ESCed
+function s:GetSexyComMarker(space, esc)
+    let sexyComMarker = b:NERDSexyComMarker
+
+    "if there is no hardcoded marker then we find one
+    if sexyComMarker == ''
+
+        "if the filetype has c style comments then use standard c sexy
+        "comments
+        if s:HasCStyleComments()
+            let sexyComMarker = '*'
+        else
+            "find a comment marker by getting the longest available left delim
+            "(that has a corresponding right delim) and taking the last char
+            let lenLeft = strlen(b:NERDLeft)
+            let lenLeftAlt = strlen(b:NERDLeftAlt)
+            let left = ''
+            let right = ''
+            if s:Multipart() && lenLeft >= lenLeftAlt
+                let left = b:NERDLeft
+            elseif s:AltMultipart()
+                let left = b:NERDLeftAlt
+            else
+                return -1
+            endif
+
+            "get the last char of left
+            let sexyComMarker = strpart(left, strlen(left)-1)
+        endif
+    endif
+
+    if a:space && g:NERDSpaceDelims
+        let sexyComMarker = sexyComMarker . s:spaceStr
+    endif
+
+    if a:esc
+        let sexyComMarker = s:Esc(sexyComMarker)
+    endif
+
+    return sexyComMarker
+endfunction
+
+" Function: s:GetSexyComLeft(space, esc) {{{2
+" Returns the left delimiter for sexy comments for this filetype or -1 if
+" there is none. C style sexy comments are used if possible
+" Args:
+"   -space: specifies if the delim has a space string on the end
+"   (the space string will only be added if NERDSpaceDelims is set)
+"   -esc: specifies whether the tricky chars in the string are ESCed
+function s:GetSexyComLeft(space, esc)
+    let lenLeft = strlen(b:NERDLeft)
+    let lenLeftAlt = strlen(b:NERDLeftAlt)
+    let left = ''
+
+    "assume c style sexy comments if possible
+    if s:HasCStyleComments()
+        let left = '/*'
+    else
+        "grab the longest left delim that has a right
+        if s:Multipart() && lenLeft >= lenLeftAlt
+            let left = b:NERDLeft
+        elseif s:AltMultipart()
+            let left = b:NERDLeftAlt
+        else
+            return -1
+        endif
+    endif
+
+    if a:space && g:NERDSpaceDelims
+        let left = left . s:spaceStr
+    endif
+
+    if a:esc
+        let left = s:Esc(left)
+    endif
+
+    return left
+endfunction
+
+" Function: s:GetSexyComRight(space, esc) {{{2
+" Returns the right delimiter for sexy comments for this filetype or -1 if
+" there is none. C style sexy comments are used if possible.
+" Args:
+"   -space: specifies if the delim has a space string on the start
+"   (the space string will only be added if NERDSpaceDelims
+"   is specified for the current filetype)
+"   -esc: specifies whether the tricky chars in the string are ESCed
+function s:GetSexyComRight(space, esc)
+    let lenLeft = strlen(b:NERDLeft)
+    let lenLeftAlt = strlen(b:NERDLeftAlt)
+    let right = ''
+
+    "assume c style sexy comments if possible
+    if s:HasCStyleComments()
+        let right = '*/'
+    else
+        "grab the right delim that pairs with the longest left delim
+        if s:Multipart() && lenLeft >= lenLeftAlt
+            let right = b:NERDRight
+        elseif s:AltMultipart()
+            let right = b:NERDRightAlt
+        else
+            return -1
+        endif
+    endif
+
+    if a:space && g:NERDSpaceDelims
+        let right = s:spaceStr . right
+    endif
+
+    if a:esc
+        let right = s:Esc(right)
+    endif
+
+    return right
+endfunction
+
+" Function: s:HasMultipartDelims() {{{2
+" Returns 1 iff the current filetype has at least one set of multipart delims
+function s:HasMultipartDelims()
+    return s:Multipart() || s:AltMultipart()
+endfunction
+
+" Function: s:HasLeadingTabs(...) {{{2
+" Returns 1 if any of the given strings have leading tabs
+function s:HasLeadingTabs(...)
+    for s in a:000
+        if s =~ '^\t.*'
+            return 1
+        end
+    endfor
+    return 0
+endfunction
+" Function: s:HasCStyleComments() {{{2
+" Returns 1 iff the current filetype has c style comment delimiters
+function s:HasCStyleComments()
+    return (b:NERDLeft == '/*' && b:NERDRight == '*/') || (b:NERDLeftAlt == '/*' && b:NERDRightAlt == '*/')
+endfunction
+
+" Function: s:IsCommentedNormOrSexy(lineNum) {{{2
+"This function is used to determine whether the given line is commented with
+"either set of delimiters or if it is part of a sexy comment
+"
+" Args:
+"   -lineNum: the line number of the line to check
+function s:IsCommentedNormOrSexy(lineNum)
+    let theLine = getline(a:lineNum)
+
+    "if the line is commented normally return 1
+    if s:IsCommented(b:NERDLeft, b:NERDRight, theLine) || s:IsCommented(b:NERDLeftAlt, b:NERDRightAlt, theLine)
+        return 1
+    endif
+
+    "if the line is part of a sexy comment return 1
+    if s:IsInSexyComment(a:lineNum)
+        return 1
+    endif
+    return 0
+endfunction
+
+" Function: s:IsCommented(left, right, line) {{{2
+"This function is used to determine whether the given line is commented with
+"the given delimiters
+"
+" Args:
+"   -line: the line that to check if commented
+"   -left/right: the left and right delimiters to check for
+function s:IsCommented(left, right, line)
+    "if the line isnt commented return true
+    if s:FindDelimiterIndex(a:left, a:line) != -1 && (s:FindDelimiterIndex(a:right, a:line) != -1 || !s:Multipart())
+        return 1
+    endif
+    return 0
+endfunction
+
+" Function: s:IsCommentedFromStartOfLine(left, line) {{{2
+"This function is used to determine whether the given line is commented with
+"the given delimiters at the start of the line i.e the left delimiter is the
+"first thing on the line (apart from spaces\tabs)
+"
+" Args:
+"   -line: the line that to check if commented
+"   -left: the left delimiter to check for
+function s:IsCommentedFromStartOfLine(left, line)
+    let theLine = s:ConvertLeadingTabsToSpaces(a:line)
+    let numSpaces = strlen(substitute(theLine, '^\( *\).*$', '\1', ''))
+    let delimIndx = s:FindDelimiterIndex(a:left, theLine)
+    return delimIndx == numSpaces
+endfunction
+
+" Function: s:IsCommentedOuttermost(left, right, leftAlt, rightAlt, line) {{{2
+" Finds the type of the outtermost delims on the line
+"
+" Args:
+"   -line: the line that to check if the outtermost comments on it are
+"    left/right
+"   -left/right: the left and right delimiters to check for
+"   -leftAlt/rightAlt: the left and right alternative delimiters to check for
+"
+" Returns:
+"   0 if the line is not commented with either set of delims
+"   1 if the line is commented with the left/right delim set
+"   2 if the line is commented with the leftAlt/rightAlt delim set
+function s:IsCommentedOuttermost(left, right, leftAlt, rightAlt, line)
+    "get the first positions of the left delims and the last positions of the
+    "right delims
+    let indxLeft = s:FindDelimiterIndex(a:left, a:line)
+    let indxLeftAlt = s:FindDelimiterIndex(a:leftAlt, a:line)
+    let indxRight = s:LastIndexOfDelim(a:right, a:line)
+    let indxRightAlt = s:LastIndexOfDelim(a:rightAlt, a:line)
+
+    "check if the line has a left delim before a leftAlt delim
+    if (indxLeft <= indxLeftAlt || indxLeftAlt == -1) && indxLeft != -1
+        "check if the line has a right delim after any rightAlt delim
+        if (indxRight > indxRightAlt && indxRight > indxLeft) || !s:Multipart()
+            return 1
+        endif
+
+        "check if the line has a leftAlt delim before a left delim
+    elseif (indxLeftAlt <= indxLeft || indxLeft == -1) && indxLeftAlt != -1
+        "check if the line has a rightAlt delim after any right delim
+        if (indxRightAlt > indxRight && indxRightAlt > indxLeftAlt) || !s:AltMultipart()
+            return 2
+        endif
+    else
+        return 0
+    endif
+
+    return 0
+
+endfunction
+
+
+" Function: s:IsDelimValid(delimiter, delIndx, line) {{{2
+" This function is responsible for determining whether a given instance of a
+" comment delimiter is a real delimiter or not. For example, in java the
+" // string is a comment delimiter but in the line:
+"               System.out.println("//");
+" it does not count as a comment delimiter. This function is responsible for
+" distinguishing between such cases. It does so by applying a set of
+" heuristics that are not fool proof but should work most of the time.
+"
+" Args:
+"   -delimiter: the delimiter we are validating
+"   -delIndx: the position of delimiter in line
+"   -line: the line that delimiter occurs in
+"
+" Returns:
+" 0 if the given delimiter is not a real delimiter (as far as we can tell) ,
+" 1 otherwise
+function s:IsDelimValid(delimiter, delIndx, line)
+    "get the delimiter without the escchars
+    let l:delimiter = a:delimiter
+
+    "get the strings before and after the delimiter
+    let preComStr = strpart(a:line, 0, a:delIndx)
+    let postComStr = strpart(a:line, a:delIndx+strlen(delimiter))
+
+    "to check if the delimiter is real, make sure it isnt preceded by
+    "an odd number of quotes and followed by the same (which would indicate
+    "that it is part of a string and therefore is not a comment)
+    if !s:IsNumEven(s:CountNonESCedOccurances(preComStr, '"', "\\")) && !s:IsNumEven(s:CountNonESCedOccurances(postComStr, '"', "\\"))
+        return 0
+    endif
+    if !s:IsNumEven(s:CountNonESCedOccurances(preComStr, "'", "\\")) && !s:IsNumEven(s:CountNonESCedOccurances(postComStr, "'", "\\"))
+        return 0
+    endif
+    if !s:IsNumEven(s:CountNonESCedOccurances(preComStr, "`", "\\")) && !s:IsNumEven(s:CountNonESCedOccurances(postComStr, "`", "\\"))
+        return 0
+    endif
+
+
+    "if the comment delimiter is escaped, assume it isnt a real delimiter
+    if s:IsEscaped(a:line, a:delIndx, "\\")
+        return 0
+    endif
+
+    "vim comments are so fuckin stupid!! Why the hell do they have comment
+    "delimiters that are used elsewhere in the syntax?!?! We need to check
+    "some conditions especially for vim
+    if &filetype == "vim"
+        if !s:IsNumEven(s:CountNonESCedOccurances(preComStr, '"', "\\"))
+            return 0
+        endif
+
+        "if the delimiter is on the very first char of the line or is the
+        "first non-tab/space char on the line then it is a valid comment delimiter
+        if a:delIndx == 0 || a:line =~ "^[ \t]\\{" . a:delIndx . "\\}\".*$"
+            return 1
+        endif
+
+        let numLeftParen =s:CountNonESCedOccurances(preComStr, "(", "\\")
+        let numRightParen =s:CountNonESCedOccurances(preComStr, ")", "\\")
+
+        "if the quote is inside brackets then assume it isnt a comment
+        if numLeftParen > numRightParen
+            return 0
+        endif
+
+        "if the line has an even num of unescaped "'s then we can assume that
+        "any given " is not a comment delimiter
+        if s:IsNumEven(s:CountNonESCedOccurances(a:line, "\"", "\\"))
+            return 0
+        endif
+    endif
+
+    return 1
+
+endfunction
+
+" Function: s:IsNumEven(num) {{{2
+" A small function the returns 1 if the input number is even and 0 otherwise
+" Args:
+"   -num: the number to check
+function s:IsNumEven(num)
+    return (a:num % 2) == 0
+endfunction
+
+" Function: s:IsEscaped(str, indx, escChar) {{{2
+" This function takes a string, an index into that string and an esc char and
+" returns 1 if the char at the index is escaped (i.e if it is preceded by an
+" odd number of esc chars)
+" Args:
+"   -str: the string to check
+"   -indx: the index into str that we want to check
+"   -escChar: the escape char the char at indx may be ESCed with
+function s:IsEscaped(str, indx, escChar)
+    "initialise numEscChars to 0 and look at the char before indx
+    let numEscChars = 0
+    let curIndx = a:indx-1
+
+    "keep going back thru str until we either reach the start of the str or
+    "run out of esc chars
+    while curIndx >= 0 && strpart(a:str, curIndx, 1) == a:escChar
+
+        "we have found another esc char so add one to the count and move left
+        "one char
+        let numEscChars  = numEscChars + 1
+        let curIndx = curIndx - 1
+
+    endwhile
+
+    "if there is an odd num of esc chars directly before the char at indx then
+    "the char at indx is escaped
+    return !s:IsNumEven(numEscChars)
+endfunction
+
+" Function: s:IsInSexyComment(line) {{{2
+" returns 1 if the given line number is part of a sexy comment
+function s:IsInSexyComment(line)
+    return !empty(s:FindBoundingLinesOfSexyCom(a:line))
+endfunction
+
+" Function: s:IsSexyComment(topline, bottomline) {{{2
+" This function takes in 2 line numbers and returns 1 if the lines between and
+" including the given line numbers are a sexy comment. It returns 0 otherwise.
+" Args:
+"   -topline: the line that the possible sexy comment starts on
+"   -bottomline: the line that the possible sexy comment stops on
+function s:IsSexyComment(topline, bottomline)
+
+    "get the delim set that would be used for a sexy comment
+    let left = ''
+    let right = ''
+    if s:Multipart()
+        let left = b:NERDLeft
+        let right = b:NERDRight
+    elseif s:AltMultipart()
+        let left = b:NERDLeftAlt
+        let right = b:NERDRightAlt
+    else
+        return 0
+    endif
+
+    "swap the top and bottom line numbers around if need be
+    let topline = a:topline
+    let bottomline = a:bottomline
+    if bottomline < topline
+        topline = bottomline
+        bottomline = a:topline
+    endif
+
+    "if there is < 2 lines in the comment it cannot be sexy
+    if (bottomline - topline) <= 0
+        return 0
+    endif
+
+    "if the top line doesnt begin with a left delim then the comment isnt sexy
+    if getline(a:topline) !~ '^[ \t]*' . left
+        return 0
+    endif
+
+    "if there is a right delim on the top line then this isnt a sexy comment
+    if s:FindDelimiterIndex(right, getline(a:topline)) != -1
+        return 0
+    endif
+
+    "if there is a left delim on the bottom line then this isnt a sexy comment
+    if s:FindDelimiterIndex(left, getline(a:bottomline)) != -1
+        return 0
+    endif
+
+    "if the bottom line doesnt begin with a right delim then the comment isnt
+    "sexy
+    if getline(a:bottomline) !~ '^.*' . right . '$'
+        return 0
+    endif
+
+    let sexyComMarker = s:GetSexyComMarker(0, 1)
+
+    "check each of the intermediate lines to make sure they start with a
+    "sexyComMarker
+    let currentLine = a:topline+1
+    while currentLine < a:bottomline
+        let theLine = getline(currentLine)
+
+        if theLine !~ '^[ \t]*' . sexyComMarker
+            return 0
+        endif
+
+        "if there is a right delim in an intermediate line then the block isnt
+        "a sexy comment
+        if s:FindDelimiterIndex(right, theLine) != -1
+            return 0
+        endif
+
+        let currentLine = currentLine + 1
+    endwhile
+
+    "we have not found anything to suggest that this isnt a sexy comment so
+    return 1
+
+endfunction
+
+" Function: s:LastIndexOfDelim(delim, str) {{{2
+" This function takes a string and a delimiter and returns the last index of
+" that delimiter in string
+" Args:
+"   -delim: the delimiter to look for
+"   -str: the string to look for delim in
+function s:LastIndexOfDelim(delim, str)
+    let delim = a:delim
+    let lenDelim = strlen(delim)
+
+    "set index to the first occurrence of delim. If there is no occurrence then
+    "bail
+    let indx = s:FindDelimiterIndex(delim, a:str)
+    if indx == -1
+        return -1
+    endif
+
+    "keep moving to the next instance of delim in str till there is none left
+    while 1
+
+        "search for the next delim after the previous one
+        let searchStr = strpart(a:str, indx+lenDelim)
+        let indx2 = s:FindDelimiterIndex(delim, searchStr)
+
+        "if we find a delim update indx to record the position of it, if we
+        "dont find another delim then indx is the last one so break out of
+        "this loop
+        if indx2 != -1
+            let indx = indx + indx2 + lenDelim
+        else
+            break
+        endif
+    endwhile
+
+    return indx
+
+endfunction
+
+" Function: s:LeftMostIndx(countCommentedLines, countEmptyLines, topline, bottomline) {{{2
+" This function takes in 2 line numbers and returns the index of the left most
+" char (that is not a space or a tab) on all of these lines.
+" Args:
+"   -countCommentedLines: 1 if lines that are commented are to be checked as
+"    well. 0 otherwise
+"   -countEmptyLines: 1 if empty lines are to be counted in the search
+"   -topline: the top line to be checked
+"   -bottomline: the bottom line to be checked
+function s:LeftMostIndx(countCommentedLines, countEmptyLines, topline, bottomline)
+
+    " declare the left most index as an extreme value
+    let leftMostIndx = 1000
+
+    " go thru the block line by line updating leftMostIndx
+    let currentLine = a:topline
+    while currentLine <= a:bottomline
+
+        " get the next line and if it is allowed to be commented, or is not
+        " commented, check it
+        let theLine = getline(currentLine)
+        if a:countEmptyLines || theLine !~ '^[ \t]*$'
+            if a:countCommentedLines || (!s:IsCommented(b:NERDLeft, b:NERDRight, theLine) && !s:IsCommented(b:NERDLeftAlt, b:NERDRightAlt, theLine))
+                " convert spaces to tabs and get the number of leading spaces for
+                " this line and update leftMostIndx if need be
+                let theLine = s:ConvertLeadingTabsToSpaces(theLine)
+                let leadSpaceOfLine = strlen( substitute(theLine, '\(^[ \t]*\).*$','\1','') )
+                if leadSpaceOfLine < leftMostIndx
+                    let leftMostIndx = leadSpaceOfLine
+                endif
+            endif
+        endif
+
+        " move on to the next line
+        let currentLine = currentLine + 1
+    endwhile
+
+    if leftMostIndx == 1000
+        return 0
+    else
+        return leftMostIndx
+    endif
+endfunction
+
+" Function: s:Multipart() {{{2
+" returns 1 if the current delims are multipart
+function s:Multipart()
+    return b:NERDRight != ''
+endfunction
+
+" Function: s:NerdEcho(msg, typeOfMsg) {{{2
+" Args:
+"   -msg: the message to echo
+"   -typeOfMsg: 0 = warning message
+"               1 = normal message
+function s:NerdEcho(msg, typeOfMsg)
+    if a:typeOfMsg == 0
+        echohl WarningMsg
+        echo 'NERDCommenter:' . a:msg
+        echohl None
+    elseif a:typeOfMsg == 1
+        echo 'NERDCommenter:' . a:msg
+    endif
+endfunction
+
+" Function: s:NumberOfLeadingTabs(s) {{{2
+" returns the number of leading tabs in the given string
+function s:NumberOfLeadingTabs(s)
+    return strlen(substitute(a:s, '^\(\t*\).*$', '\1', ""))
+endfunction
+
+" Function: s:NumLinesInBuf() {{{2
+" Returns the number of lines in the current buffer
+function s:NumLinesInBuf()
+    return line('$')
+endfunction
+
+" Function: s:ReplaceDelims(toReplace1, toReplace2, replacor1, replacor2, str) {{{2
+" This function takes in a string, 2 delimiters in that string and 2 strings
+" to replace these delimiters with.
+"
+" Args:
+"   -toReplace1: the first delimiter to replace
+"   -toReplace2: the second delimiter to replace
+"   -replacor1: the string to replace toReplace1 with
+"   -replacor2: the string to replace toReplace2 with
+"   -str: the string that the delimiters to be replaced are in
+function s:ReplaceDelims(toReplace1, toReplace2, replacor1, replacor2, str)
+    let line = s:ReplaceLeftMostDelim(a:toReplace1, a:replacor1, a:str)
+    let line = s:ReplaceRightMostDelim(a:toReplace2, a:replacor2, line)
+    return line
+endfunction
+
+" Function: s:ReplaceLeftMostDelim(toReplace, replacor, str) {{{2
+" This function takes a string and a delimiter and replaces the left most
+" occurrence of this delimiter in the string with a given string
+"
+" Args:
+"   -toReplace: the delimiter in str that is to be replaced
+"   -replacor: the string to replace toReplace with
+"   -str: the string that contains toReplace
+function s:ReplaceLeftMostDelim(toReplace, replacor, str)
+    let toReplace = a:toReplace
+    let replacor = a:replacor
+    "get the left most occurrence of toReplace
+    let indxToReplace = s:FindDelimiterIndex(toReplace, a:str)
+
+    "if there IS an occurrence of toReplace in str then replace it and return
+    "the resulting string
+    if indxToReplace != -1
+        let line = strpart(a:str, 0, indxToReplace) . replacor . strpart(a:str, indxToReplace+strlen(toReplace))
+        return line
+    endif
+
+    return a:str
+endfunction
+
+" Function: s:ReplaceRightMostDelim(toReplace, replacor, str) {{{2
+" This function takes a string and a delimiter and replaces the right most
+" occurrence of this delimiter in the string with a given string
+"
+" Args:
+"   -toReplace: the delimiter in str that is to be replaced
+"   -replacor: the string to replace toReplace with
+"   -str: the string that contains toReplace
+"
+function s:ReplaceRightMostDelim(toReplace, replacor, str)
+    let toReplace = a:toReplace
+    let replacor = a:replacor
+    let lenToReplace = strlen(toReplace)
+
+    "get the index of the last delim in str
+    let indxToReplace = s:LastIndexOfDelim(toReplace, a:str)
+
+    "if there IS a delimiter in str, replace it and return the result
+    let line = a:str
+    if indxToReplace != -1
+        let line = strpart(a:str, 0, indxToReplace) . replacor . strpart(a:str, indxToReplace+strlen(toReplace))
+    endif
+    return line
+endfunction
+
+"FUNCTION: s:RestoreScreenState() {{{2
+"
+"Sets the screen state back to what it was when s:SaveScreenState was last
+"called.
+"
+function s:RestoreScreenState()
+    if !exists("t:NERDComOldTopLine") || !exists("t:NERDComOldPos")
+        throw 'NERDCommenter exception: cannot restore screen'
+    endif
+
+    call cursor(t:NERDComOldTopLine, 0)
+    normal! zt
+    call setpos(".", t:NERDComOldPos)
+endfunction
+
+" Function: s:RightMostIndx(countCommentedLines, countEmptyLines, topline, bottomline) {{{2
+" This function takes in 2 line numbers and returns the index of the right most
+" char on all of these lines.
+" Args:
+"   -countCommentedLines: 1 if lines that are commented are to be checked as
+"    well. 0 otherwise
+"   -countEmptyLines: 1 if empty lines are to be counted in the search
+"   -topline: the top line to be checked
+"   -bottomline: the bottom line to be checked
+function s:RightMostIndx(countCommentedLines, countEmptyLines, topline, bottomline)
+    let rightMostIndx = -1
+
+    " go thru the block line by line updating rightMostIndx
+    let currentLine = a:topline
+    while currentLine <= a:bottomline
+
+        " get the next line and see if it is commentable, otherwise it doesnt
+        " count
+        let theLine = getline(currentLine)
+        if a:countEmptyLines || theLine !~ '^[ \t]*$'
+
+            if a:countCommentedLines || (!s:IsCommented(b:NERDLeft, b:NERDRight, theLine) && !s:IsCommented(b:NERDLeftAlt, b:NERDRightAlt, theLine))
+
+                " update rightMostIndx if need be
+                let theLine = s:ConvertLeadingTabsToSpaces(theLine)
+                let lineLen = strlen(theLine)
+                if lineLen > rightMostIndx
+                    let rightMostIndx = lineLen
+                endif
+            endif
+        endif
+
+        " move on to the next line
+        let currentLine = currentLine + 1
+    endwhile
+
+    return rightMostIndx
+endfunction
+
+"FUNCTION: s:SaveScreenState() {{{2
+"Saves the current cursor position in the current buffer and the window
+"scroll position
+function s:SaveScreenState()
+    let t:NERDComOldPos = getpos(".")
+    let t:NERDComOldTopLine = line("w0")
+endfunction
+
+" Function: s:SwapOutterMultiPartDelimsForPlaceHolders(line) {{{2
+" This function takes a line and swaps the outter most multi-part delims for
+" place holders
+" Args:
+"   -line: the line to swap the delims in
+"
+function s:SwapOutterMultiPartDelimsForPlaceHolders(line)
+    " find out if the line is commented using normal delims and/or
+    " alternate ones
+    let isCommented = s:IsCommented(b:NERDLeft, b:NERDRight, a:line)
+    let isCommentedAlt = s:IsCommented(b:NERDLeftAlt, b:NERDRightAlt, a:line)
+
+    let line2 = a:line
+
+    "if the line is commented and there is a right delimiter, replace
+    "the delims with place-holders
+    if isCommented && s:Multipart()
+        let line2 = s:ReplaceDelims(b:NERDLeft, b:NERDRight, g:NERDLPlace, g:NERDRPlace, a:line)
+
+    "similarly if the line is commented with the alternative
+    "delimiters
+    elseif isCommentedAlt && s:AltMultipart()
+        let line2 = s:ReplaceDelims(b:NERDLeftAlt, b:NERDRightAlt, g:NERDLPlace, g:NERDRPlace, a:line)
+    endif
+
+    return line2
+endfunction
+
+" Function: s:SwapOutterPlaceHoldersForMultiPartDelims(line) {{{2
+" This function takes a line and swaps the outtermost place holders for
+" multi-part delims
+" Args:
+"   -line: the line to swap the delims in
+"
+function s:SwapOutterPlaceHoldersForMultiPartDelims(line)
+    let left = ''
+    let right = ''
+    if s:Multipart()
+        let left = b:NERDLeft
+        let right = b:NERDRight
+    elseif s:AltMultipart()
+        let left = b:NERDLeftAlt
+        let right = b:NERDRightAlt
+    endif
+
+    let line = s:ReplaceDelims(g:NERDLPlace, g:NERDRPlace, left, right, a:line)
+    return line
+endfunction
+" Function: s:TabbedCol(line, col) {{{2
+" Gets the col number for given line and existing col number. The new col
+" number is the col number when all leading spaces are converted to tabs
+" Args:
+"   -line:the line to get the rel col for
+"   -col: the abs col
+function s:TabbedCol(line, col)
+    let lineTruncated = strpart(a:line, 0, a:col)
+    let lineSpacesToTabs = substitute(lineTruncated, s:TabSpace(), '\t', 'g')
+    return strlen(lineSpacesToTabs)
+endfunction
+"FUNCTION: s:TabSpace() {{{2
+"returns a string of spaces equal in length to &tabstop
+function s:TabSpace()
+    let tabSpace = ""
+    let spacesPerTab = &tabstop
+    while spacesPerTab > 0
+        let tabSpace = tabSpace . " "
+        let spacesPerTab = spacesPerTab - 1
+    endwhile
+    return tabSpace
+endfunction
+
+" Function: s:UnEsc(str, escChar) {{{2
+" This function removes all the escape chars from a string
+" Args:
+"   -str: the string to remove esc chars from
+"   -escChar: the escape char to be removed
+function s:UnEsc(str, escChar)
+    return substitute(a:str, a:escChar, "", "g")
+endfunction
+
+" Function: s:UntabbedCol(line, col) {{{2
+" Takes a line and a col and returns the absolute column of col taking into
+" account that a tab is worth 3 or 4 (or whatever) spaces.
+" Args:
+"   -line:the line to get the abs col for
+"   -col: the col that doesnt take into account tabs
+function s:UntabbedCol(line, col)
+    let lineTruncated = strpart(a:line, 0, a:col)
+    let lineTabsToSpaces = substitute(lineTruncated, '\t', s:TabSpace(), 'g')
+    return strlen(lineTabsToSpaces)
+endfunction
+" Section: Comment mapping setup {{{1
+" ===========================================================================
+
+" switch to/from alternative delimiters
+nnoremap <plug>NERDCommenterAltDelims :call <SID>SwitchToAlternativeDelimiters(1)<cr>
+
+" comment out lines
+nnoremap <silent> <plug>NERDCommenterComment :call NERDComment(0, "norm")<cr>
+vnoremap <silent> <plug>NERDCommenterComment <ESC>:call NERDComment(1, "norm")<cr>
+
+" toggle comments
+nnoremap <silent> <plug>NERDCommenterToggle :call NERDComment(0, "toggle")<cr>
+vnoremap <silent> <plug>NERDCommenterToggle <ESC>:call NERDComment(1, "toggle")<cr>
+
+" minimal comments
+nnoremap <silent> <plug>NERDCommenterMinimal :call NERDComment(0, "minimal")<cr>
+vnoremap <silent> <plug>NERDCommenterMinimal <ESC>:call NERDComment(1, "minimal")<cr>
+
+" sexy comments
+nnoremap <silent> <plug>NERDCommenterSexy :call NERDComment(0, "sexy")<CR>
+vnoremap <silent> <plug>NERDCommenterSexy <ESC>:call NERDComment(1, "sexy")<CR>
+
+" invert comments
+nnoremap <silent> <plug>NERDCommenterInvert :call NERDComment(0, "invert")<CR>
+vnoremap <silent> <plug>NERDCommenterInvert <ESC>:call NERDComment(1, "invert")<CR>
+
+" yank then comment
+nmap <silent> <plug>NERDCommenterYank :call NERDComment(0, "yank")<CR>
+vmap <silent> <plug>NERDCommenterYank <ESC>:call NERDComment(1, "yank")<CR>
+
+" left aligned comments
+nnoremap <silent> <plug>NERDCommenterAlignLeft :call NERDComment(0, "alignLeft")<cr>
+vnoremap <silent> <plug>NERDCommenterAlignLeft <ESC>:call NERDComment(1, "alignLeft")<cr>
+
+" left and right aligned comments
+nnoremap <silent> <plug>NERDCommenterAlignBoth :call NERDComment(0, "alignBoth")<cr>
+vnoremap <silent> <plug>NERDCommenterAlignBoth <ESC>:call NERDComment(1, "alignBoth")<cr>
+
+" nested comments
+nnoremap <silent> <plug>NERDCommenterNest :call NERDComment(0, "nested")<cr>
+vnoremap <silent> <plug>NERDCommenterNest <ESC>:call NERDComment(1, "nested")<cr>
+
+" uncomment
+nnoremap <silent> <plug>NERDCommenterUncomment :call NERDComment(0, "uncomment")<cr>
+vnoremap <silent> <plug>NERDCommenterUncomment :call NERDComment(1, "uncomment")<cr>
+
+" comment till the end of the line
+nnoremap <silent> <plug>NERDCommenterToEOL :call NERDComment(0, "toEOL")<cr>
+
+" append comments
+nmap <silent> <plug>NERDCommenterAppend :call NERDComment(0, "append")<cr>
+
+" insert comments
+inoremap <silent> <plug>NERDCommenterInInsert <SPACE><BS><ESC>:call NERDComment(0, "insert")<CR>
+
+
+function! s:CreateMaps(target, combo)
+    if !hasmapto(a:target, 'n')
+        exec 'nmap ' . a:combo . ' ' . a:target
+    endif
+
+    if !hasmapto(a:target, 'v')
+        exec 'vmap ' . a:combo . ' ' . a:target
+    endif
+endfunction
+
+if g:NERDCreateDefaultMappings
+    call s:CreateMaps('<plug>NERDCommenterComment',    ',cc')
+    call s:CreateMaps('<plug>NERDCommenterToggle',     ',c<space>')
+    call s:CreateMaps('<plug>NERDCommenterMinimal',    ',cm')
+    call s:CreateMaps('<plug>NERDCommenterSexy',       ',cs')
+    call s:CreateMaps('<plug>NERDCommenterInvert',     ',ci')
+    call s:CreateMaps('<plug>NERDCommenterYank',       ',cy')
+    call s:CreateMaps('<plug>NERDCommenterAlignLeft',  ',cl')
+    call s:CreateMaps('<plug>NERDCommenterAlignBoth',  ',cb')
+    call s:CreateMaps('<plug>NERDCommenterNest',       ',cn')
+    call s:CreateMaps('<plug>NERDCommenterUncomment',  ',cu')
+    call s:CreateMaps('<plug>NERDCommenterToEOL',      ',c$')
+    call s:CreateMaps('<plug>NERDCommenterAppend',     ',cA')
+
+    if !hasmapto('<plug>NERDCommenterAltDelims', 'n')
+        nmap ,ca <plug>NERDCommenterAltDelims
+    endif
+endif
+
+
+
+" Section: Menu item setup {{{1
+" ===========================================================================
+"check if the user wants the menu to be displayed
+if g:NERDMenuMode != 0
+
+    let menuRoot = ""
+    if g:NERDMenuMode == 1
+        let menuRoot = 'comment'
+    elseif g:NERDMenuMode == 2
+        let menuRoot = '&comment'
+    elseif g:NERDMenuMode == 3
+        let menuRoot = '&Plugin.&comment'
+    endif
+
+    function! s:CreateMenuItems(target, desc, root)
+        exec 'nmenu <silent> ' . a:root . '.' . a:desc . ' ' . a:target
+        exec 'vmenu <silent> ' . a:root . '.' . a:desc . ' ' . a:target
+    endfunction
+    call s:CreateMenuItems("<plug>NERDCommenterComment",    'Comment', menuRoot)
+    call s:CreateMenuItems("<plug>NERDCommenterToggle",     'Toggle', menuRoot)
+    call s:CreateMenuItems('<plug>NERDCommenterMinimal',    'Minimal', menuRoot)
+    call s:CreateMenuItems('<plug>NERDCommenterNest',       'Nested', menuRoot)
+    exec 'nmenu <silent> '. menuRoot .'.To\ EOL <plug>NERDCommenterToEOL'
+    call s:CreateMenuItems('<plug>NERDCommenterInvert',     'Invert', menuRoot)
+    call s:CreateMenuItems('<plug>NERDCommenterSexy',       'Sexy', menuRoot)
+    call s:CreateMenuItems('<plug>NERDCommenterYank',       'Yank\ then\ comment', menuRoot)
+    exec 'nmenu <silent> '. menuRoot .'.Append <plug>NERDCommenterAppend'
+    exec 'menu <silent> '. menuRoot .'.-Sep-    :'
+    call s:CreateMenuItems('<plug>NERDCommenterAlignLeft',  'Left\ aligned', menuRoot)
+    call s:CreateMenuItems('<plug>NERDCommenterAlignBoth',  'Left\ and\ right\ aligned', menuRoot)
+    exec 'menu <silent> '. menuRoot .'.-Sep2-    :'
+    call s:CreateMenuItems('<plug>NERDCommenterUncomment',  'Uncomment', menuRoot)
+    exec 'nmenu <silent> '. menuRoot .'.Switch\ Delimiters <plug>NERDCommenterAltDelims'
+    exec 'imenu <silent> '. menuRoot .'.Insert\ Comment\ Here <plug>NERDCommenterInInsert'
+    exec 'menu <silent> '. menuRoot .'.-Sep3-    :'
+    exec 'menu <silent>'. menuRoot .'.Help :help NERDCommenterContents<CR>'
+endif
+" vim: set foldmethod=marker :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/bundle/yankring/doc/yankring.txt	Wed Jun 09 17:00:10 2010 -0400
@@ -0,0 +1,1412 @@
+*yankring.txt*      For Vim version 7.0. 
+
+Author:	        David Fishburn                             August 29, 2009
+Version:        10.0
+
+For instructions on installing this file, type
+	:help add-local-help |add-local-help| inside Vim.
+    
+
+==============================================================================
+1. Contents                                      *yankring* *yankring-contents*
+
+    1. Contents...............................: |yankring-contents|
+    2. Description............................: |yankring-description|
+    3. Configuration..........................: |yankring-configure|
+       3.1 Global Variables...................: |yankring-globals|
+       3.2 Default Keys.......................: |yankring-mappings|
+       3.3 Customizing Maps...................: |yankring-custom-maps|
+    4. Using the YankRing Window..............: |yankring-window|
+    5. Commands...............................: |yankring-commands|
+       5.1  YRToggle..........................: |YRToggle|
+       5.2  YRClear...........................: |YRClear|
+       5.3  YRShow............................: |YRShow|
+       5.5  YRGetElem.........................: |YRGetElem|
+       5.6  YRGetMultiple.....................: |YRGetMultiple|
+       5.7  YRPush............................: |YRPush|
+       5.8  YRPop.............................: |YRPop|
+       5.9  YRYankCount.......................: |YRYankCount|
+       5.10 YRYankRange.......................: |YRYankRange|
+       5.11 YRDeleteRange.....................: |YRDeleteRange|
+       5.12 YRPaste...........................: |YRPaste|
+       5.13 YRReplace.........................: |YRReplace|
+       5.14 YRMapsCreate......................: |YRMapsCreate|
+       5.15 YRMapsDelete......................: |YRMapsDelete|
+       5.16 YRSearch..........................: |YRSearch|
+       5.17 YRRunAfterMaps....................: |yankring-custom-maps|
+    6. Tutorial...............................: |yankring-tutorial|
+       6.1  YRShow............................: |YRShow-example|
+       6.2  YRReplace.........................: |YRReplace-example|
+       6.3  YRPush............................: |YRPush-example|
+       6.4  YRClear...........................: |YRClear-example|
+       6.8  YRPop.............................: |YRPop-example|
+       6.9  Visual modes......................: |yankring-visual-example|
+       6.10 Using ranges......................: |YRYankRange-example|
+       6.11 :global...........................: |global-example|
+       6.12 YRSearch..........................: |YRSearch-example|
+    7. History................................: |yankring-history|
+
+==============================================================================
+2. Description                                   *yankring-description*
+
+Vim already maintains a list of numbered registers containing the last 9
+deletes.  These previous deletes can be referenced using [register]p, so 
+"1p will paste the last delete, "2p the 2nd last delete.  For more
+information see |quote_number|.
+
+Vim does not provide any mechanism to reference previously yanked text.  
+In Emacs this feature is called the "kill ring".
+
+The YankRing plugin allows the user to configure the number of yanked
+and deleted text.  After text has been pasted, it can be replaced with
+a previous value from the yankring.
+
+As of version 3.0, the yankring's content will persist (by default) 
+between starting and stopping Vim.
+
+The plugin can be toggled on and off, and supports:
+   Ranges
+   Registers
+   Counts
+   All visual modes
+   All motions
+   All text-objects
+
+If you have any suggestions for the improvement of this plugin, see the
+yankring.vim file for my email address.  Suggestions / bug reports are
+always welcome.
+
+For details on the changes between versions see |yankring-history|.
+
+==============================================================================
+3. Configuration                                 *yankring-configure*
+
+The YankRing allows the user to choose which keys are to be assigned to
+the various commands.  By default, the YankRing chose keys identical
+with Vim's standard behaviour/keys.  
+
+3.1 Global Variables                             *yankring-globals*
+
+You can customize the YankRing by setting various global variables in
+your |.vimrc|.
+>
+    yankring_max_history 
+<       Default: 100
+        Controls how many elements to save in the yankring. >
+            let g:yankring_max_history = 100
+    yankring_min_element_length 
+<       Default: 1
+        If the yanked element has a length less than this value 
+        if will not be added to the YankRing.  This can be useful if 
+        you want to bypass single letter deletes by adding the 
+        following to your .vimrc: >
+            let g:yankring_min_element_length = 2
+    yankring_max_element_length 
+<       Default: 1048576 (1M)
+        Will truncate a new entry to the specified maximum.  If 
+        g:yankring_max_element_length is set to 0, there is no limit. >
+            let g:yankring_max_element_length = 4194304 " 4M
+    yankring_max_display  
+<       Default: 500
+        When the YankRing window is opened, each element is displayed on a
+        separate line.  Since each yank could be very large, the display of
+        the element is limited to the above default.  >
+            let g:yankring_max_display = 70
+    yankring_enabled
+<       Default: 1
+        If you do not want to YankRing enabled by default, set this 
+        variable in your |vimrc|. >
+            let g:yankring_enabled = 0  " Disables the yankring
+    yankring_persist  
+<       Default: 1
+        If you have enabled the storing of global variables in the |viminfo|
+        file, the YankRing will be default persist the contents of the ring
+        between starting and stopping Vim.  To disable this feature: >
+            let g:yankring_persist = 0
+    yankring_share_between_instances
+<       Default: 1
+        By default, any instance of Vim will share the same yankring
+        history file.  But if want each instance to have their own history
+        you can set this option to 0.  Setting g:yankring_persist = 0 and
+        g:yankring_share_between_instances = 0 will ensure no 2 instances
+        of Vim share the same YankRing history AND the history is not 
+        remembered the next time Vim is started. >
+            let g:yankring_share_between_instances = 0
+    yankring_dot_repeat_yank
+<       Default: Based on the Vim cpoption setting
+        By default Vim will not repeat (using '.') yanking of text.  This can
+        be controlled via the |'cpoptions'| setting.  The YankRing now respects
+        the cpoptions setting, if 'y' is included and you press '.', the
+        previous yank command is repeated and added to the yankring.
+        You can also add this behaviour by setting this in your |vimrc|: >
+            let g:yankring_dot_repeat_yank = 1
+    yankring_ignore_duplicate
+<       Default: 1
+        Duplicates will not be added to the YankRing by default.  If a
+        duplicate is found, that element will be moved to the top of the
+        yankring.  This can be controlled by setting this in your |vimrc|: >
+            let g:yankring_ignore_duplicate = 0 
+    yankring_map_dot
+<       Default: 1
+        If the '.' (repeat) command should be mapped by the yankring.  Since
+        most of the normal commands yy,dd,dw,... are mapped by the yankring,
+        if g:yankring_map_dot is false the . operator will not repeat these
+        operations.  The YankRing tracks several of the internal Vim registers
+        and decides whether an action was the result of the YankRing or an
+        action outside of it.  If the previous action was a result of the
+        yankring, it will be executed again.  If it was an action outside of
+        the yankring, it asks Vim to repeat the command. >
+            let g:yankring_map_dot = 1
+    yankring_paste_using_g
+<       Default: 1
+        By default [p] and [P] are mapped to interact with the yankring.  This
+        option controls whether [gp] and [gP] are also mapped.  Setting this
+        option to 0 will not create these maps.  >
+            let g:yankring_paste_using_g = 1
+    yankring_window_use_separate 
+<       Default: 1
+        This is a new feature as of the 2.0 release.  The YankRing now uses a
+        separate split buffer to display the yankring.  There are many buffer
+        specific maps that allow you to operate over the various elements from
+        within the yankring.  Setting this option to 0, uses the 1.0
+        interface. >
+            let g:yankring_window_use_separate = 0
+    yankring_window_auto_close
+<       Default: 1
+        By default once you choose an option in the YankRing buffer, the
+        action is performed and the buffer window is closed, returning you to
+        the original buffer.  This option can be toggled from within the
+        YankRing buffer by pressing [a].  The YankRing buffer status line
+        visually indicates where auto close is enabled or disabled.  There are
+        many times where you need to paste (or delete) many items from the
+        yankring.  Pressing [a], disables auto close, allows you to paste many
+        items, and finally you can press [a] to re-enable auto close, followed
+        by [q] to quit the buffer window. >
+            let g:yankring_window_auto_close = 1
+    yankring_window_use_horiz
+<       Default: 1
+        When the YankRing window is opened, it uses a horizontal split at the
+        bottom of the Vim window.  It can optionally use a vertical split by
+        setting this option to 0.  >
+            let g:yankring_window_use_horiz = 0  " Use vertical split
+    yankring_window_height
+<       Default: 1
+        If using a horizontal split, this option controls how high to make
+        the window.  >
+            let g:yankring_window_height = 8
+    yankring_window_width
+<       Default: 1
+        If using a vertical split, this option controls how wide to make the
+        window.  >
+            let g:yankring_window_width = 30
+    yankring_window_use_bottom
+<       Default: 1
+        If using a horizontal split, this option control whether the window is
+        opened at the top or bottom of the Vim window.  Setting this option to
+        0 forces the window to open at the top of the Vim window.  >
+            let g:yankring_window_use_bottom = 1
+    yankring_window_use_right
+<       Default: 1
+        If using a vertical split, this option control whether the window is
+        opened on the left or right side of the Vim window.  To force the
+        window to open on the left side, set this option to 0.  >
+            let g:yankring_window_use_right = 1
+    yankring_window_increment
+<       Default: 1
+        If using a vertical split the default width of the vertical window may
+        be too narrow to view enough of the elements.  Pressing [<space>] will
+        increase the size of the window by this number of columns.  Pressing
+        [<space>] again will toggle it back to the original size.  >
+            let g:yankring_window_increment = 50
+    yankring_manage_numbered_reg
+<       Default: 0
+        Vim already maintains a list of numbered registers containing the last
+        yanked item and the previous 9 deletes.  These items can be referenced
+        using [register]p, so "0p will paste the last yank, "1p will paste the
+        last delete, "2p the 2nd last delete.  For more information see
+        |quote_number|.
+        If you wish the YankRing to maintain these numbered registers so 
+        the top 10 elements in the YankRing are in the numbered reqisters 0-9
+        you can put the following in your |vimrc| >
+            let g:yankring_manage_numbered_reg = 1
+    yankring_ignore_operator
+<       Default: 'g~ gu gU ! = gq g? > < zf g@'
+        There are a number of Vim operations which do not change any 
+        registers, and therefore should not be captured by the yankring.
+        This list is used to ignore the appropriate operators.
+        You can put the following in your |vimrc| >
+            let g:yankring_ignore_operator = 'g~ gu gU ! = gq g? > < zf g@'
+    yankring_history_dir
+<       Default: $HOME
+        The YankRing stores the text in a file.  This global variable
+        allows you to customize where the file(s) will be stored.
+        You can put the following in your |vimrc| >
+            let g:yankring_history_dir = '$VIM'
+    yankring_history_file
+<       Default: 'yankring_history'
+        The history filename prefix can be controlled by setting this 
+        variable.
+        You can put the following in your |vimrc| >
+            let g:yankring_history_file = 'my_yankring_history_file'
+    yankring_clipboard_monitor
+<       Default: 1
+        When flipping between applications I find I often copy text
+        and attempt to use it inside of Vim.  This is typically easy
+        by simply using "+p, but there are times when I will repeatedly
+        want to use the same text later on.  By default, the YankRing
+        will detect when Vim regains focus and check if the clipboard
+        has changed since it last checked.  If so, it will add the contents
+        of the clipboard to the YankRing.  To disable this feature 
+        you can put the following in your |vimrc| >
+            let g:yankring_clipboard_monitor = 0
+    yankring_paste_check_default_buffer
+<       Default: 1
+        If the default register has changed without the YankRing registering
+        the change the YankRing will paste the top item from the history
+		rather than what is currently in the default register.
+        This option allows you to control the behaviour.  Plugins can
+        intentionally change the default buffer which the YankRing has
+		no way to noticing.  To disable this feature you can put the following
+		in your |vimrc| >
+            let g:yankring_paste_check_default_buffer = 0
+
+<
+3.2 Default Keys                                 *yankring-mappings*
+
+You can choose to override the default keys by creating these global
+variables in your |vimrc|.
+>
+    yankring_n_keys
+<       n - normal mode
+        Default Vim 7.2: 
+            'Y D x X'
+        Default Vim 7.1 and below: 
+            'x yy dd yw dw ye de yE dE yiw diw yaw daw y$ d$ Y D yG dG ygg dgg'
+
+        With the introduction of some new features in Vim 7.2 it is no longer
+        necessary to list all cmds which the YankRing will act upon.  
+        The yankring_n_keys only lists actions which an omap cannot be used.
+        Using the yankring_separator, the above list is parsed and 
+        individual mappings are created.  For each of the above normal 
+        commands the YankRing will include the text those commands 
+        acted upon.   There are many ways to accomplish the same result 
+        in Vim, if you do not see a common key stroke you regularly use
+        simply add the following to your |vimrc| with the additional 
+        keys you wished mapped.  >
+            let g:yankring_n_keys = 'Y D x X'
+    yankring_o_keys
+<       o - omap mode
+        Default:
+            Standard motions: 'b B w W e E d y $ G ;'
+            Vim text objects: ' iw iW aw aW as is ap ip a] a[ i] i['
+                              'a) a( ab i) i( ib a> a< i> i< at it '
+                              'a} a{ aB i} i{ iB a" a'' a` i" i'' i`'
+
+        As of Vim 7.2 omaps are used to capture changes to the registers
+        in Vim.  All of the standard motion commands are captured.
+        New to YankRing 5.0 all default Vim text objects are also 
+        captured.
+        Using the yankring_separator, the above list is parsed and 
+        individual mappings are created.  For each of the above normal 
+        commands the YankRing will include the text those commands 
+        acted upon.   There are many ways to accomplish the same result 
+        in Vim, if you do not see a common key stroke you regularly use
+        simply add the following to your |vimrc| with the additional 
+        keys you wished mapped.  >
+            let g:yankring_o_keys = 'b B w W e E d y $ G ; iw iW aw aW'
+    yankring_zap_keys 
+<       Default: 'f F t T / ?'
+        omaps are enough for most operations except for f and t.
+        These motions prompt the user for a character or string which 
+        they should act upon.  These must be treated as a special case 
+        in YankRing. >
+            let g:yankring_zap_keys = 'f t'
+    yankring_ignore_operator
+<       Default: 'g~ gu gU ! = gq g? > < zf g@'
+        There are certain motions which do not update any registers
+        in Vim.  If the registers are not changed, there is nothing
+        the YankRing can capture.  This list instructs the YankRing
+        to ignore any action for these keys. >
+            let g:yankring_ignore_operator = 'g~ gu gU'
+    yankring_v_key
+<       v - visual mode
+        Default: y 
+        Yanks visually select text.   >
+    yankring_del_v_key
+<       n - normal mode
+        Default: d 
+        The visually select text is included in the YankRing and deleted. >
+    yankring_paste_n_bkey
+<       n - normal mode
+        b - before
+        Default: P
+        The default Vim paste key will retrieve from the yankring.  This 
+        will paste the text BEFORE the current position. 
+        There is a special check to see if the text in the default paste
+        register is the same as what is in the current position of the 
+        yankring.  If it is not, we assume the user used some other 
+        mechanism to yank text (ie yt<character>).  If this is the case
+        we paste the text in the default paste buffer.  Using <C-P> the
+        text can be replaced with the current entry from the yankring.
+        Since there are many ways to do things in Vim, this provides
+        the best integration. >
+    yankring_paste_n_akey
+<       n - normal mode
+        a - after
+        Default: p 
+        The default Vim paste key will retrieve from the yankring.  This 
+        will paste the text AFTER the current position. 
+        There is a special check to see if the text in the default paste
+        register is the same as what is in the current position of the 
+        yankring.  If it is not, we assume the user used some other 
+        mechanism to yank text (ie yt<character>).  If this is the case
+        we paste the text in the default paste buffer.  Using <C-P> the
+        text can be replaced with the current entry from the yankring.
+        Since there are many ways to do things in Vim, this provides
+        the best integration. >
+    yankring_paste_v_key
+<       n - normal mode
+        Default: p
+        This will replace the visually select text with the contents 
+        from the yankring.   See yankring_paste_n_akey for additional
+        details.  >
+    yankring_replace_n_pkey
+<       n - normal mode
+        Default: <C-P>
+        If you do not want to open the YankRing window to choose your
+        selection, then you can paste (as usual) then use a YankRing 
+        mapping to cycle through items in the YankRing.  This is especially
+        useful if you know you recently used the text you are looking for.
+        If you wish to cycle through the yankring, replacing the previously
+        pasted text with the previous yanked text you can repeatedly press
+        <C-P> (or whatever keystroke you choose to map it to).  This map
+        moves backwards through the yankring, so you will retrieve your
+        most recent yank.  
+
+        I prefer not to use <C-P> since I like using that key to cycle 
+        through all the matches in the QuickFix window.  You can add
+        something similar to this in your |.vimrc| to get similar 
+        functionality.
+
+        On Windows use the ALT-< character to move through the YankRing.
+        To determine what character # these are go into insert mode
+        in a new buffer.  Press CTRL-V then ALT and the < key.
+        Leave insert mode, move the cursor onto the character
+        and press ga.  This will display the decimal, hex and octal
+        representation of the character.  In this case it is 172. >
+            if has('win32')
+                let g:yankring_replace_n_pkey = '<Char-172>'
+                let g:yankring_replace_n_nkey = '<Char-174>'
+                " Instead map these keys to moving through items in the quickfix window.
+                nnoremap <C-P> :cp<cr>
+                nnoremap <C-N> :cn<cr>
+            endif
+<       Other users have also stated that this will work: >
+            let g:yankring_replace_n_pkey = '<m-p>'
+            let g:yankring_replace_n_nkey = '<m-n>'
+    yankring_replace_n_nkey
+<       n - normal mode
+        Default: <C-N>
+        If you do not want to open the YankRing window to choose your
+        selection, then you can paste (as usual) then use a YankRing 
+        mapping to cycle through items in the YankRing.  This is especially
+        useful if you know you recently used the text you are looking for.
+        If you wish to cycle through the yankring, replacing the previously
+        pasted text with the next yanked text you can repeatedly press
+        <C-N> (or whatever keystroke you choose to map it to).  This map
+        moves forwards through the YankRing, so you will retrieve your
+        most recent yank.  
+
+        I prefer not to use <C-N> since I like using that key to cycle 
+        through all the matches in the QuickFix window.  You can add
+        something similar to this in your |.vimrc| to get similar 
+        functionality.
+
+        On Windows use the ALT-> character to move through the YankRing.
+        To determine what character # these are go into insert mode
+        in a new buffer.  Press CTRL-V then ALT and the > key.
+        Leave insert mode, move the cursor onto the character
+        and press ga.  This will display the decimal, hex and octal
+        representation of the character.  In this case it is 174. >
+        if has('win32')
+            let g:yankring_replace_n_pkey = '<Char-172>'
+            let g:yankring_replace_n_nkey = '<Char-174>'
+            " Instead map these keys to moving through items in the quickfix window.
+            nnoremap <C-P> :cp<cr>
+            nnoremap <C-N> :cn<cr>
+        endif
+<       Other users have also stated that this will work: >
+            let g:yankring_replace_n_pkey = '<m-p>'
+            let g:yankring_replace_n_nkey = '<m-n>'
+
+3.3 Customizing Maps                             *yankring-custom-maps*
+
+The YankRing plugin uses the yankring_n_keys global variable to create 
+a number of defaults maps.  The maps are of the form: >
+    nnoremap Y  :<C-U>YRYankCount 'Y'<CR>
+<
+When capital Y is pressed, the YankRing will execute 'Y' and capture the
+output from Vim.  But there are cases where you do not want the default
+behaviour of Vim, since you have customized some of these maps.
+
+In this case, I usually map Y to be |y$|, which makes it consistent with 
+the |D| and |C| operators.  The way yankring_n_keys works does not allow
+me to customize this behaviour.  Since many people may like to customize
+the behaviour of these maps the YankRing will check to see if a
+function called YRRunAfterMaps() exists.  If it does, it will call 
+this function after it has created the maps.  So in my case, I created
+the following function in my |vimrc|: >
+    function! YRRunAfterMaps()
+        nnoremap Y   :<C-U>YRYankCount 'y$'<CR>
+    endfunction
+<
+You can do anything you need in this function.  >
+        nnoremap Y   :<C-U>YRYankCount 'y$'<CR>
+<
+This line remaps Y (which the user presses) to the YRYankCount command.  The
+YRYankCount tells Vim to execute y$ instead.
+
+
+==============================================================================
+4. Using the YankRing Window:                    *yankring-window*
+
+This is a new feature as of the 2.0 release.  The YankRing uses a
+separate split buffer to display the yankring.  There are many buffer
+specific maps that allow you to operate over the various elements from
+within the yankring.  
+
+To display the YankRing buffer you can issue the :YRShow command.  For
+convience you can map a key, <F11>, to this command: >
+	:nnoremap <silent> <F11> :YRShow<CR>
+
+Status line~
+The first line in the YankRing window is the status line. >
+    AutoClose=1;ClipboardMonitor=1;Cmds:p,P,d,r,s,a,c,u,q,<enter>,<space>;Help=?
+<
+Help=?, pressing [?] will toggle the display of available commands the
+yankring window supports.  Pressing [?] again will remove the additional
+items.  
+
+AutoClose=1 indicates the window will close when an action is performed
+against elements within the yankring.  If you wish to perform multiple
+yankring operations press [a] to toggle the auto close feature off.  Use the
+commands below and when finished you can press [a] to toggle auto close on and
+press [q] to close the window.  The Cmds displayed are simply reminders of 
+the available keys.
+
+ClipboardMonitor=1 indicates the YankRing will monitor the clipboard (+)
+during Focus change events.  If the clipboard has changed since the YankRing
+last checked, the contents are added to the YankRing.  Pressing [c] allows
+you to quickly toggle this setting since it may not be useful at times.
+
+YankRing window key list~
+The following table lists the description of the keys that can be used
+in the YankRing window.
+
+  Key           Description~
+  p             Puts text after the cursor.  In visual mode, all elements
+                selected will be pasted.
+  P             Puts text before the cursor.  In visual mode, all elements
+                selected will be pasted.
+  gp            Just like "p", but leave the cursor just after the new text.
+  gP            Just like "P", but leave the cursor just after the new text.
+  <CR>          Just like "p".
+  <Enter>       Just like "p".
+  <2-LeftMouse> Just like "p".  Normal mode only.
+  d             Removes the element from the yankring.  In visual mode all
+                elements selected will be removed.
+  r             Just like "p", but in visual mode if many lines are selected
+                it will paste these in reverse order.
+  s             Prompts you for a regex to search the YankRing and display
+                only matching items.
+  a             Toggles the g:yankring_window_auto_close setting.
+  u             Updates the YankRing window.
+  q             Closes the YankRing window.
+  <Space>       Toggles the width of the vertical window by the
+                g:yankring_window_increment setting.
+  ?             Toggles the display of the help.
+
+ 
+
+
+==============================================================================
+5. Commands:                                     *yankring-commands*
+
+The predefined mappings call some specific commands with special parameters.
+If you are going to create additional maps, it is important you mirror
+the same parameters.  Most of these commands have been made obsolete by 
+the YankRing window, since it incorporates the functionality below, but
+through maps against a buffer, instead of commands.  This makes it much easier
+to use.
+
+
+5.1  YRToggle                                    *YRToggle*
+         Allows you to enable and disable the YankRing quickly.  This 
+         command will remove the default maps and recreate them.
+
+         Examples: >
+            :YRToggle    " Toggles it
+            :YRToggle 1  " Enables it
+            :YRToggle 0  " Disables it
+<            
+
+5.2  YRClear                                     *YRClear*
+         Clears all elements from the yankring.
+         See also |YRClear-example|.
+
+
+5.3  YRShow                                      *YRShow*
+         Similar to |:register|, will display all the entries in the yankring.
+         The element at the top will be the next element pasted from the
+         yankring.
+
+         Examples:  >
+            :YRShow     " Shows all entries in the yankring
+
+            --- YankRing ---
+            Elem  Content
+            1     five^@
+            2     four^@
+            3     three^@
+            4     two^@
+            5     one^@
+<    
+
+5.5  YRGetElem                                   *YRGetElem*
+        This command has two modes.  If no parameters are provided, it 
+        becomes interactive.  It uses YRShow to display the list and 
+        allows you to choose which element to paste.  If a parameter
+        is supplied it will paste that element from the yankring.  If the
+        number specified is outside of the YankRing an error is returned.
+        You may want to create a separate mapping for this call. >
+            nnoremap <silent> <Leader>yr :YRGetElem<CR>
+<       See also |YRSearch|.
+ 
+        Examples:
+            Assume there are 10 elements in the YankRing and element 6 is 
+            at the top of the ring. >
+            :YRGetElem     " Interactive mode, you choose from a list
+            :YRGetElem 4   " Will paste element 5.
+            :YRGetElem 12  " Will paste element 6.
+            :YRGetElem 99  " Error, invalid choice is reported
+            :YRGetElem 0   " Error, invalid choice is reported
+ 
+
+5.6  YRGetMultiple                               *YRGetMultiple*
+        Will paste many elements from the YankRing in one command.
+        If the number specified is 1 or less, it is assumed you want
+        just the current element pasted.  If the number specified is 
+        greater than or equal to the number of elements in the yankring, 
+        it is assumed you want all elements pasted.  If a ! is included
+        as part of the command, paste the items in reverse order.  
+        See the |yankring-tutorial| for more examples.
+
+        Examples:
+            Assume there are 10 elements in the YankRing. >
+            :YRGetMultiple  4   " Will paste elements 1,2,3,4
+            :YRGetMultiple! 4   " Will paste elements 4,3,2,1
+            :YRGetMultiple      " Will paste element  1
+            :YRGetMultiple  12  " Will paste elements 1,2,...,10
+            :YRGetMultiple  99  " Will paste elements 1,2,...,10
+            :YRGetMultiple  0   " Will paste element  1
+ 
+
+5.7  YRPush                                      *YRPush*
+         Allows the user to "push" additional entries into the yankring.
+         If you yanked text via a key mapping which does not use the 
+         YankRing (or there is text on the clipboard) you can use this
+         command to add the text to the yankring.
+
+         Examples: >
+            :YRPush      " Push the "  register's contents 
+            :YRPush '*'  " Push the "* register's contents (clipboard)
+            :YRPush '+'  " Push the "+ register's contents (clipboard)
+            :YRPush 'a'  " Push the "a register's contents 
+<           See also |YRPush-example|.
+             
+
+5.8  YRPop                                       *YRPop*
+         Allows you to pop any elements from the yankring.  If no parameters
+         are provided, the 1st element is removed from the yankring.  The
+         command optionally takes a second parameter to specify how many
+         elements to pop.  The default value is 1.
+
+         Examples: >
+            :YRPop      " Removes the highest numbered element from the 
+                          yankring
+            :YRPop 3    " Removes the 3rd element from the yankring
+            :YRPop 3,5  " Removes 5 elements from the YankRing beginning
+                          at element 3
+<           See also |YRPop-example|.
+             
+
+5.9  YRYankCount                                 *YRYankCount*
+         This command has the most mappings created for it.  If you are 
+         in normal mode and you are not specifying a range, this command
+         will add the text to the yankring.
+
+         The goal of this command is to allow the YankRing to be integrated
+         as seamlessly as possible with Vim.  So it supports counts and 
+         registers.  If you create a mapping to it, you must pass as a
+         parameter the action you want Vim to perform.  You could do the 
+         following: >
+            nnoremap \test  :<C-U>YRYankCount 'dd'<CR>
+<        This map is executed when you hit the '\test' keystrokes, but
+         it will actually delete the current line and add it to the 
+         yankring.
+
+         The following are the default mappings: >
+            nnoremap yy  :<C-U>YRYankCount 'yy'<CR>
+            nnoremap dd  :<C-U>YRYankCount 'dd'<CR>
+            nnoremap yw  :<C-U>YRYankCount 'yw'<CR>
+            nnoremap dw  :<C-U>YRYankCount 'dw'<CR>
+            nnoremap ye  :<C-U>YRYankCount 'ye'<CR>
+            nnoremap de  :<C-U>YRYankCount 'de'<CR>
+            nnoremap yiw :<C-U>YRYankCount 'yiw'<CR>
+            nnoremap diw :<C-U>YRYankCount 'diw'<CR>
+            nnoremap Y   :<C-U>YRYankCount 'Y'<CR>
+            nnoremap D   :<C-U>YRYankCount 'D'<CR>
+            nnoremap y$  :<C-U>YRYankCount 'y$'<CR>
+            nnoremap d$  :<C-U>YRYankCount 'd$'<CR>
+            nnoremap yG  :<C-U>YRYankCount 'yG'<CR>
+            nnoremap dG  :<C-U>YRYankCount 'dG'<CR>
+<
+         Examples:
+                yy - Adds the current line to the yankring.
+                dd - Adds the current line to the YankRing and deletes it.
+               5yw - Adds 5 words to the yankring.
+              "ade - Deletes the word, and puts it into both the yankring
+                     and the "a register.
+            10"zyy - Places 10 lines into both the YankRing and the "z
+                     register.
+            See also |yankring-tutorial|.
+         
+         
+5.10 YRYankRange                                 *YRYankRange*
+         This command by default is only called in visual mode.  All
+         visual modes (|characterwise-visual|, |linewise-visual|,
+         |blockwise-visual|) are supported.  Any visually selected text
+         is added to the yankring.  You can also call this command
+         directly using a range.
+
+         Examples:
+            Visual mode
+            -----------
+            Press v (to enter visual mode), highlight want you want, 
+            press y (to yank the selected area).
+            Repeat using V and Control-V.
+            
+            Normal mode
+            ----------- >
+            :5,20YRYankRange   " Will yank lines 5-20 into the yankring
+            :5,20YRDeleteRange " Will delete lines 5-20 and add them to
+                                 the yankring
+<           See also |YRYankRange-example|.
+         
+         
+5.11 YRDeleteRange                               *YRDeleteRange*
+         This command is identical to YRYankRange, except the range is
+         also deleted.
+
+
+5.12 YRPaste                                     *YRPaste*
+        This command will paste elements from the yankring.  By default it has
+        been mapped to p and P to match Vim's native key strokes.  The text
+        pasted is exactly what was yanked, including newline characters and 
+        blockwise-visual mode behaviours.  It supports counts and registers.
+
+        Examples:
+            p   " Paste the current element from the YankRing after the cursor
+            P   " Paste the current element from the YankRing before the cursor
+           5p   " Paste the current element from the YankRing after the cursor
+                  5 times
+          "ap   " Ignore the YankRing and paste the contents of register "a
+         5"ap   " Ignore the YankRing and paste the contents of register "a
+                  5 times
+            See also |yankring-tutorial|.
+
+            
+5.13 YRReplace                                   *YRReplace*
+        The purpose of the YankRing is to gain access to previously yanked
+        (or deleted) elements.  This command will replace the previously 
+        paste  with a different entry from the yankring.
+        By default, I choose <C-P> (P for previous) to replace the last paste
+        while moving backwards through the yankring.  <C-N> (N for next)
+        replaces the last paste while moving forward through the yankring. 
+
+        Examples:
+            See the |yankring-tutorial| for examples.
+
+            
+5.14 YRMapsCreate                                *YRMapsCreate*
+        This public function is responsible for creating the maps which
+        enable the yankring.  This function is called by the YRToggle 
+        command.
+
+            
+5.15 YRMapsDelete                                *YRMapsDelete*
+        This public function removes the YankRing maps and disables
+        the yankring.  This function is called by the YRToggle command.
+
+            
+5.16 YRSearch                                    *YRSearch*
+        This command is similar to |YRGetElem|.  The command takes
+        one parameter which is a regular expression.  Similar to 
+        YRGetElem, it will display all items in the YankRing that match
+        the regular expression.  It is also interactive, and will 
+        prompt you to enter which match you wish pasted.
+        See also |YRSearch-example|.
+
+
+==============================================================================
+6. Tutorial                                      *yankring-tutorial*
+
+To understand how to use the yankring, the following example will
+demonstrate the various features.  Assume you have created the following
+mapping: >
+    nnoremap <silent> <F11> :YRShow<CR>
+<
+    Assume we have this buffer: >
+        one
+        two
+        three
+        four
+        five
+<                                                *YRShow-example*     
+     Now yank (yy) each line separately starting at line 1.
+     Display the contents of the YankRing by executing the command
+     YRShow, or pressing <F11>.  The contents of the YankRing is
+     displayed in a new buffer.  The size, location and type of buffer
+     is configurable via various options.  See section 3 for more details. >
+        :YRShow or F11 
+            --- YankRing ---
+            Elem  Content
+            1     five^@
+            2     four^@
+            3     three^@
+            4     two^@
+            5     one^@
+<    Since we yanked the text starting at line 1 and finishing at
+     line 5, the most current YankRing element is the last one, the
+     contents of line 5.  "five^@" is displayed, the "^@" is a 
+     newline character (since we issued a "yy").
+     
+                                                 *yankring-window-example*     
+     At this point, you have two options.  You can choose which element
+     from the YankRing you wish to paste and press <CR> or 'p' or 'P' 
+     and a variety of other options, see |yankring-window|. After pressing
+     the key, the YankRing window will close (default behaviour).  Pressing
+     '?' will display additional help for the commands that are active within
+     the YankRing window.  Pressing '?' will toggle the help.
+
+     You do not need to interact with the YankRing using the YankRing window.
+     Using the window makes many tasks must easier, but for speed using some
+     of the other maps can be preferrable if you know what you have yanked /
+     deleted recently.  It was designed to work with Vim in the usual manner.
+     You can press, 'p', to paste the last item in yanked or deleted.
+
+     Close the YankRing window by pressing 'q' or F11 (which toggles it).
+
+                                                 *YRReplace-example*     
+     Now, go to the end of the file and press 'p'.  The resulting
+     buffer appears as: >
+        one
+        two
+        three
+        four
+        five
+        five
+<
+     Assume you did not want 'five", but a different entry from within the
+     yankring.  <C-P> moves backwards through the yankring, it will replace
+     the previous pasted text with a different item from the yankring.  This
+     allows you to quickly iterate through different elements.  <C-P> is the
+     default mapping, this can be user defined. See the following options for
+     more details: >
+        yankring_replace_n_nkey, yankring_replace_n_pkey
+<
+     After pressing <C-P> the buffer results in: >
+        one
+        two
+        three
+        four
+        five
+        four
+<    Now press 2<C-P>.  This would be the same as pressing 
+     <C-P> two times in a row.  This results in: >
+        one
+        two
+        three
+        four
+        five
+        two
+<    Now press <C-N> to move forwards through the yankring, 
+     this results in: >
+        one
+        two
+        three
+        four
+        five
+        three
+<    Display the contents of the yankring. >
+        :YRShow  
+            --- YankRing ---
+            Elem  Content
+            1     five^@
+            2     four^@
+            3     three^@
+            4     two^@
+            5     one^@
+<
+    Now lets yank some text with a key stroke that has not been 
+    mapped to the yankring.  Place your cursor at the start of 
+    line 4.  Press 'ytr', yank-to-(to the character r), which yanks
+    the 'fou' letters (no newline character).  Now press p.  Here is
+    the result: >
+        one
+        two
+        three
+        ffouour
+        five
+        three
+<   This is good, even though the keys 'ytr' has not been mapped
+    to YRYankCount, the YankRing still pasted the most recently 
+    yanked text.  Since the text did not have a newline character
+    the 'fou' was inserted after the 'f'.
+
+    Now replace that previous paste with the current element from
+    the YankRing by pressing <C-N>.  This is the result: >
+        one
+        two
+        three
+        four
+        one
+        five
+        three
+<   The #1 entry in the YankRing is still the line "five@".  When
+    choosing the next entry, it wraps around to the last entry in
+    the yankring, element #5.  The 'fou' was replaced with 'one^@'.
+    Since it had a newline character in it (when it was yanked) the
+    newline is included when it is pasted.
+
+                                                 *YRPush-example*     
+    Assume you need to paste text from the system clipboard, and this 
+    is text you will need routinely.  We can simulate this by running
+    this command (see |quote+|): >
+        :let @+ = "From the clipboard\n"
+        :echo @+
+
+<   With the cursor at the start of the line with the word 'five', press 'p'.
+    We still have pasted the 'fou' which is in the default paste buffer. >
+        one
+        two
+        three
+        four
+        two
+        ffouive
+        three
+<   We have the option of getting the text from the clipboard directly
+    with the following. >
+        First undo the previous change - u
+        Next - "+p
+<   The line changes since we bypassed the yankring, and specified
+    which register to get the text from: >
+        four
+        five
+        From the clipboard
+        three
+<   <C-P> replaces this with the #1 entry in the yankring: >
+        four
+        five
+        five
+        three
+<   Now add the contents of the clipboard to the yankring: >
+        :YRPush '+'
+<   Move the cursor to the last row 'three' and press 'p'.  The result is: >
+        four
+        five
+        one
+        three
+        From the clipboard
+<   YRPush '+' adds the value of the register '+' to the yankring, but it
+    also adds its contents to the default Vim paste buffer.  So pressing
+    'p' pasted this text.  Adding a new value to the YankRing we have
+    repositioned it which you can see with: >
+        :YRShow or F11
+            --- YankRing ---
+            Elem  Content
+            1     From the clipboard^@
+            2     five^@
+            3     four^@
+            4     three^@
+            5     two^@
+            6     one^@
+<                                                *YRClear-example*     
+    Now we will clear the yankring, and begin over again.  Delete all lines
+    from the buffer and replace them with the original rows: >
+        one
+        two
+        three
+        four
+        five 
+<   Now run this command to clear the YankRing to start over: >
+        :YRClear
+<
+    Issue a 'yy' on each of the 5 lines.  If you run the YRShow command you
+    should see the following: >
+        :YRShow or F11
+            --- YankRing ---
+            Elem  Content
+            1     five^@
+            2     four^@
+            3     three^@
+            4     two^@
+            5     one^@
+<                                                *any-item-example*     
+    If you need to quickly browse the YankRing to determine which element you
+    wish to paste you can simply press 'p' or <CR> or <Enter> on any element
+    displayed in the YankRing window.  Press '?' for more detailed description
+    of the commands available.
+
+    Using the YankRing window can be much faster if you do not want to cycle
+    through the YankRing using <C-P> and <C-N> to find the element.   
+
+                                                 *multiple-items-example*     
+    There are times when you need to move through a buffer capturing many
+    different lines (or snippets of code) and eventually want to switch 
+    buffers and paste these elements.  With some advance planning you can do 
+    this without the YankRing by issuing commands of the form: >
+        "ayy
+        "Ayy
+<   When specifying the register using UPPERCASE, Vim appends the yanked text
+    to register "a, instead of replacing it.  Many times you forget the
+    advance planning (or didn't even know about this great feature) you can 
+    use the YankRing window to do this easily.  If this is the current
+    yankring: >
+        :YRShow or F11
+            --- YankRing ---
+            Elem  Content
+            1     five^@
+            2     four^@
+            3     three^@
+            4     two^@
+            5     one^@
+<   The YankRing works in |visual-mode|.  To demonstrate move the cursor in
+    the buffer to the line with 'two'.  Press 'F11' to display the yankring
+    window.  Move the cursor to element 2, press 'V' to enable
+    |linewise-visual| mode and then press 'j' twice.  This should have
+    visually highlighted elements 2,3,4.  Press 'p' to paste all the
+    highlighted elements: >
+        one
+        two
+        four
+        three
+        two
+        three
+        four
+        five 
+<   You can see here it has pasted four, three, two after the second line of
+    the buffer.  Now press 'u' to undo our last change.  Leave the cursor
+    on the second line 'two'.  Press 'F11' to show the YankRing again.
+    Visually select the same lines, but this time press 'r' instead of 'p'.
+    'r' is for reverse, so it will paste the following: >
+        one
+        two
+        two
+        three
+        four
+        three
+        four
+        five 
+<   
+                                                 *YRGetMultiple-example*     
+    The same behaviour listed above (by visually selecting items in the
+    YankRing window) can be achieved using the YRGetMultiple command.
+    Assume there are 10 elements in the YankRing. >
+        :YRGetMultiple  4   " Will paste elements 1,2,3,4
+        :YRGetMultiple! 4   " Will paste elements 4,3,2,1
+        :YRGetMultiple      " Will paste element  1
+        :YRGetMultiple  12  " Will paste elements 1,2,...,10
+        :YRGetMultiple  99  " Will paste elements 1,2,...,10
+        :YRGetMultiple  0   " Will paste element  1
+<   
+                                                 *YRSearch-example*     
+    The default size of the YankRing is 100 elements.  It can be
+    tedious searching through the YankRing to find the element you
+    need.  YRSearch is similar to YRShow except it will limit the 
+    items displayed to only those items matching the regex provided. >
+        :YRShow 
+            --- YankRing ---
+            Elem  Content
+            1     Three Mississippi
+            2     Two Mississippi
+            3     One Mississippi
+            4     @", '\\/.*$^~[]' )
+        :YRSearch Mississippi
+            --- YankRing ---
+            Elem  Content
+            1     Three Mississippi
+            2     Two Mississippi
+            3     One Mississippi
+<   Consider some items which require escaping the search string: >
+        :YRSearch @", '\\
+            --- YankRing ---
+            Elem  Content
+            1     @", '\\/.*$^~[]' )
+<   Forward slashes and various other symbols require escapes, in this
+    case the slash was not escaped enough: >
+        :YRSearch @", '\\/
+            --- YankRing ---
+            Elem  Content
+<   There are enough escapes this time: >
+        :YRSearch @", '\\\\/
+            --- YankRing ---
+            Elem  Content
+            1     @", '\\/.*$^~[]' )
+<   Period, star, dollar and so on require one slash: >
+        :YRSearch @", '\\\\/\.\*\$\^\~\[\]
+            --- YankRing ---
+            Elem  Content
+            1     @", '\\/.*$^~[]' )
+                                                 
+<                                                *YRPop-example*     
+    You can remove any element from the YankRing by pressing pressing 'd' from
+    within the YankRing window.  Visual mode is also supported to remove more
+    than one element at a time.  >
+        :YRShow 
+            --- YankRing ---
+            Elem  Content
+            1     four^@
+            2     three^@
+            3     two^@
+            4     one^@
+<   Visually select elements 2,3.  Press 'd', the result is: >
+        :YRShow 
+            --- YankRing ---
+            Elem  Content
+            1     four^@
+            2     one^@
+
+<                                                *yankring-visual-example*     
+    There are 3 visual modes and all are supported.  Any visually selected 
+    text is added to the yankring.  You can try the various modes.  Move 
+    the cursor to inside the buffer (not the YankRing window).
+
+    |characterwise-visual|
+        Go to line 1, press 'v' and move using the cursor keys until you have
+        highlighted some text.  Then press y to yank the visually selected
+        area.  Pressing p with paste the yanked region.
+    
+    |linewise-visual|
+        Go to line 2, press 'V' and move using the cursor keys until you have
+        highlighted some text.  Notice the entire line is selected (including
+        the carriage returns).  Then press y to yank the visually selected
+        area.  Pressing p with paste the yanked region.
+    
+    |blockwise-visual|
+        Go to line 3 column 4, press CTRL-V and move to the right using the
+        cursor keys until you have highlighted some text.  Then press y to
+        yank the visually selected area.  Pressing p with paste the yanked
+        region.  Notice the pasted text retained its blockwise visual
+        characteristics.
+    
+                                                 *YRYankRange-example*     
+    YRYankRange is called during visual modes, but it is also possible to
+    use this via the command line. >
+        :1,4YRYankRange
+        :3,$YRDeleteRange
+        :YRShow 
+<   
+                                                 *global-example*     
+    Using Vim's |:global| command can be very useful at times.  The example
+    adds all rows (in a buffer) to the YankRing if they have a certain
+    phrase: >
+        :g/addme/YRYankCount 'yy'
+<   This is the breakdown for the above command: >
+        :g                  - for each line in the buffer
+        /addme              - check if the string "addme" is in the line
+        /YRYankCount 'yy'   - Ask the YankRing to execute the 'yy' command
+
+
+==============================================================================
+7. History                                       *yankring-history*
+
+  10.0: January 31, 2010
+         NF: Change the buffer name to [YankRing] to resemble other
+             non-user buffers.
+         NF: Added g:yankring_min_element_length which can prevent 
+             items from being added to the YankRing if they are too small.
+             For example, single character deletes (Vedran M).
+         BF: When shifting focus back to Vim, the YankRing may incorrectly
+             report: "YR:Failed to change to the yankring buffer, 
+             please contact author".
+         BF: When entering Vim for the first time and hitting "p"
+             nothing was pasted (Mark Huiskes).
+         BF: When entering Vim for the first time and the
+             yankring_clipboard_monitor = 1, the clipboard entry 
+             was not automatically added to the yankring.
+         BF: When overriding the default and setting 
+             g:yankring_window_use_bottom = 0, the YankRing would
+             report the error (Sergey Khorev): 
+                 E21: Cannot make changes, 'modifiable' is off
+
+  9.0: August 29, 2009: 
+         BF: You cannot execute a macro with ":normal @a".  It is still
+             not possible, but you can execute it with ":normal! @a"
+             (A S Budden).  
+         BF: When g:yankring_persist = 0 the YankRing could go into
+             an infinite loop (A S Budden).  
+         BF: When replaying a macro which used any of the zap
+             keys (f,F,t,T,/,?) you were prompted again for the 
+             string to match on (Ovidiu C).
+         BF: When checking the clipboard for changes 
+             (g:yankring_clipboard_monitor == 1) only add the item 
+             if it is not already in the ring.  Previously, the item
+             was moved to the top of the YankRing each time you flipped
+             focus.
+
+  8.0: December 21, 2008: 
+         NF: Changed the implementation of YRGetSearch() (David Liang).
+         BF: Under some unknown circumstances, the yankring can fail
+             to change to the correct buffer.  Put in code to double
+             check and abort.
+         BF: Yanking and pasting a line which ends in a backslash 
+             resulted in the backslash being replaced by "@@@".
+         BF: When repeating a command (".") which used any of the zap 
+             keys (f,F,t,T,/,?) you were prompted again for the 
+             string to match on (Vasilii Pascal).
+
+  7.0: November 14, 2008: 
+         NF: Added support for the / and ? motions so that y/search is 
+             supported (Vasilii Pascal).
+         NF: When the YankRing window is displayed (or updated) an additional 
+             check is made against the default register.  If it has changed
+             since the YankRing recorded it, the value will be added to the 
+             history.
+         NF: Added support for more motions h, j, k, l, H, M, L, ^, 0, -, +, _.
+             And a pile of g motions g_, g^, gm, g$, gk, gj, gg, ge, gE.
+         NF: The YankRing window will display a message it is operating
+             in a limited mode if not using Vim 7.2 or the correct patch 
+             level.
+         BF: Correction to some internal code which could lead to an 
+             endless loop (John Beckett).
+         BF: Opening and closing the YankRing window with "set report=0"
+             reported "1 line less" messages (Bill McCarthy).
+         BF: Changed the default value of g:yankring_paste_check_default_buffer
+		     to check if the default paste buffer has changed when pressing
+			 'p'.  For example, if a plugin has changed the default registers
+			 it will be pasted rather than the top item from the YankRing.
+         BF: YRMapsDelete did not remove all the maps created by the YankRing.
+         BF: Under particular circumstances, yanking text with embedded @
+             characters were not properly stored and retrieved from the
+             YankRing (Andrew Long).
+         BF: Changed to use xmaps instead of vmaps so that the maps only work
+             in visual mode and not select mode (David Liang).
+
+  6.1: October 31, 2008: 
+         BF: If the g:yankring_history_dir contains spaces (default on
+             Windows) an error was reported.  A simple work around was to 
+             let g:yankring_history_dir = 'c:\Vim' or no spaces (Matt).  
+
+  6.0: October 25, 2008: 
+         NF: The YankRing now maintains the history in a file.  This means
+             if you are running multiple instances of Vim, they all see
+             the same yankring.
+         NF: The location and name of the file is configurable by the user.
+         NF: The g:yankring_separator is no longer used and has been removed.
+         NF: The g:yankring_max_element_length can be used to limit the size 
+             of an element in the yankring.
+         NF: The g:yankring_share_between_instances can be used to indicate
+             whether each instance of Vim running on a machine should share
+             the history file or whether each should have their own 
+             individual history file.
+         NF: The g:yankring_clipboard_monitor can be used to indicate
+             whether changes to the system clipboard should be added to the
+             YankRing (default is on).
+         NF: The YankRing window can toggle the clipboard monitor by pressing
+             'c'.  See the help in the window by pressing ?.
+         NF: Added some highlighting to the YankRing window (Marty Grenfell).
+
+  5.0: September 21, 2008: 
+         NF: The YankRing can recognize certain Vim commands which do not
+             change the contents of a buffer and not attempt to capture it.
+         NF: The global variables which allow you to customize the behaviour
+             are now space separated instead of comma separated.  This
+             provides greater flexibility but will require you to modify
+             your vimrc (if you have customized it). (Andy Wokula)
+         BF: If using <C-O> from within insert mode, the YankRing inserted
+             characters into the buffer instead of capturing the changes,
+             this was fixed by Andy Wokula (Agathoklis Hatzimanikas).
+         BF: The YankRing did not properly account for all the different
+             forms of counts "5yy" worked but "y5y" did not (Edwin Shao).
+
+  4.1: August 9, 2008: 
+         NF: The YankRing now allows you to override which operators should
+             be ignored (yankring_ignore_operator).  By default this is
+             set for the standard Vim operators which do not modify any
+             registers (Examples: = and gu) (Andy Wokula).
+         NF: The YankRing did not map v_x (Matt Tolton).
+         BF: The expression register (quote=) was not accounted for correctly
+             (Agathoklis Hatzimanikas).
+         BF: Using the v:operator variable must be escaped when used in
+             a regular expression.
+
+  4.0: June 24, 2008: 
+         NF: The YankRing by default now captures all |text-objects| and 
+             all motions (|motion.txt|) which Vim supports.  Version 3.0 only
+             supported a subset of the basic motion commands.
+         NF: Prior to this version only predefined maps triggered the 
+             capture of data into the yankring.  These maps only supported
+             yanks and deletes.  The YankRing now also supports
+             operator-pending mode, which allows a greater range of operations
+             to be automatically captured and added to the yankring.  
+             Operating pending mode functionality requires Vim 7.2 or Vim 7.1
+             with patch #205.  If using Vim 7.1 you can determine this with: 
+                echo has("patch205")
+         NF: Prior to this version only yanks and deletes were registered
+             in the yankring.  Changes are now also captured into the
+             yankring.
+         NF: The YankRing will also capture the system cliboard when focus is
+             returned to the vim window.  This is useful if you copy text
+             between applications.
+         NF: The YankRing window always opened bottom horizontal.  Now it
+             can be opened top or bottom and horizontal or vertically.
+             This can be controlled via variables in your .vimrc.
+         BF: The YankRing has an option to persist between instances
+             of Vim by storing the values in global variables within
+             the viminfo.  This has led to some unusual ordering of
+             items in the ring from conflicts between instances.
+             This option has been turn off by default.
+         BF: Their was an issue with yanking using y$.
+
+  3.1: September 10, 2007: 
+         NF: YRClear will now unlet all global variables it uses to store
+             the data if the persist storage is specified (the default).
+             Large values in the viminfo file could possibly affect other
+             applications.
+
+  3.0: September 7, 2007: 
+         NF: Converted the YankRing to use the new Vim7's List object which
+             means it is no longer compatible with Vim6.
+         NF: By default the YankRing will now maintain the yankring's items
+             persistently by default.  It does this via the |viminfo| file.
+             This means the contents of the YankRing rely on the internal
+             variables of only 1 Vim instance.
+         BF: YRToggle was not unmapping 'gp' and 'gP'.
+         BF: YRSearch prompted the user for a regex even if one was provided
+             on the command line.
+         BF: If g:yankring_manage_numbered_reg is enabled, the "." operator
+             did not correctly repeat the previous action (Pedro DeRose).
+
+  2.2: November 1, 2005: 
+         NF: Added 'x' to the list of yankring_n_keys.  This is very useful
+             in visual mode since it can delete a lot of characters.
+
+  2.2: October 19, 2005: 
+         BF: If you pressed '?' to toggle the display of the help in the
+             YankRing window, the window would close.  This also applied to
+             'a', which allowed you to toggle the autoclose feature.
+
+  2.1: October 11, 2005: 
+         NF: Added the ability for the YankRing to override Vim's numbered 
+             registers.  Instead of the numbered registers holding the last
+             yanked value, and the 9 previous deletes, they will now reflect
+             the top 10 items in the yankring.  This allows you to reference
+             them directly with "5p.
+
+  2.0: August 20, 2005: 
+         NF: Much improved usability, the YankRing now has a "GUI" to service 
+             the yankring.  If YRShow or YRSearch is used, a split buffer is
+             opened which displays all the elements in the yankring.  There
+             are a number of maps that allow you to interact with the
+             contents.  The window can be positioned vertically or
+             horizontally as well as being sized all through options 
+             specified in your vimrc.
+	     NF: YRPop can now delete any items from the yankring, rather 
+		     that just from the top.
+	     NF: YRSetTop has been removed, it is no longer required as the
+		     internal representation of the YankRing has changed.
+	     BF: If g:yankring_ignore_duplicate is set (which is the default)
+		     you could get some unpredicable results when moving 
+			 backwards and forwards (<C-P> and <C-N>) through the 
+			 previous values.
+ 
+  1.7: June 10, 2005: 
+         BF: The expression register support added in version 1.6 used
+             getreg('='), which has the side effect of executing the 
+             expression register.  Depending on what was in the register
+             this could have unusual results.  Changed to use histget().
+ 
+  1.6: April 20, 2005: 
+         NF: YRSearch is similar to YRGetElem.  Given a regular expression
+             it will interactively display all the elements in the yankring
+             that match the regular expression.  You can enter the number
+             of the element to paste it.  If you have many elements within
+             the yankring, this can help you identify them more easily.
+         NF: Updated the default history size from 30 to 100, which is 
+             partially the reason for the YRSearch command.
+         NF: By default it supports "gp" and "gP", in addition to "p" and "P".
+         NF: Added support for the expression register (:h quote=).  Here
+             is an example of how it is used:
+                "="X"<CR>P
+ 
+  1.5: March 30, 2005: 
+         NF: The YankRing now respects the cpoptions setting, if 'y' is
+             included and you press '.', the previous yank command is executed
+             and added to the yankring.  You can also add this behaviour by
+             setting this in your |vimrc|: >
+                let g:yankring_dot_repeat_yank = 1
+<        NF: Duplicates will not be added to the YankRing by default.  If
+             a duplicate is found, the element will be moved to the top
+             of the yankring.  This can be controlled by setting this in 
+             your |vimrc|: >
+                let g:yankring_ignore_duplicate = 0 (1 is default)
+<        BF: Regression from version 1.4, the '.' operator may incorrectly
+             insert garbage.
+
+  1.4: March 28, 2005: 
+         NF: YRToggle has been updated.  If you toggle the YankRing off
+             (disable) the maps it creates are removed.  Calling YRToggle
+             again will recreate the maps.  This truly disables the yankring,
+             where the previous version attempted to do this via code.
+         BF: Using the '.' operator was not correctly replaying operations
+             that did not move text in some way (g~t_) changed the case
+             of the text but a '.' did not replay it.
+         BF: When replacing previously pasted text the YankRing did not
+             respect what key was used to paste the text originally.
+             All replaced items were pasted using 'p', even if you had
+             originally pasted the text with 'P'.
+
+  1.3: March 16, 2005: 
+         BF: The '.' operator did not handle the <<, >> shift operator.
+             Pressing '.' would result in the previous YankRing operation
+             instead of repeating the shift.
+
+  1.2: March 14, 2005: 
+         NF: Added support for '.' operator to repeat the last change.
+         NF: Changed YRGetElem to show the contents of the yankring
+             and allow you to choose which element you want pasted.
+             It is only interactive if you do not provide a parameter.
+         NF: Added 'ygg,dgg' default maps by extending the yankring_n_keys
+             variable.
+
+  1.1: March 09, 2005: 
+         NF: Added support for the black hole register |quote_|.
+         NF: Custom Maps allows the user to more finely tune the yankring
+             maps to perform whatever action they require.  This function,
+             YRRunAfterMaps(), is run automatically after the YankRing 
+             creates it's default mappings.  See |yankring-custom-maps|.
+         NF: Added some more default maps by extending the yankring_n_keys
+             variable.  It now contains:
+                yy,dd,yw,dw,ye,de,yE,dE,yiw,diw,yaw,daw,y$,d$,Y,D,yG,dG
+             NOTE:  You can easily extend these default mappings by 
+             creating this global variable in your |vimrc|, you do not
+             have to wait for the plugin to be updated.
+         NF: Added support for Dr. Chips GetLatestVimScripts plugin.
+         BF: The check for g:yankring_n_keys was incorrect, so it was not
+             possible to override the default maps.
+
+  1.0: March 08, 2005: 
+         NF: Initial release.
+
+vim: ts=4 ft=help tw=78
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/bundle/yankring/plugin/yankring.vim	Wed Jun 09 17:00:10 2010 -0400
@@ -0,0 +1,2461 @@
+" yankring.vim - Yank / Delete Ring for Vim
+" ---------------------------------------------------------------
+" Version:  10.0
+" Authors:  David Fishburn <dfishburn.vim@gmail.com>
+" Last Modified: 2010 Jan 24
+" Script:   http://www.vim.org/scripts/script.php?script_id=1234
+" Based On: Mocked up version by Yegappan Lakshmanan
+"           http://groups.yahoo.com/group/vim/post?act=reply&messageNum=34406
+" License:  GPL (Gnu Public License)
+" GetLatestVimScripts: 1234 1 :AutoInstall: yankring.vim
+
+if exists('loaded_yankring') || &cp
+    finish
+endif
+
+if v:version < 700
+  echomsg 'yankring: You need at least Vim 7.0'
+  finish
+endif
+
+let loaded_yankring = 100
+
+let s:yr_has_voperator     = 0
+if v:version > 701 || ( v:version == 701 && has("patch205") )
+    let s:yr_has_voperator = 1
+endif
+
+if !exists('g:yankring_history_dir')
+    let g:yankring_history_dir = expand('$HOME')
+else
+    let g:yankring_history_dir = expand(g:yankring_history_dir)
+endif
+
+if !exists('g:yankring_history_file')
+    let g:yankring_history_file = 'yankring_history'
+endif
+
+" Allow the user to override the # of yanks/deletes recorded
+if !exists('g:yankring_max_history')
+    let g:yankring_max_history = 100
+elseif g:yankring_max_history < 0
+    let g:yankring_max_history = 100
+endif
+
+" Specify the minimum length of 1 entry 
+if !exists('g:yankring_min_element_length')
+    let g:yankring_min_element_length = 1
+endif
+
+" Specify the maximum length of 1 entry (1MB default)
+if !exists('g:yankring_max_element_length')
+    let g:yankring_max_element_length = 1048576
+endif
+
+" Allow the user to specify if the plugin is enabled or not
+if !exists('g:yankring_enabled')
+    let g:yankring_enabled = 1
+endif
+
+" Specify max display length for each element for YRShow
+if !exists('g:yankring_max_display')
+    let g:yankring_max_display = 0
+endif
+
+" Check if yankring should persist between Vim instances
+if !exists('g:yankring_persist')
+    let g:yankring_persist = 1
+endif
+
+" Check if yankring share 1 file between all instances of Vim
+if !exists('g:yankring_share_between_instances')
+    let g:yankring_share_between_instances = 1
+endif
+
+" Specify whether the results of the ring should be displayed
+" in a separate buffer window instead of the use of echo
+if !exists('g:yankring_window_use_separate')
+    let g:yankring_window_use_separate = 1
+endif
+
+" Specifies whether the window is closed after an action
+" is performed
+if !exists('g:yankring_window_auto_close')
+    let g:yankring_window_auto_close = 1
+endif
+
+" When displaying the buffer, how many lines should it be
+if !exists('g:yankring_window_height')
+    let g:yankring_window_height = 8
+endif
+
+" When displaying the buffer, how many lines should it be
+if !exists('g:yankring_window_width')
+    let g:yankring_window_width = 30
+endif
+
+" When displaying the buffer, where it should be placed
+if !exists('g:yankring_window_use_horiz')
+    let g:yankring_window_use_horiz = 1
+endif
+
+" When displaying the buffer, where it should be placed
+if !exists('g:yankring_window_use_bottom')
+    let g:yankring_window_use_bottom = 1
+endif
+
+" When displaying the buffer, where it should be placed
+if !exists('g:yankring_window_use_right')
+    let g:yankring_window_use_right = 1
+endif
+
+" If the user presses <space>, toggle the width of the window
+if !exists('g:yankring_window_increment')
+    let g:yankring_window_increment = 50
+endif
+
+" Controls whether the . operator will repeat yank operations
+" The default is based on cpoptions: |cpo-y|
+"	y	A yank command can be redone with ".".
+if !exists('g:yankring_dot_repeat_yank')
+    let g:yankring_dot_repeat_yank = (&cpoptions=~'y'?1:0)
+endif
+
+" Only adds unique items to the yankring.
+" If the item already exists, that element is set as the
+" top of the yankring.
+if !exists('g:yankring_ignore_duplicate')
+    let g:yankring_ignore_duplicate = 1
+endif
+
+" Vim automatically manages the numbered registers:
+" 0   - last yanked text
+" 1-9 - last deleted items
+" If this option is turned on, the yankring will manage the 
+" values in them.
+if !exists('g:yankring_manage_numbered_reg')
+    let g:yankring_manage_numbered_reg = 0
+endif
+
+" Allow the user to specify what characters to use for the mappings.
+if !exists('g:yankring_n_keys')
+    " 7.1.patch205 introduces the v:operator function which was essential
+    " to gain the omap support.
+    if s:yr_has_voperator == 1
+        " Use omaps for the rest of the functionality
+        let g:yankring_n_keys = 'Y D x X'
+    else
+        let g:yankring_n_keys = 'x yy dd yw dw ye de yE dE yiw diw yaw daw y$ d$ Y D yG dG ygg dgg'
+    endif
+endif
+
+" Allow the user to specify what operator pending motions to map
+if !exists('g:yankring_o_keys')
+    " o-motions and text objects, without zap-to-char motions
+    let g:yankring_o_keys  = 'b B w W e E d h j k l H M L y G ^ 0 $ , ;'
+    let g:yankring_o_keys .= ' g_  g^ gm g$ gk gj gg ge gE - + _ '
+    let g:yankring_o_keys .= ' iw iW aw aW as is ap ip a] a[ i] i[ a) a( ab i) i( ib a> a< i> i< at it a} a{ aB i} i{ iB a" a'' a` i" i'' i`'
+endif
+
+if !exists('g:yankring_zap_keys')
+    let g:yankring_zap_keys = 'f F t T / ? @'
+endif
+
+" Allow the user to specify what operator pending motions to map
+if !exists('g:yankring_ignore_operator')
+    let g:yankring_ignore_operator = 'g~ gu gU ! = gq g? > < zf g@'
+endif
+let g:yankring_ignore_operator = ' '.g:yankring_ignore_operator.' '
+
+" Whether we should map the . operator
+if !exists('g:yankring_map_dot')
+    let g:yankring_map_dot = 1
+endif
+
+" Whether we sould map the "g" paste operators
+if !exists('g:yankring_paste_using_g')
+    let g:yankring_paste_using_g = 1
+endif
+
+if !exists('g:yankring_v_key')
+    let g:yankring_v_key = 'y'
+endif
+
+if !exists('g:yankring_del_v_key')
+    let g:yankring_del_v_key = 'd x'
+endif
+
+if !exists('g:yankring_paste_n_bkey')
+    let g:yankring_paste_n_bkey = 'P'
+endif
+
+if !exists('g:yankring_paste_n_akey')
+    let g:yankring_paste_n_akey = 'p'
+endif
+
+if !exists('g:yankring_paste_v_bkey')
+    let g:yankring_paste_v_bkey = 'P'
+endif
+
+if !exists('g:yankring_paste_v_akey')
+    let g:yankring_paste_v_akey = 'p'
+endif
+
+if !exists('g:yankring_paste_check_default_buffer')
+    let g:yankring_paste_check_default_buffer = 1
+endif
+
+if !exists('g:yankring_replace_n_pkey')
+    let g:yankring_replace_n_pkey = '<C-P>'
+endif
+
+if !exists('g:yankring_replace_n_nkey')
+    let g:yankring_replace_n_nkey = '<C-N>'
+endif
+
+if !exists('g:yankring_clipboard_monitor')
+    let g:yankring_clipboard_monitor = (has('clipboard')?1:0)
+endif
+
+if !exists('g:yankring_default_menu_mode')
+    let g:yankring_default_menu_mode = 3
+endif
+
+" Script variables for the yankring buffer
+let s:yr_buffer_name       = '[YankRing]'
+let s:yr_buffer_last_winnr = -1
+let s:yr_buffer_last       = -1
+let s:yr_buffer_id         = -1
+let s:yr_search            = ''
+let s:yr_remove_omap_dot   = 0
+let s:yr_history_version   = 'v2'
+let s:yr_history_v1_nl     = '@@@'
+let s:yr_history_v1_nl_pat = '\%(\\\)\@<!@@@'
+let s:yr_history_v2_nl     = "\2" " Use double quotes for a special character
+let s:yr_history_v2_nl_pat = "\2"
+let s:yr_history_last_upd  = 0
+let s:yr_history_file_v1   = 
+            \ g:yankring_history_dir.'/'.
+            \ g:yankring_history_file.
+            \ (g:yankring_share_between_instances==1?'':'_'.v:servername).
+            \ '.txt'
+let s:yr_history_file_v2   = 
+            \ g:yankring_history_dir.'/'.
+            \ g:yankring_history_file.
+            \ (g:yankring_share_between_instances==1?'':'_'.v:servername).
+            \ '_v2.txt'
+
+
+" Vim window size is changed by the yankring plugin or not
+let s:yr_winsize_chgd      = 0
+let s:yr_maps_created      = 0
+let s:yr_maps_created_zap  = 0
+
+" Enables or disables the yankring 
+function! s:YRToggle(...)
+    " Default the current state to toggle
+    let new_state = ((g:yankring_enabled == 1) ? 0 : 1)
+
+    " Allow the user to specify if enabled
+    if a:0 > 0
+        let new_state = ((a:1 == 1) ? 1 : 0)
+    endif
+            
+    " YRToggle accepts an integer value to specify the state
+    if new_state == g:yankring_enabled 
+        return
+    elseif new_state == 1
+        call s:YRMapsCreate()
+    else
+        call s:YRMapsDelete()
+    endif
+endfunction
+ 
+
+" Enables or disables the yankring 
+function! s:YRDisplayElem(disp_nbr, script_var) 
+    if g:yankring_max_display == 0
+        if g:yankring_window_use_separate == 1
+            let max_display = 500
+        else
+            let max_display = g:yankring_window_width + 
+                        \ g:yankring_window_increment - 
+                        \ 12
+        endif
+    else
+        let max_display = g:yankring_max_display
+    endif
+
+    let elem = matchstr(a:script_var, '^.*\ze,.*$')
+    if s:yr_history_version == 'v1'
+        " v1
+        " let elem = substitute(elem, '\%(\\\)\@<!@@@', '\\n', 'g')
+        " v2
+        let elem = substitute(elem, s:yr_history_v1_nl_pat, '\\n', 'g')
+        let elem = substitute(elem, '\\@', '@', 'g')
+    else
+        let elem = substitute(elem, s:yr_history_v2_nl_pat, '\\n', 'g')
+    endif
+    let length = strlen(elem)
+    " Fancy trick to align them all regardless of how many
+    " digits the element # is
+    return a:disp_nbr.
+                \ strtrans(
+                \ strpart("      ",0,(6-strlen(a:disp_nbr+1))).
+                \ (
+                \ (length>max_display)?
+                \ (strpart(elem,0,max_display).
+                \ '...'):
+                \ elem
+                \ )
+                \ )
+
+    return ""
+endfunction
+ 
+
+" Enables or disables the yankring 
+function! s:YRShow(...) 
+    " If no parameter was provided assume the user wants to 
+    " toggle the display.
+    let toggle = 1
+    if a:0 > 0
+        let toggle = matchstr(a:1, '\d\+')
+    endif
+
+    if toggle == 1
+        if bufwinnr(s:yr_buffer_id) > -1
+            " If the YankRing window is already open close it
+            exec bufwinnr(s:yr_buffer_id) . "wincmd w"
+            hide
+
+            " Switch back to the window which the YankRing
+            " window was opened from
+            if bufwinnr(s:yr_buffer_last) != -1
+                " If the buffer is visible, switch to it
+                exec s:yr_buffer_last_winnr . "wincmd w"
+            endif
+
+            return
+        endif
+    endif
+
+    " Reset the search string, since this is automatically called
+    " if the yankring window is open.  A previous search must be
+    " cleared since we do not want to show new items.  The user can
+    " always run the search again.
+    let s:yr_search = ""
+
+    " It is possible for registers to be changed outside of the 
+    " maps of the YankRing.  Perform this quick check when we
+    " show the contents (or when it is refreshed).
+    if g:yankring_paste_check_default_buffer == 1 
+        let save_reg = 0
+        let register = ((&clipboard=='unnamed')?'+':'"')
+
+        if &clipboard == 'unnamed' && getreg('+') != s:yr_prev_clipboard
+            let save_reg = 1
+        endif
+        if register == '"' && getreg('"') != s:yr_prev_reg_unnamed
+            let save_reg = 1
+        endif
+
+        if save_reg == 1
+            " The user has performed a yank / delete operation
+            " outside of the yankring maps.  Add this 
+            " value to the yankring.
+            call YRRecord(register)
+        endif
+    endif
+
+    " List is shown in order of replacement
+    " assuming using previous yanks
+    let output = "--- YankRing ---\n"
+    let output = output . "Elem  Content\n"
+
+    call s:YRHistoryRead()
+    let disp_item_nr = 1
+    for elem in s:yr_history_list
+        let output  = output . s:YRDisplayElem(disp_item_nr, elem) . "\n"
+        let disp_item_nr   += 1
+    endfor
+
+    if g:yankring_window_use_separate == 1
+        call s:YRWindowOpen(output)
+    else 
+        echo output
+    endif
+endfunction
+
+
+" Used in omaps if a following character is required 
+" like with motions (f,t)
+function! s:YRGetChar()
+    let msg = "YR:Enter character:"
+    echomsg msg
+    let c = getchar()
+    if c =~ '^\d\+$'
+        let c = nr2char(c)
+        echomsg msg.c
+    endif
+    return c
+endfunction
+
+
+" Used in omaps if a following string is required 
+" like with motions (/,?)
+" function! s:YRGetSearch()
+"     " let msg = "YR:Enter string:"
+"     " echomsg msg
+"     let str = input("YR:Enter string:")
+"     " let str = ''
+"     " while 1==1
+"     "     let c = getchar()
+"     "     if c =~ '^\d\+$'
+"     "         let c = nr2char(c)
+"     "         if c == "\<C-C>"
+"     "             return c
+"     "         endif
+"     "         if c == "\<CR>"
+"     "             break
+"     "         endif
+"     "         let str = str.c
+"     "         echomsg msg.str
+"     "     else
+"     "         break
+"     "     endif
+"     " endwhile
+"     return str
+" endfunction
+ 
+
+" Paste a certain item from the yankring
+" If no parameter is provided, this function becomes interactive.  It will
+" display the list (using YRShow) and allow the user to choose an element.
+function! s:YRGetElem(...) 
+    if s:yr_count == 0
+        call s:YRWarningMsg('YR: yankring is empty')
+        return -1
+    endif
+
+    let default_buffer = ((&clipboard=='unnamed')?'+':'"')
+
+    let direction = 'p'
+    if a:0 > 1
+        " If the user indicated to paste above or below
+        " let direction = ((a:2 ==# 'P') ? 'P' : 'p')
+        if a:2 =~ '\(p\|gp\|P\|gP\)'
+            let direction = a:2
+        endif
+    endif
+
+    " Check to see if a specific value has been provided
+    let elem = 0
+    if a:0 > 0
+        " Ensure we get only the numeric value (trim it)
+        let elem = matchstr(a:1, '\d\+')
+        let elem = elem - 1
+    else
+        " If no parameter was supplied display the yankring
+        " and prompt the user to enter the value they want pasted.
+        call s:YRShow(0)
+
+        if g:yankring_window_use_separate == 1
+            " The window buffer is used instead of command line
+            return
+        endif
+
+        let elem = input("Enter # to paste:")
+
+        " Ensure we get only the numeric value (trim it)
+        let elem = matchstr(elem, '\d\+')
+
+        if elem == ''
+            " They most likely pressed enter without entering a value
+            return
+        endif
+
+        let elem = elem - 1
+    endif
+
+    if elem < 0 || elem >= s:yr_count
+        call s:YRWarningMsg("YR: Invalid choice:".elem)
+        return -1
+    endif
+
+    let default_buffer = ((&clipboard=='unnamed')?'+':'"')
+    call setreg(default_buffer
+                \ , s:YRGetValElemNbr((elem), 'v')
+                \ , s:YRGetValElemNbr((elem), 't')
+                \ )
+    exec "normal! ".direction
+
+    " Set the previous action as a paste in case the user
+    " press . to repeat
+    call s:YRSetPrevOP('p', '', default_buffer, 'n')
+
+endfunction
+ 
+
+" Starting the top of the ring it will paste x items from it
+function! s:YRGetMultiple(reverse_order, ...) 
+    if s:yr_count == 0
+        call s:YRWarningMsg('YR: yankring is empty')
+        return
+    endif
+
+    " If the user provided a range, exit after that many
+    " have been displayed
+    let max  = 1
+    if a:0 == 1
+        " If no yank command has been supplied, assume it is
+        " a full line yank
+        let max = matchstr(a:1, '\d\+')
+    endif
+    if max > s:yr_count
+        " Default to all items if they specified a very high value
+        let max = s:yr_count
+    endif
+
+    " Base the increment on the sort order of the results
+    let increment = ((a:reverse_order==0)?(1):(-1))
+    if a:reverse_order == 0
+        let increment = 1
+        let elem = 0
+    else
+        let increment = -1
+        let elem = (max - 1)
+    endif
+
+    if a:0 > 1
+        let iter = 1
+        while iter <= a:0
+            let elem = (a:{iter} - 1)
+            call s:YRGetElem(elem)
+            let iter = iter + 1
+        endwhile
+    else
+        while max > 0
+            " Paste the first item, and move on to the next.
+            " digits the element # is
+            call s:YRGetElem(elem)
+            let elem = elem + increment
+            let max  = max - 1
+        endwhile
+    endif
+endfunction
+ 
+
+" Given a regular expression, check each element within
+" the yankring, display only the matching items and prompt
+" the user for which item to paste
+function! s:YRSearch(...) 
+    if s:yr_count == 0
+        call s:YRWarningMsg('YR: yankring is empty')
+        return
+    endif
+
+    let s:yr_search = ""
+    " If the user provided a range, exit after that many
+    " have been displayed
+    if a:0 == 0 || (a:0 == 1 && a:1 == "")
+        let s:yr_search = input('Enter [optional] regex:')
+    else
+        let s:yr_search = a:1
+    endif
+
+    if s:yr_search == ""
+        " Show the entire yankring
+        call s:YRShow(0)
+        return
+    endif
+
+    " List is shown in order of replacement
+    " assuming using previous yanks
+    let output        = "--- YankRing ---\n"
+    let output        = output . "Elem  Content\n"
+    let valid_choices = []
+
+    let search_result = filter(copy(s:yr_history_list), "v:val =~ '".s:yr_search."'")
+
+    let disp_item_nr = 1
+
+    for elem in s:yr_history_list
+        if elem =~ s:yr_search
+            let output  = output . s:YRDisplayElem(disp_item_nr, elem) . "\n"
+            call add(valid_choices, disp_item_nr.'')
+        endif
+        let disp_item_nr   += 1
+    endfor
+
+    if len(valid_choices) == 0
+        let output = output . "Search for [".s:yr_search."] did not match any items "
+    endif
+
+    if g:yankring_window_use_separate == 1
+        call s:YRWindowOpen(output)
+    else
+        if len(valid_choices) > 0
+            echo output
+            let elem = input("Enter # to paste:")
+
+            " Ensure we get only the numeric value (trim it)
+            let elem = matchstr(elem, '\d\+')
+
+            if elem == ''
+                " They most likely pressed enter without entering a value
+                return
+            endif
+
+            if index(valid_choices, elem) != -1
+                exec 'YRGetElem ' . elem
+            else
+                " User did not choose one of the elements that were found
+                " Remove leading ,
+                call s:YRWarningMsg( "YR: Item[" . elem . "] not found, only valid choices are[" .
+                            \ join(valid_choices, ',') .
+                            \ "]"
+                            \ )
+                return -1
+            endif
+
+        else
+            call s:YRWarningMsg( "YR: The pattern [" .
+                        \ s:yr_search .
+                        \ "] does not match any items in the yankring"
+                        \ )
+        endif
+    endif
+
+endfunction
+ 
+
+" Resets the common script variables for managing the ring.
+function! s:YRReset()
+    let s:yr_history_list          = []
+    " Update the history file
+    call s:YRHistorySave()
+endfunction
+ 
+
+" Clears the yankring by simply setting the # of items in it to 0.
+" There is no need physically unlet each variable.
+function! s:YRInit(...)
+    let s:yr_next_idx              = 0
+    let s:yr_last_paste_idx        = 0
+    let s:yr_count                 = 0
+    let s:yr_history_last_upd      = 0
+    let s:yr_history_list          = []
+    let s:yr_paste_dir             = 'p'
+
+    " For the . op support
+    let s:yr_prev_op_code          = ''
+    let s:yr_prev_op_mode          = 'n'
+    let s:yr_prev_count            = ''
+    let s:yr_prev_reg              = ''
+    let s:yr_prev_reg_unnamed      = ''
+    let s:yr_prev_reg_small        = ''
+    let s:yr_prev_reg_insert       = ''
+    let s:yr_prev_reg_expres       = ''
+    let s:yr_prev_clipboard        = ''
+    let s:yr_prev_vis_lstart       = 0
+    let s:yr_prev_vis_lend         = 0
+    let s:yr_prev_vis_cstart       = 0
+    let s:yr_prev_vis_cend         = 0
+    let s:yr_prev_changenr         = 0
+    let s:yr_prev_repeating        = 0
+
+    " This is used to determine if the visual selection should be
+    " reset prior to issuing the YRReplace
+    let s:yr_prev_vis_mode         = 0
+
+    if a:0 == 0 && g:yankring_persist == 0
+        " The user wants the yankring reset each time Vim is started
+        call s:YRClear()
+    endif
+
+    call s:YRHistoryRead()
+endfunction
+ 
+
+" Clears the yankring by simply setting the # of items in it to 0.
+" There is no need physically unlet each variable.
+function! s:YRClear()
+    call s:YRReset()
+    call s:YRInit('DoNotClear')
+
+    " If the yankring window is open, refresh it
+    call s:YRWindowUpdate()
+endfunction
+ 
+
+" Determine which register the user wants to use
+" For example the 'a' register:  "ayy
+function! s:YRRegister()
+    " v:register can be blank in some (unknown) cases
+    " so test for this condition and return the 
+    " default register
+    let user_register = ((v:register=='')?('"'):(v:register))
+    if &clipboard == 'unnamed' && user_register == '"'
+        let user_register = '+'
+    endif
+    return user_register
+endfunction
+
+
+" Allows you to push a new item on the yankring.  Useful if something
+" is in the clipboard and you want to add it to the yankring.
+" Or if you yank something that is not mapped.
+function! s:YRPush(...) 
+    let user_register = s:YRRegister()
+
+    if a:0 > 0
+        " If no yank command has been supplied, assume it is
+        " a full line yank
+        let user_register = ((a:1 == '') ? user_register : a:1)
+    endif
+
+    " If we are pushing something on to the yankring, add it to
+    " the default buffer as well so the next item pasted will
+    " be the item pushed
+    let default_buffer = ((&clipboard=='unnamed')?'+':'"')
+    call setreg(default_buffer, getreg(user_register), 
+                \ getregtype(user_register))
+
+    call s:YRSetPrevOP('', '', '', 'n')
+    call YRRecord(user_register)
+endfunction
+
+
+" Allows you to pop off any element from the yankring.
+" If no parameters are provided the first element is removed.
+" If a vcount is provided, that many elements are removed 
+" from the top.
+function! s:YRPop(...)
+    if s:yr_count == 0
+        call s:YRWarningMsg('YR: yankring is empty')
+        return
+    endif
+
+    let v_count = 1
+    if a:0 > 1 
+        let v_count = a:2
+    endif
+
+    " If the user provided a parameter, remove that element 
+    " from the yankring.  
+    " If no parameter was provided assume the first element.
+    let elem_index = 0
+    if a:0 > 0
+        " Get the element # from the parameter
+        let elem_index = matchstr(a:1, '\d\+')
+        let elem_index = elem_index - 1
+    endif
+    
+    " If the user entered a count, then remove that many
+    " elements from the ring.
+    while v_count > 0 
+        call s:YRMRUDel('s:yr_history_list', elem_index)
+        let v_count = v_count - 1
+    endwhile
+
+    " If the yankring window is open, refresh it
+    call s:YRWindowUpdate()
+endfunction
+
+
+" Adds this value to the yankring.
+function! YRRecord(...) 
+
+    let register = '"'
+    if a:0 > 0
+        " If no yank command has been supplied, assume it is
+        " a full line yank
+        let register = ((a:1 == '') ? register : a:1)
+    endif
+
+    " v:register can be blank in some (unknown) cases
+    " if v:register == '' || v:register == '_'
+    if v:register == '_'
+        " Black hole register, ignore recording the operation
+        return ""
+    endif
+
+    let register = ((&clipboard=='unnamed')?'+':register)
+
+    " let s:yr_prev_changenr    = changenr()
+    if register == '"'
+        " If the change has occurred via an omap, we must delay
+        " the capture of the default register until this event
+        " since register updates are not reflected until the 
+        " omap function completes
+        let s:yr_prev_reg_unnamed = getreg('"')
+        let s:yr_prev_reg_small   = getreg('-')
+    endif
+
+    " Add item to list
+    " This will also account for duplicates.
+    call s:YRMRUAdd( 's:yr_history_list'
+                \ , getreg(register)
+                \ , getregtype(register) 
+                \ )
+
+    if register =~ '[+*]'
+        let s:yr_prev_clipboard = @+
+    endif
+
+    " If the yankring window is open, refresh it
+    call s:YRWindowUpdate()
+
+    " Manage the numbered registers
+    if g:yankring_manage_numbered_reg == 1
+        call s:YRSetNumberedReg()
+    endif
+
+    return ""
+endfunction
+
+
+" Adds this value to the yankring.
+function! YRRecord3() 
+    let register = '"'
+
+    " v:register can be blank in some (unknown) cases
+    " if v:register == '' || v:register == '_'
+    if v:register == '_'
+        " Black hole register, ignore recording the operation
+        return ""
+    endif
+
+    let register = ((&clipboard=='unnamed')?'+':register)
+
+    if register == '"'
+        " If the change has occurred via an omap, we must delay
+        " the capture of the default register until this event
+        " since register updates are not reflected until the 
+        " omap function completes
+        let s:yr_prev_reg_unnamed = getreg('"')
+        let s:yr_prev_reg_small   = getreg('-')
+    endif
+
+    if s:yr_remove_omap_dot == 1
+        call s:YRMapsCreate('add_only_zap_keys')
+    endif
+
+    " Add item to list
+    " This will also account for duplicates.
+    call s:YRMRUAdd( 's:yr_history_list'
+                \ , getreg(register)
+                \ , getregtype(register) 
+                \ )
+
+    if register =~ '[+*]'
+        let s:yr_prev_clipboard = @+
+    endif
+
+    " If the yankring window is open, refresh it
+    call s:YRWindowUpdate()
+
+    " Manage the numbered registers
+    if g:yankring_manage_numbered_reg == 1
+        call s:YRSetNumberedReg()
+    endif
+
+    return ""
+endfunction
+
+
+" Record the operation for the dot operator
+function! s:YRSetPrevOP(op_code, count, reg, mode) 
+    let s:yr_prev_op_code     = a:op_code
+    let s:yr_prev_op_mode     = a:mode
+    let s:yr_prev_count       = a:count
+    let s:yr_prev_changenr    = changenr()
+    let s:yr_prev_reg         = a:reg
+    let s:yr_prev_reg_unnamed = getreg('"')
+    let s:yr_prev_reg_small   = getreg('-')
+    let s:yr_prev_reg_insert  = getreg('.')
+    let s:yr_prev_vis_lstart  = line("'<")
+    let s:yr_prev_vis_lend    = line("'>")
+    let s:yr_prev_vis_cstart  = col("'<")
+    let s:yr_prev_vis_cend    = col("'>")
+    let s:yr_prev_reg_expres  = histget('=', -1)
+
+    if a:mode == 'n'
+        " In normal mode, the change has already
+        " occurred, therefore we can mark the
+        " actual position of the change.
+        let s:yr_prev_chg_lstart  = line("'[")
+        let s:yr_prev_chg_lend    = line("']")
+        let s:yr_prev_chg_cstart  = col("'[")
+        let s:yr_prev_chg_cend    = col("']")
+    else
+        " If in operator pending mode, the change
+        " has not yet occurred.  Therefore we cannot
+        " use the '[ and ]' markers.  But we can
+        " store the current line position.
+        let s:yr_prev_chg_lstart  = line(".")
+        let s:yr_prev_chg_lend    = line(".")
+        let s:yr_prev_chg_cstart  = col(".")
+        let s:yr_prev_chg_cend    = col(".")
+    endif
+
+    " If storing the last change position (using '[, '])
+    " is not good enough, then another option is to:
+    " Use :redir on the :changes command
+    " and grab the last item.  Store this value
+    " and compare it is YRDoRepeat.
+endfunction
+
+
+" Adds this value to the yankring.
+function! s:YRDoRepeat() 
+    let dorepeat = 0
+
+    if s:yr_has_voperator == 1
+        " Let Vim handle the repeat, just capture the updates
+        " as usual.
+        return 0
+    endif
+
+    if s:yr_prev_op_code =~ '^c'
+        " You cannot repeat change operations, let Vim's
+        " standard mechanism handle these, or the user will
+        " be prompted again, instead of repeating the
+        " previous change.
+        return 0
+    endif
+
+    if g:yankring_manage_numbered_reg == 1
+        " When resetting the numbered register we are
+        " must ignore the comparision of the " register.
+        if s:yr_prev_reg_small  == getreg('-') &&
+                    \ s:yr_prev_reg_insert == getreg('.') &&
+                    \ s:yr_prev_reg_expres == histget('=', -1) &&
+                    \ s:yr_prev_vis_lstart == line("'<") &&
+                    \ s:yr_prev_vis_lend   == line("'>") &&
+                    \ s:yr_prev_vis_cstart == col("'<") &&
+                    \ s:yr_prev_vis_cend   == col("'>") &&
+                    \ s:yr_prev_chg_lstart == line("'[") &&
+                    \ s:yr_prev_chg_lend   == line("']") &&
+                    \ s:yr_prev_chg_cstart == col("'[") &&
+                    \ s:yr_prev_chg_cend   == col("']") 
+            let dorepeat = 1
+        endif
+    else
+        " Check the previously recorded value of the registers
+        " if they are the same, we need to reissue the previous
+        " yankring command.
+        " If any are different, the user performed a command
+        " command that did not involve the yankring, therefore
+        " we should just issue the standard "normal! ." to repeat it.
+        if s:yr_prev_reg_unnamed == getreg('"') &&
+                    \ s:yr_prev_reg_small  == getreg('-') &&
+                    \ s:yr_prev_reg_insert == getreg('.') &&
+                    \ s:yr_prev_reg_expres == histget('=', -1) &&
+                    \ s:yr_prev_vis_lstart == line("'<") &&
+                    \ s:yr_prev_vis_lend   == line("'>") &&
+                    \ s:yr_prev_vis_cstart == col("'<") &&
+                    \ s:yr_prev_vis_cend   == col("'>")
+            let dorepeat = 1
+        endif
+        if dorepeat == 1 && s:yr_prev_op_mode == 'n'
+            " Hmm, not sure why I was doing this now
+            " so I will remove it
+            " let dorepeat = 0
+            " if s:yr_prev_chg_lstart == line("'[") &&
+            "             \ s:yr_prev_chg_lend   == line("']") &&
+            "             \ s:yr_prev_chg_cstart == col("'[") &&
+            "             \ s:yr_prev_chg_cend   == col("']") 
+            "     let dorepeat = 1
+            " endif
+        elseif dorepeat == 1 && s:yr_prev_op_mode == 'o'
+            " Hmm, not sure why I was doing this now
+            " so I will remove it
+            " let dorepeat = 0
+            " if s:yr_prev_chg_lstart == line("'[") &&
+            "             \ s:yr_prev_chg_lend   == line("']") &&
+            "             \ s:yr_prev_chg_cstart == col("'[") &&
+            "             \ s:yr_prev_chg_cend   == col("']") 
+            "     let dorepeat = 1
+            " endif
+        endif
+    endif
+
+    " " If another change has happened that was not part of the
+    " " yankring we cannot replay it (from the yankring).  Use
+    " " the standard ".".
+    " " If the previous op was a change, do not use the yankring
+    " " to repeat it.
+    " " changenr() is buffer specific, so anytime you move to
+    " " a different buffer you will definitely perform a 
+    " " standard "."
+    " " Any previous op that was a change, must be replaced using "."
+    " " since we do not want the user prompted to enter text again.
+    " if s:yr_prev_changenr == changenr() && s:yr_prev_op_code !~ '^c'
+    "     let dorepeat = 1
+    " endif
+
+    " If we are going to repeat check to see if the
+    " previous command was a yank operation.  If so determine
+    " if yank operations are allowed to be repeated.
+    if dorepeat == 1 && s:yr_prev_op_code =~ '^y'
+        " This value be default is set based on cpoptions.
+        if g:yankring_dot_repeat_yank == 0
+            let dorepeat = 0
+        endif
+    endif
+    return dorepeat
+endfunction
+
+
+" Manages the Vim's numbered registers
+function! s:YRSetNumberedReg() 
+
+    let i = 1
+
+    while i <= 10
+        if i > s:yr_count
+            break
+        endif
+
+        call setreg( (i-1)
+                    \ , s:YRGetValElemNbr((i-1),'v')
+                    \ , s:YRGetValElemNbr((i-1),'t')
+                    \ )
+        let i += 1
+    endwhile
+endfunction
+
+
+" This internal function will add and subtract values from a starting
+" point and return the correct element number.  It takes into account
+" the circular nature of the yankring.
+function! s:YRGetNextElem(start, iter) 
+
+    let needed_elem = a:start + a:iter
+
+    " The yankring is a ring, so if an element is
+    " requested beyond the number of elements, we
+    " must wrap around the ring.
+    if needed_elem > s:yr_count
+        let needed_elem = needed_elem % s:yr_count
+    endif
+
+    if needed_elem == 0
+        " Can happen at the end or beginning of the ring
+        if a:iter == -1
+            " Wrap to the bottom of the ring
+            let needed_elem = s:yr_count
+        else
+            " Wrap to the top of the ring
+            let needed_elem = 1
+        endif
+    elseif needed_elem < 1
+        " As we step backwards through the ring we could ask for a negative
+        " value, this will wrap it around to the end
+        let needed_elem = s:yr_count
+    endif
+
+    return needed_elem
+
+endfunction
+
+
+" Lets Vim natively perform the operation and then stores what
+" was yanked (or deleted) into the yankring.
+" Supports this for example -   5"ayy
+"
+" This is a legacy function now since the release of Vim 7.2
+" and the use of omaps with YankRing 5.0 and above.  
+" If Vim 7.1 has patch205, then the new omaps and the v:operator
+" variable is used instead.
+function! s:YRYankCount(...) range
+
+    let user_register = s:YRRegister()
+    let v_count = v:count
+
+    " Default yank command to the entire line
+    let op_code = 'yy'
+    if a:0 > 0
+        " If no yank command has been supplied, assume it is
+        " a full line yank
+        let op_code = ((a:1 == '') ? op_code : a:1)
+    endif
+
+    if op_code == '.'
+        if s:YRDoRepeat() == 1
+            if s:yr_prev_op_code != ''
+                let op_code       = s:yr_prev_op_code
+                let v_count       = s:yr_prev_count
+                let user_register = s:yr_prev_reg
+            endif
+        else
+            " Set this flag so that YRRecord will
+            " ignore repeats
+            let s:yr_prev_repeating = 1
+            exec "normal! ."
+            return
+        endif
+    else
+        let s:yr_prev_repeating = 0
+    endif
+
+    " Supports this for example -   5"ayy
+    " A delete operation will still place the items in the
+    " default registers as well as the named register
+    exec "normal! ".
+            \ ((v_count > 0)?(v_count):'').
+            \ (user_register=='"'?'':'"'.user_register).
+            \ op_code
+
+    if user_register == '_'
+        " Black hole register, ignore recording the operation
+        return
+    endif
+    
+    call s:YRSetPrevOP(op_code, v_count, user_register, 'n')
+
+    call YRRecord(user_register)
+endfunction
+ 
+
+" Handles ranges.  There are visual ranges and command line ranges.
+" Visual ranges are easy, since we pass through and let Vim deal
+" with those directly.
+" Command line ranges means we must yank the entire line, and not
+" just a portion of it.
+function! s:YRYankRange(do_delete_selection, ...) range
+
+    let user_register  = s:YRRegister()
+    let default_buffer = ((&clipboard=='unnamed')?'+':'"')
+
+    " Default command mode to normal mode 'n'
+    let cmd_mode = 'n'
+    if a:0 > 0
+        " Change to visual mode, if command executed via
+        " a visual map
+        let cmd_mode = ((a:1 == 'v') ? 'v' : 'n')
+    endif
+
+    if cmd_mode == 'v' 
+        " We are yanking either an entire line, or a range 
+        exec "normal! gv".
+                    \ (user_register==default_buffer?'':'"'.user_register).
+                    \ 'y'
+        if a:do_delete_selection == 1
+            exec "normal! gv".
+                        \ (user_register==default_buffer?'':'"'.user_register).
+                        \ 'd'
+        endif
+    else
+        " In normal mode, always yank the complete line, since this
+        " command is for a range.  YRYankCount is used for parts
+        " of a single line
+        if a:do_delete_selection == 1
+            exec a:firstline . ',' . a:lastline . 'delete '.user_register
+        else
+            exec a:firstline . ',' . a:lastline . 'yank ' . user_register
+        endif
+    endif
+
+    if user_register == '_'
+        " Black hole register, ignore
+        return
+    endif
+    
+    call s:YRSetPrevOP('', '', user_register, 'n')
+    call YRRecord(user_register)
+endfunction
+ 
+
+" Paste from either the yankring or from a specified register
+" Optionally a count can be provided, so paste the same value 10 times 
+function! s:YRPaste(replace_last_paste_selection, nextvalue, direction, ...) 
+    " Disabling the yankring removes the default maps.
+    " But there are some maps the user can create on their own, and 
+    " these would most likely call this function.  So place an extra
+    " check and display a message.
+    if g:yankring_enabled == 0
+        call s:YRWarningMsg(
+                    \ 'YR: The yankring is currently disabled, use YRToggle.'
+                    \ )
+        return
+    endif
+    
+
+    let user_register  = s:YRRegister()
+    let default_buffer = ((&clipboard == 'unnamed')?'+':'"')
+    let v_count        = v:count
+
+    " Default command mode to normal mode 'n'
+    let cmd_mode = 'n'
+    if a:0 > 0
+        " Change to visual mode, if command executed via
+        " a visual map
+        let cmd_mode = ((a:1 == 'v') ? 'v' : 'n')
+    endif
+
+    " User has decided to bypass the yankring and specify a specific 
+    " register
+    if user_register != default_buffer
+        if a:replace_last_paste_selection == 1
+            call s:YRWarningMsg( 'YR: A register cannot be specified in replace mode' )
+            return
+        else
+            " Check for the expression register, in this special case
+            " we must copy it's evaluation into the default buffer and paste
+            if user_register == '='
+                " Save the default register since Vim will only
+                " allow the expression register to be pasted once
+                " and will revert back to the default buffer
+                let save_default_reg = @"
+                call setreg(default_buffer, eval(histget('=', -1)) )
+            else
+                let user_register = '"'.user_register
+            endif
+            exec "normal! ".
+                        \ ((cmd_mode=='n') ? "" : "gv").
+                        \ ((v_count > 0)?(v_count):'').
+                        \ ((user_register=='=')?'':user_register).
+                        \ a:direction
+            if user_register == '='
+                let @" = save_default_reg
+            endif
+            " In this case, we have bypassed the yankring
+            " If the user hits next or previous we want the
+            " next item pasted to be the top of the yankring.
+            let s:yr_last_paste_idx = 0
+        endif
+        let s:yr_paste_dir     = a:direction
+        let s:yr_prev_vis_mode = ((cmd_mode=='n') ? 0 : 1)
+        return
+    endif
+
+    " Try to second guess the user to make these mappings less intrusive.
+    " If the user hits paste, compare the contents of the paste register
+    " to the current entry in the yankring.  If they are different, lets
+    " assume the user wants the contents of the paste register.
+    " So if they pressed [yt ] (yank to space) and hit paste, the yankring
+    " would not have the word in it, so assume they want the word pasted.
+    if a:replace_last_paste_selection != 1 
+        if s:yr_count > 0 || (default_buffer == '+' && len(@+) == 0)
+            " Only check the default buffer is the user wants us to.
+            " This was necessary prior to version 4.0 since we did not 
+            " capture as many items as 4.0 and above does. (A. Budden)
+            if g:yankring_paste_check_default_buffer == 1 && 
+                        \ getreg(default_buffer) != s:yr_prev_reg_unnamed
+                " The user has performed a yank / delete operation
+                " outside of the yankring maps.  First, add this 
+                " value to the yankring.
+                call YRRecord(default_buffer)
+                " Now, use the most recently yanked text, rather than the
+                " value from the yankring.
+                exec "normal! ".
+                            \ ((cmd_mode=='n') ? "" : "gv").
+                            \ ((v_count > 0)?(v_count):'').
+                            \ a:direction
+                let s:yr_paste_dir     = a:direction
+                let s:yr_prev_vis_mode = ((cmd_mode=='n') ? 0 : 1)
+
+                " In this case, we have bypassed the yankring
+                " If the user hits next or previous we want the
+                " next item pasted to be the top of the yankring.
+                let s:yr_last_paste_idx = 0
+                return
+            endif
+        else
+            exec "normal! ".
+                        \ ((cmd_mode=='n') ? "" : "gv").
+                        \ ((v_count > 0)?(v_count):'').
+                        \ a:direction
+            let s:yr_paste_dir     = a:direction
+            let s:yr_prev_vis_mode = ((cmd_mode=='n') ? 0 : 1)
+            return
+        endif
+    endif
+
+    if s:yr_count == 0 || (default_buffer == '+' && len(@+) == 0)
+        " Nothing to paste
+        return
+    endif
+
+    if a:replace_last_paste_selection == 1
+        " Replacing the previous put
+        let start = line("'[")
+        let end = line("']")
+
+        if start != line('.')
+            call s:YRWarningMsg( 'YR: You must paste text first, before you can replace' )
+            return
+        endif
+
+        if start == 0 || end == 0
+            return
+        endif
+
+        " If a count was provided (ie 5<C-P>), multiply the 
+        " nextvalue accordingly and position the next paste index
+        let which_elem = a:nextvalue * ((v_count > 0)?(v_count):1) * -1
+        let s:yr_last_paste_idx = s:YRGetNextElem(
+		    \ s:yr_last_paste_idx, which_elem
+		    \ )
+
+        let save_reg            = getreg(default_buffer)
+        let save_reg_type       = getregtype(default_buffer)
+        call setreg( default_buffer
+                    \ , s:YRGetValElemNbr((s:yr_last_paste_idx-1),'v')
+                    \ , s:YRGetValElemNbr((s:yr_last_paste_idx-1),'t')
+                    \ )
+
+        " First undo the previous paste
+        exec "normal! u"
+        " Check if the visual selection should be reselected
+        " Next paste the correct item from the ring
+        " This is done as separate statements since it appeared that if 
+        " there was nothing to undo, the paste never happened.
+        exec "normal! ".
+                    \ ((s:yr_prev_vis_mode==0) ? "" : "gv").
+                    \ s:yr_paste_dir
+        call setreg(default_buffer, save_reg, save_reg_type)
+        call s:YRSetPrevOP('', '', '', 'n')
+    else
+        " User hit p or P
+        " Supports this for example -   5"ayy
+        " And restores the current register
+        let save_reg            = getreg(default_buffer)
+        let save_reg_type       = getregtype(default_buffer)
+        let s:yr_last_paste_idx = 1
+        call setreg(default_buffer
+                    \ , s:YRGetValElemNbr(0,'v')
+                    \ , s:YRGetValElemNbr(0,'t')
+                    \ )
+        exec "normal! ".
+                    \ ((cmd_mode=='n') ? "" : "gv").
+                    \ (
+                    \ ((v_count > 0)?(v_count):'').
+                    \ a:direction
+                    \ )
+        call setreg(default_buffer, save_reg, save_reg_type)
+        call s:YRSetPrevOP(
+                    \ a:direction
+                    \ , v_count
+                    \ , default_buffer
+                    \ , 'n'
+                    \ )
+        let s:yr_paste_dir     = a:direction
+        let s:yr_prev_vis_mode = ((cmd_mode=='n') ? 0 : 1)
+    endif
+
+endfunction
+ 
+
+" Handle any omaps
+function! YRMapsExpression(sid, motion, ...)
+    let cmds     = a:motion
+    " echomsg "YRMapsE:".localtime()
+    " echomsg "YRMapsE 1:".cmds.":".v:operator.":".s:yr_maps_created_zap
+
+    if  (a:motion =~ '\.' && s:yr_remove_omap_dot == 1) || a:motion =~ '@'
+        " If we are repeating a series of commands we must
+        " unmap the _zap_ keys so that the user is not
+        " prompted when a command is replayed.
+        " These maps must be re-instated in YRRecord3()
+        " after the action of the replay is completed.
+        call s:YRMapsDelete('remove_only_zap_keys')
+    endif
+
+    " Check if we are in operator-pending mode
+    if a:motion =~ '\('.substitute(g:yankring_zap_keys, ' ', '\\|', 'g').'\)'
+        if a:motion =~ '\(/\|?\)'
+            let zapto = (a:0==0 ? "" : input("YR:Enter string:"))
+            if zapto != ""
+                let zapto = zapto . "\<CR>"
+            else
+                let zapto = "\<C-C>"
+            endif
+        else
+            let zapto = (a:0==0 ? "" : s:YRGetChar())
+        endif
+
+        if zapto == "\<C-C>"
+            " Abort if the user hits Control C
+            call s:YRWarningMsg( "YR:Aborting command:".v:operator.a:motion )
+            return "\<C-C>"
+        endif
+
+        let cmds = cmds . zapto
+    endif
+
+    " There are a variety of commands which do not change the
+    " registers, so these operators should be ignored when
+    " determining which operations to record
+    " Simple example is '=' which simply formats the 
+    " the selected text.
+    if ' \('.escape(join(split(g:yankring_ignore_operator), '\|'), '/.*~$^[]' ).'\) ' !~ escape(v:operator, '/.*~$^[]') 
+        " Check if we are performing an action that will
+        " take us into insert mode
+        if '[cCsS]' !~ escape(v:operator, '/.*~$^[]') && a:motion !~ '@'
+        " if '[cCsS]' !~ escape(v:operator, '/.*~$^[]')
+            " If we have not entered insert mode, feed the call
+            " to record the current change when the function ends.
+            " This is necessary since omaps do not update registers
+            " until the function completes.
+            " The InsertLeave event will handle the motions
+            " that place us in insert mode and record the
+            " changes when insert mode ends.
+            let cmds .= a:sid. "yrrecord"
+        endif
+    endif
+
+    " echomsg "YRMapsE 5:".a:motion.":'".cmds."':".s:yr_maps_created_zap
+    return cmds
+ 
+endfunction
+ 
+
+" Handle any the @
+function! s:YRMapsMacro(bang, ...) range
+    " If we are repeating a series of commands we must
+    " unmap the _zap_ keys so that the user is not
+    " prompted when a command is replayed.
+    " These maps must be re-instated in YRRecord3()
+    " after the action of the replay is completed.
+    call s:YRMapsDelete('remove_only_zap_keys')
+
+    " let zapto = (a:0==0 ? "" : s:YRGetChar())
+    let zapto = s:YRGetChar()
+
+    if zapto == "\<C-C>"
+        " Abort if the user hits Control C
+        call s:YRWarningMsg( "YR:Aborting command:".v:operator.a:motion )
+        return ""
+    endif
+
+    let v_count    = v:count
+    " If no count was specified it will have a value of 0
+    " so set it to at least 1
+    let v_count = ((v_count > 0)?(v_count):'')
+
+    let range = ''
+    if a:firstline != a:lastline
+        let rannge = a:firstline.','.a:lastline
+    endif
+
+    let cmd = range."normal! ".v_count.'@'.zapto
+    " DEBUG
+    " echomsg cmd
+    exec cmd
+
+    call s:YRMapsCreate('add_only_zap_keys')
+endfunction
+ 
+
+" Create the default maps
+function! s:YRMapsCreate(...)
+    " 7.1.patch205 introduces the v:operator function which was 
+    " essential to gain the omap support.
+    if s:yr_has_voperator == 1
+        let s:yr_remove_omap_dot   = 1
+        for key in split(g:yankring_zap_keys)
+            try
+                if key != '@'
+                    exec 'omap <expr>' key 'YRMapsExpression("<SID>", "'. key. '", 1)'
+                endif
+            catch
+            endtry
+        endfor
+    endif
+
+    silent! nmap <expr> @ YRMapsExpression("<SID>", "@", "1")
+
+    let s:yr_maps_created_zap = 1
+
+    if a:0 > 0
+        " We have only removed the _zap_ keys temporarily
+        " so abandon further changes.
+        return
+    endif
+
+    " 7.1.patch205 introduces the v:operator function which was essential
+    " to gain the omap support.
+    if s:yr_has_voperator == 1
+        let s:yr_remove_omap_dot   = 1
+        " Set option to add and remove _zap_ keys when
+        " repeating commands
+        let o_maps = split(g:yankring_o_keys)
+        " Loop through and prompt the user for all buffer connection parameters.
+        for key in o_maps
+            exec 'omap <expr>' key 'YRMapsExpression("<SID>", "'. escape(key,'\"'). '")'
+        endfor
+    endif
+
+    " Iterate through a space separated list of mappings and create
+    " calls to the YRYankCount function
+    let n_maps = split(g:yankring_n_keys)
+    " Loop through and prompt the user for all buffer connection parameters.
+    for key in n_maps
+        " exec 'nnoremap <silent>'.key." :<C-U>YRYankCount '".key."'<CR>"
+        " exec 'nnoremap <silent>'.key." :<C-U>YRYankCount '".key."'<CR>"
+        " Andy Wokula's suggestion
+        exec 'nmap' key key."<SID>yrrecord"
+    endfor
+
+    if g:yankring_map_dot == 1
+        if s:yr_has_voperator == 1
+            nmap <expr> . YRMapsExpression("<SID>", ".")
+        else
+            nnoremap <silent> . :<C-U>YRYankCount '.'<CR>
+        endif
+    endif
+
+    if g:yankring_v_key != ''
+        exec 'xnoremap <silent>'.g:yankring_v_key." :YRYankRange 'v'<CR>"
+    endif
+    if g:yankring_del_v_key != ''
+        for v_map in split(g:yankring_del_v_key)
+            if strlen(v_map) > 0
+                try
+                    exec 'xnoremap <silent>'.v_map." :YRDeleteRange 'v'<CR>"
+                catch
+                endtry
+            endif
+        endfor
+    endif
+    if g:yankring_paste_n_bkey != ''
+        exec 'nnoremap <silent>'.g:yankring_paste_n_bkey." :<C-U>YRPaste 'P'<CR>"
+        if g:yankring_paste_using_g == 1
+            exec 'nnoremap <silent> g'.g:yankring_paste_n_bkey." :<C-U>YRPaste 'gP'<CR>"
+        endif
+    endif
+    if g:yankring_paste_n_akey != ''
+        exec 'nnoremap <silent>'.g:yankring_paste_n_akey." :<C-U>YRPaste 'p'<CR>"
+        if g:yankring_paste_using_g == 1
+            exec 'nnoremap <silent> g'.g:yankring_paste_n_akey." :<C-U>YRPaste 'gp'<CR>"
+        endif
+    endif
+    if g:yankring_paste_v_bkey != ''
+        exec 'xnoremap <silent>'.g:yankring_paste_v_bkey." :<C-U>YRPaste 'P', 'v'<CR>"
+    endif
+    if g:yankring_paste_v_akey != ''
+        exec 'xnoremap <silent>'.g:yankring_paste_v_akey." :<C-U>YRPaste 'p', 'v'<CR>"
+    endif
+    if g:yankring_replace_n_pkey != ''
+        exec 'nnoremap <silent>'.g:yankring_replace_n_pkey." :<C-U>YRReplace '-1', 'P'<CR>"
+    endif
+    if g:yankring_replace_n_nkey != ''
+        exec 'nnoremap <silent>'.g:yankring_replace_n_nkey." :<C-U>YRReplace '1', 'p'<CR>"
+    endif
+
+    let g:yankring_enabled    = 1
+    let s:yr_maps_created     = 1
+endfunction
+ 
+
+" Create the default maps
+function! s:YRMapsDelete(...)
+
+    let o_maps = split(g:yankring_zap_keys)
+    for key in o_maps
+        try
+            if key != '@'
+                silent! exec 'ounmap' key
+            endif
+        catch
+        endtry
+    endfor
+
+    let s:yr_maps_created_zap = 0
+
+    if a:0 > 0
+        " We have only removed the _zap_ keys temporarily
+        " so abandon further changes.
+        return
+    endif
+
+    " Iterate through a space separated list of mappings and create
+    " calls to an appropriate YankRing function
+    let n_maps = split(g:yankring_n_keys)
+    " Loop through and prompt the user for all buffer connection parameters.
+    for key in n_maps
+        try
+            silent! exec 'nunmap' key
+        catch
+        endtry
+    endfor
+
+    let o_maps = split(g:yankring_o_keys)
+    for key in o_maps
+        try
+            silent! exec 'ounmap' key
+        catch
+        endtry
+    endfor
+
+    if g:yankring_map_dot == 1
+        exec "nunmap ."
+    endif
+    if g:yankring_v_key != ''
+        exec 'vunmap '.g:yankring_v_key
+    endif
+    if g:yankring_del_v_key != ''
+        for v_map in split(g:yankring_del_v_key)
+            if strlen(v_map) > 0
+                try
+                    exec 'vunmap '.v_map
+                catch
+                endtry
+            endif
+        endfor
+    endif
+    if g:yankring_paste_n_bkey != ''
+        exec 'nunmap '.g:yankring_paste_n_bkey
+        if g:yankring_paste_using_g == 1
+            exec 'nunmap g'.g:yankring_paste_n_bkey
+        endif
+    endif
+    if g:yankring_paste_n_akey != ''
+        exec 'nunmap '.g:yankring_paste_n_akey
+        if g:yankring_paste_using_g == 1
+            exec 'nunmap g'.g:yankring_paste_n_akey
+        endif
+    endif
+    if g:yankring_paste_v_bkey != ''
+        exec 'vunmap '.g:yankring_paste_v_bkey
+    endif
+    if g:yankring_paste_v_akey != ''
+        exec 'vunmap '.g:yankring_paste_v_akey
+    endif
+    if g:yankring_replace_n_pkey != ''
+        exec 'nunmap '.g:yankring_replace_n_pkey
+    endif
+    if g:yankring_replace_n_nkey != ''
+        exec 'nunmap '.g:yankring_replace_n_nkey
+    endif
+
+    let g:yankring_enabled    = 0
+    let s:yr_maps_created     = 0
+endfunction
+
+function! s:YRGetValElemNbr( position, type )
+
+    let needed_elem = a:position
+
+    " The List which contains the items in the yankring
+    " history is also ordered, most recent at the top
+    let elem = s:YRMRUGet('s:yr_history_list', needed_elem)
+
+    if elem >= 0
+        if a:type == 't'
+            return matchstr(elem, '^.*,\zs.*$')
+        else
+            let elem = matchstr(elem, '^.*\ze,.*$')
+            if s:yr_history_version == 'v1'
+                " Match three @@@ in a row as long as it is not
+                " preceeded by a @@@            
+                " v1
+                let elem = substitute(elem, s:yr_history_v1_nl_pat, "\n", 'g')
+                let elem = substitute(elem, '\\@', '@', 'g')
+            else
+                let elem = substitute(elem, s:yr_history_v2_nl_pat, "\n", 'g')
+            endif
+            return elem
+        endif
+    else
+        return -1
+    endif
+
+    return ""
+endfunction
+
+function! s:YRMRUReset( mru_list )
+
+    let {a:mru_list} = []
+
+    return 1
+endfunction
+
+function! s:YRMRUSize( mru_list )
+    return len({a:mru_list})
+endfunction
+
+function! s:YRMRUElemFormat( element, element_type )
+    let elem    = a:element
+    if g:yankring_max_element_length != 0
+        let elem    = strpart(a:element, 0, g:yankring_max_element_length)
+    endif
+    if s:yr_history_version == 'v1'
+        let elem    = escape(elem, '@')
+        let elem    = substitute(elem, "\n", s:yr_history_v1_nl, 'g')
+    else
+        let elem    = substitute(elem, "\n", s:yr_history_v2_nl, 'g')
+    endif
+    " Append the regtype to the end so we have it available
+    let elem    = elem.",".a:element_type
+
+    return elem
+endfunction
+
+function! s:YRMRUHas( mru_list, find_str )
+    " This function will find a string and return the element #
+    let find_idx = index({a:mru_list}, a:find_str)
+
+    return find_idx
+endfunction
+
+function! s:YRMRUGet( mru_list, position )
+    " This function will return the value of the item at a:position
+    " Find the value of one element
+    let value = get({a:mru_list}, a:position, -2)
+
+    return value
+endfunction
+
+function! s:YRMRUAdd( mru_list, element, element_type )
+    " Only add new items if they do not already exist in the MRU.
+    " If the item is found, move it to the start of the MRU.
+    let found   = -1
+    " let elem    = a:element
+    " if g:yankring_max_element_length != 0
+    "     let elem    = strpart(a:element, 0, g:yankring_max_element_length)
+    " endif
+    " if s:yr_history_version == 'v1'
+    "     let elem    = escape(elem, '@')
+    "     let elem    = substitute(elem, "\n", s:yr_history_v1_nl, 'g')
+    " else
+    "     let elem    = substitute(elem, "\n", s:yr_history_v2_nl, 'g')
+    " endif
+    " " Append the regtype to the end so we have it available
+    " let elem    = elem.",".a:element_type
+
+    if strlen(a:element) < g:yankring_min_element_length
+        return 1
+    endif
+
+    let elem = s:YRMRUElemFormat(a:element, a:element_type)
+
+    " Refresh the List
+    call s:YRHistoryRead()
+
+    let found   = s:YRMRUHas(a:mru_list, elem)
+
+    " Special case for efficiency, if it is first item in the 
+    " List, do nothing
+    if found != 0
+        if found != -1
+            " Remove found item since we will add it to the top
+            call remove({a:mru_list}, found)
+        endif
+        call insert({a:mru_list}, elem, 0)
+        call s:YRHistorySave()
+    endif
+
+    return 1
+endfunction
+
+function! s:YRMRUDel( mru_list, elem_nbr )
+
+    if a:elem_nbr >= 0 && a:elem_nbr < s:yr_count 
+        call remove({a:mru_list}, a:elem_nbr)
+        call s:YRHistorySave()
+    endif
+
+    return 1
+endfunction
+
+function! s:YRHistoryRead()
+    let refresh_needed  = 1
+    let yr_history_list = []
+    let yr_filename     = s:yr_history_file_{s:yr_history_version}
+
+    if filereadable(yr_filename)
+        let last_upd = getftime(yr_filename)
+
+        if s:yr_history_last_upd != 0 && last_upd <= s:yr_history_last_upd
+            let refresh_needed = 0
+        endif
+
+        if refresh_needed == 1
+            let s:yr_history_list = readfile(yr_filename)
+            let s:yr_history_last_upd = last_upd
+            let s:yr_count = len(s:yr_history_list)
+            return
+        else
+            return
+        endif
+    else
+        if s:yr_history_version == 'v2'
+            " Check to see if an upgrade is required
+            " else, let the empty yr_history_list be returned.
+            if filereadable(s:yr_history_file_v1)
+                " Perform upgrade to v2 of the history file
+                call s:YRHistoryUpgrade('v1')
+                return
+            endif
+        endif
+    endif
+
+    let s:yr_history_list = yr_history_list
+    call s:YRHistorySave()
+
+endfunction 
+
+function! s:YRHistorySave()
+    if len(s:yr_history_list) > g:yankring_max_history
+        " Remove items which exceed the max # specified
+        call remove(s:yr_history_list, g:yankring_max_history)
+    endif
+
+    let rc = writefile(s:yr_history_list, s:yr_history_file_{s:yr_history_version})
+
+    if rc == 0
+        let s:yr_history_last_upd = getftime(s:yr_history_file_{s:yr_history_version})
+        let s:yr_count = len(s:yr_history_list)
+    else
+        call s:YRErrorMsg(
+                    \ 'YRHistorySave: Unable to save yankring history file: '.
+                    \ s:yr_history_file_{s:yr_history_version}
+                    \ )
+    endif
+endfunction 
+
+function! s:YRHistoryUpgrade(version)
+    if a:version == 'v1'
+        if filereadable(s:yr_history_file_v1)
+            let v1_list = readfile(s:yr_history_file_v1)
+            let v2_list = []
+            for elem in v1_list
+                " Restore from version 1
+                let elem = substitute(elem, s:yr_history_v1_nl_pat, "\n", 'g')
+                let elem = substitute(elem, '\\@', '@', 'g')
+                " Encode to version 2
+                let elem = substitute(elem, "\n", s:yr_history_v2_nl, 'g')
+                call add(v2_list, elem)
+            endfor
+            let s:yr_history_list = v2_list
+            call s:YRHistorySave()
+            call s:YRWarningMsg(
+                        \ "YR:History file:".
+                        \ s:yr_history_file_v1.
+                        \ ' has been upgraded.'
+                        \ )
+        endif
+    endif
+endfunction 
+
+" YRWindowUpdate
+" Checks if the yankring window is already open.
+" If it is, it will refresh it.
+function! s:YRWindowUpdate()
+    let orig_win_bufnr = bufwinnr('%')
+
+    " Switch to the yankring buffer
+    " only if it is already visible
+    if bufwinnr(s:yr_buffer_id) != -1
+        call s:YRShow(0)
+        " Switch back to the original buffer
+        exec orig_win_bufnr . "wincmd w"
+    endif
+endfunction
+
+" YRWindowStatus
+" Displays a brief command list and option settings.
+" It also will toggle the Help text.
+function! s:YRWindowStatus(show_help)
+    let full_help      = 0
+    let orig_win_bufnr = bufwinnr('%')
+    let yr_win_bufnr   = bufwinnr(s:yr_buffer_id)
+
+    if yr_win_bufnr == -1
+        " Do not update the window status since the
+        " yankring is not currently displayed.
+        return ""
+    endif
+    " Switch to the yankring buffer
+    if orig_win_bufnr != yr_win_bufnr 
+        " If the buffer is visible, switch to it
+        exec yr_win_bufnr . "wincmd w"
+    endif
+
+    let msg = 'AutoClose='.g:yankring_window_auto_close.
+                \ ';ClipboardMonitor='.g:yankring_clipboard_monitor.
+                \ ';Cmds:<enter>,[g]p,[g]P,d,r,s,a,c,u,q,<space>;Help=?'.
+                \ (s:yr_search==""?"":';SearchRegEx='.s:yr_search)
+
+    if s:yr_has_voperator == 0
+        let msg = msg . "\nYankRing has limited functionality without Vim 7.2 or higher"
+    endif
+
+    " Toggle help by checking the first line of the buffer
+    if a:show_help == 1 && getline(1) !~ 'selection'
+        let full_help = 1
+        let msg = 
+                    \ '" <enter>      : [p]aste selection'."\n".
+                    \ '" double-click : [p]aste selection'."\n".
+                    \ '" [g]p         : [g][p]aste selection'."\n".
+                    \ '" [g]P         : [g][P]aste selection'."\n".
+                    \ '" r            : [p]aste selection in reverse order'."\n".
+                    \ '" s            : [s]earch the yankring for text'."\n".
+                    \ '" u            : [u]pdate display'."\n".
+                    \ '" a            : toggle [a]utoclose setting'."\n".
+                    \ '" c            : toggle [c]lipboard monitor setting'."\n".
+                    \ '" q            : [q]uit / close the yankring window'."\n".
+                    \ '" ?            : Remove help text'."\n".
+                    \ '" <space>      : toggles the width of the window'."\n".
+                    \ '" Visual mode is supported for above commands'."\n".
+                    \ msg
+    endif 
+
+    let saveMod = &modifiable
+
+    " Go to the top of the buffer and remove any previous status
+    " Use the blackhole register so it does not affect the yankring
+    setlocal modifiable
+    exec 0
+    silent! exec 'norm! "_d/^---'."\n"
+    call histdel("search", -1)
+
+    silent! 0put =msg
+
+    " Erase it's contents to the blackhole
+    silent! exec '%g/^\s*$/delete _'
+    call histdel("search", -1)
+
+    call cursor(1,1)
+    if full_help == 0
+        call search('^\d', 'W')
+    endif
+
+    let &modifiable = saveMod
+
+    if orig_win_bufnr != s:yr_buffer_id 
+        exec orig_win_bufnr . "wincmd w"
+    endif
+endfunction
+
+" YRWindowOpen
+" Display the Most Recently Used file list in a temporary window.
+function! s:YRWindowOpen(results)
+
+    " Setup the cpoptions properly for the maps to work
+    let old_cpoptions = &cpoptions
+    set cpoptions&vim
+    setlocal cpoptions-=a,A
+
+    " Save the current buffer number. The yankring will switch back to
+    " this buffer when an action is taken.
+    let s:yr_buffer_last       = bufnr('%')
+    let s:yr_buffer_last_winnr = winnr()
+
+    if bufwinnr(s:yr_buffer_id) == -1
+        if g:yankring_window_use_horiz == 1
+            if g:yankring_window_use_bottom == 1
+                let location = 'botright'
+            else
+                let location = 'topleft'
+                " Creating the new window will offset all other
+                " window numbers.  Account for that so we switch
+                " back to the correct window.
+                let s:yr_buffer_last_winnr = s:yr_buffer_last_winnr + 1
+            endif
+            let win_size = g:yankring_window_height
+        else
+            " Open a horizontally split window. Increase the window size, if
+            " needed, to accomodate the new window
+            if g:yankring_window_width &&
+                        \ &columns < (80 + g:yankring_window_width)
+                " one extra column is needed to include the vertical split
+                let &columns             = &columns + g:yankring_window_width + 1
+                let s:yr_winsize_chgd = 1
+            else
+                let s:yr_winsize_chgd = 0
+            endif
+
+            if g:yankring_window_use_right == 1
+                " Open the window at the rightmost place
+                let location = 'botright vertical'
+            else
+                " Open the window at the leftmost place
+                let location = 'topleft vertical'
+                " Creating the new window will offset all other
+                " window numbers.  Account for that so we switch
+                " back to the correct window.
+                let s:yr_buffer_last_winnr = s:yr_buffer_last_winnr + 1
+            endif
+            let win_size = g:yankring_window_width
+        endif
+
+        " Special consideration was involved with these sequence
+        " of commands.  
+        "     First, split the current buffer.
+        "     Second, edit a new file.
+        "     Third record the buffer number.
+        " If a different sequence is followed when the yankring
+        " buffer is closed, Vim's alternate buffer is the yanking
+        " instead of the original buffer before the yankring 
+        " was shown.
+        let cmd_mod = ''
+        if v:version >= 700
+            let cmd_mod = 'keepalt '
+        endif
+        exec 'silent! ' . cmd_mod . location . ' ' . win_size . 'split ' 
+
+        " Using :e and hide prevents the alternate buffer
+        " from being changed.
+        exec ":e " . escape(s:yr_buffer_name, ' ')
+        " Save buffer id
+        let s:yr_buffer_id = bufnr('%') + 0
+    else
+        " If the buffer is visible, switch to it
+        exec bufwinnr(s:yr_buffer_id) . "wincmd w"
+    endif
+
+    " Perform a double check to ensure we have entered the correct
+    " buffer since we don't want to do the %d_ in the wrong buffer!
+    if (bufnr('%') + 0) != s:yr_buffer_id
+        call s:YRWarningMsg(
+                    \ "YR:Failed to change to the yankring buffer, please contact author id:".
+                    \ s:yr_buffer_id.
+                    \ ' last:'.s:yr_buffer_last
+                    \ )
+        return -1
+    endif
+
+    " Mark the buffer as scratch
+    setlocal buftype=nofile
+    setlocal bufhidden=hide
+    setlocal noswapfile
+    setlocal nowrap
+    setlocal nonumber
+    setlocal nobuflisted
+    setlocal noreadonly
+    setlocal modifiable
+
+    " set up syntax highlighting
+    syn match yankringTitle #^--- YankRing ---$#hs=s+4,he=e-4
+    syn match yankringHeaders #^Elem  Content$#
+    syn match yankringItemNumber #^\d\+#
+
+    syn match yankringKey #^AutoClose.*<enter>#hs=e-6
+    syn match yankringKey #^AutoClose.*\[g\]p#hs=e-3 contains=yankringKey
+    syn match yankringKey #^AutoClose.*\[p\]P#hs=e-3 contains=yankringKey
+    syn match yankringKey #^AutoClose.*,d,#hs=e-1,he=e-1 contains=yankringKey
+    syn match yankringKey #^AutoClose.*,r,#hs=e-1,he=e-1 contains=yankringKey
+    syn match yankringKey #^AutoClose.*,s,#hs=e-1,he=e-1 contains=yankringKey
+    syn match yankringKey #^AutoClose.*,a,#hs=e-1,he=e-1 contains=yankringKey
+    syn match yankringKey #^AutoClose.*,c,#hs=e-1,he=e-1 contains=yankringKey
+    syn match yankringKey #^AutoClose.*,u,#hs=e-1,he=e-1 contains=yankringKey
+    syn match yankringKey #^AutoClose.*,q,#hs=e-1,he=e-1 contains=yankringKey
+    syn match yankringKey #^AutoClose.*<space>#hs=e-6 contains=yankringKey
+    syn match yankringKey #^AutoClose.*?$#hs=e contains=yankringKey
+
+    syn match yankringKey #^".*:#hs=s+1,he=e-1
+    syn match yankringHelp #^".*$# contains=yankringKey
+
+    hi link yankringTitle directory
+    hi link yankringHeaders keyword
+    hi link yankringItemNumber constant
+    hi link yankringKey identifier
+    hi link yankringHelp string
+
+    " Clear all existing maps for this buffer
+    " We should do this for all maps, but I am not sure how to do
+    " this for this buffer/window only without affecting all the
+    " other buffers.
+    mapclear <buffer>
+    " Create a mapping to act upon the yankring
+    nnoremap <buffer> <silent> <2-LeftMouse> :call <SID>YRWindowActionN('p' ,'n')<CR>
+    nnoremap <buffer> <silent> <CR>          :call <SID>YRWindowActionN('p' ,'n')<CR>
+    xnoremap <buffer> <silent> <CR>          :call <SID>YRWindowAction ('p' ,'v')<CR>
+    nnoremap <buffer> <silent> p             :call <SID>YRWindowActionN('p' ,'n')<CR>
+    xnoremap <buffer> <silent> p             :call <SID>YRWindowAction ('p' ,'v')<CR>
+    nnoremap <buffer> <silent> P             :call <SID>YRWindowActionN('P' ,'n')<CR>
+    xnoremap <buffer> <silent> P             :call <SID>YRWindowAction ('P' ,'v')<CR>
+    nnoremap <buffer> <silent> gp            :call <SID>YRWindowActionN('gp','n')<CR>
+    xnoremap <buffer> <silent> gp            :call <SID>YRWindowAction ('gp','v')<CR>
+    nnoremap <buffer> <silent> gP            :call <SID>YRWindowActionN('gP','n')<CR>
+    xnoremap <buffer> <silent> gP            :call <SID>YRWindowAction ('gP','v')<CR>
+    nnoremap <buffer> <silent> d             :call <SID>YRWindowActionN('d' ,'n')<CR>
+    xnoremap <buffer> <silent> d             :call <SID>YRWindowAction ('d' ,'v')<CR>
+    xnoremap <buffer> <silent> r             :call <SID>YRWindowAction ('r' ,'v')<CR>
+    nnoremap <buffer> <silent> s             :call <SID>YRWindowAction ('s' ,'n')<CR>
+    nnoremap <buffer> <silent> a             :call <SID>YRWindowAction ('a' ,'n')<CR>
+    nnoremap <buffer> <silent> c             :call <SID>YRWindowAction ('c' ,'n')<CR>
+    nnoremap <buffer> <silent> ?             :call <SID>YRWindowAction ('?' ,'n')<CR>
+    nnoremap <buffer> <silent> u             :call <SID>YRWindowAction ('u' ,'n')<CR>
+    nnoremap <buffer> <silent> q             :call <SID>YRWindowAction ('q' ,'n')<CR>
+    nnoremap <buffer> <silent> <space>     \|:silent exec 'vertical resize '.
+                \ (
+                \ g:yankring_window_use_horiz!=1 && winwidth('.') > g:yankring_window_width
+                \ ?(g:yankring_window_width)
+                \ :(winwidth('.') + g:yankring_window_increment)
+                \ )<CR>
+
+    " Erase it's contents to the blackhole
+    silent! exec '%delete _'
+
+    " Display the status line / help 
+    call s:YRWindowStatus(0)
+    exec 'normal! G'
+
+    " Display the contents of the yankring
+    silent! put =a:results
+
+    if getline('$') == ''
+        " Erase last blank line
+        silent! exec '$delete _'
+    endif
+
+    " Move the cursor to the first line with an element
+    exec 0
+    call search('^\d','W') 
+
+    setlocal nomodifiable
+    "
+    " Restore the previous cpoptions settings
+    let &cpoptions = old_cpoptions
+
+endfunction
+
+function! s:YRWindowActionN(op, cmd_mode) 
+    let v_count    = v:count
+    " If no count was specified it will have a value of 0
+    " so set it to at least 1
+    let v_count = ((v_count > 0)?(v_count):1)
+
+    if v_count > 1
+        if !exists("b:yankring_show_range_error")
+            let b:yankring_show_range_error = v_count
+        else
+            let b:yankring_show_range_error = b:yankring_show_range_error - 1
+        endif
+
+        if b:yankring_show_range_error == 1
+            call s:YRWarningMsg("YR:Use visual mode if you need to specify a count")
+            unlet b:yankring_show_range_error
+        endif
+        return
+    endif
+    
+    call s:YRWindowAction(a:op, a:cmd_mode)
+    let v_count = v_count - 1
+
+    if g:yankring_window_auto_close == 1 && v_count == 0 && a:op != 'd'
+        " If autoclose is set close the window unless 
+        " you are removing items from the YankRing
+        exec 'bdelete '.s:yr_buffer_id
+        return "" 
+    endif
+
+    return "" 
+endfunction
+
+function! s:YRWindowAction(op, cmd_mode) range
+    let default_buffer = ((&clipboard=='unnamed')?'+':'"')
+    let opcode     = a:op
+    let lines      = []
+    let v_count    = v:count
+    let cmd_mode   = a:cmd_mode
+    let firstline  = a:firstline
+    let lastline   = a:lastline
+
+    if a:lastline < a:firstline
+        let firstline = a:lastline
+        let lastline  = a:firstline
+    endif
+
+    if cmd_mode == 'n'
+        let v_count = 1
+        " If a count was provided (5p), we want to repeat the paste
+        " 5 times, but this also alters the a:firstline and a:lastline
+        " ranges, which while in normal mode we do not want
+        let lastline = firstline
+    endif
+    " If no count was specified it will have a value of 0
+    " so set it to at least 1
+    let v_count = ((v_count > 0)?(v_count):1)
+
+    if '[dr]' =~ opcode 
+        " Reverse the order of the lines to act on
+        let begin = lastline
+        while begin >= firstline 
+            call add(lines, getline(begin))
+            let begin = begin - 1
+        endwhile
+    else
+        " Process the selected items in order
+        let begin = firstline
+        while begin <= lastline 
+            call add(lines, getline(begin))
+            let begin = begin + 1
+        endwhile
+    endif
+
+    if opcode ==# 'q'
+        " Close the yankring window
+        if s:yr_winsize_chgd == 1
+            " Adjust the Vim window width back to the width
+            " it was before we showed the yankring window
+            let &columns= &columns - (g:yankring_window_width)
+        endif
+
+        " Hide the YankRing window
+        hide
+
+        if bufwinnr(s:yr_buffer_last) != -1
+            " If the buffer is visible, switch to it
+            exec s:yr_buffer_last_winnr . "wincmd w"
+        endif
+
+        return
+    elseif opcode ==# 's'
+        " Switch back to the original buffer
+        exec s:yr_buffer_last_winnr . "wincmd w"
+    
+        call s:YRSearch()
+        return
+    elseif opcode ==# 'u'
+        " Switch back to the original buffer
+        exec s:yr_buffer_last_winnr . "wincmd w"
+    
+        call s:YRShow(0)
+        return
+    elseif opcode ==# 'a'
+        let l:curr_line = line(".")
+        " Toggle the auto close setting
+        let g:yankring_window_auto_close = 
+                    \ (g:yankring_window_auto_close == 1?0:1)
+        " Display the status line / help 
+        call s:YRWindowStatus(0)
+        call cursor(l:curr_line,0)
+        return
+    elseif opcode ==# 'c'
+        let l:curr_line = line(".")
+        " Toggle the clipboard monitor setting
+        let g:yankring_clipboard_monitor = 
+                    \ (g:yankring_clipboard_monitor == 1?0:1)
+        " Display the status line / help 
+        call s:YRWindowStatus(0)
+        call cursor(l:curr_line,0)
+        return
+    elseif opcode ==# '?'
+        " Display the status line / help 
+        call s:YRWindowStatus(1)
+        return
+    endif
+
+    " Switch back to the original buffer
+    exec s:yr_buffer_last_winnr . "wincmd w"
+    
+    " Intentional case insensitive comparision
+    if opcode =~? 'p'
+        let cmd   = 'YRGetElem '
+        let parms = ", '".opcode."' "
+    elseif opcode ==? 'r'
+        let opcode = 'p'
+        let cmd    = 'YRGetElem '
+        let parms  = ", 'p' "
+    elseif opcode ==# 'd'
+        let cmd   = 'YRPop '
+        let parms = ""
+    endif
+
+    " Only execute this code if we are operating on elements
+    " within the yankring
+    if '[auq?]' !~# opcode 
+        while v_count > 0
+            " let iter  = 0
+            " let index = 0
+            for line in lines
+                let elem = matchstr(line, '^\d\+')
+                if elem > 0
+                    if elem > 0 && elem <= s:yr_count
+                        " if iter > 0 && opcode =~# 'p'
+                        if opcode =~# 'p'
+                            " Move to the end of the last pasted item
+                            " only if pasting after (not above)
+                            " ']
+                        endif
+                        exec cmd . elem . parms
+                        " let iter += 1
+                    endif
+                endif
+            endfor
+            let v_count = v_count - 1
+        endwhile
+
+        if opcode ==# 'd'
+            call s:YRShow(0)
+            return ""
+        endif
+
+        if g:yankring_window_auto_close == 1 && cmd_mode == 'v'
+            exec 'bdelete '.s:yr_buffer_id
+            return "" 
+        endif
+
+    endif
+
+    return "" 
+
+endfunction
+      
+function! s:YRWarningMsg(msg)
+    echohl WarningMsg
+    echomsg a:msg 
+    echohl None
+endfunction
+      
+function! s:YRErrorMsg(msg)
+    echohl ErrorMsg
+    echomsg a:msg 
+    echohl None
+endfunction
+      
+function! s:YRWinLeave()
+    " Track which window we are last in.  We will use this information
+    " to determine where we need to paste any contents, or which 
+    " buffer to return to.
+    
+    if s:yr_buffer_id < 0
+        " The yankring window has never been activated
+        return
+    endif
+
+    if winbufnr(winnr()) == s:yr_buffer_id
+        " Ignore leaving the yankring window
+        return
+    endif
+
+    if bufwinnr(s:yr_buffer_id) != -1
+        " YankRing window is visible, so save off the previous buffer ids
+        let s:yr_buffer_last_winnr = winnr()
+        let s:yr_buffer_last       = winbufnr(s:yr_buffer_last_winnr)
+    " else
+    "     let s:yr_buffer_last_winnr = -1
+    "     let s:yr_buffer_last       = -1
+    endif
+endfunction
+      
+function! s:YRFocusGained()
+    if g:yankring_clipboard_monitor == 1
+        " If the clipboard has changed record it inside the yankring
+        " echomsg "YRFocusGained[".len(@+)."][".@+.']['.s:yr_prev_clipboard.']'
+        if len(@+) > 0 && @+ != s:yr_prev_clipboard
+            let elem    = s:YRMRUElemFormat( 
+                        \   getreg('+')
+                        \ , getregtype('+') 
+                        \ )
+            let found   = s:YRMRUHas('s:yr_history_list', elem)
+
+            " Only add the item to the "top" of the ring if it is
+            " not in the ring already.
+            if found == -1
+                call YRRecord("+")
+                " silent! call YRRecord("+")
+            endif
+        endif
+
+        " If the yankring window is open, refresh it
+        call s:YRWindowUpdate()
+    endif
+endfunction
+
+function! s:YRInsertLeave()
+    " The YankRing uses omaps to execute the prescribed motion
+    " and then appends to the motion a call to a YankRing 
+    " function to record the contents of the changed register.
+    "
+    " We cannot append a function call to the end of a motion
+    " that results in Insert mode.  For example, any command
+    " like 'cw' enters insert mode.  Appending a function call
+    " after the w, simply writes out the call as if the user 
+    " typed it.
+    "
+    " Using the InsertLeave event, allows us to capture the 
+    " contents of any changed register after it completes.
+    
+    call YRRecord(s:YRRegister())
+
+    " When performing a change (not a yank or delete)
+    " it is not possible to call <SID>yrrecord at the end
+    " of the command (or it's contents will be inserted 
+    " into the buffer instead of executed).
+    " So, when using ".", we have to remove the _zap_
+    " keys and then re-add them back again after we 
+    " record the updates.
+    if s:yr_remove_omap_dot == 1
+        call s:YRMapsCreate('add_only_zap_keys')
+    endif
+
+endfunction
+      
+" Deleting autocommands first is a good idea especially if we want to reload
+" the script without restarting vim.
+" Call YRFocusGained to check if the clipboard has been updated
+augroup YankRing
+    autocmd!
+    autocmd VimEnter    * :if has('clipboard') | call <SID>YRFocusGained() | endif
+    autocmd WinLeave    * :call <SID>YRWinLeave()
+    autocmd FocusGained * :if has('clipboard') | call <SID>YRFocusGained() | endif
+    autocmd InsertLeave * :call <SID>YRInsertLeave()
+augroup END
+
+
+" copy register
+inoremap <script> <SID>YRGetChar <c-r>=YRGetChar()<CR>
+" inoremap <script> <SID>YRGetSearch <c-r>=YRGetSearch()<CR>
+nnoremap <silent> <SID>yrrecord :call YRRecord3()<cr>
+inoremap <silent> <SID>yrrecord <C-R>=YRRecord3()<cr>
+
+
+" Public commands
+command!                           YRClear        call s:YRClear()
+command!                  -nargs=0 YRMapsCreate   call s:YRMapsCreate()
+command!                  -nargs=0 YRMapsDelete   call s:YRMapsDelete()
+command! -range -bang     -nargs=? YRDeleteRange  <line1>,<line2>call s:YRYankRange(<bang>1, <args>)
+command!                  -nargs=* YRGetElem      call s:YRGetElem(<args>)
+command!        -bang     -nargs=? YRGetMultiple  call s:YRGetMultiple(<bang>0, <args>)
+command! -count -register -nargs=* YRPaste        call s:YRPaste(0,1,<args>)
+command!                  -nargs=? YRPop          <line1>,<line2>call s:YRPop(<args>)
+command!        -register -nargs=? YRPush         call s:YRPush(<args>)
+command! -count -register -nargs=* YRReplace      call s:YRPaste(1,<args>)
+command!                  -nargs=? YRSearch       call s:YRSearch(<q-args>)
+command!                  -nargs=? YRShow         call s:YRShow(<args>)
+command!                  -nargs=? YRToggle       call s:YRToggle(<args>)
+command! -count -register -nargs=* YRYankCount    call s:YRYankCount(<args>)
+command! -range -bang     -nargs=? YRYankRange    <line1>,<line2>call s:YRYankRange(<bang>0, <args>)
+" command! -range -bang     -nargs=0 YRMapsMacro    <line1>,<line2>call s:YRMapsMacro(<bang>0, <args>)
+
+" Menus 
+if has("gui_running") && has("menu") && g:yankring_default_menu_mode != 0
+    if g:yankring_default_menu_mode == 1
+        let menuRoot = 'YankRing'
+    elseif g:yankring_default_menu_mode == 2
+        let menuRoot = '&YankRing'
+    else
+        let menuRoot = '&Plugin.&YankRing'
+    endif
+
+    exec 'noremenu  <script> '.menuRoot.'.YankRing\ Window  :YRShow<CR>'
+    exec 'noremenu  <script> '.menuRoot.'.YankRing\ Search  :YRSearch<CR>'
+    exec 'noremenu  <script> '.menuRoot.'.Replace\ with\ Previous  :YRReplace ''-1'', ''P''<CR>'
+    exec 'noremenu  <script> '.menuRoot.'.Replace\ with\ Next  :YRReplace ''1'', ''P''<CR>'
+    exec 'noremenu  <script> '.menuRoot.'.Clear  :YRClear<CR>'
+    exec 'noremenu  <script> '.menuRoot.'.Toggle :YRToggle<CR>'
+endif
+
+if g:yankring_enabled == 1
+    " Create YankRing Maps
+    call s:YRMapsCreate()
+endif
+
+if exists('*YRRunAfterMaps') 
+    " This will allow you to override the default maps if necessary
+    call YRRunAfterMaps()
+endif
+
+call s:YRInit()
+call s:YRHistoryRead()
+
+" vim:fdm=marker:nowrap:ts=4:expandtab: