#! /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.words -> $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.1 =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