[comp.editors] vi macro: `fold' lines

bowles@is.s.u-tokyo.ac.jp (Eric E. Bowles) (05/02/91)

In article <DANJ1.91Apr28061619@cbnewse.ATT.COM> might as well reply to netnews, it's the usual editor war writes:
>In article <1991Apr24.155049.21710@njitgw.njit.edu> ken@hertz.njit.edu 
>(Ken Ng CCCC) writes:
>>  Instead of scrolling through the actual function source code each and every
>>  time, if you could hide or close off certain sections of code from being
>>  presently displayable, you could find the functions easier.  If you were
>>  not sure how function 'foo' works, you could open up/display the text that
>>  was hidden.
>
> GNU Emacs got things like that:

Now so does vi... well, sort of.

My previous "word completion" macros were well received, so I decided
to put together a couple of macros to fold and unfold lines of text in
vi, more or less.  That is, it's possible to hide selected lines of
text and then expose them.   Text can be recursively folded (as long as
it's more than one line you're folding).  If you're careful, it's even
possible to save the folded file, quit, edit that file again, and
unfold it.  It's also quite easy to lose that text unless you know what
you're doing. :-(

Here is the basic command:

<1>  !<address> vfold <CR>

        To fold (hide) text, position the cursor on the first line that
        you want to hide, then hit "!" followed by a motion command
        that indicates the last line to be hidden, then type "vfold"
        and return.  (This filters the range of text to the shell
        command "vfold", which perhaps you should install in ~/bin).
        This command replaces the range of lines with the following
        ugly marker:

        $$FOLDED:-- 15 /usr/tmp/vifold.8137 --$$

        The number after the two dashes (e.g., "15") indicates the number of
        hidden lines.  The filename after that (e.g., "/usr/tmp/vifold.8137")
        tells where the hidden text was stored.  

        To unfold (expose) the hidden text, just pass the line containing the
        "folded" marker to "vfold", like this:  "!!vfold", and hit return.
        The `[u' macro below does precisely this.

Now here are some macros to make things easier:

<2>  [f   - This macro folds all lines between the opening and closing braces
            of a C function.  Specifically, it will find the previous 
            occurrence of ?^{? and fold lines until /^}/ is encountered.
            (Try it on a copy of a C source file and you'll understand what
            I'm trying to say...)

<3>  [u   - This unfolds the folded text that the cursor currently lies on.

<4>  [n   - This finds the next "folded text" marker (that ugly thingy).


WARNING: Do not use 'u' (undo) with these macros.  The "vfold" script 
         currently deletes the temporary file when text is unfolded.  By
         using "undo", it is possible to return to the "folded" state within
         vi, but the shell script will not know this.  The upshot is, if you
         unfold something, undo it, then unfold the same line, you will lose 
         the original text!  

         One solution would be to comment out the code in "vfold" that
         deletes the file.  However, you could be left with a bunch of
         temporary files that you'd have to remove yourself.

Here is the stuff you need to add to your .exrc (passed through "cat -v"):

|     " vi macros to fold and unfold text.
|     " by Eric Bowles <bowles@is.s.u-tokyo.ac.jp>
|     " (Let me know of improvements & bug fixes).
|     "
|     " Commands:
|     "   !<address> vfold   - fold specified range of lines.
|     "   [f                 - fold current C function.
|     "   [u                 - unfold current line.
|     "   [n                 - go to next folded line.
|     "
|     :map [f j[[j!/^}/-1^M~/bin/vfold^M
|     :map [u !!~/bin/vfold^M 
|     :map [n /^$$FOLDED:-- /^M

I've attached at the end of this posting a shar file containing a uuencoded
version of the above macros (just append it to your .exrc -- how convenient),
and the "vfold" shell script, which should be in your ~/bin directory.

Experiment with these, and be sure to let me know of any comments, 
improvements, and bug fixes.  
===============================================================================
Eric Edward Bowles              Dept of Information Science, Faculty of Science
                                University of Tokyo, 7-3-1 Hongo, Bunkyo-ku
bowles@is.s.u-tokyo.ac.jp       Tokyo, JAPAN 113.     +81-3-3812-2111 x4096

-----------------------------CUT HERE------------------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  exrc.fold.uu vfold
# Wrapped by bowles@adara on Thu May  2 15:57:56 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'exrc.fold.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'exrc.fold.uu'\"
else
echo shar: Extracting \"'exrc.fold.uu'\" \(614 characters\)
sed "s/^X//" >'exrc.fold.uu' <<'END_OF_FILE'
Xbegin 644 exrc.fold
XM(B!V:2!M86-R;W,@=&\@9F]L9"!A;F0@=6YF;VQD('1E>'0N"B(@8GD@17)I
XM8R!";W=L97,@/&)O=VQE<T!I<RYS+G4M=&]K>6\N86,N:G ^"B(@*$QE="!M
XM92!K;F]W(&]F(&EM<')O=F5M96YT<R F(&)U9R!F:7AE<RDN"B(*(B!#;VUM
XM86YD<SH*(B @(#H\861D<F5S<SX@=F9O;&0@(" M(&9O;&0@<W!E8VEF:65D
XM(')A;F=E(&]F(&QI;F5S+@HB(" @6V8@(" @(" @(" @(" @(" @("T@9F]L
XM9"!C=7)R96YT($,@9G5N8W1I;VXN"B(@("!;=2 @(" @(" @(" @(" @(" @
XM+2!U;F9O;&0@8W5R<F5N="!L:6YE+@HB(" @6VX@(" @(" @(" @(" @(" @
XM("T@9V\@=&\@;F5X="!F;VQD960@;&EN92X*(@HZ;6%P(%MF(&I;6VHA+UY]
XM+RTQ#7XO8FEN+W9F;VQD#0HZ;6%P(%MU("$A?B]B:6XO=F9O;&0-( HZ;6%P
X5(%MN("]>)"1&3TQ$140Z+2T@+PT*
X 
Xend
END_OF_FILE
if test 614 -ne `wc -c <'exrc.fold.uu'`; then
    echo shar: \"'exrc.fold.uu'\" unpacked with wrong size!
fi
# end of 'exrc.fold.uu'
fi
if test -f 'vfold' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'vfold'\"
else
echo shar: Extracting \"'vfold'\" \(1610 characters\)
sed "s/^X//" >'vfold' <<'END_OF_FILE'
X#!/bin/csh -f
X#
X# Shell script to fold and unfold lines in vi.
X#
X# By Eric Bowles <bowles@is.s.u-tokyo.ac.jp>
X# Public domain, of course.
X# Let me know of improvements and bug fixes!
X#
X# This script does two things.  First, if it receives from standard
X# input a bunch of text whose first line doesn't match the special
X# "folded line" pattern (see below), it will save the text in a temporary 
X# file and return a new "folded line" pattern containing the name of that
X# temporary file.  
X# Second, if this script receives a line that matches the "folded line"
X# pattern, it will return the contents of the file encoded in the pattern.
X# NOTE: It will also delete that temporary file.  Comment out that line if
X#       you wish to stay on the safe side.
X#
X# The "folded line" pattern looks like:
X# 	$$FOLDED:-- <# of lines> <filename> --$$
X#
X
Xset taghead             = '$$FOLDED:-- '
Xset tagtail             = ' --$$'
Xset filename_template   = /usr/tmp/vifold
X
X# Decide what to do based on the contents of the first input line.
Xset first_line = $<
X
Xif ("$first_line" =~ "$taghead"*"$tagtail") then	# Unfold text.
X    set line = ($first_line)
X    set filename = $line[3]
X
X    if (! -e $filename) then
X        echo '*** ACK! Cannot find '$filename' -- folded text may be lost.'
X		exit 1
X    endif
X    cat $filename
X    rm -f $filename		# not really safe... could comment this line out.
Xelse	# Fold text.
X    set filename = $filename_template.$$
X    echo "$first_line" >! $filename
X    cat >> $filename
X    set output = `wc -l $filename`
X    echo "$taghead$output$tagtail"		# Return "folded" marker.
Xendif
Xexit 0
END_OF_FILE
if test 1610 -ne `wc -c <'vfold'`; then
    echo shar: \"'vfold'\" unpacked with wrong size!
fi
chmod +x 'vfold'
# end of 'vfold'
fi
echo shar: End of shell archive.
exit 0
===============================================================================
Eric Edward Bowles              Dept of Information Science, Faculty of Science
                                University of Tokyo, 7-3-1 Hongo, Bunkyo-ku
bowles@is.s.u-tokyo.ac.jp       Tokyo, JAPAN 113.     +81-3-3812-2111 x4096