#!/usr/bin/perl

=begin metadata

Name: fmt
Description: reformat paragraphs
Author: Dmitri Tikhonov dmitri@cpan.org
License: perl

=end metadata

=cut


use strict;
use warnings;

use File::Basename qw(basename);
use Getopt::Long;

use constant EX_SUCCESS => 0;
use constant EX_FAILURE => 1;

my $Program = basename($0);

my $MAX_WIDTH = 75;

@ARGV = new_argv();
Getopt::Long::config('bundling');
GetOptions(
    'w=i' => \$MAX_WIDTH,
) or usage();

my $fmt_line = '<' x $MAX_WIDTH;

my $line;

eval <<"FORMAT";
format =
^$fmt_line~~
\$line
.
FORMAT

my $rc = EX_SUCCESS;
foreach my $file (@ARGV) {
    next if (-d $file);
    my $fh;
    unless (open $fh, '<', $file) {
        warn "$Program: failed to open '$file': $!\n";
        $rc = EX_FAILURE;
        next;
    }
    fmt_file($fh);
    unless (close $fh) {
        warn "$Program: failed to close '$file': $!\n";
        $rc = EX_FAILURE;
    }
}
unless (@ARGV) {
    fmt_file(*STDIN);
}
if (length $line) {
    do write while length $line;
}
exit $rc;

sub usage {
    warn "usage: $Program [-w WIDTH] [file...]\n";
    exit EX_FAILURE;
}

sub fmt_file {
    my $fh = shift;

    while (<$fh>) {
        chomp;
        if (length) {
            if (length $line) {
                my $last_char = substr $line, -1, 1;
                if ('.' eq $last_char) {
                    $line .= "  ";
                } elsif (' ' ne $last_char and "\t" ne $last_char) {
                    $line .= " ";
                }
            }
            $line .= $_;
        } else {
            do write while length $line;
            print "\n";
        }
    }
}

# Take care of special case, bare -width option
sub new_argv {
    my @new;
    my $end = 0;

    foreach my $arg (@ARGV) {
        if ($arg eq '--' || $arg !~ m/\A\-/) {
            push @new, $arg;
            $end = 1;
            next;
        }

        if (!$end && $arg =~ m/\A\-([0-9]+)\Z/) { # historic
            push @new, "-w$1";
        } else {
            push @new, $arg;
        }
    }
    return @new;
}

__END__

=head1 NAME

fmt - simple text formatter

=head1 SYNOPSIS

B<fmt> [-WIDTH] [OPTION]... [FILE]...

=head1 DESCRIPTION

Reformat each paragraph in FILE(s), writing to standard output.  The
option -WIDTH is an abbreviated form of -w DIGITS.

=head1 OPTIONS

=over 4

=item -w DIGITS

Maximum line width.  This option can be specified in shortened version,
-DIGITS.  The default is 75.

=back

=head1 BUGS

Only ASCII text is handled correctly.

=head1 AUTHORS

Dmitri Tikhonov

This code is freely modifiable and freely redistributable under Perl's
Artistic License.
