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 --- CHANGELOG.md | 14 +++++ lib/String/Fold.pm6 | 95 +++++++++++++-------------------- t/files/input/indented-block.txt | 1 - t/files/output/indented-block.txt | 11 ---- t/files/output/multiple-long-lines.txt | 19 +++---- t/files/output/multiple-short-lines.txt | 5 +- t/files/output/three-paragraphs.txt | 10 ++-- t/indented-block.t | 19 ------- t/simple-blocks.t | 2 - 9 files changed, 66 insertions(+), 110 deletions(-) delete mode 100644 t/files/input/indented-block.txt delete mode 100644 t/files/output/indented-block.txt delete mode 100644 t/indented-block.t diff --git a/CHANGELOG.md b/CHANGELOG.md index 618a64d..964bf7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,5 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [UNRELEASED] + +### Changed + +The method of folding strings has been rewritten, to hopefully work better in +all circumstances. + +### Removed + +The `indent` parameter has been removed from `&fold`. This functionality is +left up to the user, and can still be easily achieved by lowering the `width` +parameter and calling `&indent` from the upstream code. + ## [0.1.0] - 2018-07-08 + - Initial release 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 diff --git a/t/files/input/indented-block.txt b/t/files/input/indented-block.txt deleted file mode 100644 index c6d096f..0000000 --- a/t/files/input/indented-block.txt +++ /dev/null @@ -1 +0,0 @@ -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent sit amet diam at ipsum malesuada pulvinar. Cras ut aliquet purus. Pellentesque vehicula urna felis, non facilisis libero volutpat egestas. Aliquam placerat tempor neque nec consectetur. Maecenas lacinia egestas tellus eu lacinia. Aenean tincidunt quam ante, at pharetra enim maximus et. Proin scelerisque metus at neque rutrum commodo at at mi. Vivamus fringilla ullamcorper euismod. Donec finibus non justo at tempus. Suspendisse efficitur felis a consequat scelerisque. Suspendisse consectetur eu nisl nec pellentesque. Sed vitae quam pellentesque, dignissim quam vitae, scelerisque urna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; diff --git a/t/files/output/indented-block.txt b/t/files/output/indented-block.txt deleted file mode 100644 index 3930b9f..0000000 --- a/t/files/output/indented-block.txt +++ /dev/null @@ -1,11 +0,0 @@ - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent sit - amet diam at ipsum malesuada pulvinar. Cras ut aliquet purus. - Pellentesque vehicula urna felis, non facilisis libero volutpat egestas. - Aliquam placerat tempor neque nec consectetur. Maecenas lacinia egestas - tellus eu lacinia. Aenean tincidunt quam ante, at pharetra enim maximus - et. Proin scelerisque metus at neque rutrum commodo at at mi. Vivamus - fringilla ullamcorper euismod. Donec finibus non justo at tempus. - Suspendisse efficitur felis a consequat scelerisque. Suspendisse - consectetur eu nisl nec pellentesque. Sed vitae quam pellentesque, - dignissim quam vitae, scelerisque urna. Vestibulum ante ipsum primis in - faucibus orci luctus et ultrices posuere cubilia Curae; diff --git a/t/files/output/multiple-long-lines.txt b/t/files/output/multiple-long-lines.txt index e2588ba..dac14e7 100644 --- a/t/files/output/multiple-long-lines.txt +++ b/t/files/output/multiple-long-lines.txt @@ -1,12 +1,9 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur dictum, -magnanon semper maximus, est ex -mattis ipsum, eu sodales lectus est nec nibh. Maecenas porttitor nisi non tortor -ultricies, quis vulputate nunc -convallis. Mauris lacus mi, malesuada vel metus in, tempor malesuada leo. Mauris -id neque et sem efficitur ornare. -Praesent egestas nisi malesuada sagittis tempor. Quisque nunc arcu, ullamcorper -et sem et, tristique auctor tortor. -Nullam sagittis malesuada placerat. Aenean pretium leo et odio molestie porta. -Praesent eu arcu sit amet risus -convallis consectetur vel in quam. Integer id augue mauris. Morbi eget dictum -ligula. Nulla facilisi. +magnanon semper maximus, est ex mattis ipsum, eu sodales lectus est nec nibh. +Maecenas porttitor nisi non tortor ultricies, quis vulputate nunc convallis. +Mauris lacus mi, malesuada vel metus in, tempor malesuada leo. Mauris id neque +et sem efficitur ornare. Praesent egestas nisi malesuada sagittis tempor. +Quisque nunc arcu, ullamcorper et sem et, tristique auctor tortor. Nullam +sagittis malesuada placerat. Aenean pretium leo et odio molestie porta. +Praesent eu arcu sit amet risus convallis consectetur vel in quam. Integer id +augue mauris. Morbi eget dictum ligula. Nulla facilisi. diff --git a/t/files/output/multiple-short-lines.txt b/t/files/output/multiple-short-lines.txt index 886c6e3..f8e91c2 100644 --- a/t/files/output/multiple-short-lines.txt +++ b/t/files/output/multiple-short-lines.txt @@ -1,3 +1,2 @@ -This is a short line. -This is another short line. -For good measure, let's use a third line. +This is a short line. This is another short line. For good measure, let's use a +third line. diff --git a/t/files/output/three-paragraphs.txt b/t/files/output/three-paragraphs.txt index 8f884f4..b9a23d8 100644 --- a/t/files/output/three-paragraphs.txt +++ b/t/files/output/three-paragraphs.txt @@ -3,11 +3,11 @@ at ipsum malesuada pulvinar. Cras ut aliquet purus. Pellentesque vehicula urna felis, non facilisis libero volutpat egestas. Aliquam placerat tempor neque nec consectetur. Maecenas lacinia egestas tellus eu lacinia. Aenean tincidunt quam ante, at pharetra enim maximus et. Proin scelerisque metus at neque rutrum -commodo at at mi. Vivamus fringilla ullamcorper euismod. Donec finibus non justo -at tempus. Suspendisse efficitur felis a consequat scelerisque. Suspendisse -consectetur eu nisl nec pellentesque. Sed vitae quam pellentesque, dignissim -quam vitae, scelerisque urna. Vestibulum ante ipsum primis in faucibus orci -luctus et ultrices posuere cubilia Curae; +commodo at at mi. Vivamus fringilla ullamcorper euismod. Donec finibus non +justo at tempus. Suspendisse efficitur felis a consequat scelerisque. +Suspendisse consectetur eu nisl nec pellentesque. Sed vitae quam pellentesque, +dignissim quam vitae, scelerisque urna. Vestibulum ante ipsum primis in +faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dignissim diam dui, eu maximus dolor tincidunt id. Aenean gravida elementum pellentesque. Ut consectetur ante quis mauris facilisis faucibus. diff --git a/t/indented-block.t b/t/indented-block.t deleted file mode 100644 index 9acf5e6..0000000 --- a/t/indented-block.t +++ /dev/null @@ -1,19 +0,0 @@ -#! /usr/bin/env perl6 - -use v6.c; - -use String::Fold; -use Test; - -my @result-lines = fold(slurp("t/files/input/indented-block.txt"), :indent(8)).lines; -my @expected-lines = slurp("t/files/output/indented-block.txt").trim-trailing.lines; - -plan 1 + @expected-lines.elems; - -is @result-lines.elems, @expected-lines.elems, "Expected number of lines"; - -for ^@expected-lines { - is @result-lines[$_], @expected-lines[$_], "Line {$_ + 1} is the same"; -} - -# vim: ft=perl6 noet diff --git a/t/simple-blocks.t b/t/simple-blocks.t index b52e721..e47572b 100644 --- a/t/simple-blocks.t +++ b/t/simple-blocks.t @@ -24,8 +24,6 @@ subtest "Single short line" => { } subtest "Single long line" => { - plan 1; - my $result = slurp("t/files/input/single-long-line.txt").trim.&fold(); my @expected-lines = slurp("t/files/output/single-long-line.txt").trim.lines; my @result-lines = $result.lines; -- cgit v1.1