#!/usr/bin/perl -w
#<mfmt: formats long text lines for easier reading.

use strict;
use Getopt::Long;
use Pod::Usage;
use File::Basename;
use Text::Format;

use subs qw(manpage myuuid usage version where);
$ENV{'PATH'} = join ":", qw(/bin /usr/bin /usr/local/bin /opt/sfw/bin);

my $myname = basename($0);
$myname =~ s/\.\w*$//;   # strip any extension

# Handle defaults and command line arguments.

my $tabwidth = $ENV{'TABWIDTH'} || 8;
my $tab      = " " x $tabwidth;
my $top      = "$tab" . '-' x 68 . "S\n";
my $bottom   = "$tab" . '-' x 68 . "E\n";
my $linelen  = $ENV{'FMTWIDTH'} || 72;
my $infile   = '';
my $text;

my %options;
my @getopt_args = (
    'h|?',    # print usage
    'm',      # print manpage
    'n',      # no whitespace
    's',      # print source location
    'u',      # print UUID
    'v',      # print version
    'w=i',    # output width
    );

Getopt::Long::config("noignorecase", "bundling");
usage unless GetOptions(\%options, @getopt_args);

manpage if $options{'m'};
where   if $options{'s'};
myuuid  if $options{'u'};
version if $options{'v'};
usage   if $options{'h'};

if ($options{'n'}) {
    $top = $bottom = $tab = '';
    $tabwidth = 0;
}

if ($options{'w'}) {
    $linelen = $options{'w'};
}

# We want output lines to start with whitespace, and be indented
# an additional 4 spaces if it's a long line.  If it's a short
# line, leave it alone except for any leading whitespace.

$text = new Text::Format or die "Text::Format: $!\n";

$text->columns($linelen);
$text->leftMargin($tabwidth);
$text->tabstop($tabwidth);
$text->firstIndent(0);
$text->bodyIndent(4);

print $top;
while (<>) {
    if (length() >= $linelen) {
        $_ = $text->format($_);
    }
    else {
        $_ = "$tab" . $_;
    }

    $_ = $text->expand($_);
    s/  *$//;
    print;
}
print $bottom;

exit(0);

#---------------------------------------------------------------------
# Print a usage message from the comments and exit.

sub usage {
    my ($emsg) = @_;
    use Pod::Usage qw(pod2usage);
    warn "$emsg\n" if defined $emsg;
    pod2usage(-verbose => 99, -sections => "NAME|SYNOPSIS|OPTIONS");
}

sub manpage {
    my @args = ("perldoc", "$0");
    exec { $args[0] } @args;          # safe even with one-arg list
    die("should not get here\n");
}

#---------------------------------------------------------------------
# Print the UUID, current version, or source location.

sub myuuid {
    my $UUID = $1
        if q$UUID: 6fde6d69-e6ba-3ff8-8701-236c3bd4f10f $ =~ /UUID: (.*) /;
    print "$UUID\n";
    exit(0);
}

sub version {
    my $VERSION = sprintf("%d.%02d", q$Revision: 2.15 $ =~ /(\d+)\.(\d+)/);
    my $DATE = $1 if q$Date: 2010-09-07 14:59:59-04 $ =~ /Date: (.*) /;
    print "$myname $VERSION $DATE\n";
    exit(0);
}

sub where {
    my $SOURCE = $1
        if q$Source: /usr/local/src/m/mfmt/RCS/mfmt.pl,v $ =~
          /Source: (.*) /;
    my $HOST = $1 if q$Host: cmswramdas.wpafb.af.mil $ =~ /Host: (.*) /;
    print "file://$HOST", "$SOURCE\n";
    exit(0);
}

#---------------------------------------------------------------------
__END__

=head1 NAME

mfmt - formats output from make or script commands

=head1 SYNOPSIS

mfmt [-hmnsuv] [-w length] [file]

=head1 OPTIONS

=over 4

=item B<-h>

Print a brief help message and exit.

=item B<-m>

Print the manual page and exit.

=item B<-n>

Don't include dashed borders or leading whitespace.

=item B<-s>

Print the source location and exit.

=item B<-u>

Print the script UUID and exit.

=item B<-v>

Print the version and exit.

=item B<-w> LENGTH

Sets the maximum line length to LENGTH chars.

=back

=head1 DESCRIPTION

B<mfmt> formats output from B<make> or B<script> to fit on tabbed lines.
If the line is long enough, it will be broken and formatted
according to the supplied margins.  Continuation lines are preceded
by additional whitespace.

This picture describes the output in terms of variables
understood by Text::Format.

                          columns
  <--------------------------------------------------------->
  <----------><------><------------------------><----------->
   leftMargin  indent  text formatted into here  rightMargin

B<indent> is B<firstIndent> or B<bodyIndent> depending on where
we are in the paragraph.

=head1 EXAMPLE

Here's an unformatted line from "make":

  cc -I. -I../include -DOPENSSL... [191 chars] -o tmdiff.o tmdiff.c

Running it through "mfmt":

  --------------------------------------------------------------------S
  cc -I. -I../include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN
      -DHAVE_DLFCN_H -xtarget=ultra -m32 -xarch=sparc -xO5 -xstrconst
      -xdepend -Xa -DB_ENDIAN -DBN_DIV2W -c -o tmdiff.o tmdiff.c
  --------------------------------------------------------------------E

=head1 ENVIRONMENT

The following environment variables are used if present:

=over 4

=item B<TABWIDTH>

How many spaces per tab you want.  Default = 8.

=item B<FMTWIDTH>

Maximum length of each output line.  Default = 72.

=back

=head1 NOTES

Requires Text::Format.

=head1 AUTHOR

 Karl Vogel <vogelke+unix@pobox.com>
 Array Information Technology

=cut
