#!/usr/bin/env perl
# This way of calling perl is universal - it should work
# on Sun, Linux, OpenBSD and MacOS.
# The previous call for perl was: !/usr/local/bin/perl
#
# fmt
#
# Lawrence Kesteloot, lk@unc.edu, November 27th, 1994
#
# This script is similar to "fmt", except that if a leading set of
# non-alphanumeric characters is present on all lines, it is stripped
# before formatting and reinserted afterwards.
#
# usage:   fmt [width] file
#    or:   fmt [width] <file
#
# $emptyfirst is for vi's !} command, which includes the empty line just
# before the paragraph.
#

# 2002 April 10 source:
# http://tofu.alt.net/~lk/fmt
# (now gone)

# 2003 June 2: Tom Schneider's note:
# a line with about 80 '*' causes an infinite loop!

# 2003 June 2:
#    ----- The following addresses had permanent fatal errors -----
# <lk@unc.edu>
#     (reason: 550 5.1.1 <kesteloo@cs.unc.edu>... User unknown)
# try from the web site:
# lk1@teamten.com

$width = 70;
$emptyfirst = 0;

if ($ARGV[0] =~ /^\d+$/) {
    $width = shift;
}

@line = <>;
chop @line;

if ($#line >= 0 && $line[0] =~ /^$/) {
    splice (@line, 0, 1);
    $emptyfirst = 1;
}

$linenum = @line;

$leader = "";
leader: while (($toadd = substr ($line[0], length ($leader), 1)) =~ /\W|_/) {
    $leader .= $toadd;
    ($chopleader = $leader) =~ s/\s+$//;
    line: for ($i = 0; $i < $linenum; $i++) {
	if ((substr ($line[$i], 0, length ($leader)) ne $leader) &&
	    $line[$i] ne $chopleader) {
	    last line;
	}
    }
    if ($i < $linenum) {
	chop $leader;
	last leader;
    }
}
($chopleader = $leader) =~ s/\s+$//;

# print "Leader = '$leader', chopleader = '$chopleader'\n";

$paranum = 0;
for ($i = 0; $i < $linenum; $i++) {
    $line[$i] = substr ($line[$i], length ($leader));
    $line[$i] =~ s/ +$//; # Remove trailing spaces from line
    if ($line[$i] =~ /^$/) {
	$paranum++;
    } else {
	$para[$paranum] .= $line[$i] . " ";
	if ($line[$i] =~ /(\.|\!|\?)$/) {
	    $para[$paranum] .= " ";
	}
    }
}

$paranum++;
$width -= length ($leader);
while ($leader =~ /\t/g) {
    # Subtract tabs.  Not quite accurate, but close enough.
    $width -= 7;
}

if ($emptyfirst) {
    print "\n";
}

for ($i = 0; $i < $paranum; $i++) {
    $para[$i] =~ s/\s+$//;  # Remove trailing spaces
    while (length ($para[$i]) > $width) {
	$p = $para[$i];
	$space = rindex ($p, " ", $width);
	if ($space == -1) {
	    $para[$i] = substr ($p, $width);
	    $p = substr ($p, 0, $width) . "-";
	} else {
	    $para[$i] = substr ($p, $space + 1);
	    $p = substr ($p, 0, $space);
	}
	$para[$i] =~ s/^ +//;  # Remove leading spaces of non-first lines
	print "$leader$p\n";
    }
    print "$leader$para[$i]\n";
    print "$chopleader\n" if ($i < $paranum - 1 && length ($para[$i]) > 0);
}
