From f902fa2cc62c60aa614ef7efb60bde0d1c9d2e15 Mon Sep 17 00:00:00 2001 From: Patrick Spek Date: Mon, 5 Aug 2019 15:26:46 +0200 Subject: Rewrite String::Fold --- lib/String/Fold.pm6 | 95 +++++++++++++++++++++-------------------------------- 1 file changed, 37 insertions(+), 58 deletions(-) (limited to 'lib/String/Fold.pm6') diff --git a/lib/String/Fold.pm6 b/lib/String/Fold.pm6 index 2db1155..0bd2296 100644 --- a/lib/String/Fold.pm6 +++ b/lib/String/Fold.pm6 @@ -7,65 +7,55 @@ 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, + Str() $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, + Int() :$width where 0 < * = 79, --> 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; - } + my @paragraphs; - # 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; + for $string.split("\n\n") -> $paragraph { + my @lines; + my $current-line = 0; + + for $paragraph.lines.join(" ").words -> $word { + # If this word would make the line too long, go to the next line. + if (@lines[$current-line].&line-length + $word.chars > $width) { + $current-line++; } - @folded-lines.append(@current-words.join(" ")); - @current-words = [$word]; + # Append the current word to the line. + @lines[$current-line].append($word); } - # Clean up the current list of words. - @folded-lines.append(@current-words.join(" ")); - @current-words = []; + @paragraphs.append(@lines.join("\n")); } - # 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"); + @paragraphs.join("\n\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, +#| Get the length of a line array. If the array does not exist yet, it is +#| clearly empty, and this sub returns 0. +multi sub line-length ( + Any, + --> Int ) { - my Int $chars = 0; - - # Get the number of characters in each word. - $chars += [+] @words>>.chars; + 0 +} - $chars += @words.elems; # Spaces inbetween the words. - $chars += $new-word.chars; - $chars += $indent-width; +#| Get the length of a line array. This counts the characters of all words in +#| the array, and adds up the number of spaces required for it to be a human +#| representable line. +multi sub line-length ( + #| The line array, containing any number of words. + @line, - $chars; + --> Int +) { + @line.map(*.chars).sum + @line.elems } =begin pod @@ -76,12 +66,12 @@ sub new-line-length ( =head1 SYNOPSIS -fold(Str:D $, Int:D :$width, Int:D :$indent); +fold(Str:D $, Int:D :$width); =head1 DESCRIPTION -Fold a C to a given width. Accepts a C<:$width>N> and a -C<:$indent>N>. +Fold a C to a given width. Accepts a C<:$width>N> +argument. =head1 EXAMPLES @@ -94,7 +84,7 @@ 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. +lines folded to a maximum width of 79 characters. =head2 Folding at a custom width @@ -104,19 +94,8 @@ 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. +This will yield a string folded at 40 characters, instead of the default of 79 +characters. Any number higher than C<0> is accepted. =end pod -- cgit v1.1