File Coverage

blib/script/article-wrap
Criterion Covered Total %
statement 38 40 95.0
branch 13 16 81.2
condition 7 12 58.3
subroutine 1 1 100.0
pod n/a
total 59 69 85.5


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2             =head1 Article Wrap
3              
4             Wrap news articles or mail files. That is to say, don't wrap the header lines at
5             the top but do wrap the rest of the file. Also don't wrap "source code" which is
6             fenced by Markdown code fences: trible backticks. Don't wrap short lines (10
7             characters or less). Don't wrap lines with whitespace at the end. Don't wrap
8             empty lines.
9              
10             This is useful when post-processing a message written using ed for posting using
11             tin, for example.
12             =cut
13 7     7   41040 use Modern::Perl;
  7         87220  
  7         49  
14 7 50       1227803 die "This filter wraps news posts.\n" if @ARGV;
15 7         48 binmode(STDIN, ':utf8');
16 7         38 binmode(STDOUT, ':utf8');
17             # headers
18 7         268 while () {
19 14         48 chomp;
20 14 100       40 last if not $_; # end of headers
21 7         85 say; # header line
22             }
23 7         35 print "\n"; # empty line after headers
24 7         26 my $max = 72;
25 7         17 my $buffer;
26 7         19 my $prefix = '';
27 7         11 my $wrap = 1;
28 7         29 while () {
29 10         20 chomp;
30 10         146 my ($new_prefix) = /([> ]*)/;
31             # empty lines don't get wrapped, nor lines with a space at the end, nor indented lines
32 10   66     1051 my $empty = length() == 0 || /^$prefix\s*$/ || /\s$/ || /^\s/ || /^$prefix.{0,10}$/;
33             # ``` toggles wrap
34 10 50       277 $wrap = not $wrap if /^$prefix\s*```$/;
35             # end old paragraph with the old prefix if the prefix changed, an empty line,
36             # or not wrapping anymore
37 10 50 33     111 if ($buffer and ($new_prefix ne $prefix or $empty or not $wrap)) {
      66        
38 0         0 say $prefix . $buffer;
39 0         0 $buffer = '';
40             }
41             # print empty lines or not wrapped lines without stripping trailing whitespace
42 10 100 66     81 if ($empty or not $wrap) {
43 3         6 say $_;
44 3         24 next;
45             }
46             # continue old paragraph
47 7 100       25 $buffer .= " " if $buffer;
48             # strip the prefix
49 7         33 $prefix = $new_prefix;
50 7         47 $buffer .= substr($_, length($prefix));
51             # wrap what we have
52 7         53 while (length($buffer) > $max) {
53             # this is the max line + 1
54 3         12 my $test_line = substr($buffer, 0, $max - length($prefix) + 1);
55             # if there's a word that reaches into that last character, break before
56 3 100       48 if ($test_line =~ /(\s+(\S+)\S)$/) {
57             # $1 is the last word: strip it, print prefix and stripped line
58 2         17 say $prefix . substr($buffer, 0, $max - length($prefix) - length($1) + 1);
59             # the new buffer starts with the word just stripped
60 2         30 $buffer = substr($buffer, $max - length($prefix) - length($2));
61             } else {
62             # we know that there is no word at the boundary, so cut there
63 1         3 my $line = substr($buffer, 0, $max - length($prefix));
64             # strip trailing whitespace and print it
65 1         9 $line =~ s/\s+$//;
66 1         5 say $prefix . $line;
67             # the new buffer starts where we did the cut, strip leading whitespace
68 1         3 $buffer = substr($buffer, $max - length($prefix));
69 1         23 $buffer =~ s/^\s+//;
70             }
71             }
72             }
73 7 100       73 say $prefix . $buffer if $buffer;
74             1;