home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / elvis22g.zip / lib / elvis.ali < prev    next >
Text File  |  2002-04-10  |  17KB  |  716 lines

  1. switch os
  2. case unix alias! lf !!ls -CF
  3. default alias! lf !!dir/w
  4.  
  5. alias! pwd calc getcwd("!*")
  6.  
  7. alias! save {
  8.  "Write this file, but only if it has been modified
  9.  if modified
  10.  then w!? !*
  11. }
  12.  
  13. alias! w {
  14.  "Write this file, but if readonly then check it out first
  15.  if readonly && "!?!%!*" == ""
  16.  then !!co -l %
  17.  then w!!
  18.  else !%w!? !*
  19. }
  20.  
  21. alias! man {
  22.  "Display a man page in a new window
  23.  local b report=0 nosaveregexp magic magicchar=^$.[*
  24.  let b = newbuffer()
  25.  (=b) set bd=man
  26.  (=b)r !!man !*
  27.  try (=b)1 s/^Reformatting.*ait\.\.\.$//
  28.  try (=b)% s/\\/\\\\/g
  29.  try (=b)% s/_\(.\)/\\fI\1\\fR/g
  30.  try (=b)% s/.\(.\)/\\fB\1\\fR/g
  31.  try (=b)% s/\\fR\\fB//g
  32.  try (=b)% s/\\fR\\fI//g
  33.  (=b)1 i .nf
  34.  (=b) set nomod
  35.  (=b)split
  36. }
  37.  
  38. alias! kwic {
  39.  "Build a table showing instances of a word from the manual
  40.  local d
  41.  if "!^" == ""
  42.  then error :kwic missing lhs
  43.  let d=dirdir(elvispath("elvis.html"))
  44.  eval split +"kwictweak !^" !!grep -i -n -w !\^ (d/"*.html")
  45. }
  46.  
  47. alias! kwictweak {
  48.  "Convert grep's output to a nice HTML table
  49.  local ic report=0 magic magicchar=^$.[*
  50.  try %s/    / /g
  51.  try %s/ \{2,}/ /g
  52.  try %s/<[^>]*>//g
  53.  try %s/&[[:alnum:]]*;//g
  54.  try v/\<!\^\>/d
  55.  %s/^\([^:]*\):\([^:]*\):\(.*\)\<\(!\^\)\>\(.*\)$/\3<a href="\1?\2">\4<\/a\>\5/
  56.  %s/^/                              /
  57.  %s/^[^<]*\([^<]\{30}<.*>.\{0,30}\).*$/\1/
  58.  1 i <h1>Instances of "!^" in elvis' manual</h1><pre>
  59.  $ a </pre>
  60.  se bd=html mapmode=html nomod
  61.  dis html
  62.  1;/>\=!\^
  63. }
  64.  
  65. alias! text {
  66.  "Like :tag but for any text in *.c or *.h
  67.  local tagprg="grep -nsw '(quote(\"'\",$1))' *.[ch] /dev/null \| sed 's/^\\\\\\(.*\\\\\\):\\\\\\(.*\\\\\\):.*/!^    \\1    \\2/'"
  68.  tag!? !*
  69. }
  70.  
  71. alias! btext {
  72.  "Like :browse but for any text in *.c or *.h
  73.  local tagprg="grep -nsw '(quote(\"'\",$1))' *.[ch] /dev/null \| sed 's/^\\\\\\(.*\\\\\\):\\\\\\(.*\\\\\\):.*/!^    \\1    \\2/'"
  74.  browse!! !*
  75. }
  76.  
  77. if gui=="x11"
  78. then {
  79.  alias! courier {
  80.   "Use courier fonts of a given size (X11 only)
  81.   local s=!(18)1 w=!(medium)2
  82.   if !isnumber(s)
  83.   then error usage: courier [fontsize ["bold"]]
  84.   let font="*-courier-";w;"-r-*-";s;"-*"
  85.   let italicfont="*-courier-";w;"-o-*-";s;"-*"
  86.   if w != "bold"
  87.    then let boldfont="*-courier-bold-r-*-";s;"-*"
  88.  }
  89.  
  90.  alias! fork {
  91.   "Run a program in the background (X11 only)
  92.   !! >/dev/null 2>&1 !* &
  93.  }
  94.  
  95.  alias! theme {
  96.    "list themes, or load one
  97.    local a="" i j k d f
  98.    if "!1" == ""
  99.    then {
  100.      for i (1..elvispath[:,0])
  101.      do {
  102.        let d=elvispath[:,i]
  103.        for f shell("echo" d/"themes/*.ex")
  104.        do {
  105.      set k=0
  106.      for j a
  107.      do {
  108.        if basename(f) == j
  109.        then set k=1
  110.      }
  111.      if basename(f) != "*" && k == 0
  112.      then let a=a basename(f)
  113.        }
  114.      }
  115.      if a == ""
  116.      then error no themes
  117.      else calc a
  118.    }
  119.    else {
  120.      source (elvispath("themes/!1.ex"))
  121.    }
  122.  }
  123.  
  124.  alias! readTHEME {
  125.    " download a "theme:name" URL
  126.    local a="ftp://ftp.cs.pdx.edu/pub/elvis/themes_archive"
  127.    local f nowrapscan magicchar="^$[*." magic report=0 nolock
  128.    set reol=text bufdisplay=normal
  129.    "
  130.    " Read the theme's files, in a single "*.thm" file
  131.    if "!2" == "" || "!2" == "/" || dirext("!2") != ""
  132.    then {
  133.      if "!2" == "" || "!2" == "/"
  134.      then let f=a/"index.html"
  135.      else let f=a/"!2"
  136.      r (f)
  137.      if strlen("!2") < 2 || tolower(basename("!2")<<4) == ".htm"
  138.      then {
  139.        eval %s/index.html/(quote("/~", a))\/&/g
  140.        eval %s/src="/&(quote("/~", a))\//g
  141.        set bd=html mapmode=html
  142.      }
  143.      else set bd=hex
  144.    }
  145.    else {
  146.      r (a)/!2.thm
  147.      "ta !2.thm
  148.      "
  149.      " Make sure the user's themes directory exists
  150.      if dirperm($HOME/".elvislib") != "notfile"
  151.      then !!mkdir ~/.elvislib
  152.      if dirperm($HOME/".elvislib/themes") != "notfile"
  153.      then !!mkdir ~/.elvislib/themes
  154.      "
  155.      " Extract the theme files
  156.      %s?^BEGIN \([^.][^[:space:]$/\\!!~]*\)?+;/^END /-w!! \~/.elvislib/themes/\1?x
  157.      "
  158.      " Delete the data, but keep any introductory comments
  159.      1;/^BEGIN /,$d
  160.      "
  161.      " The above steps are not considered to be modifications
  162.      set nomod
  163.      "
  164.      " Load the theme
  165.      theme !2
  166.    }
  167.  }
  168.  
  169.  alias! mktheme {
  170.    " Create a new theme, in the current buffer
  171.    local i p f="" magicname wrapscan report=0
  172.    if "!1" == ""
  173.    then error usage: mkthtme name
  174.    "
  175.    " put the introductory text into the buffer
  176.    %d
  177.    i !1
  178.    s/.*/\U&\E\n\nDescribe the theme here.  Include your name and any credits.\n/
  179.    "
  180.    " add the ex script for setting up the colors
  181.    $a BEGIN !1.ex
  182.    a try set textcursor=opaque
  183.    eval a color normal (color("normal"))
  184.    a if color("idle") != "like normal"
  185.    eval a then color idle (color("idle"))
  186.    if color("idle") == "like normal"
  187.    then warning You should probably set the idle colors to something other than "like normal"
  188.    for i in cursor selection bottom toolbar tool scrollbar scroll statusbar status 
  189.    do {
  190.      if color(i) == ""
  191.      then error You need to set the (i) colors
  192.      else eval a color (i) (color(i))
  193.    }
  194.    a END !1.ex
  195.    "
  196.    " add any image files
  197.    %s/\S\+\.xpm/let f = f "&"/x
  198.    for i (f)
  199.    do {
  200.      try 1;/^BEGIN $i/goto
  201.      else {
  202.        eval ("$")a BEGIN (i)
  203.        if exists(i)
  204.        then let p = i
  205.        else let p = elvispath("themes"/i)
  206.        "Note: The odd method of reading the image files is necessary due to the
  207.        "fact that sometimes the last line is a comment without a \n terminator.
  208.        eval r !! cat (p); echo
  209.        $s/.*/END $i/
  210.      }
  211.    }
  212.    "
  213.    " leave the cursor on the line with the comment
  214.    3
  215.    "
  216.    " rename the edit buffer.  This also displays the new name on the bottom row
  217.    if filename != "!1.thm"
  218.    then file !1.thm
  219.  }
  220. }
  221.  
  222. alias! copying split (elvispath("license"))
  223.  
  224. alias! howto {
  225.  "Search elvis' "How To" appendix.  ! makes it try harder.
  226.  local magic magicchar=^$.[*
  227.  if "!?" == "!!"
  228.  then split +/*!1.*!2.*!3.*!4 (elvispath("howto.html"))
  229.  else split +/^<dt>.*!1.*!2.*!3.*!4 (elvispath("howto.html"))
  230. }
  231.  
  232. alias! cbload {
  233.  "Load cut-buffers from a file
  234.  local b report=0 magic magicchar=^$.[*
  235.  let b=buffer
  236.  if "!1" == ""
  237.  then error cbload requires a file name
  238.  e !1
  239.  %s:^--CBS-- \([a-z]\)$:+;/^--CBS--/-1 y \1:x
  240.  eval buffer (b)
  241. }
  242.  
  243. alias! cbsave {
  244.  "Save cut-buffers to a file
  245.  local a b report=0
  246.  let b = buffer
  247.  if "!1" == ""
  248.  then error cbsave requires a file name
  249.  e !1
  250.  %d
  251.  let a = 'a'
  252.  while a <= 'z'
  253.  do {
  254.   if buffer("Elvis cut buffer ";char(a))
  255.   then {
  256.    eval $ a --CBS-- (char(a))
  257.    eval $ put (char(a))
  258.   }
  259.   let a = a + 1
  260.  }
  261.  $ a --CBS--  
  262.  w!?
  263.  eval buffer (b)
  264. }
  265.  
  266. alias! cbshow {
  267.  "Show contents of cut-buffers
  268.  local b c i l="!*" q u s
  269.  if l == ""
  270.  then let l = "abcdefghijklmnopqrstuvwxyz123456789"
  271.  echo Buf\| Size & Type \| Contents
  272.  echo ---+-------------+----------------------------------------------------
  273.  for i (1 .. strlen(l))
  274.  do {
  275.   let c = ((l;" ") << i) >> 1
  276.   let b = "Elvis cut buffer ";c
  277.   if buffer(b)
  278.   then {
  279.    (=b) let u = putstyle << 4;
  280.    (=b) let q = u=="char" ? bufchars - 1 : buflines
  281.    let s = q; " "; u; (q == 1 ? " " : "s")
  282.    (=b) calc " "; c; " |"; s >> 12; " | "; line(b,1) << 52
  283.   }
  284.   let i = i + 1
  285.  }
  286. }
  287.  
  288. alias! fe features
  289. alias! features {
  290.  "Describe the configuration of this elvis
  291.  local i f l
  292.  
  293.  calc "Elvis version:     ";version
  294.  
  295.  set f="normal"
  296.  for i in syntax hex html man tex
  297.  do let f=f (feature(i) ? i)
  298.  calc "Display modes:     ";f
  299.  
  300.  set f=""
  301.  let f=f (feature("ftp") ? "ftp")
  302.  let f=f (feature("http") ? "http")
  303.  calc "Network protocols: ";(f ? f : "none")
  304.  
  305.  set f="" l="Other features:    "
  306.  for i in alias array autocmd backtick browse cachedesc calc complete fold g hlobject hlsearch image incsearch litre lpr make mapdb misc mkexrc normal proto ram rcsid showtag smartargs spell split tags textobj v
  307.  do {
  308.   if feature(i)
  309.   then {
  310.    if strlen(l;f i) > columns-2
  311.    then {
  312.     calc l;f
  313.     set l="                   " f="" 
  314.    }
  315.    let f=f i
  316.   }
  317.  }
  318.  if f != ""
  319.  then calc l;f
  320. }
  321.  
  322. alias! customize {
  323.  "Edit a personal copy of one of elvis' configuration files
  324.  local d o n f="!^"
  325.  if f == ""
  326.  then error :customize requires the name of a configuation file
  327.  let o = elvispath(f)
  328.  if o == ""
  329.  then error "!^" is not a known configuration file
  330.  if os=="msdos" || os=="os2" || os == "win32"
  331.  then let d=$HOME/"elvislib"
  332.  else let d=$HOME/".elvislib"
  333.  if dirperm(d) == "new"
  334.  then eval !mkdir "(d)"
  335.  let n = d / f
  336.  if exists(n)
  337.  then e (n)
  338.  else {
  339.     e (o)
  340.     (=o) file (n)
  341.     (=n)se noro
  342.  }
  343. }
  344.  
  345. alias! left {
  346.  "Move text to the left side of each line
  347.  local report=0 magic magicchar=^$.[*
  348.  !%s/^\s*
  349.  !%s/\s*$
  350. }
  351.  
  352. alias! right {
  353.  "Move text to the right side of each line
  354.  local w report=0 magic magicchar=^$.[*
  355.  !%left
  356.  try !%s/ \{2,}/ /g
  357.  let w = (textwidth == 0) ? columns : textwidth
  358.  eval !%s/.$/&("" << w)
  359.  eval !%s/^\\\(.\\{(w)}\\\).*/\\1
  360.  !%s/^\(.*[^ ]\)\( \+\)$/\2\1/
  361. }
  362.  
  363. alias! center {
  364.  "Move text to the center of each line
  365.  local report=0 magic magicchar=^$.[*
  366.  !%right
  367.  !%s/  / /g
  368. }
  369.  
  370. alias! rot13 {
  371.  "Perform rot-13 encryption/decryption
  372.  local i report=0 magic magicchar=^$.[*
  373.  for i (0..12)
  374.  do {
  375.   try eval !%s/(char(i + 'a'))/<TEMP>/g
  376.   try eval !%s/(char(i + 'n'))/(char(i + 'a'))/g
  377.   try eval !%s/<TEMP>/(char(i + 'n'))/g
  378.   try eval !%s/(char(i + 'A'))/<temp>/g
  379.   try eval !%s/(char(i + 'N'))/(char(i + 'A'))/g
  380.   try eval !%s/<temp>/(char(i + 'N'))/g
  381.  }
  382. }
  383.  
  384. alias! cfmt {
  385.  "Adjust C or C++ comment block.  Omit the */ line from range.
  386.  local report=0 nosaveregexp magic magicchar=^$.[*
  387.  if !< == !>
  388.  then error you must invoke cfmt with a range of two or more lines
  389.  !>a STOP!!
  390.  try !%s/^\(\s*\)\/\/\s*/\1/
  391.  then {
  392.   "C++ comments, already removed the //
  393.   !%!!fmt
  394.   !<,/^STOP!!$/- s/^\s*/&\/\/ /
  395.  }
  396.  else {
  397.   "C comments, still need to remove the /* or *
  398.   !<s,^\s*\([/ ]\*\)\s*,let a="\1",x
  399.   !%s,^\(\s*\)[/ ]\*\s*,\1,
  400.   !%!!fmt
  401.   eval !< s,^\\s*,&(a) ,
  402.   try !<+,/^STOP!!$/- s,^\s*,& * ,
  403.  }
  404.  /^STOP!!$/d
  405. }
  406.  
  407. alias! wascii {
  408.  "Write formatted text as plain ASCII
  409.  local lptype=dumb nolpheader lplines=0
  410.  if "!*" == ""
  411.  then error You must specify a file name
  412.  !% lp!? !*
  413. }
  414.  
  415. alias! lpd {
  416.  "Print text using the current display mode
  417.  local bufdisplay
  418.  let bufdisplay=display
  419.  !%lpr!? !*
  420. }
  421.  
  422. if feature("fold")
  423. then {
  424.   alias! foldc {
  425.     " Fold C functions and conditional code
  426.     local l magic magicchar=^$.[*
  427.     let l = current("line")
  428.  
  429.     " This alias works around a bug -- The :g command gets confused by
  430.     " the :fold command, apparently because it changes the definition of
  431.     " `line' as the :g is running.  The work-around is to use :unfold
  432.     " until all of the :g commands are finished, and then do :%fold! to
  433.     " fold them.
  434.  
  435.     " #if and #else directives
  436.     g/^\s*#\s*[ie][fl]/ {
  437.       local t a z
  438.       let t = quote("()$",line())
  439.       let a = current("line");
  440.       normal ^%
  441.       eval (a),- unfold (t)
  442.     }
  443.  
  444.     " function bodies
  445.     if feature("showtag")
  446.     then {
  447.       g/^{/ {
  448.     if current("tag")
  449.     then .,/^}/ unfold { (current("tag")) }
  450.     else .,/^}/ unfold { ... }
  451.       }
  452.     }
  453.     else g/^{/,/^}/ unfold { ... }
  454.  
  455.     " now fold everything
  456.     %fold!
  457.     eval (l)
  458.   }
  459. }
  460.  
  461. alias! sperror {
  462.   " Show the errors from a :make or :cc command, in a new window
  463.   if !window("Elvis error list")
  464.   then (Elvis error list)split
  465. }
  466.  
  467. alias! makehtml {
  468.  "Convert plain text to HTML source
  469.  local report=0 m=text n=text b=false magic magicchar=^$.[*
  470.  "
  471.  " m is current line mode -- one of "text", "pre", "ol", or "ul"
  472.  " n is next line mode
  473.  " b is a flag for detecting series of blank lines.
  474.  " 
  475.  " For each line...
  476.  !%g /^/ {
  477.   " Protect characters which are special to HTML
  478.   try s/&/\&/g
  479.   try s/</\</g
  480.   try s/>/\>/g
  481.   "
  482.   " Convert uppercase lines into headings
  483.   try s/^[A-Z0-9][A-Z0-9-.)     ]*$/<h1>&<\/h1>/
  484.   then set n=text
  485.   "
  486.   " Convert horizontal lines into <hr> tags
  487.   try s/^\s*[-=]\{10,}\s*$/<hr>/
  488.   then set n=text
  489.   "
  490.   " Try to be clever about finding links
  491.   try s/http:[^">,     )]\+/<a href="&">&<\/a>/g
  492.   try s/ftp:[^">,     )]\+/<a href="&">&<\/a>/g
  493.   try s/[a-zA-Z]\w*@[a-zA-Z][[:alnum:].-]\+/<a href="mailto:&">&<\/a>/g
  494.   "
  495.   " Convert asterisked lines into "ul" list items.
  496.   try s/^\s*\* */<li>/
  497.   then set n=ul
  498.   "
  499.   " Convert numbered lines (other than headings) into "ol" list items.
  500.   try s/^\s*\d\+[.)] \+/<li>
  501.   then set n=ol
  502.   "
  503.   " if in normal text, then assume indented text is preformatted.
  504.   if m=="text"
  505.   then {
  506.    try s/^\s/set n=pre/x
  507.   }
  508.   "
  509.   " if in preformatted text, then assume non-indented line ends <pre> block
  510.   if m=="pre" && n=="pre"
  511.   then {
  512.    try s/^\S/set n=text/x
  513.   }
  514.   "
  515.   " Any non-blank line turns off the "b" flag.
  516.   try s/./set b=false/x
  517.   "
  518.   " if not in formatted text, then blank lines are paragraph breaks.  Avoid
  519.   " consecutive <p> tags, though.
  520.   if m!="pre" && b=="false"
  521.   then {
  522.    try s/^$/<p>/
  523.    then set b=true
  524.   }
  525.   "
  526.   " if mode switched, then add tags for that.
  527.   if m!=n
  528.   then {
  529.    if m!="text"
  530.    then eval i </(m)>
  531.    if n!="text"
  532.    then eval i <(n)>
  533.    let m=n
  534.    set b=false
  535.   }
  536.  }
  537.  "
  538.  " If converting the whole file, then add <html>...</html>
  539.  if "!%" == ""
  540.  then {
  541.   $a </body></html>
  542.   eval 1i <html><head><title>(htmlsafe(filename))</title></head><body>
  543.   "
  544.   " minor conveniences...
  545.   set bufdisplay=html mapmode=html
  546.   display html
  547.   eval file (dirdir(filename)/basename(filename)).html
  548.  }
  549. }
  550.  
  551. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  552. " The following were contributed by Ian Utley (iu@apertus.uk.com)
  553.  
  554. alias! align {
  555.     "Align any = signs (or other given text) in selected line
  556.     local f=0 i=0 k report=0 nosaveregexp magic magicchar=^$.[*
  557.     "
  558.     " The following if tests to see if we have visually highlighted lines.
  559.     "
  560.     if ( !> !!= "" )
  561.     then {
  562.         !< mark a
  563.         !> mark b
  564.         let f=1
  565.     }
  566.     if ( f == 1)
  567.     then {
  568.         "
  569.         " Initialise i which will store the alignment column.
  570.         " Mark the current line to return the cursor at the end.
  571.         "
  572.         set i=0
  573.         mark z
  574.         "
  575.         " Remove any whitespace before the alignment character.
  576.         "
  577.         'a,'b s/[     ]*!(=)\$/!(=)\$/
  578.         "
  579.         " We could be aligning != <= or >= so we want to keep this letter
  580.         " near. Of course we may not be aligning an equals but we commonly do.
  581.         "
  582.         if ( "!(=)\$" == "=" )
  583.         then {
  584.             'a,'b s/[     ]*\([!!<>]*\)!(=)\$[     ]*/ \1!(=)\$ /
  585.         } 
  586.         "
  587.         "
  588.         let f=0
  589.         'a,'bglobal /!(=)\$/ {
  590.             " 
  591.             " Special case for the top line as -1 will not work.
  592.             "
  593.             if ( current("line") == 1 )
  594.             then {
  595.                 1 insert ""
  596.                 let f=1
  597.             }
  598.             -1
  599.             /!(=)\$
  600.             "
  601.             "
  602.             " Remember the largest column number for alignment.
  603.             "
  604.             if (current("column")>i)
  605.             then let i=current("column")
  606.             "
  607.             " Special case removal
  608.             "
  609.             if ( current("line") > 1 && f == 1)
  610.             then {
  611.                 1 delete
  612.                 let f=0
  613.             }
  614.         }
  615.         "
  616.         " Do the alignment.
  617.         "
  618.         let f=0
  619.         'a,'bglobal /!(=)\$/ {
  620.             " 
  621.             " Special case for the top line as -1 will not work.
  622.             "
  623.             if ( current("line") == 1 )
  624.             then {
  625.                 1i ""
  626.                 let f=1
  627.             }
  628.             -1
  629.             /!(=)\$
  630.             "
  631.             " Not sure why I need to add +1
  632.             "
  633.             let k=i-current("column")+1
  634.             s/\([!!<>]*\)!(=)\$/                                                                                \1!(=)\$/
  635.             eval s/ *\\\( \{(k)\}[!!<>]*!(=)\$\\\)/\1
  636.             "
  637.             " Special case removal
  638.             "
  639.             if ( current("line") > 1 && f == 1 )
  640.             then {
  641.                 1 delete
  642.                 let f=0
  643.             }
  644.         }
  645.         "
  646.         " Return the cursor to the line it was previously on.
  647.         "
  648.         'z
  649.     }
  650. }
  651.  
  652. alias! match {
  653.     "Move to the line where the pairing keyword is located
  654.     local a b="" d x y i nowrapscan magic magicchar=^$.[*
  655.     "x and y are lists of matching words -- we'll seek forward from x words
  656.     "and backward from y words.  The words listed here are appropriate for
  657.     "Unix shell scripts.
  658.     set x="if/then/case/do/begin/repeat" y="fi/else/esac/done/end/until"
  659.     let a=current("word")
  660.     if (a == "")
  661.     then error Cursor is not on a word
  662.     while b=="" && x!="."
  663.     do {
  664.     if a==dirfile(x)
  665.     then {
  666.         let b=dirfile(y)
  667.         set d=forward
  668.     }
  669.     if a==dirfile(y)
  670.     then {
  671.         let b=dirfile(x)
  672.         set d=backward
  673.     }
  674.     let x=dirdir(x)
  675.     let y=dirdir(y)
  676.     }
  677.     if ( b=="" )
  678.     then error (a) is not a matchable keyword 
  679.     mark c
  680.     set i=1
  681.     if (d=="forward")
  682.     then {
  683.         while ( i != 0 )
  684.         do {
  685.             set i=0
  686.             try eval /\<(b)\>
  687.             else {
  688.                 " Failed to locate a match
  689.                 'c
  690.                 error No matching (b) located
  691.             }
  692.             mark d
  693.             eval 'c,'d global /\<(a)\>/ let i=i+1
  694.             eval 'c,'d global /\<(b)\>/ let i=i-1
  695.         }
  696.     }
  697.     if (d=="backward") 
  698.     then {
  699.         while ( i != 0 )
  700.         do {
  701.             set i=0
  702.             try eval ?\<(b)\>
  703.             else {
  704.                 " Failed to find a match
  705.                 'c
  706.                 error No matching (b) located
  707.             }
  708.             mark d
  709.             eval 'd,'c global /\<(a)\>/ let i=i+1
  710.             eval 'd,'c global /\<(b)\>/ let i=i-1
  711.             " global command has moved cursor back to 'c
  712.             'd
  713.         }
  714.     }
  715. }
  716.