From 281408b4852ae74af28ecc8f1c03457c766136b8 Mon Sep 17 00:00:00 2001 From: Patrick Spek Date: Sun, 8 Jul 2018 17:37:25 +0200 Subject: Initial release --- lib/String/Fold.pm6 | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 lib/String/Fold.pm6 (limited to 'lib') 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 +=VERSION 0.1.0 + +=head1 SYNOPSIS + +fold(Str:D $, Int:D :$width, Int:D :$indent); + +=head1 DESCRIPTION + +Fold a C to a given width. Accepts a C<:$width>N> and a +C<:$indent>N>. + +=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 -- cgit v1.1