@EXPORT = qw(expand unexpand $tabstop);
use vars qw($VERSION $tabstop $debug);
-$VERSION = 2007.1117;
+$VERSION = 2009.0305;
use strict;
+= 2009/03/05
+
+Test improvements from Dave Mitchel sent back in 2005...
+
+Added code to increase $columns if it's not big enough to accommodate
+the subsequent tab.
+
+Minor documentation fixes from David Landgren <david at landgren.net>.
+
Use warnings::warnif instead of just warn for columns < 2. Appled per
request of Rafael Garcia-Suarez <rgarciasuarez at gmail.com>.
$Text::Wrap::columns=9;
$break="(?<=[,.])";
eval {
-$a=wrap('','',
+$a=$a=wrap('','',
"mmmm,n,ooo,ppp.qqqq.rrrrr,sssssssssssss,ttttttttt,uu,vvv wwwwwwwww####\n");
};
$Text::Wrap::columns=9;
$break="(?<=[,.])";
eval {
-$a=wrap('','',
+$a=$a=wrap('','',
"mmmm,n,ooo,ppp.qqqq.rrrrr.adsljasdf\nlasjdflajsdflajsdfljasdfl\nlasjdflasjdflasf,sssssssssssss,ttttttttt,uu,vvv wwwwwwwww####\n");
};
--- /dev/null
+
+use Text::Wrap;
+use Test::More tests => 2;
+$Text::Wrap::columns = 4;
+eval { $x = Text::Wrap::wrap('', '123', 'some text'); };
+is($@, '');
+is($x, "some\n123t\n123e\n123x\n123t");
+
--- /dev/null
+#!/usr/bin/perl -I. -w
+
+BEGIN {
+ if ($ENV{HARNESS_ACTIVE}) {
+ print "1..0 # Skipped: not a standard regression test\n";
+ exit;
+ }
+ unless (eval { require Benchmark; }) {
+ print "1..0 # Skipped: this test requires Benchmark.pm\n";
+ exit;
+ }
+}
+
+#From: dnsparks@juno.com
+#Subject: Text::Wrap suggestions
+#To: muir@idiom.com
+#Date: Sat, 10 Feb 2001 21:50:29 -0500
+#
+#David,
+#
+#I had a "word wrapping" problem to solve at work the other week.
+#Text::Wrap would have done exactly what I needed, but at work we use
+#Smalltalk. :-) (I ended up thinking about it at home, where I don't have
+#Smalltalk, so I first coded it in Perl and then "translated" my solution
+#at work.)
+#
+#I must admit that I was dealing with a specialized case; I didn't want to
+#prepend any strings on the first or subsequent lines of the paragraph
+#begin created. In other words, had we been using Perl at work, I would
+#have done something like this:
+#
+# use Text::Wrap qw(wrap $columns);
+# # ... set $columns, $string, etc. ...
+# return wrap("", "", $string);
+#
+#By the way, the copy of Wrap.pm came with the IndigoPerl distribution I
+#recently downloaded. This is the version string: $VERSION = 98.112902; I
+#don't know if that's the most recent.
+#
+#When I had some time, I was curious to see how my solution compared to
+#using your module. So, I threw together the following script:
+#
+#The interesting thing, which really surprised me, was that the results
+#seemed to indicate that my version ran faster. I was surprised because
+#I'm used to thinking that the standard Perl modules would always present
+#a better solution than "reinventing the wheel".
+#
+# mine: 24 wallclock secs (18.49 usr + 0.00 sys = 18.49 CPU) @ 54.09/s
+#(n=1000)
+# module: 58 wallclock secs (56.44 usr + 0.02 sys = 56.46 CPU) @ 17.71/s
+#(n=1000)
+#
+#Then, it occurred to me that the diffrence may be attributable to my
+#using substr() vs. the module relying on s///. (I recall reading
+#something on perlmonks.org a while back that indicated that substr() is
+#often faster than s///.)
+#
+#I realize that my solution has its problems (doesn't include ability to
+#specify first/subsequent line prefixes, and the possibility that it may
+#recurse itself out of memory, given a big enough input string). But I
+#though you might be interested in my findings.
+#
+#Dan
+#(perlmonks.org nick: t'mo)
+
+
+use strict;
+use Text::Wrap qw(wrap $columns);
+use Benchmark;
+
+my $testString = 'a;kjdf;ldsjf afkjad;fkjafkjafkj; dsfljasdfkjasfj;dThis
+is a test. It is only a test. Do not be alarmed, as the test should only
+take several seconds to run. Yadda yadda yadda...a;kjdf;ldsjf
+afkjad;fkjafkjafkj; dsfljasdfkjasfj;dThis is a test. It is only a test.
+Do not be alarmed, as the test should only take several seconds to run.
+Yadda yadda yadda...a;kjdf;ldsjf afkjad;fkjafkjafkj;
+dsfljasdfkjasfj;dThis is a test. It is only a test. Do not be alarmed, as
+the test should only take several seconds to run. Yadda yadda
+yadda...a;kjdf;ldsjf afkjad;fkjafkjafkj; dsfljasdfkjasfj;dThis is a test.
+It is only a test. Do not be alarmed, as the test should only take
+several seconds to run. Yadda yadda yadda...' x 5;
+
+$columns = 55;
+
+sub prefix {
+ my $length = shift;
+ my $string = shift;
+
+ return "" if( ! $string );
+
+ return prefix($length, substr($string, 1))
+ if( $string =~ /^\s/ );
+
+ if( length $string <= $length ) {
+ chop($string) while( $string =~ /\s$/ );
+ return $string . "\n";
+ }
+
+ my $pre = substr($string, 0, $length);
+ my $post = substr($string, $length);
+
+ if( $pre =~ /\s$/ ) {
+ chop($pre) while( $pre =~ /\s$/ );
+ return $pre . "\n" . prefix($length, $post);
+ }
+ else {
+ if( $post =~ /^\s/ ) {
+ return $pre . "\n" . prefix($length, $post);
+ }
+ else {
+ if( $pre !~ /\s/ ) {
+ return $pre . "\n" . prefix($length, $post);
+ }
+ else {
+ $pre =~ /(.*)\s+([^\s]*)/;
+ $post = $2 . $post;
+ return $1 . "\n" . prefix($length, $post);
+ }
+ }
+ }
+}
+
+my $x = prefix($columns, $testString);
+my $y = wrap("", "", $testString);
+
+unless ($x ne $y) {
+ print "1..0 # Skipped: dnspark's module doesn't give the same answer\n";
+ exit;
+}
+
+my $cnt = -T STDOUT ? 200 : 40;
+my $results = timethese($cnt, {
+ mine => sub { my $res = prefix($columns, $testString) },
+ module => sub { my $res = wrap("", "", $testString) },
+});
+
+if ($results->{module}[1] < $results->{mine}[1]) {
+ print "1..1\nok 1\n";
+} else {
+ print "1..0 # Skipped: Dan's implmentation is faster\n";
+}
+
+
$| = 1;
-my $numtests = scalar(@tests) / 2;
-print "1..$numtests\n";
+print "1..";
+print @tests/2;
+print "\n";
use Text::Wrap;
$| = 1;
-my $numtests = scalar(@tests) / 2;
-print "1..$numtests\n";
+print "1..";
+print @tests/2;
+print "\n";
use Text::Tabs;
-#!/usr/bin/perl5.00502
+#!/usr/bin/perl
-@tests = (split(/\nEND\n/s, <<DONE));
+@tests = (split(/\nEND\n/s, <<'DONE'));
TEST1
This
is
Lines
END
+TEST13 break=\d
+I saw 3 ships come sailing in
+END
+ I saw 3 ships come sailing in
+END
+TEST14 break=\d
+the.quick.brown.fox.jumps.over.the.9.lazy.dogs.for.no.good.reason.whatsoever.apparently
+END
+ the.quick.brown.fox.jumps.over.the.
+ .lazy.dogs.for.no.good.reason.whatsoever.apparently
+END
DONE
my $in = shift(@st);
my $out = shift(@st);
- $in =~ s/^TEST(\d+)?\n//;
+ $in =~ s/^TEST(\d+)( break=(.*))?\n//
+ or die "bad TEST header line: $in\n";
+ local $Text::Wrap::break = $3 if defined $3;
my $back = wrap(' ', ' ', $in);
my $in = shift(@st);
my $out = shift(@st);
- $in =~ s/^TEST(\d+)?\n//;
+ $in =~ s/^TEST(\d+)( break=(.*))?\n//
+ or die "bad TEST header line: $in\n";
+ local $Text::Wrap::break = $3 if defined $3;
my @in = split("\n", $in, -1);
@in = ((map { "$_\n" } @in[0..$#in-1]), $in[-1]);
--- /dev/null
+#!/usr/local/bin/perl -w
+#Author: Dan Dascalescu
+use strict;
+use Test::More tests => 1;
+
+use Text::Wrap;
+
+local $Text::Wrap::columns = 15;
+local $Text::Wrap::separator2 = '[N]';
+
+is(wrap('','','some long text here that should be wrapped on at least three lines'),
+"some long text[N]here that[N]should be[N]wrapped on at[N]least three[N]lines",
+'If you just to preserve existing newlines but add new breaks with something else, set $Text::Wrap::separator2 instead.');
@EXPORT = qw(wrap fill);
@EXPORT_OK = qw($columns $break $huge);
-$VERSION = 2006.1117;
+$VERSION = 2009.0305;
use vars qw($VERSION $columns $debug $break $huge $unexpand $tabstop
$separator $separator2);
my $tail = pop(@t);
my $t = expand(join("", (map { /\s+\z/ ? ( $_ ) : ($_, ' ') } @t), $tail));
my $lead = $ip;
+ my $nll = $columns - length(expand($xp)) - 1;
+ if ($nll <= 0 && $xp ne '') {
+ my $nc = length(expand($xp)) + 2;
+ warnings::warnif "Increasing \$Text::Wrap::columns from $columns to $nc to accommodate length of subsequent tab";
+ $columns = $nc;
+ $nll = 1;
+ }
my $ll = $columns - length(expand($ip)) - 1;
$ll = 0 if $ll < 0;
- my $nll = $columns - length(expand($xp)) - 1;
my $nl = "";
my $remainder = "";
values so that the original value is restored. This C<local()> trick
will not work if you import the variable into your own namespace.
-Lines are wrapped at C<$Text::Wrap::columns> columns. C<$Text::Wrap::columns>
-should be set to the full width of your output device. In fact,
-every resulting line will have length of no more than C<$columns - 1>.
+Lines are wrapped at C<$Text::Wrap::columns> columns (default value: 76).
+C<$Text::Wrap::columns> should be set to the full width of your output
+device. In fact, every resulting line will have length of no more than
+C<$columns - 1>.
It is possible to control which characters terminate words by
modifying C<$Text::Wrap::break>. Set this to a string such as
default is simply C<'\s'>; that is, words are terminated by spaces.
(This means, among other things, that trailing punctuation such as
full stops or commas stay with the word they are "attached" to.)
+Setting C<$Text::Wrap::break> to a regular expression that doesn't
+eat any characters (perhaps just a forward look-ahead assertion) will
+cause warnings.
Beginner note: In example 2, above C<$columns> is imported into
the local namespace, and set locally. In example 3,
If you want to separate your lines with something other than C<\n>
then set C<$Text::Wrap::separator> to your preference. This replaces
-all newlines with C<$Text::Wrap::separator>. If you just want to
-preserve existing newlines but add new breaks with something else, set
+all newlines with C<$Text::Wrap::separator>. If you just want to
+preserve existing newlines but add new breaks with something else, set
C<$Text::Wrap::separator2> instead.
When words that are longer than C<$columns> are encountered, they
"This is a bit of|text that forms a|normal book-style|paragraph"
+=head1 SEE ALSO
+
+For wrapping multi-byte characters: L<Text::WrapI18N>.
+For more detailed controls: L<Text::Format>.
+
=head1 LICENSE
-David Muir Sharnoff <muir@idiom.com> with help from Tim Pierce and
-many many others. Copyright (C) 1996-2006 David Muir Sharnoff.
+David Muir Sharnoff <muir@idiom.org> with help from Tim Pierce and
+many many others. Copyright (C) 1996-2009 David Muir Sharnoff.
This module may be modified, used, copied, and redistributed at
-your own risk. Publicly redistributed modified versions must use
-a different name.
+your own risk. Publicly redistributed versions that are modified
+must use a different name.