summaryrefslogtreecommitdiff
path: root/lib/String/Fold.pm6
diff options
context:
space:
mode:
Diffstat (limited to 'lib/String/Fold.pm6')
-rw-r--r--lib/String/Fold.pm6123
1 files changed, 123 insertions, 0 deletions
diff --git a/lib/String/Fold.pm6 b/lib/String/Fold.pm6
new file mode 100644
index 0000000..7b47be3
--- /dev/null
+++ b/lib/String/Fold.pm6
@@ -0,0 +1,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