These three routines (given inside a simple utility program) perform full justification of text by expanding the spaces between words until the line meets the specified width.
Each routine uses a different method, which basically means they use a different starting point within the line and work out from there. I think that middle_out() looks the best, followed closely by right_to_left(). Your call, though.
These routines are simple. They do not do any reflowing and if the lines start out longer than the width given, they just pass it through unmodified. Update: If you want reflowing, just pass the text through Text::Wrap first.
Significate Update: I posted a new version as a reply below. It simplifies the code in the method somewhat and fixes a few bugs related to getting the options. More info below. :-)
#!/usr/bin/perl -wn BEGIN { $LINE_WIDTH = 75; $METHOD = 'middle_out'; $CONDENSE = 1; use Getopt::Long; Getopt::Long::Configure('bundling'); GetOptions( 'condense!' => \$CONDENSE, 'm|middle' => sub { $METHOD = 'middle_out' }, 'l|left' => sub { $METHOD = 'left_to_right' }, 'r|right' => sub { $METHOD = 'right_to_left' }, 'w|width=i' => \$LINE_WIDTH, 'help' => sub { my $self = $0; $self =~ s/^.*\///; die << "USAGE"; Usage: $self [OPTION]... [FILE]... Fully justifies a stream of text using one of three different methods. --condense condense multiple spaces before justifying (de +fault) --nocondense -m, --middle use the middle-out method (default) -l, --left use the left-to-right method -r, --right use the right-to-left method -w, --width=WIDTH set the line-width to WIDTH (default is 75) --help display this help and exit The different methods describe where $self starts expanding spaces to get lines to be the appropriate width. For example, middle-out starts in the middle of the line, expanding spaces in both directions. The middle-out method usually looks best, although right-to-left is some- times better. USAGE }, ); } if($CONDENSE) { s/^ +| +$//g; s/(?<!\. ) {2,}/ /g; } if(defined $last_line) { if($last_line !~ /^$/ and $_ !~ /^$/) { $last_line = $METHOD->($last_line, $LINE_WIDTH); } print $last_line; } $last_line = $_; END { print $last_line if defined $last_line } sub middle_out { my $line = shift; my $width = shift; while(length($line) < $width) { my $pr = my $pf = int(length($line) / 2); # Start from the mid +dle until($pr == -1 and $pf == -1) { $pr = rindex $line, ' ', $pr; if($pr > -1) { substr $line, $pr, 1, ' '; --$pr; # Skip the space that was there. ++$pf; ++$pf; # Adjust $pf to match what's really the +re now last unless(length($line) < $width); } $pf = index $line, ' ', $pf; if($pf > -1) { substr $line, $pf, 1, ' '; ++$pf; ++$pf; # Skip the two spaces we just made last unless(length($line) < $width); } } } return $line; } sub right_to_left { my $line = shift; my $width = shift; while(length($line) < $width) { my $pr = rindex $line, ' '; while($pr >= 0 and length($line) < $width) { substr $line, $pr, 1, ' '; --$pr; # Skip the space that was there $pr = rindex $line, ' ', $pr; } } return $line; } sub left_to_right { my $line = shift; my $width = shift; my $width = shift; while(length($line) < $width) { my $pr = rindex $line, ' '; while($pr >= 0 and length($line) < $width) { substr $line, $pr, 1, ' '; --$pr; # Skip the space that was there $pr = rindex $line, ' ', $pr; } } return $line; } sub left_to_right { my $line = shift; my $width = shift; while(length($line) < $width) { my $pf = index $line, ' '; while($pf >= 0 and length($line) < $width) { substr $line, $pf, 1, ' '; ++$pf; # Skip the space that was there ++$pf; # Skip the extra space we just put in $pf = index $line, ' ', $pf; } } return $line; }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
(bbfu) (Version 2) Re: Full justification - 3 methods
by bbfu (Curate) on Apr 13, 2001 at 05:30 UTC | |
|
Re: Full justification - 3 methods
by tinman (Curate) on Apr 06, 2001 at 01:54 UTC | |
by bbfu (Curate) on Apr 06, 2001 at 03:02 UTC |