add maphash to the array wrapper maphash
authorTony Cook <tony@develop-help.com>
Mon, 15 Oct 2018 07:39:52 +0000 (18:39 +1100)
committerTony Cook <tony@develop-help.com>
Mon, 15 Oct 2018 07:39:52 +0000 (18:39 +1100)
site/cgi-bin/modules/Squirrel/Template/Expr/WrapArray.pm
t/020-templater/040-original.t

index 157a2e5..6dba38f 100644 (file)
@@ -4,7 +4,7 @@ use base qw(Squirrel::Template::Expr::WrapBase);
 use Scalar::Util ();
 use List::Util ();
 
 use Scalar::Util ();
 use List::Util ();
 
-our $VERSION = "1.010";
+our $VERSION = "1.011";
 
 my $list_make_key = sub {
   my ($item, $field) = @_;
 
 my $list_make_key = sub {
   my ($item, $field) = @_;
@@ -215,6 +215,77 @@ sub _do_map {
     ];
 }
 
     ];
 }
 
+sub _do_maphash {
+  my ($self, $args) = @_;
+
+   @$args <= 2
+     or die [ error => "list.maphash requires 0 to 2 parameters" ];
+
+  if (@$args) {
+    my $id = $args->[0];
+    my $value = @$args > 1 ? $args->[1] : undef;
+
+    my $eval = $self->expreval;
+    if (ref $id) {
+      if (defined $value) {
+       if (ref $value) {
+         return +{
+                  map {
+                    scalar($eval->call_function($id, [ $_ ])) =>
+                      scalar($eval->call_function($value, [ $_ ]))
+                    } @{$self->[0]}
+                 };
+       }
+       else {
+         return +{
+                  map {
+                    scalar($eval->call_function($id), [ $_ ]) =>
+                      scalar($list_make_key->($_, $value))
+                    } @{$self->[0]}
+                 };
+       }
+      }
+      else {
+       return +{
+                map {
+                  scalar($eval->call_function($id), [ $_ ]) => $_
+                } @{$self->[0]}
+               };
+      }
+    }
+    else {
+      if (defined $value) {
+       if (ref $value) {
+         return +{
+                  map {
+                    scalar($list_make_key->($_, $id)) =>
+                      scalar($eval->call_function($value, [ $_ ]))
+                    } @{$self->[0]}
+                 };
+       }
+       else {
+         return +{
+                  map {
+                    scalar($list_make_key->($_, $id)) =>
+                      scalar($list_make_key->($_, $value))
+                    } @{$self->[0]}
+                 };
+       }
+      }
+      else {
+       return +{
+                map {
+                  scalar($list_make_key->($_, $id)) => $_
+                } @{$self->[0]}
+               };
+      }
+    }
+  }
+  else {
+    return +{ map {$_ => 1} @{$self->[0]} };
+  }
+}
+
 sub _do_slice {
   my ($self, $args) = @_;
 
 sub _do_slice {
   my ($self, $args) = @_;
 
@@ -410,6 +481,38 @@ C<undef>.
 
  [ "a", 1, "b", 2 ].as_hash => { a:1, b:2 }
 
 
  [ "a", 1, "b", 2 ].as_hash => { a:1, b:2 }
 
+=item maphash
+
+Returns a new hash with each item from the array as a key, and all values of 1.
+
+This simiplifies turning a list of strings into an existence checking hash.
+
+  <:.set strs = [ "one", "two", "three" ] :>
+  <:.set strhash = strs.maphash :>
+  <:= strhash.exists["one"] :>   # 1
+  <:= strhash.exists["four"] :>  # (empty string)
+
+=item maphash(key)
+
+=item maphash(key, value)
+
+Returns a new hash with the key and values derived from the elements
+of the list.
+
+Each I<key> and I<value> can be either an element name, treating the
+array elements as hashes/objects, or a block.
+
+If I<value> isn't supplied then the element from the array is used.
+
+  <:.set objs = [ { id: 1, firstn: "Tony", lastn: "Cook", note: "Programming Geek" },
+                  { id: 2, firstn: "Adrian", lastn: "Oldham", note: "Design Geek" } ] :>
+  <:.set byid = objs.maphash("id") :>
+  <:= byid[2]firstn :>   # Adrian
+  <:.set byname = objs.maphash(@{i: i.firstn _ " " _ i.lastn }) :>
+  <:= byname["Tony Cook"].note :>  # Programming Geek
+  <:=.set namebynote = objs.maphash(@{i: i.note.lower }, @{i: i.firstn _ " " _ i.lastn }) :>
+  <:= namebynote["design geek"] :>  # Adrian Oldham
+
 =item is_list
 
 Test if this object is a list.  Always true for a list.
 =item is_list
 
 Test if this object is a list.  Always true for a list.
index 8c6ff45..c0be6ef 100644 (file)
@@ -1,7 +1,7 @@
 #!perl -w
 # Basic tests for Squirrel::Template
 use strict;
 #!perl -w
 # Basic tests for Squirrel::Template
 use strict;
-use Test::More tests => 209;
+use Test::More;
 use HTML::Entities;
 
 sub template_test($$$$;$$);
 use HTML::Entities;
 
 sub template_test($$$$;$$);
@@ -68,6 +68,11 @@ SKIP: {
        use Data::Dumper;
        Dumper($_[0]);
      },
        use Data::Dumper;
        Dumper($_[0]);
      },
+     objs =>
+     [
+      { id => 1, val1 => "abc", val2 => "def" },
+      { id => 2, val1 => "ghi", val2 => "jkl" }
+     ],
     );
   template_test("<:str:>", "ABC", "simple", \%acts);
   template_test("<:strref:>", "ABC", "scalar ref", \%acts);
     );
   template_test("<:str:>", "ABC", "simple", \%acts);
   template_test("<:strref:>", "ABC", "scalar ref", \%acts);
