updated for version 7.0001
diff --git a/runtime/macros/README.txt b/runtime/macros/README.txt
new file mode 100644
index 0000000..61066c5
--- /dev/null
+++ b/runtime/macros/README.txt
@@ -0,0 +1,22 @@
+The macros in the maze, hanoi and urm directories can be used to test Vim for
+vi compatibility. They have been written for vi to show its unlimited
+possibilities. The life macros can be used for performance comparisons.
+
+hanoi Macros that solve the tower of hanoi problem.
+life Macros that run Conway's game of life.
+maze Macros that solve a maze (amazing!).
+urm Macros that simulate a simple computer: "Universal Register Machine"
+
+
+The other files contain some handy utilities. They also serve as examples for
+how to use Vi and Vim functionality.
+
+dvorak for when you use a Dvorak keyboard
+justify.vim user function for justifying text
+matchit.vim + matchit.txt make % match if-fi, HTML tags, and much more
+less.sh + less.vim make Vim work like less (or more)
+shellmenu.vim menus for editing shell scripts in the GUI version
+swapmous.vim swap left and right mouse buttons
+
+This one is only for Unix. It can be found in the extra archive:
+file_select.vim macros that make a handy file selector
diff --git a/runtime/macros/README.txt.info b/runtime/macros/README.txt.info
new file mode 100644
index 0000000..d173e72
--- /dev/null
+++ b/runtime/macros/README.txt.info
Binary files differ
diff --git a/runtime/macros/dvorak b/runtime/macros/dvorak
new file mode 100644
index 0000000..0c75888
--- /dev/null
+++ b/runtime/macros/dvorak
@@ -0,0 +1,164 @@
+When using a dvorak keyboard this file may be of help to you.
+These mappings have been made by Lawrence Kesteloot <kesteloo@cs.unc.edu>.
+What they do is that the most often used keys, like hjkl, are put in a more
+easy to use position.
+It may take some time to learn using this.
+
+Put these lines in your .vimrc:
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+" Key to go into dvorak mode:
+map ,d :source ~/.dvorak
+" Key to get out of dvorak mode:
+map ,q :source ~/.qwerty
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+write these lines into the file ~/.dvorak:
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+" Dvorak keyboard, only in insert mode and ex mode.
+" You may want to add a list of map's too.
+imap! a a
+imap! b x
+imap! c j
+imap! d e
+imap! e .
+imap! f u
+imap! g i
+imap! h d
+imap! i c
+imap! j h
+imap! k t
+imap! l n
+imap! m m
+imap! n b
+imap! o r
+imap! p l
+imap! q '
+imap! r p
+imap! s o
+imap! t y
+imap! u g
+imap! v k
+imap! w ,
+imap! x q
+imap! y f
+imap! z ;
+imap! ; s
+imap! ' -
+imap! " _
+imap! , w
+imap! . v
+imap! / z
+imap! A A
+imap! B X
+imap! C J
+imap! D E
+imap! E >
+imap! F U
+imap! G I
+imap! H D
+imap! I C
+imap! J H
+imap! K T
+imap! L N
+imap! M M
+imap! N B
+imap! O R
+imap! P L
+imap! Q "
+imap! R P
+imap! S O
+imap! T Y
+imap! U G
+imap! V K
+imap! W <
+imap! X Q
+imap! Y F
+imap! Z :
+imap! < W
+imap! > V
+imap! ? Z
+imap! : S
+imap! [ /
+imap! ] =
+imap! { ?
+imap! } +
+imap! - [
+imap! _ {
+imap! = ]
+imap! + }
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+write these lines into the file ~/.qwerty
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+" Qwerty keyboard
+unmap! a
+unmap! b
+unmap! c
+unmap! d
+unmap! e
+unmap! f
+unmap! g
+unmap! h
+unmap! i
+unmap! j
+unmap! k
+unmap! l
+unmap! m
+unmap! n
+unmap! o
+unmap! p
+unmap! q
+unmap! r
+unmap! s
+unmap! t
+unmap! u
+unmap! v
+unmap! w
+unmap! x
+unmap! y
+unmap! z
+unmap! ;
+unmap! '
+unmap! \"
+unmap! ,
+unmap! .
+unmap! /
+unmap! A
+unmap! B
+unmap! C
+unmap! D
+unmap! E
+unmap! F
+unmap! G
+unmap! H
+unmap! I
+unmap! J
+unmap! K
+unmap! L
+unmap! M
+unmap! N
+unmap! O
+unmap! P
+unmap! Q
+unmap! R
+unmap! S
+unmap! T
+unmap! U
+unmap! V
+unmap! W
+unmap! X
+unmap! Y
+unmap! Z
+unmap! <
+unmap! >
+unmap! ?
+unmap! :
+unmap! [
+unmap! ]
+unmap! {
+unmap! }
+unmap! -
+unmap! _
+unmap! =
+unmap! +
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
diff --git a/runtime/macros/hanoi.info b/runtime/macros/hanoi.info
new file mode 100644
index 0000000..8072e56
--- /dev/null
+++ b/runtime/macros/hanoi.info
Binary files differ
diff --git a/runtime/macros/hanoi/click.me b/runtime/macros/hanoi/click.me
new file mode 100644
index 0000000..24f178b
--- /dev/null
+++ b/runtime/macros/hanoi/click.me
@@ -0,0 +1,14 @@
+
+
+See Vim solve the towers of Hanoi!
+
+Instructions:
+ type ":so hanoi.vim<RETURN>" to load the macros
+ type "g" to start it
+
+and watch it go.
+
+ to quit type ":q!<RETURN>"
+to interrupt type CTRL-C
+
+(This text will disappear as soon as you type "g")
diff --git a/runtime/macros/hanoi/click.me.info b/runtime/macros/hanoi/click.me.info
new file mode 100644
index 0000000..f38cb5a
--- /dev/null
+++ b/runtime/macros/hanoi/click.me.info
Binary files differ
diff --git a/runtime/macros/hanoi/hanoi.vim b/runtime/macros/hanoi/hanoi.vim
new file mode 100644
index 0000000..834d6f2
--- /dev/null
+++ b/runtime/macros/hanoi/hanoi.vim
Binary files differ
diff --git a/runtime/macros/hanoi/poster b/runtime/macros/hanoi/poster
new file mode 100644
index 0000000..dd03b26
--- /dev/null
+++ b/runtime/macros/hanoi/poster
@@ -0,0 +1,36 @@
+Article 2913 of alt.sources:
+Path: oce-rd1!hp4nl!mcsun!uunet!munnari.oz.au!metro!cluster!swift!softway!otc!gregm
+From: gregm@otc.otca.oz.au (Greg McFarlane)
+Newsgroups: comp.sources.d,alt.sources,comp.editors
+Subject: VI SOLVES HANOI
+Message-ID: <2323@otc.otca.oz>
+Date: 19 Feb 91 01:32:14 GMT
+Sender: news@otc.otca.oz
+Reply-To: gregm@otc.otca.oz.au (Greg McFarlane)
+Organization: OTC Development Unit, Australia
+Lines: 80
+Xref: oce-rd1 comp.sources.d:5702 alt.sources:2913 comp.editors:2313
+
+Submitted-by: gregm@otc.otca.oz.au
+Archive-name: hanoi.vi.macros/part01
+
+Everyone seems to be writing stupid Tower of Hanoi programs.
+Well, here is the stupidest of them all: the hanoi solving vi macros.
+
+Save this article, unshar it, and run uudecode on hanoi.vi.macros.uu.
+This will give you the macro file hanoi.vi.macros.
+Then run vi (with no file: just type "vi") and type:
+ :so hanoi.vi.macros
+ g
+and watch it go.
+
+The default height of the tower is 7 but can be easily changed by editing
+the macro file.
+
+The disks aren't actually shown in this version, only numbers representing
+each disk, but I believe it is possible to write some macros to show the
+disks moving about as well. Any takers?
+
+(For maze solving macros, see alt.sources or comp.editors)
+
+Greg
diff --git a/runtime/macros/hanoi/poster.info b/runtime/macros/hanoi/poster.info
new file mode 100644
index 0000000..780fa35
--- /dev/null
+++ b/runtime/macros/hanoi/poster.info
Binary files differ
diff --git a/runtime/macros/justify.vim b/runtime/macros/justify.vim
new file mode 100644
index 0000000..41d0591
--- /dev/null
+++ b/runtime/macros/justify.vim
@@ -0,0 +1,316 @@
+" Function to left and rigt align text.
+"
+" Written by: Preben "Peppe" Guldberg <c928400@student.dtu.dk>
+" Created: 980806 14:13 (or around that time anyway)
+" Revised: 001103 00:36 (See "Revisions" below)
+
+
+" function Justify( [ textwidth [, maxspaces [, indent] ] ] )
+"
+" Justify() will left and right align a line by filling in an
+" appropriate amount of spaces. Extra spaces are added to existing
+" spaces starting from the right side of the line. As an example, the
+" following documentation has been justified.
+"
+" The function takes the following arguments:
+
+" textwidth argument
+" ------------------
+" If not specified, the value of the 'textwidth' option is used. If
+" 'textwidth' is zero a value of 80 is used.
+"
+" Additionally the arguments 'tw' and '' are accepted. The value of
+" 'textwidth' will be used. These are handy, if you just want to specify
+" the maxspaces argument.
+
+" maxspaces argument
+" ------------------
+" If specified, alignment will only be done, if the longest space run
+" after alignment is no longer than maxspaces.
+"
+" An argument of '' is accepted, should the user like to specify all
+" arguments.
+"
+" To aid user defined commands, negative values are accepted aswell.
+" Using a negative value specifies the default behaviour: any length of
+" space runs will be used to justify the text.
+
+" indent argument
+" ---------------
+" This argument specifies how a line should be indented. The default is
+" to keep the current indentation.
+"
+" Negative values: Keep current amount of leading whitespace.
+" Positive values: Indent all lines with leading whitespace using this
+" amount of whitespace.
+"
+" Note that the value 0, needs to be quoted as a string. This value
+" leads to a left flushed text.
+"
+" Additionally units of 'shiftwidth'/'sw' and 'tabstop'/'ts' may be
+" added. In this case, if the value of indent is positive, the amount of
+" whitespace to be added will be multiplied by the value of the
+" 'shiftwidth' and 'tabstop' settings. If these units are used, the
+" argument must be given as a string, eg. Justify('','','2sw').
+"
+" If the values of 'sw' or 'tw' are negative, they are treated as if
+" they were 0, which means that the text is flushed left. There is no
+" check if a negative number prefix is used to change the sign of a
+" negative 'sw' or 'ts' value.
+"
+" As with the other arguments, '' may be used to get the default
+" behaviour.
+
+
+" Notes:
+"
+" If the line, adjusted for space runs and leading/trailing whitespace,
+" is wider than the used textwidth, the line will be left untouched (no
+" whitespace removed). This should be equivalent to the behaviour of
+" :left, :right and :center.
+"
+" If the resulting line is shorter than the used textwidth it is left
+" untouched.
+"
+" All space runs in the line are truncated before the alignment is
+" carried out.
+"
+" If you have set 'noexpandtab', :retab! is used to replace space runs
+" with whitespace using the value of 'tabstop'. This should be
+" conformant with :left, :right and :center.
+"
+" If joinspaces is set, an extra space is added after '.', '?' and '!'.
+" If 'cpooptions' include 'j', extra space is only added after '.'.
+" (This may on occasion conflict with maxspaces.)
+
+
+" Related mappings:
+"
+" Mappings that will align text using the current text width, using at
+" most four spaces in a space run and keeping current indentation.
+nmap _j :%call Justify('tw',4)<CR>
+vmap _j :call Justify('tw',4)<CR>
+"
+" Mappings that will remove space runs and format lines (might be useful
+" prior to aligning the text).
+nmap ,gq :%s/\s\+/ /g<CR>gq1G
+vmap ,gq :s/\s\+/ /g<CR>gvgq
+
+
+" User defined command:
+"
+" The following is an ex command that works as a shortcut to the Justify
+" function. Arguments to Justify() can be added after the command.
+com! -range -nargs=* Justify <line1>,<line2>call Justify(<f-args>)
+"
+" The following commands are all equivalent:
+"
+" 1. Simplest use of Justify():
+" :call Justify()
+" :Justify
+"
+" 2. The _j mapping above via the ex command:
+" :%Justify tw 4
+"
+" 3. Justify visualised text at 72nd column while indenting all
+" previously indented text two shiftwidths
+" :'<,'>call Justify(72,'','2sw')
+" :'<,'>Justify 72 -1 2sw
+"
+" This documentation has been justified using the following command:
+":se et|kz|1;/^" function Justify(/+,'z-g/^" /s/^" //|call Justify(70,3)|s/^/" /
+
+" Revisions:
+" 001103: If 'joinspaces' was set, calculations could be wrong.
+" Tabs at start of line could also lead to errors.
+" Use setline() instead of "exec 's/foo/bar/' - safer.
+" Cleaned up the code a bit.
+"
+" Todo: Convert maps to the new script specific form
+
+" Error function
+function! Justify_error(message)
+ echohl Error
+ echo "Justify([tw, [maxspaces [, indent]]]): " . a:message
+ echohl None
+endfunction
+
+
+" Now for the real thing
+function! Justify(...) range
+
+ if a:0 > 3
+ call Justify_error("Too many arguments (max 3)")
+ return 1
+ endif
+
+ " Set textwidth (accept 'tw' and '' as arguments)
+ if a:0 >= 1
+ if a:1 =~ '^\(tw\)\=$'
+ let tw = &tw
+ elseif a:1 =~ '^\d\+$'
+ let tw = a:1
+ else
+ call Justify_error("tw must be a number (>0), '' or 'tw'")
+ return 2
+ endif
+ else
+ let tw = &tw
+ endif
+ if tw == 0
+ let tw = 80
+ endif
+
+ " Set maximum number of spaces between WORDs
+ if a:0 >= 2
+ if a:2 == ''
+ let maxspaces = tw
+ elseif a:2 =~ '^-\d\+$'
+ let maxspaces = tw
+ elseif a:2 =~ '^\d\+$'
+ let maxspaces = a:2
+ else
+ call Justify_error("maxspaces must be a number or ''")
+ return 3
+ endif
+ else
+ let maxspaces = tw
+ endif
+ if maxspaces <= 1
+ call Justify_error("maxspaces should be larger than 1")
+ return 4
+ endif
+
+ " Set the indentation style (accept sw and ts units)
+ let indent_fix = ''
+ if a:0 >= 3
+ if (a:3 == '') || a:3 =~ '^-[1-9]\d*\(shiftwidth\|sw\|tabstop\|ts\)\=$'
+ let indent = -1
+ elseif a:3 =~ '^-\=0\(shiftwidth\|sw\|tabstop\|ts\)\=$'
+ let indent = 0
+ elseif a:3 =~ '^\d\+\(shiftwidth\|sw\|tabstop\|ts\)\=$'
+ let indent = substitute(a:3, '\D', '', 'g')
+ elseif a:3 =~ '^\(shiftwidth\|sw\|tabstop\|ts\)$'
+ let indent = 1
+ else
+ call Justify_error("indent: a number with 'sw'/'ts' unit")
+ return 5
+ endif
+ if indent >= 0
+ while indent > 0
+ let indent_fix = indent_fix . ' '
+ let indent = indent - 1
+ endwhile
+ let indent_sw = 0
+ if a:3 =~ '\(shiftwidth\|sw\)'
+ let indent_sw = &sw
+ elseif a:3 =~ '\(tabstop\|ts\)'
+ let indent_sw = &ts
+ endif
+ let indent_fix2 = ''
+ while indent_sw > 0
+ let indent_fix2 = indent_fix2 . indent_fix
+ let indent_sw = indent_sw - 1
+ endwhile
+ let indent_fix = indent_fix2
+ endif
+ else
+ let indent = -1
+ endif
+
+ " Avoid substitution reports
+ let save_report = &report
+ set report=1000000
+
+ " Check 'joinspaces' and 'cpo'
+ if &js == 1
+ if &cpo =~ 'j'
+ let join_str = '\(\. \)'
+ else
+ let join_str = '\([.!?!] \)'
+ endif
+ endif
+
+ let cur = a:firstline
+ while cur <= a:lastline
+
+ let str_orig = getline(cur)
+ let save_et = &et
+ set et
+ exec cur . "retab"
+ let &et = save_et
+ let str = getline(cur)
+
+ let indent_str = indent_fix
+ let indent_n = strlen(indent_str)
+ " Shall we remember the current indentation
+ if indent < 0
+ let indent_orig = matchstr(str_orig, '^\s*')
+ if strlen(indent_orig) > 0
+ let indent_str = indent_orig
+ let indent_n = strlen(matchstr(str, '^\s*'))
+ endif
+ endif
+
+ " Trim trailing, leading and running whitespace
+ let str = substitute(str, '\s\+$', '', '')
+ let str = substitute(str, '^\s\+', '', '')
+ let str = substitute(str, '\s\+', ' ', 'g')
+ let str_n = strlen(str)
+
+ " Possible addition of space after punctuation
+ if exists("join_str")
+ let str = substitute(str, join_str, '\1 ', 'g')
+ endif
+ let join_n = strlen(str) - str_n
+
+ " Can extraspaces be added?
+ " Note that str_n may be less than strlen(str) [joinspaces above]
+ if strlen(str) < tw - indent_n && str_n > 0
+ " How many spaces should be added
+ let s_add = tw - str_n - indent_n - join_n
+ let s_nr = strlen(substitute(str, '\S', '', 'g') ) - join_n
+ let s_dup = s_add / s_nr
+ let s_mod = s_add % s_nr
+
+ " Test if the changed line fits with tw
+ if 0 <= (str_n + (maxspaces - 1)*s_nr + indent_n) - tw
+
+ " Duplicate spaces
+ while s_dup > 0
+ let str = substitute(str, '\( \+\)', ' \1', 'g')
+ let s_dup = s_dup - 1
+ endwhile
+
+ " Add extra spaces from the end
+ while s_mod > 0
+ let str = substitute(str, '\(\(\s\+\S\+\)\{' . s_mod . '}\)$', ' \1', '')
+ let s_mod = s_mod - 1
+ endwhile
+
+ " Indent the line
+ if indent_n > 0
+ let str = substitute(str, '^', indent_str, '' )
+ endif
+
+ " Replace the line
+ call setline(cur, str)
+
+ " Convert to whitespace
+ if &et == 0
+ exec cur . 'retab!'
+ endif
+
+ endif " Change of line
+ endif " Possible change
+
+ let cur = cur + 1
+ endwhile
+
+ norm ^
+
+ let &report = save_report
+
+endfunction
+
+" EOF vim: tw=78 ts=8 sw=4 sts=4 noet ai
diff --git a/runtime/macros/less.sh b/runtime/macros/less.sh
new file mode 100755
index 0000000..256936b
--- /dev/null
+++ b/runtime/macros/less.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+# Shell script to start Vim with less.vim.
+# Read stdin if no arguments were given.
+
+if test $# = 0; then
+ vim --cmd 'let no_plugin_maps = 1' -c 'runtime! macros/less.vim' -
+else
+ vim --cmd 'let no_plugin_maps = 1' -c 'runtime! macros/less.vim' "$@"
+fi
diff --git a/runtime/macros/less.vim b/runtime/macros/less.vim
new file mode 100644
index 0000000..48ee7ab
--- /dev/null
+++ b/runtime/macros/less.vim
@@ -0,0 +1,244 @@
+" Vim script to work like "less"
+" Maintainer: Bram Moolenaar <Bram@vim.org>
+" Last Change: 2004 Feb 19
+
+" Avoid loading this file twice, allow the user to define his own script.
+if exists("loaded_less")
+ finish
+endif
+let loaded_less = 1
+
+" If not reading from stdin, skip files that can't be read.
+" Exit if there is no file at all.
+if argc() > 0
+ let s:i = 0
+ while 1
+ if filereadable(argv(s:i))
+ if s:i != 0
+ sleep 3
+ endif
+ break
+ endif
+ if isdirectory(argv(s:i))
+ echomsg "Skipping directory " . argv(s:i)
+ elseif getftime(argv(s:i)) < 0
+ echomsg "Skipping non-existing file " . argv(s:i)
+ else
+ echomsg "Skipping unreadable file " . argv(s:i)
+ endif
+ echo "\n"
+ let s:i = s:i + 1
+ if s:i == argc()
+ quit
+ endif
+ next
+ endwhile
+endif
+
+set nocp
+syntax on
+set so=0
+set hlsearch
+set incsearch
+nohlsearch
+" Don't remember file names and positions
+set viminfo=
+set nows
+" Inhibit screen updates while searching
+let s:lz = &lz
+set lz
+
+" Used after each command: put cursor at end and display position
+if &wrap
+ noremap <SID>L L0:redraw<CR>:file<CR>
+ au VimEnter * normal! L0
+else
+ noremap <SID>L Lg0:redraw<CR>:file<CR>
+ au VimEnter * normal! Lg0
+endif
+
+" When reading from stdin don't consider the file modified.
+au VimEnter * set nomod
+
+" Can't modify the text
+set noma
+
+" Give help
+noremap h :call <SID>Help()<CR>
+map H h
+fun! s:Help()
+ echo "<Space> One page forward b One page backward"
+ echo "d Half a page forward u Half a page backward"
+ echo "<Enter> One line forward k One line backward"
+ echo "G End of file g Start of file"
+ echo "N% percentage in file"
+ echo "\n"
+ echo "/pattern Search for pattern ?pattern Search backward for pattern"
+ echo "n next pattern match N Previous pattern match"
+ echo "\n"
+ echo ":n<Enter> Next file :p<Enter> Previous file"
+ echo "\n"
+ echo "q Quit v Edit file"
+ let i = input("Hit Enter to continue")
+endfun
+
+" Scroll one page forward
+noremap <script> <Space> :call <SID>NextPage()<CR><SID>L
+map <C-V> <Space>
+map f <Space>
+map <C-F> <Space>
+map z <Space>
+map <Esc><Space> <Space>
+fun! s:NextPage()
+ if line(".") == line("$")
+ if argidx() + 1 >= argc()
+ quit
+ endif
+ next
+ 1
+ else
+ exe "normal! \<C-F>"
+ endif
+endfun
+
+" Re-read file and page forward "tail -f"
+map F :e<CR>G<SID>L:sleep 1<CR>F
+
+" Scroll half a page forward
+noremap <script> d <C-D><SID>L
+map <C-D> d
+
+" Scroll one line forward
+noremap <script> <CR> <C-E><SID>L
+map <C-N> <CR>
+map e <CR>
+map <C-E> <CR>
+map j <CR>
+map <C-J> <CR>
+
+" Scroll one page backward
+noremap <script> b <C-B><SID>L
+map <C-B> b
+map w b
+map <Esc>v b
+
+" Scroll half a page backward
+noremap <script> u <C-U><SID>L
+noremap <script> <C-U> <C-U><SID>L
+
+" Scroll one line backward
+noremap <script> k <C-Y><SID>L
+map y k
+map <C-Y> k
+map <C-P> k
+map <C-K> k
+
+" Redraw
+noremap <script> r <C-L><SID>L
+noremap <script> <C-R> <C-L><SID>L
+noremap <script> R <C-L><SID>L
+
+" Start of file
+noremap <script> g gg<SID>L
+map < g
+map <Esc>< g
+
+" End of file
+noremap <script> G G<SID>L
+map > G
+map <Esc>> G
+
+" Go to percentage
+noremap <script> % %<SID>L
+map p %
+
+" Search
+noremap <script> / H$:call <SID>Forward()<CR>/
+if &wrap
+ noremap <script> ? H0:call <SID>Backward()<CR>?
+else
+ noremap <script> ? Hg0:call <SID>Backward()<CR>?
+endif
+
+fun! s:Forward()
+ " Searching forward
+ noremap <script> n H$nzt<SID>L
+ if &wrap
+ noremap <script> N H0Nzt<SID>L
+ else
+ noremap <script> N Hg0Nzt<SID>L
+ endif
+ cnoremap <script> <CR> <CR>:cunmap <lt>CR><CR>zt<SID>L
+endfun
+
+fun! s:Backward()
+ " Searching backward
+ if &wrap
+ noremap <script> n H0nzt<SID>L
+ else
+ noremap <script> n Hg0nzt<SID>L
+ endif
+ noremap <script> N H$Nzt<SID>L
+ cnoremap <script> <CR> <CR>:cunmap <lt>CR><CR>zt<SID>L
+endfun
+
+call s:Forward()
+
+" Quitting
+noremap q :q<CR>
+
+" Switch to editing (switch off less mode)
+map v :silent call <SID>End()<CR>
+fun! s:End()
+ set ma
+ if exists(s:lz)
+ let &lz = s:lz
+ endif
+ unmap h
+ unmap H
+ unmap <Space>
+ unmap <C-V>
+ unmap f
+ unmap <C-F>
+ unmap z
+ unmap <Esc><Space>
+ unmap F
+ unmap d
+ unmap <C-D>
+ unmap <CR>
+ unmap <C-N>
+ unmap e
+ unmap <C-E>
+ unmap j
+ unmap <C-J>
+ unmap b
+ unmap <C-B>
+ unmap w
+ unmap <Esc>v
+ unmap u
+ unmap <C-U>
+ unmap k
+ unmap y
+ unmap <C-Y>
+ unmap <C-P>
+ unmap <C-K>
+ unmap r
+ unmap <C-R>
+ unmap R
+ unmap g
+ unmap <
+ unmap <Esc><
+ unmap G
+ unmap >
+ unmap <Esc>>
+ unmap %
+ unmap p
+ unmap n
+ unmap N
+ unmap q
+ unmap v
+ unmap /
+ unmap ?
+endfun
+
+" vim: sw=2
diff --git a/runtime/macros/life/click.me b/runtime/macros/life/click.me
new file mode 100644
index 0000000..c2ed469
--- /dev/null
+++ b/runtime/macros/life/click.me
@@ -0,0 +1,9 @@
+
+To run the "Conway's game of life" macros:
+
+ 1. Type ":so life.vim". This loads the macros.
+ 2. Type "g" to run the macros.
+ 3. Type CTRL-C to interrupt.
+ 4. Type ":q!" to get out.
+
+See life.vim for more advanced usage.
diff --git a/runtime/macros/life/click.me.info b/runtime/macros/life/click.me.info
new file mode 100644
index 0000000..f575650
--- /dev/null
+++ b/runtime/macros/life/click.me.info
Binary files differ
diff --git a/runtime/macros/life/life.vim b/runtime/macros/life/life.vim
new file mode 100644
index 0000000..adf4e20
--- /dev/null
+++ b/runtime/macros/life/life.vim
Binary files differ
diff --git a/runtime/macros/matchit.txt b/runtime/macros/matchit.txt
new file mode 100644
index 0000000..8ea4de5
--- /dev/null
+++ b/runtime/macros/matchit.txt
@@ -0,0 +1,402 @@
+*matchit.txt* Extended "%" matching
+
+For instructions on installing this file, type
+ :help matchit-install
+inside Vim.
+
+For Vim version 6.3. Last change: 2004 May 12
+
+
+ VIM REFERENCE MANUAL by Benji Fisher
+
+*matchit* *matchit.vim*
+
+1. Extended matching with "%" |matchit-intro|
+2. Activation |matchit-activate|
+3. Configuration |matchit-configure|
+4. Supporting a New Language |matchit-newlang|
+5. Known Bugs and Limitations |matchit-bugs|
+
+The functionality mentioned here is a plugin, see |add-plugin|.
+This plugin is only available if 'compatible' is not set.
+You can avoid loading this plugin by setting the "loaded_matchit" variable
+in your |vimrc| file: >
+ :let loaded_matchit = 1
+
+{Vi does not have any of this}
+
+==============================================================================
+1. Extended matching with "%" *matchit-intro*
+
+ *matchit-%*
+% Cycle forward through matching groups, such as "if", "else", "endif",
+ as specified by |b:match_words|.
+
+ *g%* *v_g%* *o_g%*
+g% Cycle backwards through matching groups, as specified by
+ |b:match_words|. For example, go from "endif" to "else" to "if".
+
+ *[%* *v_[%* *o_[%*
+[% Go to [count] previous unmatched group, as specified by
+ |b:match_words|. Similar to |[{|.
+
+ *]%* *v_]%* *o_]%*
+]% Go to [count] next unmatched group, as specified by
+ |b:match_words|. Similar to |]}|.
+
+ *v_a%*
+a% In Visual mode, select the matching group, as specified by
+ |b:match_words|, containing the cursor. Similar to |v_a[|.
+ A [count] is ignored, and only the first character of the closing
+ pattern is selected.
+
+In Vim, as in plain vi, the percent key, |%|, jumps the cursor from a brace,
+bracket, or paren to its match. This can be configured with the 'matchpairs'
+option. The matchit plugin extends this in several ways:
+
+ You can match whole words, such as "if" and "endif", not just
+ single characters. You can also specify a |regular-expression|.
+ You can define groups with more than two words, such as "if",
+ "else", "endif". Banging on the "%" key will cycle from the "if" to
+ the first "else", the next "else", ..., the closing "endif", and back
+ to the opening "if". Nested structures are skipped. Using |g%| goes
+ in the reverse direction.
+ By default, words inside comments and strings are ignored, unless
+ the cursor is inside a comment or string when you type "%". If the
+ only thing you want to do is modify the behavior of "%" so that it
+ behaves this way, you can >
+ :let b:match_words = &matchpairs
+<
+See |matchit-details| for details on what the script does, and |b:match_words|
+for how to specify matching patterns.
+
+MODES: *matchit-modes* *matchit-v_%* *matchit-o_%*
+
+Mostly, % and related motions (|g%| and |[%| and |]%|) work just like built-in
+|motion| commands in |Operator-pending| and |Visual| modes. However, you
+cannot make these motions |linewise| or |characterwise|, since the |:omap|s
+that define them start with "v" in order to make the default behavior
+inclusive. (See |o_v|.) In other words, "dV%" will not work. The
+work-around is to go through Visual mode: "V%d" will work.
+
+LANGUAGES: *matchit-languages*
+
+Currently, the following languages are supported: Ada, ASP with VBS, Csh,
+DTD, Entity, Essbase, Fortran, HTML, JSP (same as HTML), LaTeX, Lua, Pascal,
+SGML, Shell, Tcsh, Vim, XML. Other languages may already have support via
+|filetype-plugin|s.
+
+To support a new language, see |matchit-newlang| below.
+
+DETAILS: *matchit-details* *matchit-parse*
+
+Here is an outline of what matchit.vim does each time you hit the "%" key. If
+there are |backref|s in |b:match_words| then the first step is to produce a
+version in which these back references have been eliminated; if there are no
+|backref|s then this step is skipped. This step is called parsing. For
+example, "\(foo\|bar\):end\1" is parsed to yield
+"\(foo\|bar\):end\(foo\|bar\)". This can get tricky, especially if there are
+nested groups. If debugging is turned on, the parsed version is saved as
+|b:match_pat|.
+
+ *matchit-choose*
+Next, the script looks for a word on the current line that matches the pattern
+just constructed. It includes the patterns from the 'matchpairs' option.
+The goal is to do what you expect, which turns out to be a little complicated.
+The script follows these rules:
+
+ Insist on a match that ends on or after the cursor.
+ Prefer a match that includes the cursor position (that is, one that
+ starts on or before the cursor).
+ Prefer a match that starts as close to the cursor as possible.
+ Prefer a match in |b:match_words| to a match in 'matchpairs'.
+ If more than one pattern in |b:match_words| matches, choose the one
+ that is listed first.
+
+Examples:
+
+ Suppose you >
+ :let b:match_words = '<:>,<tag>:</tag>'
+< and hit "%" with the cursor on or before the "<" in "a <tag> is born".
+ The pattern '<' comes first, so it is preferred over '<tag>', which
+ also matches. If the cursor is on the "t", however, then '<tag>' is
+ preferred, because this matches a bit of text containing the cursor.
+ If the two groups of patterns were reversed then '<' would never be
+ preferred.
+
+ Suppose you >
+ :let b:match_words = 'if:end if'
+< (Note the space!) and hit "%" with the cursor at the end of "end if".
+ Then "if" matches, which is probably not what you want, but if the
+ cursor starts on the "end " then "end if" is chosen. (You can avoid
+ this problem by using a more complicated pattern.)
+
+If there is no match, the script falls back on the usual behavior of |%|. If
+debugging is turned on, the matched bit of text is saved as |b:match_match|
+and the cursor column of the start of the match is saved as |b:match_col|.
+
+Next, the script looks through |b:match_words| (original and parsed versions)
+for the group and pattern that match. If debugging is turned on, the group is
+saved as |b:match_ini| (the first pattern) and |b:match_tail| (the rest). If
+there are |backref|s then, in addition, the matching pattern is saved as
+|b:match_word| and a table of translations is saved as |b:match_table|. If
+there are |backref|s, these are determined from the matching pattern and
+|b:match_match| and substituted into each pattern in the matching group.
+
+The script decides whether to search forwards or backwards and chooses
+arguments for the |searchpair()| function. Then, the cursor is moved to the
+start of the match, and |searchpair()| is called. By default, matching
+structures inside strings and comments are ignored. This can be changed by
+setting |b:match_skip|.
+
+==============================================================================
+2. Activation *matchit-activate*
+
+You can use this script as a plugin, by copying it to your plugin directory.
+See |add-global-plugin| for instructions. You can also add a line to your
+|vimrc| file, such as >
+ :source $VIMRUNTIME/macros/matchit.vim
+or >
+ :runtime macros/matchit.vim
+Either way, the script should start working the next time you start up Vim.
+
+The script does nothing unless it finds a |buffer-variable| named
+|b:match_words|. The script contains autocommands that set this variable for
+various file types: see |matchit-languages| above. For a new language, you
+can add autocommands to the script or to your vimrc file, but the recommended
+method is to add a line such as >
+ let b:match_words = '\<foo\>:\<bar\>'
+to the |filetype-plugin| for your language. See |b:match_words| below for how
+this variable is interpreted.
+
+TROUBLESHOOTING *matchit-troubleshoot*
+
+The script should work in most installations of Vim. It may not work if Vim
+was compiled with a minimal feature set, for example if the |+syntax| option
+was not enabled. If your Vim has support for syntax compiled in, but you do
+not have |syntax| highlighting turned on, matchit.vim should work, but it may
+fail to skip matching groups in comments and strings. If the |filetype|
+mechanism is turned off, the |b:match_words| variable will probably not be
+defined automatically.
+
+==============================================================================
+3. Configuration *matchit-configure*
+
+There are several variables that govern the behavior of matchit.vim. Note
+that these are variables local to the buffer, not options, so use |:let| to
+define them, not |:set|. Some of these variables have values that matter; for
+others, it only matters whether the variable has been defined. All of these
+can be defined in the |filetype-plugin| or autocommand that defines
+|b:match_words| or "on the fly."
+
+The main variable is |b:match_words|. It is described in the section below on
+supporting a new language.
+
+ *MatchError* *matchit-hl* *matchit-highlight*
+MatchError is the highlight group for error messages from the script. By
+default, it is linked to WarningMsg. If you do not want to be bothered by
+error messages, you can define this to be something invisible. For example,
+if you use the GUI version of Vim and your command line is normally white, you
+can do >
+ :hi MatchError guifg=white guibg=white
+<
+ *b:match_ignorecase*
+If you >
+ :let b:match_ignorecase = 1
+then matchit.vim acts as if 'ignorecase' is set: for example, "end" and "END"
+are equivalent. If you >
+ :let b:match_ignorecase = 0
+then matchit.vim treats "end" and "END" differently. (There will be no
+b:match_infercase option unless someone requests it.)
+
+ *b:match_debug*
+Define b:match_debug if you want debugging information to be saved. See
+|matchit-debug|, below.
+
+ *b:match_skip*
+If b:match_skip is defined, it is passed as the skip argument to
+|searchpair()|. This controls when matching structures are skipped, or
+ignored. By default, they are ignored inside comments and strings, as
+determined by the |syntax| mechanism. (If syntax highlighting is turned off,
+nothing is skipped.) You can set b:match_skip to a string, which evaluates to
+a non-zero, numerical value if the match is to be skipped or zero if the match
+should not be skipped. In addition, the following special values are
+supported by matchit.vim:
+ s:foo becomes (current syntax item) =~ foo
+ S:foo becomes (current syntax item) !~ foo
+ r:foo becomes (line before cursor) =~ foo
+ R:foo becomes (line before cursor) !~ foo
+(The "s" is meant to suggest "syntax", and the "r" is meant to suggest
+"regular expression".)
+
+Examples:
+
+ You can get the default behavior with >
+ :let b:match_skip = 's:comment\|string'
+<
+ If you want to skip matching structures unless they are at the start
+ of the line (ignoring whitespace) then you can >
+ :let b:match_skip = 'R:^\s*'
+< Do not do this if strings or comments can span several lines, since
+ the normal syntax checking will not be done if you set b:match_skip.
+
+ In LaTeX, since "%" is used as the comment character, you can >
+ :let b:match_skip = 'r:%'
+< Unfortunately, this will skip anything after "\%", an escaped "%". To
+ allow for this, and also "\\%" (an excaped backslash followed by the
+ comment character) you can >
+ :let b:match_skip = 'r:\(^\|[^\\]\)\(\\\\\)*%'
+<
+ See the $VIMRUNTIME/syntax/vim.vim for an example that uses both
+ syntax and a regular expression.
+
+==============================================================================
+4. Supporting a New Language *matchit-newlang*
+ *b:match_words*
+In order for matchit.vim to support a new language, you must define a suitable
+pattern for |b:match_words|. You may also want to set some of the
+|matchit-configure| variables, as described above. If your language has a
+complicated syntax, or many keywords, you will need to know something about
+Vim's |regular-expression|s.
+
+The format for |b:match_words| is similar to that of the 'matchpairs' option:
+it is a comma (,)-separated list of groups; each group is a colon(:)-separated
+list of patterns (regular expressions). It is OK to have only one group; the
+effect is undefined if a group has only one pattern. A simple example is >
+ :let b:match_words = '\<if\>:\<endif\>,'
+ \ . '\<while\>:\<continue\>:\<break\>:\<endwhile\>'
+(In Vim regular expressions, |\<| and |\>| denote word boundaries. Thus "if"
+matches the end of "endif" but "\<if\>" does not.) Then banging on the "%"
+key will bounce the cursor between "if" and the matching "endif"; and from
+"while" to any matching "continue" or "break", then to the matching "endwhile"
+and back to the "while". It is almost always easier to use |literal-string|s
+(single quotes) as above: '\<if\>' rather than "\\<if\\>" and so on.
+
+Exception: If the ":" character does not appear in b:match_words, then it is
+treated as an expression to be evaluated. For example, >
+ :let b:match_words = 'GetMatchWords()'
+allows you to define a function. This can return a different string depending
+on the current syntax, for example.
+
+Once you have defined the appropriate value of |b:match_words|, you will
+probably want to have this set automatically each time you edit the
+appropriate file type. The recommended way to do this is by adding the
+definition to a |filetype-plugin| file.
+
+Tips: Be careful that your initial pattern does not match your final pattern.
+See the example above for the use of word-boundary expressions. It is usually
+better to use ".\{-}" (as many as necessary) instead of ".*" (as many as
+possible). See |\{-|. For example, in the string "<tag>label</tag>", "<.*>"
+matches the whole string whereas "<.\{-}>" and "<[^>]*>" match "<tag>" and
+"</tag>".
+
+ *matchit-spaces* *matchit-s:notend*
+If "if" is to be paired with "end if" (Note the space!) then word boundaries
+are not enough. Instead, define a regular expression s:notend that will match
+anything but "end" and use it as follows: >
+ :let s:notend = '\%(\<end\s\+\)\@<!'
+ :let b:match_words = s:notend . '\<if\>:\<end\s\+if\>'
+< *matchit-s:sol*
+This is a simplified version of what is done for Ada. The s:notend is a
+|script-variable|. Similarly, you may want to define a start-of-line regular
+expression >
+ :let s:sol = '\%(^\|;\)\s*'
+if keywords are only recognized after the start of a line or after a
+semicolon (;), with optional white space.
+
+ *matchit-backref* *matchit-\1*
+In any group, the expressions |\1|, |\2|, ..., |\9| refer to parts of the
+INITIAL pattern enclosed in |\(|escaped parentheses|\)|. These are referred
+to as back references, or backrefs. For example, >
+ :let b:match_words = '\<b\(o\+\)\>:\(h\)\1\>'
+means that "bo" pairs with "ho" and "boo" pairs with "hoo" and so on. Note
+that "\1" does not refer to the "\(h\)" in this example. If you have
+"\(nested \(parentheses\)\) then "\d" refers to the d-th "\(" and everything
+up to and including the matching "\)": in "\(nested\(parentheses\)\)", "\1"
+refers to everything and "\2" refers to "\(parentheses\)". If you use a
+variable such as |s:notend| or |s:sol| in the previous paragraph then remember
+to count any "\(" patterns in this variable. You do not have to count groups
+defined by |\%(\)|.
+
+It should be possible to resolve back references from any pattern in the
+group. For example, >
+ :let b:match_words = '\(foo\)\(bar\):more\1:and\2:end\1\2'
+would not work because "\2" cannot be determined from "morefoo" and "\1"
+cannot be determined from "andbar". On the other hand, >
+ :let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'
+should work (and have the same effect as "foobar:barfoo:endfoobar"), although
+this has not been thoroughly tested.
+
+You can use |zero-width| patterns such as |\@<=| and |\zs|. (The latter has
+not been thouroughly tested in matchit.vim.) For example, if the keyword "if"
+must occur at the start of the line, with optional white space, you might use
+the pattern "\(^\s*\)\@<=if" so that the cursor will end on the "i" instead of
+at the start of the line. For another example, if HTML had only one tag then
+one could >
+ :let b:match_words = '<:>,<\@<=tag>:<\@<=/tag>'
+so that "%" can bounce between matching "<" and ">" pairs or (starting on
+"tag" or "/tag") between matching tags. Without the |\@<=|, the script would
+bounce from "tag" to the "<" in "</tag>", and another "%" would not take you
+back to where you started.
+
+DEBUGGING *matchit-debug* *:MatchDebug*
+
+If you are having trouble figuring out the appropriate definition of
+|b:match_words| then you can take advantage of the same information I use when
+debugging the script. This is especially true if you are not sure whether
+your patterns or my script are at fault! To make this more convenient, I have
+made the command :MatchDebug, which defines the variable |b:match_debug| and
+creates a Matchit menu. This menu makes it convenient to check the values of
+the variables described below. You will probably also want to read
+|matchit-details| above.
+
+Defining the variable |b:match_debug| causes the script to set the following
+variables, each time you hit the "%" key. Several of these are only defined
+if |b:match_words| includes |backref|s.
+
+ *b:match_pat*
+The b:match_pat variable is set to |b:match_words| with |backref|s parsed.
+ *b:match_match*
+The b:match_match variable is set to the bit of text that is recognized as a
+match.
+ *b:match_col*
+The b:match_col variable is set to the cursor column of the start of the
+matching text.
+ *b:match_wholeBR*
+The b:match_wholeBR variable is set to the comma-separated group of patterns
+that matches, with |backref|s unparsed.
+ *b:match_iniBR*
+The b:match_iniBR variable is set to the first pattern in |b:match_wholeBR|.
+ *b:match_ini*
+The b:match_ini variable is set to the first pattern in |b:match_wholeBR|,
+with |backref|s resolved from |b:match_match|.
+ *b:match_tail*
+The b:match_tail variable is set to the remaining patterns in
+|b:match_wholeBR|, with |backref|s resolved from |b:match_match|.
+ *b:match_word*
+The b:match_word variable is set to the pattern from |b:match_wholeBR| that
+matches |b:match_match|.
+ *b:match_table*
+The back reference '\'.d refers to the same thing as '\'.b:match_table[d] in
+|b:match_word|.
+
+==============================================================================
+5. Known Bugs and Limitations *matchit-bugs*
+
+Just because I know about a bug does not mean that it is on my todo list. I
+try to respond to reports of bugs that cause real problems. If it does not
+cause serious problems, or if there is a work-around, a bug may sit there for
+a while. Moral: if a bug (known or not) bothers you, let me know.
+
+The various |:vmap|s defined in the script (%, |g%|, |[%|, |]%|, |a%|) may
+have undesired effects in Select mode |Select-mode-mapping|. At least, if you
+want to replace the selection with any character in "ag%[]" there will be a
+pause of |'updatetime'| first.
+
+It would be nice if "\0" were recognized as the entire pattern. That is, it
+would be nice if "foo:\end\0" had the same effect as "\(foo\):\end\1". I may
+try to implement this in a future version. (This is not so easy to arrange as
+you might think!)
+
+==============================================================================
+vim:tw=78:fo=tcq2:
diff --git a/runtime/macros/matchit.vim b/runtime/macros/matchit.vim
new file mode 100644
index 0000000..2960994
--- /dev/null
+++ b/runtime/macros/matchit.vim
@@ -0,0 +1,806 @@
+" matchit.vim: (global plugin) Extended "%" matching
+" Last Change: Sat May 15 11:00 AM 2004 EDT
+" Maintainer: Benji Fisher PhD <benji@member.AMS.org>
+" Version: 1.9, for Vim 6.3
+" URL: http://www.vim.org/script.php?script_id=39
+
+" Documentation:
+" The documentation is in a separate file, matchit.txt .
+
+" Credits:
+" Vim editor by Bram Moolenaar (Thanks, Bram!)
+" Original script and design by Raul Segura Acevedo
+" Support for comments by Douglas Potts
+" Support for back references and other improvements by Benji Fisher
+" Support for many languages by Johannes Zellner
+" Suggestions for improvement, bug reports, and support for additional
+" languages by Jordi-Albert Batalla, Neil Bird, Servatius Brandt, Mark
+" Collett, Stephen Wall, Dany St-Amant, and Johannes Zellner.
+
+" Debugging:
+" If you'd like to try the built-in debugging commands...
+" :MatchDebug to activate debugging for the current buffer
+" This saves the values of several key script variables as buffer-local
+" variables. See the MatchDebug() function, below, for details.
+
+" TODO: I should think about multi-line patterns for b:match_words.
+" This would require an option: how many lines to scan (default 1).
+" This would be useful for Python, maybe also for *ML.
+" TODO: Maybe I should add a menu so that people will actually use some of
+" the features that I have implemented.
+" TODO: Eliminate the MultiMatch function. Add yet another argument to
+" Match_wrapper() instead.
+" TODO: Allow :let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'
+" TODO: Make backrefs safer by using '\V' (very no-magic).
+" TODO: Add a level of indirection, so that custom % scripts can use my
+" work but extend it.
+
+" allow user to prevent loading
+" and prevent duplicate loading
+if exists("loaded_matchit") || &cp
+ finish
+endif
+let loaded_matchit = 1
+let s:last_mps = ""
+let s:last_words = ""
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+nnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'n') <CR>
+nnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'n') <CR>
+vnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'v') <CR>m'gv``
+vnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'v') <CR>m'gv``
+onoremap <silent> % v:<C-U>call <SID>Match_wrapper('',1,'o') <CR>
+onoremap <silent> g% v:<C-U>call <SID>Match_wrapper('',0,'o') <CR>
+
+" Analogues of [{ and ]} using matching patterns:
+nnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "n") <CR>
+nnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "n") <CR>
+vmap [% <Esc>[%m'gv``
+vmap ]% <Esc>]%m'gv``
+" vnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "v") <CR>m'gv``
+" vnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "v") <CR>m'gv``
+onoremap <silent> [% v:<C-U>call <SID>MultiMatch("bW", "o") <CR>
+onoremap <silent> ]% v:<C-U>call <SID>MultiMatch("W", "o") <CR>
+
+" text object:
+vmap a% <Esc>[%v]%
+
+" Auto-complete mappings: (not yet "ready for prime time")
+" TODO Read :help write-plugin for the "right" way to let the user
+" specify a key binding.
+" let g:match_auto = '<C-]>'
+" let g:match_autoCR = '<C-CR>'
+" if exists("g:match_auto")
+" execute "inoremap " . g:match_auto . ' x<Esc>"=<SID>Autocomplete()<CR>Pls'
+" endif
+" if exists("g:match_autoCR")
+" execute "inoremap " . g:match_autoCR . ' <CR><C-R>=<SID>Autocomplete()<CR>'
+" endif
+" if exists("g:match_gthhoh")
+" execute "inoremap " . g:match_gthhoh . ' <C-O>:call <SID>Gthhoh()<CR>'
+" endif " gthhoh = "Get the heck out of here!"
+
+let s:notslash = '\\\@<!\%(\\\\\)*'
+
+function! s:Match_wrapper(word, forward, mode) range
+ " In s:CleanUp(), :execute "set" restore_options .
+ let restore_options = (&ic ? " " : " no") . "ignorecase"
+ if exists("b:match_ignorecase")
+ let &ignorecase = b:match_ignorecase
+ endif
+ let restore_options = " ve=" . &ve . restore_options
+ set ve=
+ " If this function was called from Visual mode, make sure that the cursor
+ " is at the correct end of the Visual range:
+ if a:mode == "v"
+ execute "normal! gv\<Esc>"
+ endif
+ " In s:CleanUp(), we may need to check whether the cursor moved forward.
+ let startline = line(".")
+ let startcol = col(".")
+ " Use default behavior if called with a count or if no patterns are defined.
+ if v:count
+ exe "normal! " . v:count . "%"
+ return s:CleanUp(restore_options, a:mode, startline, startcol)
+ elseif !exists("b:match_words") || b:match_words == ""
+ silent! normal! %
+ return s:CleanUp(restore_options, a:mode, startline, startcol)
+ end
+
+ " First step: if not already done, set the script variables
+ " s:do_BR flag for whether there are backrefs
+ " s:pat parsed version of b:match_words
+ " s:all regexp based on s:pat and the default groups
+ "
+ " Allow b:match_words = "GetVimMatchWords()" .
+ if b:match_words =~ ":"
+ let match_words = b:match_words
+ else
+ execute "let match_words =" b:match_words
+ endif
+" Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion!
+ if (match_words != s:last_words) || (&mps != s:last_mps) ||
+ \ exists("b:match_debug")
+ let s:last_words = match_words
+ let s:last_mps = &mps
+ if match_words !~ s:notslash . '\\\d'
+ let s:do_BR = 0
+ let s:pat = match_words
+ else
+ let s:do_BR = 1
+ let s:pat = s:ParseWords(match_words)
+ endif
+ " The next several lines were here before
+ " BF started messing with this script.
+ " quote the special chars in 'matchpairs', replace [,:] with \| and then
+ " append the builtin pairs (/*, */, #if, #ifdef, #else, #elif, #endif)
+ " let default = substitute(escape(&mps, '[$^.*~\\/?]'), '[,:]\+',
+ " \ '\\|', 'g').'\|\/\*\|\*\/\|#if\>\|#ifdef\>\|#else\>\|#elif\>\|#endif\>'
+ let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") .
+ \ '\/\*:\*\/,#if\%(def\)\=:#else\>:#elif\>:#endif\>'
+ " s:all = pattern with all the keywords
+ let s:all = s:pat . (strlen(s:pat) ? "," : "") . default
+ let s:all = substitute(s:all, s:notslash . '\zs[,:]\+', '\\|', 'g')
+ let s:all = '\%(' . s:all . '\)'
+ " let s:all = '\%(' . substitute(s:all, '\\\ze[,:]', '', 'g') . '\)'
+ if exists("b:match_debug")
+ let b:match_pat = s:pat
+ endif
+ endif
+
+ " Second step: set the following local variables:
+ " matchline = line on which the cursor started
+ " curcol = number of characters before match
+ " prefix = regexp for start of line to start of match
+ " suffix = regexp for end of match to end of line
+ " Require match to end on or after the cursor and prefer it to
+ " start on or before the cursor.
+ let matchline = getline(startline)
+ if a:word != ''
+ " word given
+ if a:word !~ s:all
+ echohl WarningMsg|echo 'Missing rule for word:"'.a:word.'"'|echohl NONE
+ return s:CleanUp(restore_options, a:mode, startline, startcol)
+ endif
+ let matchline = a:word
+ let curcol = 0
+ let prefix = '^\%('
+ let suffix = '\)$'
+ " Now the case when "word" is not given
+ else " Find the match that ends on or after the cursor and set curcol.
+ let regexp = s:Wholematch(matchline, s:all, startcol-1)
+ let curcol = match(matchline, regexp)
+ let suf = strlen(matchline) - matchend(matchline, regexp)
+ let prefix = (curcol ? '^.\{' . curcol . '}\%(' : '^\%(')
+ let suffix = (suf ? '\).\{' . suf . '}$' : '\)$')
+ " If the match comes from the defaults, bail out.
+ if matchline !~ prefix .
+ \ substitute(s:pat, s:notslash.'\zs[,:]\+', '\\|', 'g') . suffix
+ silent! norm! %
+ return s:CleanUp(restore_options, a:mode, startline, startcol)
+ endif
+ endif
+ if exists("b:match_debug")
+ let b:match_match = matchstr(matchline, regexp)
+ let b:match_col = curcol+1
+ endif
+
+ " Third step: Find the group and single word that match, and the original
+ " (backref) versions of these. Then, resolve the backrefs.
+ " Set the following local variable:
+ " group = colon-separated list of patterns, one of which matches
+ " = ini:mid:fin or ini:fin
+ "
+ " Reconstruct the version with unresolved backrefs.
+ let patBR = substitute(match_words.',',
+ \ s:notslash.'\zs[,:]*,[,:]*', ',', 'g')
+ let patBR = substitute(patBR, s:notslash.'\zs:\{2,}', ':', 'g')
+ " Now, set group and groupBR to the matching group: 'if:endif' or
+ " 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns
+ " group . "," . groupBR, and we pick it apart.
+ let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR)
+ let i = matchend(group, s:notslash . ",")
+ let groupBR = strpart(group, i)
+ let group = strpart(group, 0, i-1)
+ " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix
+ if s:do_BR " Do the hard part: resolve those backrefs!
+ let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline)
+ endif
+ if exists("b:match_debug")
+ let b:match_wholeBR = groupBR
+ let i = matchend(groupBR, s:notslash . ":")
+ let b:match_iniBR = strpart(groupBR, 0, i-1)
+ endif
+
+ " Fourth step: Set the arguments for searchpair().
+ let i = matchend(group, s:notslash . ":")
+ let j = matchend(group, '.*' . s:notslash . ":")
+ let ini = strpart(group, 0, i-1)
+ let mid = substitute(strpart(group, i,j-i-1), s:notslash.'\zs:', '\\|', 'g')
+ let fin = strpart(group, j)
+ " searchpair() requires that these patterns avoid \(\) groups.
+ let ini = substitute(ini, s:notslash . '\zs\\(', '\\%(', 'g')
+ let mid = substitute(mid, s:notslash . '\zs\\(', '\\%(', 'g')
+ let fin = substitute(fin, s:notslash . '\zs\\(', '\\%(', 'g')
+ " Set mid. This is optimized for readability, not micro-efficiency!
+ if a:forward && matchline =~ prefix . fin . suffix
+ \ || !a:forward && matchline =~ prefix . ini . suffix
+ let mid = ""
+ endif
+ " Set flag. This is optimized for readability, not micro-efficiency!
+ if a:forward && matchline =~ prefix . fin . suffix
+ \ || !a:forward && matchline !~ prefix . ini . suffix
+ let flag = "bW"
+ else
+ let flag = "W"
+ endif
+ " Set skip.
+ if exists("b:match_skip")
+ let skip = b:match_skip
+ elseif exists("b:match_comment") " backwards compatibility and testing!
+ let skip = "r:" . b:match_comment
+ else
+ let skip = 's:comment\|string'
+ endif
+ let skip = s:ParseSkip(skip)
+ if exists("b:match_debug")
+ let b:match_ini = ini
+ let b:match_tail = (strlen(mid) ? mid.'\|' : '') . fin
+ endif
+
+ " Fifth step: actually start moving the cursor and call searchpair().
+ " Later, :execute restore_cursor to get to the original screen.
+ let restore_cursor = virtcol(".") . "|"
+ normal! g0
+ let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor
+ normal! H
+ let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
+ execute restore_cursor
+ normal! 0
+ if curcol
+ execute "normal!" . curcol . "l"
+ endif
+ if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
+ let skip = "0"
+ else
+ execute "if " . skip . "| let skip = '0' | endif"
+ endif
+ let sp_return = searchpair(ini, mid, fin, flag, skip)
+ let final_position = "call cursor(" . line(".") . "," . col(".") . ")"
+ " Restore cursor position and original screen.
+ execute restore_cursor
+ normal! m'
+ if sp_return > 0
+ execute final_position
+ endif
+ return s:CleanUp(restore_options, a:mode, startline, startcol, mid.'\|'.fin)
+endfun
+
+" Restore options and do some special handling for Operator-pending mode.
+" The optional argument is the tail of the matching group.
+fun! s:CleanUp(options, mode, startline, startcol, ...)
+ execute "set" a:options
+ " Open folds, if appropriate.
+ if a:mode != "o"
+ if &foldopen =~ "percent"
+ normal! zv
+ endif
+ " In Operator-pending mode, we want to include the whole match
+ " (for example, d%).
+ " This is only a problem if we end up moving in the forward direction.
+ elseif (a:startline < line(".")) ||
+ \ (a:startline == line(".") && a:startcol < col("."))
+ if a:0
+ " Check whether the match is a single character. If not, move to the
+ " end of the match.
+ let matchline = getline(".")
+ let currcol = col(".")
+ let regexp = s:Wholematch(matchline, a:1, currcol-1)
+ let endcol = matchend(matchline, regexp)
+ if endcol > currcol " This is NOT off by one!
+ execute "normal!" . (endcol - currcol) . "l"
+ endif
+ endif " a:0
+ endif " a:mode != "o" && etc.
+ return 0
+endfun
+
+" Example (simplified HTML patterns): if
+" a:groupBR = '<\(\k\+\)>:</\1>'
+" a:prefix = '^.\{3}\('
+" a:group = '<\(\k\+\)>:</\(\k\+\)>'
+" a:suffix = '\).\{2}$'
+" a:matchline = "123<tag>12" or "123</tag>12"
+" then extract "tag" from a:matchline and return "<tag>:</tag>" .
+fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline)
+ if a:matchline !~ a:prefix .
+ \ substitute(a:group, s:notslash . '\zs:', '\\|', 'g') . a:suffix
+ return a:group
+ endif
+ let i = matchend(a:groupBR, s:notslash . ':')
+ let ini = strpart(a:groupBR, 0, i-1)
+ let tailBR = strpart(a:groupBR, i)
+ let word = s:Choose(a:group, a:matchline, ":", "", a:prefix, a:suffix,
+ \ a:groupBR)
+ let i = matchend(word, s:notslash . ":")
+ let wordBR = strpart(word, i)
+ let word = strpart(word, 0, i-1)
+ " Now, a:matchline =~ a:prefix . word . a:suffix
+ if wordBR != ini
+ let table = s:Resolve(ini, wordBR, "table")
+ else
+ " let table = "----------"
+ let table = ""
+ let d = 0
+ while d < 10
+ if tailBR =~ s:notslash . '\\' . d
+ " let table[d] = d
+ let table = table . d
+ else
+ let table = table . "-"
+ endif
+ let d = d + 1
+ endwhile
+ endif
+ let d = 9
+ while d
+ if table[d] != "-"
+ let backref = substitute(a:matchline, a:prefix.word.a:suffix,
+ \ '\'.table[d], "")
+ " Are there any other characters that should be escaped?
+ let backref = escape(backref, '*,:')
+ execute s:Ref(ini, d, "start", "len")
+ let ini = strpart(ini, 0, start) . backref . strpart(ini, start+len)
+ let tailBR = substitute(tailBR, s:notslash . '\zs\\' . d,
+ \ escape(backref, '\\'), 'g')
+ endif
+ let d = d-1
+ endwhile
+ if exists("b:match_debug")
+ if s:do_BR
+ let b:match_table = table
+ let b:match_word = word
+ else
+ let b:match_table = ""
+ let b:match_word = ""
+ endif
+ endif
+ return ini . ":" . tailBR
+endfun
+
+" Input a comma-separated list of groups with backrefs, such as
+" a:groups = '\(foo\):end\1,\(bar\):end\1'
+" and return a comma-separated list of groups with backrefs replaced:
+" return '\(foo\):end\(foo\),\(bar\):end\(bar\)'
+fun! s:ParseWords(groups)
+ let groups = substitute(a:groups.",", s:notslash.'\zs[,:]*,[,:]*', ',', 'g')
+ let groups = substitute(groups, s:notslash . '\zs:\{2,}', ':', 'g')
+ let parsed = ""
+ while groups =~ '[^,:]'
+ let i = matchend(groups, s:notslash . ':')
+ let j = matchend(groups, s:notslash . ',')
+ let ini = strpart(groups, 0, i-1)
+ let tail = strpart(groups, i, j-i-1) . ":"
+ let groups = strpart(groups, j)
+ let parsed = parsed . ini
+ let i = matchend(tail, s:notslash . ':')
+ while i != -1
+ " In 'if:else:endif', ini='if' and word='else' and then word='endif'.
+ let word = strpart(tail, 0, i-1)
+ let tail = strpart(tail, i)
+ let i = matchend(tail, s:notslash . ':')
+ let parsed = parsed . ":" . s:Resolve(ini, word, "word")
+ endwhile " Now, tail has been used up.
+ let parsed = parsed . ","
+ endwhile " groups =~ '[^,:]'
+ return parsed
+endfun
+
+" TODO I think this can be simplified and/or made more efficient.
+" TODO What should I do if a:start is out of range?
+" Return a regexp that matches all of a:string, such that
+" matchstr(a:string, regexp) represents the match for a:pat that starts
+" as close to a:start as possible, before being preferred to after, and
+" ends after a:start .
+" Usage:
+" let regexp = s:Wholematch(getline("."), 'foo\|bar', col(".")-1)
+" let i = match(getline("."), regexp)
+" let j = matchend(getline("."), regexp)
+" let match = matchstr(getline("."), regexp)
+fun! s:Wholematch(string, pat, start)
+ let group = '\%(' . a:pat . '\)'
+ let prefix = (a:start ? '\(^.\{,' . a:start . '}\)\zs' : '^')
+ let len = strlen(a:string)
+ let suffix = (a:start+1 < len ? '\(.\{,'.(len-a:start-1).'}$\)\@=' : '$')
+ if a:string !~ prefix . group . suffix
+ let prefix = ''
+ endif
+ return prefix . group . suffix
+endfun
+
+" No extra arguments: s:Ref(string, d) will
+" find the d'th occurrence of '\(' and return it, along with everything up
+" to and including the matching '\)'.
+" One argument: s:Ref(string, d, "start") returns the index of the start
+" of the d'th '\(' and any other argument returns the length of the group.
+" Two arguments: s:Ref(string, d, "foo", "bar") returns a string to be
+" executed, having the effect of
+" :let foo = s:Ref(string, d, "start")
+" :let bar = s:Ref(string, d, "len")
+fun! s:Ref(string, d, ...)
+ let len = strlen(a:string)
+ if a:d == 0
+ let start = 0
+ else
+ let cnt = a:d
+ let match = a:string
+ while cnt
+ let cnt = cnt - 1
+ let index = matchend(match, s:notslash . '\\(')
+ if index == -1
+ return ""
+ endif
+ let match = strpart(match, index)
+ endwhile
+ let start = len - strlen(match)
+ if a:0 == 1 && a:1 == "start"
+ return start - 2
+ endif
+ let cnt = 1
+ while cnt
+ let index = matchend(match, s:notslash . '\\(\|\\)') - 1
+ if index == -2
+ return ""
+ endif
+ " Increment if an open, decrement if a ')':
+ let cnt = cnt + (match[index]=="(" ? 1 : -1) " ')'
+ " let cnt = stridx('0(', match[index]) + cnt
+ let match = strpart(match, index+1)
+ endwhile
+ let start = start - 2
+ let len = len - start - strlen(match)
+ endif
+ if a:0 == 1
+ return len
+ elseif a:0 == 2
+ return "let " . a:1 . "=" . start . "| let " . a:2 . "=" . len
+ else
+ return strpart(a:string, start, len)
+ endif
+endfun
+
+" Count the number of disjoint copies of pattern in string.
+" If the pattern is a literal string and contains no '0' or '1' characters
+" then s:Count(string, pattern, '0', '1') should be faster than
+" s:Count(string, pattern).
+fun! s:Count(string, pattern, ...)
+ let pat = escape(a:pattern, '\\')
+ if a:0 > 1
+ let foo = substitute(a:string, '[^'.a:pattern.']', "a:1", "g")
+ let foo = substitute(a:string, pat, a:2, "g")
+ let foo = substitute(foo, '[^' . a:2 . ']', "", "g")
+ return strlen(foo)
+ endif
+ let result = 0
+ let foo = a:string
+ let index = matchend(foo, pat)
+ while index != -1
+ let result = result + 1
+ let foo = strpart(foo, index)
+ let index = matchend(foo, pat)
+ endwhile
+ return result
+endfun
+
+" s:Resolve('\(a\)\(b\)', '\(c\)\2\1\1\2') should return table.word, where
+" word = '\(c\)\(b\)\(a\)\3\2' and table = '-32-------'. That is, the first
+" '\1' in target is replaced by '\(a\)' in word, table[1] = 3, and this
+" indicates that all other instances of '\1' in target are to be replaced
+" by '\3'. The hard part is dealing with nesting...
+" Note that ":" is an illegal character for source and target,
+" unless it is preceded by "\".
+fun! s:Resolve(source, target, output)
+ let word = a:target
+ let i = matchend(word, s:notslash . '\\\d') - 1
+ let table = "----------"
+ while i != -2 " There are back references to be replaced.
+ let d = word[i]
+ let backref = s:Ref(a:source, d)
+ " The idea is to replace '\d' with backref. Before we do this,
+ " replace any \(\) groups in backref with :1, :2, ... if they
+ " correspond to the first, second, ... group already inserted
+ " into backref. Later, replace :1 with \1 and so on. The group
+ " number w+b within backref corresponds to the group number
+ " s within a:source.
+ " w = number of '\(' in word before the current one
+ let w = s:Count(
+ \ substitute(strpart(word, 0, i-1), '\\\\', '', 'g'), '\(', '1')
+ let b = 1 " number of the current '\(' in backref
+ let s = d " number of the current '\(' in a:source
+ while b <= s:Count(substitute(backref, '\\\\', '', 'g'), '\(', '1')
+ \ && s < 10
+ if table[s] == "-"
+ if w + b < 10
+ " let table[s] = w + b
+ let table = strpart(table, 0, s) . (w+b) . strpart(table, s+1)
+ endif
+ let b = b + 1
+ let s = s + 1
+ else
+ execute s:Ref(backref, b, "start", "len")
+ let ref = strpart(backref, start, len)
+ let backref = strpart(backref, 0, start) . ":". table[s]
+ \ . strpart(backref, start+len)
+ let s = s + s:Count(substitute(ref, '\\\\', '', 'g'), '\(', '1')
+ endif
+ endwhile
+ let word = strpart(word, 0, i-1) . backref . strpart(word, i+1)
+ let i = matchend(word, s:notslash . '\\\d') - 1
+ endwhile
+ let word = substitute(word, s:notslash . '\zs:', '\\', 'g')
+ if a:output == "table"
+ return table
+ elseif a:output == "word"
+ return word
+ else
+ return table . word
+ endif
+endfun
+
+" Assume a:comma = ",". Then the format for a:patterns and a:1 is
+" a:patterns = "<pat1>,<pat2>,..."
+" a:1 = "<alt1>,<alt2>,..."
+" If <patn> is the first pattern that matches a:string then return <patn>
+" if no optional arguments are given; return <patn>,<altn> if a:1 is given.
+fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...)
+ let tail = (a:patterns =~ a:comma."$" ? a:patterns : a:patterns . a:comma)
+ let i = matchend(tail, s:notslash . a:comma)
+ if a:0
+ let alttail = (a:1 =~ a:comma."$" ? a:1 : a:1 . a:comma)
+ let j = matchend(alttail, s:notslash . a:comma)
+ endif
+ let current = strpart(tail, 0, i-1)
+ if a:branch == ""
+ let currpat = current
+ else
+ let currpat = substitute(current, a:branch, '\\|', 'g')
+ endif
+ while a:string !~ a:prefix . currpat . a:suffix
+ let tail = strpart(tail, i)
+ let i = matchend(tail, s:notslash . a:comma)
+ if i == -1
+ return -1
+ endif
+ let current = strpart(tail, 0, i-1)
+ if a:branch == ""
+ let currpat = current
+ else
+ let currpat = substitute(current, a:branch, '\\|', 'g')
+ endif
+ if a:0
+ let alttail = strpart(alttail, j)
+ let j = matchend(alttail, s:notslash . a:comma)
+ endif
+ endwhile
+ if a:0
+ let current = current . a:comma . strpart(alttail, 0, j-1)
+ endif
+ return current
+endfun
+
+" Call this function to turn on debugging information. Every time the main
+" script is run, buffer variables will be saved. These can be used directly
+" or viewed using the menu items below.
+if !exists(":MatchDebug")
+ command! -nargs=0 MatchDebug call s:Match_debug()
+endif
+
+fun! s:Match_debug()
+ let b:match_debug = 1 " Save debugging information.
+ " pat = all of b:match_words with backrefs parsed
+ amenu &Matchit.&pat :echo b:match_pat<CR>
+ " match = bit of text that is recognized as a match
+ amenu &Matchit.&match :echo b:match_match<CR>
+ " curcol = cursor column of the start of the matching text
+ amenu &Matchit.&curcol :echo b:match_col<CR>
+ " wholeBR = matching group, original version
+ amenu &Matchit.wh&oleBR :echo b:match_wholeBR<CR>
+ " iniBR = 'if' piece, original version
+ amenu &Matchit.ini&BR :echo b:match_iniBR<CR>
+ " ini = 'if' piece, with all backrefs resolved from match
+ amenu &Matchit.&ini :echo b:match_ini<CR>
+ " tail = 'else\|endif' piece, with all backrefs resolved from match
+ amenu &Matchit.&tail :echo b:match_tail<CR>
+ " fin = 'endif' piece, with all backrefs resolved from match
+ amenu &Matchit.&word :echo b:match_word<CR>
+ " '\'.d in ini refers to the same thing as '\'.table[d] in word.
+ amenu &Matchit.t&able :echo '0:' . b:match_table . ':9'<CR>
+endfun
+
+" Jump to the nearest unmatched "(" or "if" or "<tag>" if a:spflag == "bW"
+" or the nearest unmatched "</tag>" or "endif" or ")" if a:spflag == "W".
+" Return a "mark" for the original position, so that
+" let m = MultiMatch("bW", "n") ... execute m
+" will return to the original position. If there is a problem, do not
+" move the cursor and return "", unless a count is given, in which case
+" go up or down as many levels as possible and again return "".
+" TODO This relies on the same patterns as % matching. It might be a good
+" idea to give it its own matching patterns.
+fun! s:MultiMatch(spflag, mode)
+ if !exists("b:match_words") || b:match_words == ""
+ return ""
+ end
+ let restore_options = (&ic ? "" : "no") . "ignorecase"
+ if exists("b:match_ignorecase")
+ let &ignorecase = b:match_ignorecase
+ endif
+ let startline = line(".")
+ let startcol = col(".")
+
+ " First step: if not already done, set the script variables
+ " s:do_BR flag for whether there are backrefs
+ " s:pat parsed version of b:match_words
+ " s:all regexp based on s:pat and the default groups
+ " This part is copied and slightly modified from s:Match_wrapper().
+ let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") .
+ \ '\/\*:\*\/,#if\%(def\)\=:$else\>:#elif\>:#endif\>'
+ " Allow b:match_words = "GetVimMatchWords()" .
+ if b:match_words =~ ":"
+ let match_words = b:match_words
+ else
+ execute "let match_words =" b:match_words
+ endif
+ if (match_words != s:last_words) || (&mps != s:last_mps) ||
+ \ exists("b:match_debug")
+ let s:last_words = match_words
+ let s:last_mps = &mps
+ if match_words !~ s:notslash . '\\\d'
+ let s:do_BR = 0
+ let s:pat = match_words
+ else
+ let s:do_BR = 1
+ let s:pat = s:ParseWords(match_words)
+ endif
+ let s:all = '\%(' . substitute(s:pat . (strlen(s:pat)?",":"") . default,
+ \ '[,:]\+','\\|','g') . '\)'
+ if exists("b:match_debug")
+ let b:match_pat = s:pat
+ endif
+ endif
+
+ " Second step: figure out the patterns for searchpair()
+ " and save the screen, cursor position, and 'ignorecase'.
+ " - TODO: A lot of this is copied from s:Match_wrapper().
+ " - maybe even more functionality should be split off
+ " - into separate functions!
+ let cdefault = (s:pat =~ '[^,]$' ? "," : "") . default
+ let open = substitute(s:pat . cdefault, ':[^,]*,', '\\),\\(', 'g')
+ let open = '\(' . substitute(open, ':[^,]*$', '\\)', '')
+ let close = substitute(s:pat . cdefault, ',[^,]*:', '\\),\\(', 'g')
+ let close = substitute(close, '[^,]*:', '\\(', '') . '\)'
+ if exists("b:match_skip")
+ let skip = b:match_skip
+ elseif exists("b:match_comment") " backwards compatibility and testing!
+ let skip = "r:" . b:match_comment
+ else
+ let skip = 's:comment\|string'
+ endif
+ let skip = s:ParseSkip(skip)
+ " let restore_cursor = line(".") . "G" . virtcol(".") . "|"
+ " normal! H
+ " let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
+ let restore_cursor = virtcol(".") . "|"
+ normal! g0
+ let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor
+ normal! H
+ let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
+ execute restore_cursor
+
+ " Third step: call searchpair().
+ " Replace '\('--but not '\\('--with '\%(' and ',' with '\|'.
+ let openpat = substitute(open, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
+ let openpat = substitute(openpat, ',', '\\|', 'g')
+ let closepat = substitute(close, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
+ let closepat = substitute(closepat, ',', '\\|', 'g')
+ if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
+ let skip = '0'
+ else
+ execute "if " . skip . "| let skip = '0' | endif"
+ endif
+ mark '
+ let level = v:count1
+ while level
+ if searchpair(openpat, '', closepat, a:spflag, skip) < 1
+ call s:CleanUp(restore_options, a:mode, startline, startcol)
+ return ""
+ endif
+ let level = level - 1
+ endwhile
+
+ " Restore options and return a string to restore the original position.
+ call s:CleanUp(restore_options, a:mode, startline, startcol)
+ return restore_cursor
+endfun
+
+" Search backwards for "if" or "while" or "<tag>" or ...
+" and return "endif" or "endwhile" or "</tag>" or ... .
+" For now, this uses b:match_words and the same script variables
+" as s:Match_wrapper() . Later, it may get its own patterns,
+" either from a buffer variable or passed as arguments.
+" fun! s:Autocomplete()
+" echo "autocomplete not yet implemented :-("
+" if !exists("b:match_words") || b:match_words == ""
+" return ""
+" end
+" let startpos = s:MultiMatch("bW")
+"
+" if startpos == ""
+" return ""
+" endif
+" " - TODO: figure out whether 'if' or '<tag>' matched, and construct
+" " - the appropriate closing.
+" let matchline = getline(".")
+" let curcol = col(".") - 1
+" " - TODO: Change the s:all argument if there is a new set of match pats.
+" let regexp = s:Wholematch(matchline, s:all, curcol)
+" let suf = strlen(matchline) - matchend(matchline, regexp)
+" let prefix = (curcol ? '^.\{' . curcol . '}\%(' : '^\%(')
+" let suffix = (suf ? '\).\{' . suf . '}$' : '\)$')
+" " Reconstruct the version with unresolved backrefs.
+" let patBR = substitute(b:match_words.',', '[,:]*,[,:]*', ',', 'g')
+" let patBR = substitute(patBR, ':\{2,}', ':', "g")
+" " Now, set group and groupBR to the matching group: 'if:endif' or
+" " 'while:endwhile' or whatever.
+" let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR)
+" let i = matchend(group, s:notslash . ",")
+" let groupBR = strpart(group, i)
+" let group = strpart(group, 0, i-1)
+" " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix
+" if s:do_BR
+" let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline)
+" endif
+" " let g:group = group
+"
+" " - TODO: Construct the closing from group.
+" let fake = "end" . expand("<cword>")
+" execute startpos
+" return fake
+" endfun
+
+" Close all open structures. "Get the heck out of here!"
+" fun! s:Gthhoh()
+" let close = s:Autocomplete()
+" while strlen(close)
+" put=close
+" let close = s:Autocomplete()
+" endwhile
+" endfun
+
+" Parse special strings as typical skip arguments for searchpair():
+" s:foo becomes (current syntax item) =~ foo
+" S:foo becomes (current syntax item) !~ foo
+" r:foo becomes (line before cursor) =~ foo
+" R:foo becomes (line before cursor) !~ foo
+fun! s:ParseSkip(str)
+ let skip = a:str
+ if skip[1] == ":"
+ if skip[0] == "s"
+ let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" .
+ \ strpart(skip,2) . "'"
+ elseif skip[0] == "S"
+ let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" .
+ \ strpart(skip,2) . "'"
+ elseif skip[0] == "r"
+ let skip = "strpart(getline('.'),0,col('.'))=~'" . strpart(skip,2). "'"
+ elseif skip[0] == "R"
+ let skip = "strpart(getline('.'),0,col('.'))!~'" . strpart(skip,2). "'"
+ endif
+ endif
+ return skip
+endfun
+
+let &cpo = s:save_cpo
+
+" vim:sts=2:sw=2:
diff --git a/runtime/macros/maze.info b/runtime/macros/maze.info
new file mode 100644
index 0000000..2ad27db
--- /dev/null
+++ b/runtime/macros/maze.info
Binary files differ
diff --git a/runtime/macros/maze/Makefile b/runtime/macros/maze/Makefile
new file mode 100644
index 0000000..c34e115
--- /dev/null
+++ b/runtime/macros/maze/Makefile
@@ -0,0 +1,7 @@
+# It's simple...
+
+maze: mazeansi.c
+ cc -o maze mazeansi.c
+
+mazeclean: mazeclean.c
+ cc -o mazeclean mazeclean.c
diff --git a/runtime/macros/maze/README.txt b/runtime/macros/maze/README.txt
new file mode 100644
index 0000000..be8e8ef
--- /dev/null
+++ b/runtime/macros/maze/README.txt
@@ -0,0 +1,49 @@
+To run the maze macros with Vim:
+
+ vim -u maze_mac maze_5.78
+ press "g"
+
+The "-u maze.mac" loads the maze macros and skips loading your .vimrc, which
+may contain settings and mappings that get in the way.
+
+
+The original README:
+
+To prove that you can do anything in vi, I wrote a couple of macros that
+allows vi to solve mazes. It will solve any maze produced by maze.c
+that was posted to the net recently.
+
+Just follow this recipe and SEE FOR YOURSELF.
+ 1. run uudecode on the file "maze.vi.macros.uu" to
+ produce the file "maze.vi.macros"
+ (If you can't wait to see the action, jump to step 4)
+ 2. compile maze.c with "cc -o maze maze.c"
+ 3. run maze > maze.out and input a small number (for example 10 if
+ you are on a fast machine, 3-5 if slow) which
+ is the size of the maze to produce
+ 4. edit the maze (vi maze.out)
+ 5. include the macros with the vi command:
+ :so maze.vi.macros
+ 6. type the letter "g" (for "go") and watch vi solve the maze
+ 7. when vi solves the maze, you will see why it lies
+ 8. now look at maze.vi.macros and all will be revealed
+
+Tested on a sparc, a sun and a pyramid (although maze.c will not compile
+on the pyramid).
+
+Anyone who can't get the maze.c file to compile, get a new compiler,
+try maze.ansi.c which was also posted to the net.
+If you can get it to compile but the maze comes out looking like a fence
+and not a maze and you are using SysV or DOS replace the "27" on the
+last line of maze.c by "11"
+Thanks to John Tromp (tromp@piring.cwi.nl) for maze.c.
+Thanks to antonyc@nntp-server.caltech.edu (Bill T. Cat) for maze.ansi.c.
+
+Any donations should be in unmarked small denomination bills :^)=.
+
+ ACSnet: gregm@otc.otca.oz.au
+Greg McFarlane UUCP: {uunet,mcvax}!otc.otca.oz.au!gregm
+|||| OTC || Snail: OTC R&D GPO Box 7000, Sydney 2001, Australia
+ Phone: +61 2 287 3139 Fax: +61 2 287 3299
+
+
diff --git a/runtime/macros/maze/README.txt.info b/runtime/macros/maze/README.txt.info
new file mode 100644
index 0000000..263ddcd
--- /dev/null
+++ b/runtime/macros/maze/README.txt.info
Binary files differ
diff --git a/runtime/macros/maze/main.aap b/runtime/macros/maze/main.aap
new file mode 100644
index 0000000..ee9af21
--- /dev/null
+++ b/runtime/macros/maze/main.aap
@@ -0,0 +1,4 @@
+# Aap recipe to build the maze program
+:program maze : mazeansi.c
+
+:program mazeclean : mazeclean.c
diff --git a/runtime/macros/maze/maze.c b/runtime/macros/maze/maze.c
new file mode 100644
index 0000000..b917453
--- /dev/null
+++ b/runtime/macros/maze/maze.c
@@ -0,0 +1,7 @@
+char*M,A,Z,E=40,J[40],T[40];main(C){for(*J=A=scanf(M="%d",&C);
+-- E; J[ E] =T
+[E ]= E) printf("._"); for(;(A-=Z=!Z) || (printf("\n|"
+) , A = 39 ,C --
+) ; Z || printf (M ))M[Z]=Z[A-(E =A[J-Z])&&!C
+& A == T[ A]
+|6<<27<rand()||!C&!Z?J[T[E]=T[A]]=E,J[T[A]=A-Z]=A,"_.":" |"];}
diff --git a/runtime/macros/maze/maze_5.78 b/runtime/macros/maze/maze_5.78
new file mode 100644
index 0000000..dbe3d27
--- /dev/null
+++ b/runtime/macros/maze/maze_5.78
@@ -0,0 +1,16 @@
+._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
+| ._| . . ._| | |_._._. . ._|_._._._._. ._|_. ._|_._. ._| . ._|_. | . ._._. |
+| ._|_| |_. | | | | ._._|_._|_._. . |_. | | | ._._| |_._._| | ._. ._| . . |_|
+|_._._._. | ._|_. ._._._. | | ._. |_._. . | ._._| |_. | ._._._. |_. | |_|_| |
+| | . |_._| . ._._._| ._._. ._._| | | |_| . | |_. . ._|_| ._._. |_._|_| . | |
+|_._|_._._._|_._._._|_|_._._._|_._|_._._._|_._._._|_._._._|_._._._._._._|_._|
+
+See Vim solve a maze!
+
+ type ":so maze_mac<RETURN>" to load the macros
+
+ type "g" to start
+
+to interrupt type "<CTRL-C>"
+ to quit type ":q!<RETURN>"
+
diff --git a/runtime/macros/maze/maze_5.78.info b/runtime/macros/maze/maze_5.78.info
new file mode 100644
index 0000000..fd65cef
--- /dev/null
+++ b/runtime/macros/maze/maze_5.78.info
Binary files differ
diff --git a/runtime/macros/maze/maze_mac b/runtime/macros/maze/maze_mac
new file mode 100644
index 0000000..621aeec
--- /dev/null
+++ b/runtime/macros/maze/maze_mac
Binary files differ
diff --git a/runtime/macros/maze/mazeansi.c b/runtime/macros/maze/mazeansi.c
new file mode 100644
index 0000000..b8e5e79
--- /dev/null
+++ b/runtime/macros/maze/mazeansi.c
@@ -0,0 +1,7 @@
+char*M,A,Z,E=40,J[80],T[3];main(C){for(M=J+E,*J=A=scanf("%d",&
+C) ;-- E;J [E ]=M
+[E ]= E) printf("._"); for(;(A-=Z=!Z) || (printf("\n|"
+) , A = 39 ,C --
+) ; Z || printf (T ))T[Z]=Z[A-(E =A[J-Z])&&!C
+& A == M[ A]
+|6<<27<rand()||!C&!Z?J[M[E]=M[A]]=E,J[M[A]=A-Z]=A,"_.":" |"];}
diff --git a/runtime/macros/maze/mazeclean.c b/runtime/macros/maze/mazeclean.c
new file mode 100644
index 0000000..04dcebd
--- /dev/null
+++ b/runtime/macros/maze/mazeclean.c
@@ -0,0 +1,22 @@
+/*
+ * Cleaned-up version of the maze program.
+ * Doesn't look as nice, but should work with all C compilers.
+ * Sascha Wilde, October 2003
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+char *M, A, Z, E = 40, line[80], T[3];
+int
+main (C)
+{
+ for (M = line + E, *line = A = scanf ("%d", &C); --E; line[E] = M[E] = E)
+ printf ("._");
+ for (; (A -= Z = !Z) || (printf ("\n|"), A = 39, C--); Z || printf (T))
+ T[Z] = Z[A - (E = A[line - Z]) && !C
+ & A == M[A]
+ | RAND_MAX/3 < rand ()
+ || !C & !Z ? line[M[E] = M[A]] = E, line[M[A] = A - Z] =
+ A, "_." : " |"];
+ return 0;
+}
diff --git a/runtime/macros/maze/poster b/runtime/macros/maze/poster
new file mode 100644
index 0000000..9114f59
--- /dev/null
+++ b/runtime/macros/maze/poster
@@ -0,0 +1,37 @@
+Article 2846 of alt.sources:
+Path: oce-rd1!hp4nl!mcsun!uunet!munnari.oz.au!metro!otc!gregm
+From: gregm@otc.otca.oz.au (Greg McFarlane)
+Newsgroups: alt.sources
+Subject: VI SOLVES MAZE (commented macros)
+Message-ID: <2289@otc.otca.oz>
+Date: 10 Feb 91 23:31:02 GMT
+Sender: news@otc.otca.oz
+Reply-To: gregm@otc.otca.oz.au (Greg McFarlane)
+Organization: OTC Development Unit, Australia
+Lines: 464
+
+Submitted-by: gregm@otc.otca.oz.au
+Archive-name: maze_solving_vi_macros
+
+A real working model. See it walk the maze in front of your very own eyes.
+
+To prove that you can do anything in vi, I wrote a couple of macros that
+allows vi to solve mazes. It will solve any maze produced by maze.c
+that was posted to the alt.sources last month. (Maze.c is also included
+in this posting as well as an example of its output.)
+
+The uncommented version of the macros was sent to alt.sources last month.
+However, so many people mailed me requesting the commented version of the
+macros that I decided to post it. I have made some modifications to the
+original macros to make them easier to follow and also after I learnt
+that you can escape the special meaning of '|' in macros by using '^V|'.
+
+Save this article and unshar it. Then read maze.README.
+
+After studying these macros, anyone who cannot write an emacs emulator
+in vi macros should just curl up and :q!.
+
+Coming soon to a newsgroup near you: "Vi macros solve Tower of Hanoi",
+and a repost of the original "Turing Machine implemented in Vi macros"
+
+Anyone who has a version of these macros for edlin or nroff, please post.
diff --git a/runtime/macros/maze/poster.info b/runtime/macros/maze/poster.info
new file mode 100644
index 0000000..9a478d6
--- /dev/null
+++ b/runtime/macros/maze/poster.info
Binary files differ
diff --git a/runtime/macros/shellmenu.vim b/runtime/macros/shellmenu.vim
new file mode 100644
index 0000000..6175d1d
--- /dev/null
+++ b/runtime/macros/shellmenu.vim
Binary files differ
diff --git a/runtime/macros/swapmous.vim b/runtime/macros/swapmous.vim
new file mode 100644
index 0000000..8b85be0
--- /dev/null
+++ b/runtime/macros/swapmous.vim
@@ -0,0 +1,22 @@
+" These macros swap the left and right mouse buttons (for left handed)
+" Don't forget to do ":set mouse=a" or the mouse won't work at all
+noremap <LeftMouse> <RightMouse>
+noremap <2-LeftMouse> <2-RightMouse>
+noremap <3-LeftMouse> <3-RightMouse>
+noremap <4-LeftMouse> <4-RightMouse>
+noremap <LeftDrag> <RightDrag>
+noremap <LeftRelease> <RightRelease>
+noremap <RightMouse> <LeftMouse>
+noremap <2-RightMouse> <2-LeftMouse>
+noremap <3-RightMouse> <3-LeftMouse>
+noremap <4-RightMouse> <4-LeftMouse>
+noremap <RightDrag> <LeftDrag>
+noremap <RightRelease> <LeftRelease>
+noremap g<LeftMouse> <C-RightMouse>
+noremap g<RightMouse> <C-LeftMouse>
+noremap! <LeftMouse> <RightMouse>
+noremap! <LeftDrag> <RightDrag>
+noremap! <LeftRelease> <RightRelease>
+noremap! <RightMouse> <LeftMouse>
+noremap! <RightDrag> <LeftDrag>
+noremap! <RightRelease> <LeftRelease>
diff --git a/runtime/macros/urm.info b/runtime/macros/urm.info
new file mode 100644
index 0000000..65e8234
--- /dev/null
+++ b/runtime/macros/urm.info
Binary files differ
diff --git a/runtime/macros/urm/README.txt b/runtime/macros/urm/README.txt
new file mode 100644
index 0000000..a1ecc65
--- /dev/null
+++ b/runtime/macros/urm/README.txt
@@ -0,0 +1,47 @@
+This is another proof that Vim is perfectly compatible with Vi.
+The URM macro package was written by Rudolf Koenig ("Rudi")
+(rudolf@koeniglich.de) for hpux-vi in August 1991.
+
+Getting started:
+
+type
+in your shell: vim urm<RETURN>
+in vim: :so urm.vim<RETURN>
+in vim: * (to load the registers and boot the URM-machine :-)
+in vim: g (for 'go') and watch the fun. Per default, 3 and 4
+ are multiplied. Watch the Program counter, it is
+ visible as a komma moving around.
+
+This is a "standard URM" (Universal register machine) interpreter. The URM
+concept is used in theoretical computer science to aid in theorem proving.
+Here it proves that vim is a general problem solver (if you bring enough
+patience).
+
+The interpreter begins with register 1 (not 0), without macros and more-lines
+capability. A dot marks the end of a program. (Bug: there must be a space
+after the dot.)
+
+The registers are the first few lines, beginning with a '>' .
+The program is the first line after the registers.
+You should always initialize the registers required by the program.
+
+Output register: line 2
+Input registers: line 2 to ...
+
+Commands:
+a<n> increment register <n>
+s<n> decrement register <n>
+<x>;<y> execute command <x> and then <y>
+(<x>)<n> execute command <x> while register <n> is nonzero
+. ("dot blank") halt the machine.
+
+Examples:
+
+Add register 2 to register 3:
+ (a2;s3)3.
+Multiply register 2 with register 3:
+ (a4;a5;s2)2; ((a2;s4)4; s3; (a1;a4;s5)5; (a5;s1)1)3.
+
+There are more (complicated) examples in the file examples.
+Note, undo may take a while after a division.
+
diff --git a/runtime/macros/urm/README.txt.info b/runtime/macros/urm/README.txt.info
new file mode 100644
index 0000000..1337937
--- /dev/null
+++ b/runtime/macros/urm/README.txt.info
Binary files differ
diff --git a/runtime/macros/urm/examples b/runtime/macros/urm/examples
new file mode 100644
index 0000000..9907d4a
--- /dev/null
+++ b/runtime/macros/urm/examples
@@ -0,0 +1,16 @@
+Note that enough temporary registers should be provided for each example.
+All should be initialised to 0.
+
+Initial register values for benchmarking: 0,8,3,0,...
+
+Performed on a Xenix 386/16:
+Operation [sec, kbyte tmp space]: program
+
+Asym. Diff.[ 7, 4]: (s2;s3)3.
+Abs. Diff. [90,81]: (a1;a4;s2)2; (a2;s1)1; (a1;a5;s3)3; (a3;s1)1; (s2;s3)3; (s5;s4)4; (a2;s5)5.
+Add [ 7, 4]: (a2;s3)3.
+Mult [227, 161]: (a4;a5;s2)2; ((a2;s4)4; s3; (a1;a4;s5)5; (a5;s1)1)3.
+Copy [ 48, 25]: (a1;a3;s2)2; (a2;s1)1.
+sign [ 30, 17]: (a3;s2)2; (a2;(s3)3)3.
+!sign[ 36, 28]: (a3;s2)2; (a2;(s3)3)3; a3; (s3;s2)2; (s3;a2)3.
+Div [630,1522]: (a9;s2)2; (a2;a10;s3)3; (a3;s2)2; (a2;(s3)3)3; a3; (s3;s2)2; (s3;a2)3; (a2)2;(a2;s9)9;(a3;s10)10; (a9;a10;s2)2; (a11;a12;s3)3; (a2;s12)12; (a3;s9)9; (s2;s3)3; (a3;s2)2; (a2;(s3)3)3; a3; (s3;s2)2; (s3;a2)3; (a1;s2)2; (a2;s10)10; (a3;s11)11; ((a12;a13;s3)3; (a3;s13)13; (s2;s3)3; (a3;s12)12; a14; (s1)1; (a9;a10;s2)2; (a11;a12;s3)3; (a2;s12)12; (a3;s9)9; (s2;s3)3; (a3;s2)2; (a2;(s3)3)3; a3; (s3;s2)2; (s3;a2)3; (a1;s2)2; (a2;s10)10; (a3;s11)11)1; (s2)2; (a2;s14)14.
diff --git a/runtime/macros/urm/urm b/runtime/macros/urm/urm
new file mode 100644
index 0000000..9cbefb7
--- /dev/null
+++ b/runtime/macros/urm/urm
Binary files differ
diff --git a/runtime/macros/urm/urm.vim b/runtime/macros/urm/urm.vim
new file mode 100644
index 0000000..3108180
--- /dev/null
+++ b/runtime/macros/urm/urm.vim
Binary files differ