1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#! /usr/bin/env false
use v6.c;
unit module String::Fold;
#| Fold a string to contain no lines longer than the given width.
sub fold (
#| The string to fold.
Str:D $string,
#| The maximum width of lines in the text.
Int:D :$width where 0 < * = 80,
#| The number of spaces used to indent the text.
Int:D :$indent where -1 < * = 0,
--> Str
) is export {
my Str @folded-lines = [];
my Str @current-words = [];
for $string.trim.lines -> $line {
# Nothing to do if the line is less than the maximum width.
if ($line.chars <= $width) {
@folded-lines.append($line);
next;
}
# Work through each word on the line and fold them to the maximum width.
for $line.comb(/\S+/) -> $word {
if (new-line-length(@current-words, $word, $indent) <= $width) {
@current-words.append($word);
next;
}
@folded-lines.append(@current-words.join(" "));
@current-words = [$word];
}
# Clean up the current list of words.
@folded-lines.append(@current-words.join(" "));
@current-words = [];
}
# Add the last line if we have any leftover current words.
@folded-lines.push(@current-words.join(" ")) if @current-words;
return @folded-lines>>.indent($indent).join("\n");
}
#| Calculate the total line length of a would-be line.
sub new-line-length (
Str:D @words,
Str:D $new-word,
Int:D $indent-width,
--> Int
) {
my Int $chars = 0;
# Get the number of characters in each word.
$chars += [+] @words>>.chars;
$chars += @words.elems; # Spaces inbetween the words.
$chars += $new-word.chars;
$chars += $indent-width;
$chars;
}
=begin pod
=NAME String::Fold
=AUTHOR Patrick Spek <p.spek@tyil.work>
=VERSION 0.1.0
=head1 SYNOPSIS
fold(Str:D $, Int:D :$width, Int:D :$indent);
=head1 DESCRIPTION
Fold a C<Str> to a given width. Accepts a C<:$width>N<Defaults to C<80>> and a
C<:$indent>N<Defaults to C<0>>.
=head1 EXAMPLES
=head2 Basic usage
=begin input
use String::Fold;
my Str $folded = fold(slurp("some-text-file"));
=end input
This will yield a folded string in C<$folded>. The input file will have all its
lines folded to a maximum width of 80 characters.
=head2 Folding at a custom width
=begin input
use String::Fold;
my Str $folded = slurp("some-text-file").&fold(:width(40));
=end input
This will yield a string folded at 40 characters, instead of the default of 80
characters. Any number higher that C<0> is accepted.
=head2 Indented block
=begin input
use String::Fold;
my Str $indented = slurp("some-text-file").&fold(:indent(8));
=end input
This will yield a string folded at 80 characters (the default), and indented by
8 spaces.
=end pod
# vim: ft=perl6 noet
|