@@ -629,6 +634,13 @@ OUT
      [ '[ "A" .. "Z" ].slice([ 0 .. 5 ]).join("")', 'ABCDEF' ],
      [ '[ "A" .. "Z" ].slice(0, 1, -2, -1).join("")', 'ABYZ' ],
      [ '[ "A" .. "Z" ].splice(0, 5).join("")', 'ABCDE' ],
      [ '[ "A" .. "Z" ].slice([ 0 .. 5 ]).join("")', 'ABCDEF' ],
      [ '[ "A" .. "Z" ].slice(0, 1, -2, -1).join("")', 'ABYZ' ],
      [ '[ "A" .. "Z" ].splice(0, 5).join("")', 'ABCDE' ],
+     [ 'objs.maphash("id")[2].val2', 'jkl' ],
+     [ 'objs.maphash("id", "val1")[1]', 'abc' ],
+     [ 'objs.maphash("val1", "val2")["abc"]', 'def' ],
+     [ 'objs.maphash("val1", @{i: i.id _ i.val2 })["abc"]', '1def' ],
+     [ 'objs.maphash(@{i: i.val1 _ i.val2 }, @{i: i.id _ i.val2 })["abcdef"]', '1def' ],
+     [ 'somelist.maphash().exists("a")', '1' ],
+     [ 'somelist.maphash().exists("k")', '' ],
 
      # WrapHash
      [ '{ "foo": 1 }.is_list', 0 ],
 
      # WrapHash
      [ '{ "foo": 1 }.is_list', 0 ],
@@ -870,6 +882,8 @@ OUT
   }
 }
 
   }
 }
 
+done_testing();
+
 sub template_test ($$$$;$$) {
   my ($in, $out, $desc, $acts, $stripnl, $vars) = @_;
 
 sub template_test ($$$$;$$) {
   my ($in, $out, $desc, $acts, $stripnl, $vars) = @_;