Added libraries needed for lintian-style output.
[maemian] / lib / Text_utils.pm
1 # Hey emacs! This is a -*- Perl -*- script!
2 # Text_utils -- Perl utility functions for lintian
3
4 # Copyright (C) 1998 Christian Schwarz and Richard Braakman
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, you can find it on the World Wide
18 # Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
19 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
20 # MA 02110-1301, USA.
21
22 package Text_utils;
23
24 use Exporter;
25 our @ISA    = qw(Exporter);
26 our @EXPORT = qw(split_paragraphs wrap_paragraphs dtml_to_html dtml_to_text);
27
28 use strict;
29
30 # requires wrap() function
31 use Text::Wrap;
32 # requires fail() function
33 use Util;
34
35 # html_wrap -- word-wrap a paragaph.  The wrap() function from Text::Wrap
36 # is not suitable, because it chops words that are longer than the line
37 # length.
38 sub html_wrap {
39     my ($lead, @text) = @_;
40     my @words = split(' ', join(' ', @text));
41     # subtract 1 to compensate for the lack of a space before the first word.
42     my $ll = length($lead) - 1;
43     my $cnt = 0;
44     my $r = "";
45
46     while ($cnt <= $#words) {
47         if ($ll + 1 + length($words[$cnt]) > 76) {
48             if ($cnt == 0) {
49                 # We're at the start of a line, and word still does not
50                 # fit.  Don't wrap it.
51                 $r .= $lead . shift(@words) . "\n";
52             } else {
53                 # start new line
54                 $r .= $lead . join(' ', splice(@words, 0, $cnt)) . "\n";
55                 $ll = length($lead) - 1;
56                 $cnt = 0;
57             }
58         } else {
59             $ll += 1 + length($words[$cnt]);
60             $cnt++;
61         }
62     }
63
64     if ($#words >= 0) {
65         # finish last line
66         $r .= $lead . join(' ', @words) . "\n";
67     }
68
69     return $r;
70 }
71
72 # split_paragraphs -- splits a bunch of text lines into paragraphs.
73 # This function returns a list of paragraphs.
74 # Paragraphs are separated by empty lines. Each empty line is a
75 # paragraph. Furthermore, indented lines are considered a paragraph.
76 sub split_paragraphs {
77     return "" unless (@_);
78
79     my $t = join("\n",@_);
80
81     my ($l,@o);
82     while ($t) {
83         $t =~ s/^\.\n/\n/o;
84         # starts with space or empty line?
85         if (($t =~ s/^([ \t][^\n]*)\n?//o) or ($t =~ s/^()\n//o)) {
86             #FLUSH;
87             if ($l) {
88                 $l =~ s/\s+/ /go;
89                 $l =~ s/^\s+//o;
90                 $l =~ s/\s+$//o;
91                 push(@o,$l);
92                 undef $l;
93             }
94             #
95             push(@o,$1);
96         }
97         # normal line?
98         elsif ($t =~ s/^([^\n]*)\n?//o) {
99             $l .= "$1 ";
100         }
101         # what else can happen?
102         else {
103             fail("internal error in wrap");
104         }
105     }
106     #FLUSH;
107     if ($l) {
108         $l =~ s/\s+/ /go;
109         $l =~ s/^\s+//o;
110         $l =~ s/\s+$//o;
111         push(@o,$l);
112         undef $l;
113     }
114     #
115
116     return @o;
117 }
118
119 sub dtml_to_html {
120     my @o;
121
122     my $pre=0;
123     for $_ (@_) {
124         s,\&maint\;,<a href=\"mailto:lintian-maint\@debian.org\">Lintian maintainer</a>,o; # "
125         s,\&debdev\;,<a href=\"mailto:debian-devel\@lists.debian.org\">debian-devel</a>,o; # "
126
127         # empty line?
128         if (/^\s*$/o) {
129             if ($pre) {
130                 push(@o,"\n");
131             }
132         }
133         # preformatted line?
134         elsif (/^\s/o) {
135             if (not $pre) {
136                 push(@o,"<pre>");
137                 $pre=1;
138             }
139             push(@o,"$_");
140         }
141         # normal line
142         else {
143             if ($pre) {
144                 push(@o,"</pre>");
145                 $pre=0;
146             }
147             push(@o,"<p>$_\n");
148         }
149     }
150     if ($pre) {
151         push(@o,"</pre>");
152         $pre=0;
153     }
154
155     return @o;
156 }
157
158 sub dtml_to_text {
159     for $_ (@_) {
160         # substitute Lintian &tags;
161         s,&maint;,lintian-maint\@debian.org,go;
162         s,&debdev;,debian-devel\@lists.debian.org,go;
163
164         # substitute HTML <tags>
165         s,<i>,&lt;,go;
166         s,</i>,&gt;,go;
167         s,<[^>]+>,,go;
168
169         # substitute HTML &tags;
170         s,&lt;,<,go;
171         s,&gt;,>,go;
172         s,&amp;,\&,go;
173
174         # preformatted?
175         if (not /^\s/o) {
176             # no.
177
178             s,\s\s+, ,go;
179             s,^ ,,o;
180             s, $,,o;
181         }
182     }
183
184     return @_;
185 }
186
187 # wrap_paragraphs -- wrap paragraphs in dpkg/dselect style.
188 # indented lines are not wrapped but displayed "as is"
189 sub wrap_paragraphs {
190     my $lead = shift;
191     my $html = 0;
192
193     if ($lead eq 'HTML') {
194         $html = 1;
195         $lead = shift;
196     }
197
198     my $o;
199     for my $t (split_paragraphs(@_)) {
200         # empty or indented line?
201         if ($t =~ /^$/ or $t =~ /^\s/) {
202             $o .= "$lead$t\n";
203         } else {
204             if ($html) {
205                 $o .= html_wrap($lead, "$t\n");
206             } else {
207                 $o .= wrap($lead, $lead, "$t\n");
208             }
209         }
210     }
211     return $o;
212 }
213
214 1;