Permalink
Browse files

add a new .while construct to templates

  • Loading branch information...
1 parent 2470cfc commit 394018efa6828e755188701c0286c03ece4a7fbe @tonycoz committed Mar 22, 2013
View
8 site/cgi-bin/modules/Squirrel/Template.pm
@@ -20,7 +20,7 @@ BEGIN {
use constant DEBUG_GET_PARMS => 0;
-our $VERSION = "1.026";
+our $VERSION = "1.027";
my %compile_cache;
@@ -863,6 +863,12 @@ C<< <:.iterateover I<callback>, I<arguments>... :> I<content> <:.end :> >>
Calls back into the target supplied callback to set variables which
can then be replaced on each iteration.
+=item *
+
+C<< <:.while I<condition> :> I<content> <:.end :> >>
+
+Produce I<content> while I<condition> is true.
+
=back
=head1 Special Variables
View
7 site/cgi-bin/modules/Squirrel/Template/Constants.pm
@@ -2,7 +2,7 @@ package Squirrel::Template::Constants;
use strict;
use Exporter qw(import);
-our $VERSION = "1.006";
+our $VERSION = "1.007";
sub _define_sequence {
my ($keys, $start) = @_;
@@ -64,6 +64,8 @@ my @node_extif = qw(NODE_EXTIF_CONDS NODE_EXTIF_ELSE NODE_EXTIF_END);
_define_sequence(\@node_extif, 4);
my @node_iterateover = qw(NODE_ITERATEOVER_CALL NODE_ITERATEOVER_ARGS NODE_ITERATEOVER_CONTENT);
_define_sequence(\@node_iterateover, 4);
+my @node_while = qw(NODE_WHILE_COND NODE_WHILE_CONTENT NODE_WHILE_END);
+_define_sequence(\@node_while, 4);
our %EXPORT_TAGS =
(
@@ -74,7 +76,8 @@ our %EXPORT_TAGS =
[
@node_base, @node_iter, @node_cond, @node_comp, @node_with,
@node_wrap, @node_switch, @node_error, @node_expr, @node_set,
- @node_define, @node_call, @node_for, @node_extif, @node_iterateover
+ @node_define, @node_call, @node_for, @node_extif, @node_iterateover,
+ @node_while,
],
);
View
31 site/cgi-bin/modules/Squirrel/Template/Parser.pm
@@ -2,7 +2,7 @@ package Squirrel::Template::Parser;
use strict;
use Squirrel::Template::Constants qw(:token :node);
-our $VERSION = "1.014";
+our $VERSION = "1.015";
use constant TOK => 0;
use constant TMPLT => 1;
@@ -557,6 +557,35 @@ sub _parse_ext_if {
return @errors ? $self->_comp($if, @errors) : $if;
}
+sub _parse_ext_while {
+ my ($self, $while) = @_;
+
+ my @errors;
+ my $content = $self->_parse_content;
+ my $end = $self->[TOK]->get;
+ if ($end->[TOKEN_TYPE] eq 'end') {
+ if ($end->[TOKEN_END_TYPE] ne "" && $end->[TOKEN_END_TYPE] ne 'while') {
+ push @errors, $self->_error($end, "Expected '.end' or '.end while' for .while started $while->[TOKEN_FILENAME]:$while->[TOKEN_LINE] but found '.end $end->[TOKEN_END_TYPE]'");
+ }
+ }
+ else {
+ push @errors, $self->_error($end, "Expected '.end' for .while started $while->[TOKEN_FILENAME]:$while->[TOKEN_LINE] but found $end->[TOKEN_TYPE]");
+ $self->[TOK]->unget($end);
+ $end = $self->_empty($end);
+ }
+
+ my $parser = Squirrel::Template::Expr::Parser->new;
+ my $cond_expr;
+ unless (eval { $cond_expr = $parser->parse($while->[TOKEN_EXT_EXPR]); 1 }) {
+ return $self->_error($while, "Could not parse condition for .while: " . ref $@ ? $@->[0] : $@);
+ }
+
+ @{$while}[NODE_TYPE, NODE_WHILE_COND, NODE_WHILE_CONTENT, NODE_WHILE_END] =
+ ( "while", $cond_expr, $content, $end );
+
+ return @errors ? $self->_comp($while, @errors) : $while;
+}
+
sub _parse_iterateover {
my ($self, $token) = @_;
View
49 site/cgi-bin/modules/Squirrel/Template/Processor.pm
@@ -3,7 +3,7 @@ use strict;
use Squirrel::Template::Constants qw(:node);
use Scalar::Util ();
-our $VERSION = "1.021";
+our $VERSION = "1.022";
use constant ACTS => 0;
use constant TMPLT => 1;
@@ -681,6 +681,53 @@ sub _process_iterateover {
return @result;
}
+sub _process_while {
+ my ($self, $node) = @_;
+
+ my $cond = $node->[NODE_WHILE_COND];
+ my $result;
+ unless (eval { $result = $self->[EVAL]->process($cond); 1 }) {
+ my $msg = $@;
+ if (!ref $msg && $msg ==~ /\bENOIMPL\b/) {
+ return
+ (
+ $node->[NODE_ORIG],
+ $self->process($node->[NODE_WHILE_CONTENT]),
+ $node->[NODE_WHILE_END][NODE_ORIG],
+ );
+ }
+ else {
+ return $self->_error($node, ref $msg ? $msg->[1] : $msg);
+ }
+ }
+ my @output;
+ while ($result) {
+ push @output, $self->process($node->[NODE_WHILE_CONTENT]);
+
+ unless (eval { $result = $self->[EVAL]->process($cond); 1 }) {
+ my $msg = $@;
+ if (!ref $msg && $msg ==~ /\bENOIMPL\b/) {
+ return
+ (
+ @output,
+ $node->[NODE_ORIG],
+ $self->process($node->[NODE_WHILE_CONTENT]),
+ $node->[NODE_WHILE_END][NODE_ORIG],
+ );
+ }
+ else {
+ return
+ (
+ @output,
+ $self->_error($node, ref $msg ? $msg->[1] : $msg),
+ );
+ }
+ }
+ }
+
+ return @output;
+}
+
1;
=head1 NAME
View
22 t/020-templater/040-original.t
@@ -1,7 +1,7 @@
#!perl -w
# Basic tests for Squirrel::Template
use strict;
-use Test::More tests => 170;
+use Test::More tests => 180;
use HTML::Entities;
sub template_test($$$$;$$);
@@ -367,6 +367,17 @@ IN
</foo>
OUT
+ template_test(<<IN, <<OUT, "while", \%acts);
+<:.set work = [ "a" .. "z" ] -:>
+<:.while work.size and work[0] ne "d" -:>
+<:= work.shift :>
+<:.end while -:>
+IN
+a
+b
+c
+OUT
+
template_test(<<IN, <<OUT, "space complex", \%acts, "both");
<div class="window">
<h1><:str:></h1>
@@ -520,6 +531,15 @@ OUT
[ '"test".is_hash', 0 ],
[ '"abc".replace(/(.)(.)(.)/, "$3$2$1")', "cba" ],
[ '"a&b".escape("html")', 'a&amp;b' ],
+ [ '"abc".match(/b/).start', "1" ],
+ [ '"abc".match(/b/).end', "2" ],
+ [ '"abc".match(/b/).length', "1" ],
+ [ '"abc".match(/(b)/).subexpr[0].start', "1" ],
+ [ '"abc".match(/(b)/).subexpr[0].end', "2" ],
+ [ '"abc".match(/(b)/).subexpr[0].length', "1" ],
+ [ '"abcd".substring(1)', "bcd" ],
+ [ '"abcd".substring(1,2)', "bc" ],
+ [ '"abcd".substring(1,-2)', "b" ],
# WrapArray
[ '[ [ 1, 2 ], 3 ].expand.join(",")', "1,2,3" ],

0 comments on commit 394018e

Please sign in to comment.