xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/Text/Wrap.pm (revision 0:68f95e015346)
1*0Sstevel@tonic-gatepackage Text::Wrap;
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gaterequire Exporter;
4*0Sstevel@tonic-gate
5*0Sstevel@tonic-gate@ISA = qw(Exporter);
6*0Sstevel@tonic-gate@EXPORT = qw(wrap fill);
7*0Sstevel@tonic-gate@EXPORT_OK = qw($columns $break $huge);
8*0Sstevel@tonic-gate
9*0Sstevel@tonic-gate$VERSION = 2001.09291;
10*0Sstevel@tonic-gate
11*0Sstevel@tonic-gateuse vars qw($VERSION $columns $debug $break $huge $unexpand $tabstop
12*0Sstevel@tonic-gate	$separator);
13*0Sstevel@tonic-gateuse strict;
14*0Sstevel@tonic-gate
15*0Sstevel@tonic-gateBEGIN	{
16*0Sstevel@tonic-gate	$columns = 76;  # <= screen width
17*0Sstevel@tonic-gate	$debug = 0;
18*0Sstevel@tonic-gate	$break = '\s';
19*0Sstevel@tonic-gate	$huge = 'wrap'; # alternatively: 'die' or 'overflow'
20*0Sstevel@tonic-gate	$unexpand = 1;
21*0Sstevel@tonic-gate	$tabstop = 8;
22*0Sstevel@tonic-gate	$separator = "\n";
23*0Sstevel@tonic-gate}
24*0Sstevel@tonic-gate
25*0Sstevel@tonic-gateuse Text::Tabs qw(expand unexpand);
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gatesub wrap
28*0Sstevel@tonic-gate{
29*0Sstevel@tonic-gate	my ($ip, $xp, @t) = @_;
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gate	local($Text::Tabs::tabstop) = $tabstop;
32*0Sstevel@tonic-gate	my $r = "";
33*0Sstevel@tonic-gate	my $tail = pop(@t);
34*0Sstevel@tonic-gate	my $t = expand(join("", (map { /\s+\z/ ? ( $_ ) : ($_, ' ') } @t), $tail));
35*0Sstevel@tonic-gate	my $lead = $ip;
36*0Sstevel@tonic-gate	my $ll = $columns - length(expand($ip)) - 1;
37*0Sstevel@tonic-gate	$ll = 0 if $ll < 0;
38*0Sstevel@tonic-gate	my $nll = $columns - length(expand($xp)) - 1;
39*0Sstevel@tonic-gate	my $nl = "";
40*0Sstevel@tonic-gate	my $remainder = "";
41*0Sstevel@tonic-gate
42*0Sstevel@tonic-gate	use re 'taint';
43*0Sstevel@tonic-gate
44*0Sstevel@tonic-gate	pos($t) = 0;
45*0Sstevel@tonic-gate	while ($t !~ /\G\s*\Z/gc) {
46*0Sstevel@tonic-gate		if ($t =~ /\G([^\n]{0,$ll})($break|\z)/xmgc) {
47*0Sstevel@tonic-gate			$r .= $unexpand
48*0Sstevel@tonic-gate				? unexpand($nl . $lead . $1)
49*0Sstevel@tonic-gate				: $nl . $lead . $1;
50*0Sstevel@tonic-gate			$remainder = $2;
51*0Sstevel@tonic-gate		} elsif ($huge eq 'wrap' && $t =~ /\G([^\n]{$ll})/gc) {
52*0Sstevel@tonic-gate			$r .= $unexpand
53*0Sstevel@tonic-gate				? unexpand($nl . $lead . $1)
54*0Sstevel@tonic-gate				: $nl . $lead . $1;
55*0Sstevel@tonic-gate			$remainder = $separator;
56*0Sstevel@tonic-gate		} elsif ($huge eq 'overflow' && $t =~ /\G([^\n]*?)($break|\z)/xmgc) {
57*0Sstevel@tonic-gate			$r .= $unexpand
58*0Sstevel@tonic-gate				? unexpand($nl . $lead . $1)
59*0Sstevel@tonic-gate				: $nl . $lead . $1;
60*0Sstevel@tonic-gate			$remainder = $2;
61*0Sstevel@tonic-gate		} elsif ($huge eq 'die') {
62*0Sstevel@tonic-gate			die "couldn't wrap '$t'";
63*0Sstevel@tonic-gate		} else {
64*0Sstevel@tonic-gate			die "This shouldn't happen";
65*0Sstevel@tonic-gate		}
66*0Sstevel@tonic-gate
67*0Sstevel@tonic-gate		$lead = $xp;
68*0Sstevel@tonic-gate		$ll = $nll;
69*0Sstevel@tonic-gate		$nl = $separator;
70*0Sstevel@tonic-gate	}
71*0Sstevel@tonic-gate	$r .= $remainder;
72*0Sstevel@tonic-gate
73*0Sstevel@tonic-gate	print "-----------$r---------\n" if $debug;
74*0Sstevel@tonic-gate
75*0Sstevel@tonic-gate	print "Finish up with '$lead'\n" if $debug;
76*0Sstevel@tonic-gate
77*0Sstevel@tonic-gate	$r .= $lead . substr($t, pos($t), length($t)-pos($t))
78*0Sstevel@tonic-gate		if pos($t) ne length($t);
79*0Sstevel@tonic-gate
80*0Sstevel@tonic-gate	print "-----------$r---------\n" if $debug;;
81*0Sstevel@tonic-gate
82*0Sstevel@tonic-gate	return $r;
83*0Sstevel@tonic-gate}
84*0Sstevel@tonic-gate
85*0Sstevel@tonic-gatesub fill
86*0Sstevel@tonic-gate{
87*0Sstevel@tonic-gate	my ($ip, $xp, @raw) = @_;
88*0Sstevel@tonic-gate	my @para;
89*0Sstevel@tonic-gate	my $pp;
90*0Sstevel@tonic-gate
91*0Sstevel@tonic-gate	for $pp (split(/\n\s+/, join("\n",@raw))) {
92*0Sstevel@tonic-gate		$pp =~ s/\s+/ /g;
93*0Sstevel@tonic-gate		my $x = wrap($ip, $xp, $pp);
94*0Sstevel@tonic-gate		push(@para, $x);
95*0Sstevel@tonic-gate	}
96*0Sstevel@tonic-gate
97*0Sstevel@tonic-gate	# if paragraph_indent is the same as line_indent,
98*0Sstevel@tonic-gate	# separate paragraphs with blank lines
99*0Sstevel@tonic-gate
100*0Sstevel@tonic-gate	my $ps = ($ip eq $xp) ? "\n\n" : "\n";
101*0Sstevel@tonic-gate	return join ($ps, @para);
102*0Sstevel@tonic-gate}
103*0Sstevel@tonic-gate
104*0Sstevel@tonic-gate1;
105*0Sstevel@tonic-gate__END__
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate=head1 NAME
108*0Sstevel@tonic-gate
109*0Sstevel@tonic-gateText::Wrap - line wrapping to form simple paragraphs
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate=head1 SYNOPSIS
112*0Sstevel@tonic-gate
113*0Sstevel@tonic-gateB<Example 1>
114*0Sstevel@tonic-gate
115*0Sstevel@tonic-gate	use Text::Wrap
116*0Sstevel@tonic-gate
117*0Sstevel@tonic-gate	$initial_tab = "\t";	# Tab before first line
118*0Sstevel@tonic-gate	$subsequent_tab = "";	# All other lines flush left
119*0Sstevel@tonic-gate
120*0Sstevel@tonic-gate	print wrap($initial_tab, $subsequent_tab, @text);
121*0Sstevel@tonic-gate	print fill($initial_tab, $subsequent_tab, @text);
122*0Sstevel@tonic-gate
123*0Sstevel@tonic-gate	@lines = wrap($initial_tab, $subsequent_tab, @text);
124*0Sstevel@tonic-gate
125*0Sstevel@tonic-gate	@paragraphs = fill($initial_tab, $subsequent_tab, @text);
126*0Sstevel@tonic-gate
127*0Sstevel@tonic-gateB<Example 2>
128*0Sstevel@tonic-gate
129*0Sstevel@tonic-gate	use Text::Wrap qw(wrap $columns $huge);
130*0Sstevel@tonic-gate
131*0Sstevel@tonic-gate	$columns = 132;		# Wrap at 132 characters
132*0Sstevel@tonic-gate	$huge = 'die';
133*0Sstevel@tonic-gate	$huge = 'wrap';
134*0Sstevel@tonic-gate	$huge = 'overflow';
135*0Sstevel@tonic-gate
136*0Sstevel@tonic-gateB<Example 3>
137*0Sstevel@tonic-gate
138*0Sstevel@tonic-gate	use Text::Wrap
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate	$Text::Wrap::columns = 72;
141*0Sstevel@tonic-gate	print wrap('', '', @text);
142*0Sstevel@tonic-gate
143*0Sstevel@tonic-gate=head1 DESCRIPTION
144*0Sstevel@tonic-gate
145*0Sstevel@tonic-gateC<Text::Wrap::wrap()> is a very simple paragraph formatter.  It formats a
146*0Sstevel@tonic-gatesingle paragraph at a time by breaking lines at word boundries.
147*0Sstevel@tonic-gateIndentation is controlled for the first line (C<$initial_tab>) and
148*0Sstevel@tonic-gateall subsequent lines (C<$subsequent_tab>) independently.  Please note:
149*0Sstevel@tonic-gateC<$initial_tab> and C<$subsequent_tab> are the literal strings that will
150*0Sstevel@tonic-gatebe used: it is unlikley you would want to pass in a number.
151*0Sstevel@tonic-gate
152*0Sstevel@tonic-gateText::Wrap::fill() is a simple multi-paragraph formatter.  It formats
153*0Sstevel@tonic-gateeach paragraph separately and then joins them together when it's done.  It
154*0Sstevel@tonic-gatewill destory any whitespace in the original text.  It breaks text into
155*0Sstevel@tonic-gateparagraphs by looking for whitespace after a newline.  In other respects
156*0Sstevel@tonic-gateit acts like wrap().
157*0Sstevel@tonic-gate
158*0Sstevel@tonic-gate=head1 OVERRIDES
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gateC<Text::Wrap::wrap()> has a number of variables that control its behavior.
161*0Sstevel@tonic-gateBecause other modules might be using C<Text::Wrap::wrap()> it is suggested
162*0Sstevel@tonic-gatethat you leave these variables alone!  If you can't do that, then
163*0Sstevel@tonic-gateuse C<local($Text::Wrap::VARIABLE) = YOURVALUE> when you change the
164*0Sstevel@tonic-gatevalues so that the original value is restored.  This C<local()> trick
165*0Sstevel@tonic-gatewill not work if you import the variable into your own namespace.
166*0Sstevel@tonic-gate
167*0Sstevel@tonic-gateLines are wrapped at C<$Text::Wrap::columns> columns.  C<$Text::Wrap::columns>
168*0Sstevel@tonic-gateshould be set to the full width of your output device.  In fact,
169*0Sstevel@tonic-gateevery resulting line will have length of no more than C<$columns - 1>.
170*0Sstevel@tonic-gate
171*0Sstevel@tonic-gateIt is possible to control which characters terminate words by
172*0Sstevel@tonic-gatemodifying C<$Text::Wrap::break>. Set this to a string such as
173*0Sstevel@tonic-gateC<'[\s:]'> (to break before spaces or colons) or a pre-compiled regexp
174*0Sstevel@tonic-gatesuch as C<qr/[\s']/> (to break before spaces or apostrophes). The
175*0Sstevel@tonic-gatedefault is simply C<'\s'>; that is, words are terminated by spaces.
176*0Sstevel@tonic-gate(This means, among other things, that trailing punctuation  such as
177*0Sstevel@tonic-gatefull stops or commas stay with the word they are "attached" to.)
178*0Sstevel@tonic-gate
179*0Sstevel@tonic-gateBeginner note: In example 2, above C<$columns> is imported into
180*0Sstevel@tonic-gatethe local namespace, and set locally.  In example 3,
181*0Sstevel@tonic-gateC<$Text::Wrap::columns> is set in its own namespace without importing it.
182*0Sstevel@tonic-gate
183*0Sstevel@tonic-gateC<Text::Wrap::wrap()> starts its work by expanding all the tabs in its
184*0Sstevel@tonic-gateinput into spaces.  The last thing it does it to turn spaces back
185*0Sstevel@tonic-gateinto tabs.  If you do not want tabs in your results, set
186*0Sstevel@tonic-gateC<$Text::Wrap::unexapand> to a false value.  Likewise if you do not
187*0Sstevel@tonic-gatewant to use 8-character tabstops, set C<$Text::Wrap::tabstop> to
188*0Sstevel@tonic-gatethe number of characters you do want for your tabstops.
189*0Sstevel@tonic-gate
190*0Sstevel@tonic-gateIf you want to separate your lines with something other than C<\n>
191*0Sstevel@tonic-gatethen set C<$Text::Wrap::seporator> to your preference.
192*0Sstevel@tonic-gate
193*0Sstevel@tonic-gateWhen words that are longer than C<$columns> are encountered, they
194*0Sstevel@tonic-gateare broken up.  C<wrap()> adds a C<"\n"> at column C<$columns>.
195*0Sstevel@tonic-gateThis behavior can be overridden by setting C<$huge> to
196*0Sstevel@tonic-gate'die' or to 'overflow'.  When set to 'die', large words will cause
197*0Sstevel@tonic-gateC<die()> to be called.  When set to 'overflow', large words will be
198*0Sstevel@tonic-gateleft intact.
199*0Sstevel@tonic-gate
200*0Sstevel@tonic-gateHistorical notes: 'die' used to be the default value of
201*0Sstevel@tonic-gateC<$huge>.  Now, 'wrap' is the default value.
202*0Sstevel@tonic-gate
203*0Sstevel@tonic-gate=head1 EXAMPLE
204*0Sstevel@tonic-gate
205*0Sstevel@tonic-gate	print wrap("\t","","This is a bit of text that forms
206*0Sstevel@tonic-gate		a normal book-style paragraph");
207*0Sstevel@tonic-gate
208*0Sstevel@tonic-gate=head1 AUTHOR
209*0Sstevel@tonic-gate
210*0Sstevel@tonic-gateDavid Muir Sharnoff <muir@idiom.com> with help from Tim Pierce and
211*0Sstevel@tonic-gatemany many others.
212*0Sstevel@tonic-gate
213