diff --git a/README b/README index f7c655d..57a1ae5 100644 --- a/README +++ b/README @@ -11,6 +11,7 @@ TODO * Numeric fields with decimal separator and justification * Numeric fields with thousands separators and justification * Currencies +* Rendering of Complex numbers (currently restricted to Real) * Everything else diff --git a/lib/Form.pm b/lib/Form.pm index 26325fa..ec23d32 100644 --- a/lib/Form.pm +++ b/lib/Form.pm @@ -5,7 +5,7 @@ use Form::Grammar; use Form::Actions; use Form::Field; -sub form(*@args is Scalar) returns Str is export { +sub form(*@args is Scalar --> Str) is export { my @lines; my $result = ''; diff --git a/lib/Form/Field.pm b/lib/Form/Field.pm index 143e653..0134df3 100644 --- a/lib/Form/Field.pm +++ b/lib/Form/Field.pm @@ -5,7 +5,7 @@ use Form::NumberFormatting; # RAKUDO: Field is now a class, because overriding multis doesn't # work correctly from roles -class Field { +our class Field { has Bool $.block is rw; has Int $.width is rw; has $.alignment is rw; @@ -49,7 +49,7 @@ class Field { } } -class TextField is Field { +our class TextField is Field { has $.justify is rw; @@ -78,7 +78,7 @@ class TextField is Field { } } -class NumericField is Field { +our class NumericField is Field { has Num $.ints-width; has Num $.fracs-width; @@ -91,7 +91,7 @@ class NumericField is Field { } } -class VerbatimField is Field { +our class VerbatimField is Field { multi method format(Str $data) { my @lines = $data.split("\n"); $.block or @lines = @lines[^1]; diff --git a/lib/Form/NumberFormatting.pm b/lib/Form/NumberFormatting.pm index 6934a8f..49c2551 100644 --- a/lib/Form/NumberFormatting.pm +++ b/lib/Form/NumberFormatting.pm @@ -13,18 +13,21 @@ Utility functions for formatting numbers in Form.pm. =begin pod -=head2 obtain-number-parts(Num $number) +=head2 obtain-number-parts(Real $number) Splits out the integer and non-integer components of a number. Returns a list of int part, float part. -This should probably be done with mathematical operations rather than Str::split, but once floating-point gets involved it breaks, so that's a TODO until RAKUDO has the Rat type and we can do it sanely. - =end pod -sub obtain-number-parts(Num $number) { - my ($ints, $fractions) = (~$number).split(/\./); +our sub obtain-number-parts(Real $number) { + my $ints = $number.Int; + my $fractions = $number - $ints; + + # it's much easier if we have this as an integer as it's rendered separately to the ints + $fractions.=abs; + $fractions *= 10 while $fractions.Int != $fractions; - return (+$ints, +$fractions); + return ($ints, $fractions); } =begin pod diff --git a/lib/Form/TextFormatting.pm b/lib/Form/TextFormatting.pm index 64525c7..b6b3d47 100644 --- a/lib/Form/TextFormatting.pm +++ b/lib/Form/TextFormatting.pm @@ -23,7 +23,7 @@ sub chop-first-word(Str $source is rw) returns Str { } } -sub fit-in-width(Str $text, Int $width) { +our sub fit-in-width(Str $text, Int $width) { my Str $fitted = ''; my Str $remainder = $text; @@ -59,7 +59,7 @@ sub fit-in-width(Str $text, Int $width) { } -sub unjustified-wrap(Str $text, Int $width) { +our sub unjustified-wrap(Str $text, Int $width) { my $rem = $text; my $line; @@ -80,7 +80,7 @@ sub trim-ending-whitespace(Str $line) returns Str { return $line.subst(/ $$ /, ''); } -sub left-justify(Str $line, Int $width, Str $space = ' ') returns Str { +our sub left-justify(Str $line, Int $width, Str $space = ' ') returns Str { if $line.chars < $width { return $line ~ (($space x ($width - $line.chars) / $space.chars)); } @@ -88,7 +88,7 @@ sub left-justify(Str $line, Int $width, Str $space = ' ') returns Str { return $line.substr(0, $width); } -sub right-justify(Str $line, Int $width, Str $space = ' ') returns Str { +our sub right-justify(Str $line, Int $width, Str $space = ' ') returns Str { if $line.chars < $width { return ($space x (($width - $line.chars) / $space.chars)) ~ $line; } @@ -96,7 +96,7 @@ sub right-justify(Str $line, Int $width, Str $space = ' ') returns Str { return $line.substr($line.chars - $width, $width); } -sub centre-justify(Str $line, Int $width, Str $space = ' ') returns Str { +our sub centre-justify(Str $line, Int $width, Str $space = ' ') returns Str { if $line.chars < $width { my Int $to-add = $width - $line.chars; my Int $before = $to-add div 2; @@ -109,7 +109,7 @@ sub centre-justify(Str $line, Int $width, Str $space = ' ') returns Str { return $line.substr(0, $width); } -sub full-justify(Str $line, Int $width, Str $space = ' ') returns Str { +our sub full-justify(Str $line, Int $width, Str $space = ' ') returns Str { # TODO need a justify algorithm # for now, do something entirely unsatisfactory if $line.chars < $width { @@ -118,11 +118,8 @@ sub full-justify(Str $line, Int $width, Str $space = ' ') returns Str { my $words = @words.elems; my @spaces = $space xx ($words - 1); - # RAKUDO: reduce meta-op not in master post-ng - #my $words-width = [+] @words.map: *.chars; - my $words-width = @words.map({.chars}).reduce(&infix:<+>); - #my $spaces-width = [+] @spaces.map: *.chars; - my $spaces-width = @spaces.map({.chars}).reduce(&infix:<+>); + my $words-width = [+] @words.map: *.chars; + my $spaces-width = [+] @spaces.map: *.chars; my $act-space = 0; while $words-width + $spaces-width < $width diff --git a/t/02-fieldobjects.t b/t/02-fieldobjects.t index 97632f6..530ca80 100644 --- a/t/02-fieldobjects.t +++ b/t/02-fieldobjects.t @@ -1,4 +1,3 @@ -# use v6; use Test; diff --git a/t/06-form.t b/t/06-form.t index 182d42c..f25a636 100644 --- a/t/06-form.t +++ b/t/06-form.t @@ -5,23 +5,23 @@ use Form; plan 21; -ok(Form::form('a') eq "a\n", "Literal"); -ok(Form::form('{<<}', 'a') eq "a \n", "Single left-line field"); -ok(Form::form('{<<}a', 'a') eq "a a\n", "Single left-line field with literal after"); -ok(Form::form('{>>}a', 'a') eq " aa\n", "Single right-line field with literal after"); -ok(Form::form('{>>><<}{<<<}', 'a', 'b') eq " a b \n", "Single centred-line field with single left-line field after"); -ok(Form::form('{<<}', 'a', '{>>}', 'b') eq "a \n b\n", "Two fields"); -ok(Form::form( +ok(form('a') eq "a\n", "Literal"); +ok(form('{<<}', 'a') eq "a \n", "Single left-line field"); +ok(form('{<<}a', 'a') eq "a a\n", "Single left-line field with literal after"); +ok(form('{>>}a', 'a') eq " aa\n", "Single right-line field with literal after"); +ok(form('{>>><<}{<<<}', 'a', 'b') eq " a b \n", "Single centred-line field with single left-line field after"); +ok(form('{<<}', 'a', '{>>}', 'b') eq "a \n b\n", "Two fields"); +ok(form( '+----+', '|{<<}|', 'aa', '+----+' ) eq "+----+\n|aa |\n+----+\n", "Two literals, one field"); -dies_ok(-> { Form::form('{<<}{>>}', 'a') }, "Insufficient arguments"); -ok(Form::form('{<<<<<}', "The quick brown fox jumps over the lazy dog") eq "The \n", "Line field overflow"); +dies_ok(-> { form('{<<}{>>}', 'a') }, "Insufficient arguments"); +ok(form('{<<<<<}', "The quick brown fox jumps over the lazy dog") eq "The \n", "Line field overflow"); # TODO: reformat these as here-documents for neatness - when Rakudo supports them -ok(Form::form('{[[[[[}', "The quick brown fox jumps over the lazy dog") eq "The \nquick \nbrown \nfox \njumps \nover \nthe \nlazy \ndog \n", "Block field overflow"); +ok(form('{[[[[[}', "The quick brown fox jumps over the lazy dog") eq "The \nquick \nbrown \nfox \njumps \nover \nthe \nlazy \ndog \n", "Block field overflow"); ok( - Form::form( + form( '{[[[[[[[[} {]]]]]]]]}', "The quick brown fox", "jumps over the lazy dog" ) @@ -29,19 +29,19 @@ ok( "The quick jumps over\nbrown fox the lazy\n dog\n", "Multiple block overflow" ); -ok(Form::form('{""}', "Boo\nYah") eq "Boo \nYah \n", "Literal block field"); +ok(form('{""}', "Boo\nYah") eq "Boo \nYah \n", "Literal block field"); -dies_ok({Form::form('{<<<<}')}, 'Too few arguments'); +dies_ok({form('{<<<<}')}, 'Too few arguments'); # time for some numbers -ok(Form::form('{>>.<}', 456.78) eq "456.78\n", "Simple numeric field"); -ok(Form::form('{>>.<}', 56.7) eq " 56.7 \n", "Non-full simple numeric field"); -ok(Form::form('{>>.<}', 4567.89) eq "567.89\n", "Left-side overflow numeric field"); -ok(Form::form('{>>.<}', 56.789) eq " 56.78\n", "Right-side overflow numeric field"); +ok(form('{>>.<}', 456.78) eq "456.78\n", "Simple numeric field"); +ok(form('{>>.<}', 56.7) eq " 56.7 \n", "Non-full simple numeric field"); +ok(form('{>>.<}', 4567.89) eq "567.89\n", "Left-side overflow numeric field"); +ok(form('{>>.<}', 56.789) eq " 56.78\n", "Right-side overflow numeric field"); # Mixed numbers and text -ok(Form::form( +ok(form( '{[[[[[[} {>.<<<}', "Six short people went down to the sea", 6.78 ) @@ -53,7 +53,7 @@ ok(Form::form( # Multiple numbers my @nums = (4.5, 5.6, 6.78, 9.101); ok( - Form::form( + form( '{>>.<<}', \@nums ) eq @@ -64,7 +64,7 @@ ok( # Multiple strings my @strings = ; ok( - Form::form( + form( '{>>>>>>}', \@strings ) @@ -76,7 +76,7 @@ ok( # Both! ok( - Form::form( + form( '{>>>>>>}|{>.<<}', \@strings, \@nums )