Paragraph reform in vi
JimG
jim at bilpin.UUCP
Tue Jun 20 03:17:30 AEST 1989
#{ v_unix.3 }
[ Long - about 280 lines ]
IN ARTICLE <19890 at adm.BRL.MIL>, thoyt at ddn-wms.arpa (Thomas Hoyt)
WRITES:
> Can vi reformat a paragraph, justifying it properly(left, right, or
> centered)?
IN ARTICLE <13816 at dartvax.Dartmouth.EDU>, andyb at coat.com (Andy Behrens)
WRITES:
> If you put the following line in your .exrc file, you can type "V" when
> the cursor is anywhere in a paragraph, and the entire paragraph will be
> rejustified by being piped through "fmt".
> map V 0}!{fmt^M}
For those, like me, who don't have fmt on their system, here are three
Bourne shell scripts which use awk to effect the required reformatting.
Use the usual vi ! operator to execute them, preceded by an optional
count, and succeeded by a context marker, ) for sentences, } for
paragraphs, and G for lines ( remember that vi requires two spaces after
a full stop to delimit a sentence ). The reformat scripts preserve blank
lines, so multiple paragraphs can be altered at once; lines can also be
protected by appending a CTRL M character, so a chunk of text can be
reformatted while leaving certain lines within it unchanged; optional
line width and left margin size can be specified, otherwise defaults are
taken from specified system variables, or assumed. See the detailed
comments at the start of each script for more information.
The following scripts are delimited by lines of +'s.
#+ START OF centre + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#{ centre 1.2 } Last update: 20-Apr-89 11:44
# Author: Jim Grimwood, Hatfield, England
# CENTRE TEXT TO SPECIFIED MARGIN
# Syntax : centre [arg1] [arg2]
# Optional arguments are :
# arg1 line size ( range 10 - 136 )
# arg2 margin size ( range 0 - 40 )
# Line/margin arguments on the command line are given priority; if not
# defined, shell environment variables PSIZE/PMARG are used; if not defined,
# defaults of 80/0 are used. Errors in any arguments supplied are trapped
# silently and defaults substituted.
# NOTE: Assumes tabstep to be 8.
# WARNING!: Avoid embedded apostrophes in awk comments!
PSIZE=${1:-$PSIZE}
PMARG=${2:-$PMARG}
if [ "$PSIZE" -lt 10 -o "$PSIZE" -gt 136 ]
then
PSIZE=80
fi
# The next line *shouldn't* be -lt 0 ( rather than -lt 1 ), because then
# invalid alphanumeric arguments wouldn't be trapped
if [ "$PMARG" -lt 1 -o "$PMARG" -gt 40 ]
then
PMARG=0
fi
# Convert embedded tabs to spaces first, to get 'length' char count correct
pr -e -t | \
awk '
BEGIN { SPACES = " " # 40 spaces
TABS = " " # 5 tabs
}
{ TEXT = substr( $0, index( $0, $1 ) ) # Omit leading white space
OFFSET = PMARG + int( ( PSIZE - length( TEXT ) ) / 2 )
CT = int( OFFSET / 8 )
CB = OFFSET - 8 * CT
print substr( TABS, 1, CT ) substr( SPACES, 1, CB ) TEXT
} ' PSIZE=$PSIZE PMARG=$PMARG
#+ END OF centre + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#+ START OF reform + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#{ reform 1.2 } Last update: 20-Apr-89 11:55
# Author: Jim Grimwood, Hatfield, England
# REFORMAT TEXT TO SPECIFIED LINE LENGTH / MARGIN - RAGGED RIGHT
# Syntax : reform [arg1] [arg2]
# Optional arguments are :
# arg1 line size ( range 10 - 136 )
# arg2 margin size ( range 0 - 40 )
# Line/margin arguments on the command line are given priority; if not
# defined, shell environment variables PSIZE/PMARG are used; if not defined,
# defaults of 80/0 are used. Errors in any arguments supplied are trapped
# silently and defaults substituted.
# Multiple paragraphs in the context area are re-formatted individually and
# kept separate; if you always want the context area to be merged into a
# single paragraph, then remove the clause 'NF == 0 ||' on the line marked
# '# <<<<' in the main awk program below.
# Lines marked with a CTRL M as the last character will print unchanged
# (useful for headings, embedded tables, and so on).
# NOTE: Assumes tabstep to be 8.
# WARNING!: Avoid embedded apostrophes in awk comments!
PSIZE=${1:-$PSIZE}
PMARG=${2:-$PMARG}
if [ "$PSIZE" -lt 10 -o "$PSIZE" -gt 136 ]
then
PSIZE=80
fi
# The next line *shouldn't* be -lt 0 ( rather than -lt 1 ), because then
# invalid alphanumeric arguments wouldn't be trapped
if [ "$PMARG" -lt 1 -o "$PMARG" -gt 40 ]
then
PMARG=0
fi
awk '
BEGIN { SPACES = " " # 40 spaces
TABS = " " # 5 tabs
}
# I`d like to be able to do the next bit in the BEGIN, but awk pretends not
# to know about the command line arguments at that time
NR == 1 { PSIZE = int( PSIZE ) # coerce to type int
CT = int( PMARG / 8 )
CB = PMARG - 8 * CT
MARGIN = substr( TABS,1,CT ) substr( SPACES,1,CB ) # set left margin
}
# The next un-commented line may display partially overprinted on
# your terminal, except in vi; the line should read (minus the #):
# { if( NF == 0 || substr( $0, length ) == "^M" )
# where the character in quotes is a single-byte CTRL M
{ if( NF == 0 || substr( $0, length ) == "
{ if( TEXT > "" )
{ print MARGIN TEXT
TEXT = ""
}
print
next
}
$1 = $1 # compress white space
# discard leading white space and append to previous text, if any
if( length( TEXT ) == 0 )
TEXT = substr( $0, index( $0, $1 ) )
else
TEXT = TEXT " " substr( $0, index( $0, $1 ) )
while( length( TEXT ) > PSIZE )
{ for( L = PSIZE+1; L > 0; L-- ) # find last word which fits
if( substr( TEXT, L, 1 ) == " " )
break
print MARGIN substr( TEXT, 1, L-1 )
TEXT = substr( TEXT, L+1 )
}
}
END { print MARGIN TEXT }
' PSIZE=$PSIZE PMARG=$PMARG
#+ END OF reform + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#+ START OF rjust + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#{ rjust 1.2 } Last update: 20-Apr-89 11:55
# Author: Jim Grimwood, Hatfield, England
# REFORMAT TEXT TO SPECIFIED LINE LENGTH / MARGIN - ALIGNED TO BOTH MARGINS
# Syntax : rjust [arg1] [arg2]
# Optional arguments are :
# arg1 line size ( range 10 - 136 )
# arg2 margin size ( range 0 - 40 )
# Line/margin arguments on the command line are given priority; if not
# defined, shell environment variables PSIZE/PMARG are used; if not defined,
# defaults of 80/0 are used. Errors in any arguments supplied are trapped
# silently and defaults substituted.
# Multiple paragraphs in the context area are re-formatted individually and
# kept separate; if you always want the context area to be merged into a
# single paragraph, then remove the clause 'NF == 0 ||' on the line marked
# '# <<<<' in the main awk program below.
# Lines marked with a CTRL M as the last character will print unchanged
# (useful for headings, embedded tables, and so on).
# NOTE: Assumes tabstep to be 8.
# WARNING!: Avoid embedded apostrophes in awk comments!
PSIZE=${1:-$PSIZE}
PMARG=${2:-$PMARG}
if [ "$PSIZE" -lt 10 -o "$PSIZE" -gt 136 ]
then
PSIZE=80
fi
# The next line *shouldn't* be -lt 0 ( rather than -lt 1 ), because then
# invalid alphanumeric arguments wouldn't be trapped
if [ "$PMARG" -lt 1 -o "$PMARG" -gt 40 ]
then
PMARG=0
fi
awk '
BEGIN { SPACES = " " # 40 spaces
TABS = " " # 5 tabs
}
# I`d like to be able to do the next bit in the BEGIN, but awk pretends not
# to know about the command line arguments at that time
NR == 1 { PSIZE = int( PSIZE ) # coerce to type int
CT = int( PMARG / 8 )
CB = PMARG - 8 * CT
MARGIN = substr( TABS,1,CT ) substr( SPACES,1,CB ) # set left margin
}
# The next un-commented line may display partially overprinted on
# your terminal, except in vi; the line should read (minus the #):
# { if( NF == 0 || substr( $0, length ) == "^M" )
# where the character in quotes is a single-byte CTRL M
{ if( NF == 0 || substr( $0, length ) == "
{ if( TEXT > "" )
{ print MARGIN TEXT
TEXT = ""
}
print
next
}
$1 = $1 # compress white space
# discard leading white space and append to previous text, if any
if( length( TEXT ) == 0 )
TEXT = substr( $0, index( $0, $1 ) )
else
TEXT = TEXT " " substr( $0, index( $0, $1 ) )
while( length( TEXT ) > PSIZE )
{ for( L = PSIZE+1; L > 0; L-- ) # find last word which fits
if( substr( TEXT, L, 1 ) == " " )
break
if( L-1 < PSIZE ) # if it`s a short line, spread it out
{ SPACE = 0
for( I = 1; I <= L-1; I++ ) # count spaces
if( substr( TEXT, I, 1 ) == " " )
SPACE++
CHARS = L - 1 - SPACE # no of non-space chars
WSEP = int( ( PSIZE - CHARS ) / SPACE ) # avg separation requ`d
WSEPC = substr( SPACES, 1, WSEP ) # avg separation spaces
LSEP = PSIZE - CHARS - WSEP * ( SPACE - 1 ) # remainder sep`tion
WTEXT = ""; WORDL=0; LASTW=0
for( I = 1; I <= L-1; I++ )
{ TCHAR = substr( TEXT, I, 1 )
if( TCHAR == " " )
{ if( LSEP > 2 ) # even out the separation
{ WTEXT = WTEXT WSEPC " "
LASTW += WORDL + WSEP + 1
LSEP--
}
else
{ WTEXT = WTEXT WSEPC
LASTW += WORDL + WSEP
}
WORDL = 0
}
else
{ WTEXT = WTEXT TCHAR
WORDL++ # length of current word
}
}
print MARGIN substr( WTEXT,1,LASTW-WSEP ) \
substr( SPACES,1,LSEP ) \
substr( WTEXT,LASTW+1 ) # phew! finally done it!
}
else
print MARGIN substr( TEXT, 1, L-1 )
TEXT = substr( TEXT, L+1 )
}
}
END { print MARGIN TEXT }
' PSIZE=$PSIZE PMARG=$PMARG
#+ END OF rjust + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
--
<Path: mcvax!ukc!icdoc!bilpin!jim> <UUCP: jim at bilpin.uucp>
{JimG : Hatfield, England}
This line has been intentionally left blank.
More information about the Comp.unix.questions
mailing list