Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
  • 2 commits
  • 7 files changed
  • 0 commit comments
  • 1 contributor
View
16 site/cgi-bin/modules/Squirrel/Template.pm
@@ -20,7 +20,7 @@ BEGIN {
use constant DEBUG_GET_PARMS => 0;
-our $VERSION = "1.028";
+our $VERSION = "1.029";
my %compile_cache;
@@ -394,9 +394,9 @@ sub set_var {
}
sub define_macro {
- my ($self, $name, $content) = @_;
+ my ($self, $name, $content, $defaults) = @_;
- $self->{defines}{$name} = $content;
+ $self->{defines}{$name} = [ $content, $defaults ];
return 1;
}
@@ -404,10 +404,10 @@ sub define_macro {
sub get_macro {
my ($self, $name) = @_;
- my $content = $self->{defines}{$name}
+ my $define = $self->{defines}{$name}
or return;
- return $content;
+ return @$define;
}
sub parse {
@@ -825,6 +825,10 @@ The C<.end> token can also be C<.end for>.
C<< <:.define I<name> :> I<content> <:.end:> >>
+=item *
+
+C<< <:.define I<name>; name1:value1, name2:value2 :> I<content> <:.end:> >>
+
Define a macro called I<name> with the specified content. The C<.end>
token can be C<.end define>.
@@ -834,6 +838,8 @@ eg.
some content
<:.end define:>
+The second form provides defaults for calls to the macro.
+
=item *
C<< <:.call I<name-expression> :> >>
View
4 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.008";
+our $VERSION = "1.009";
sub _define_sequence {
my ($keys, $start) = @_;
@@ -54,7 +54,7 @@ my @node_expr = qw(NODE_EXPR_EXPR NODE_EXPR_FORMAT);
_define_sequence(\@node_expr, 4);
my @node_set = qw(NODE_SET_VAR NODE_SET_EXPR);
_define_sequence(\@node_set, 4);
-my @node_define = qw(NODE_DEFINE_NAME NODE_DEFINE_END NODE_DEFINE_CONTENT);
+my @node_define = qw(NODE_DEFINE_NAME NODE_DEFINE_END NODE_DEFINE_CONTENT NODE_DEFINE_DEFAULTS);
_define_sequence(\@node_define, 4);
my @node_call = qw(NODE_CALL_NAME NODE_CALL_LIST);
_define_sequence(\@node_call, 4);
View
59 site/cgi-bin/modules/Squirrel/Template/Expr.pm
@@ -1,7 +1,7 @@
package Squirrel::Template::Expr;
use strict;
-our $VERSION = "1.012";
+our $VERSION = "1.013";
package Squirrel::Template::Expr::Eval;
use Scalar::Util ();
@@ -585,25 +585,12 @@ sub _parse_primary {
return [ list => $list ];
}
elsif ($t->[0] eq 'op{') {
- my @pairs;
- if ($tok->peektype eq 'op}') {
- $tok->get; # discard '}'
- }
- else {
- my $next;
- do {
- my $key = $self->_parse_additive($tok);
- my $colon = $tok->get;
- $colon->[0] eq 'op:'
- or die [ error => "Expected : in hash but found $colon->[1]" ];
- my $value = $self->_parse_expr($tok);
- push @pairs, [ $key, $value ];
- } while ($next = $tok->get and $next->[0] eq 'op,');
- $next->[0] eq 'op}'
- or die [ error => "Expected , or } but found $tok->[1]" ];
- }
+ my $pairs = $self->parse_pairs($tok);
+ my $next = $tok->get;
+ $next->[0] eq 'op}'
+ or die [ error => "Expected , or } but found $next->[1]" ];
- return [ hash => \@pairs ];
+ return [ hash => $pairs ];
}
elsif ($t->[0] eq 're') {
return [ re => $t->[2], $t->[3] ];
@@ -613,6 +600,40 @@ sub _parse_primary {
}
}
+sub parse_pairs {
+ my ($self, $tok) = @_;
+
+ my $nexttype = $tok->peektype;
+ if ($nexttype eq 'op}' || $nexttype eq 'eof') {
+ return [];
+ }
+ else {
+ my $next;
+ my @pairs;
+ do {
+ my $key;
+ if ($tok->peektype eq 'id') {
+ my $id = $tok->get;
+ if ($tok->peektype eq 'op:') {
+ $key = [ const => $id->[2] ];
+ }
+ else {
+ $tok->unget($id);
+ }
+ }
+ $key ||= $self->_parse_additive($tok);
+ my $colon = $tok->get;
+ $colon->[0] eq 'op:'
+ or die [ error => "Expected : in hash but found $colon->[1]" ];
+ my $value = $self->_parse_expr($tok);
+ push @pairs, [ $key, $value ];
+ } while ($next = $tok->get and $next->[0] eq 'op,');
+ $tok->unget($next);
+
+ return \@pairs;
+ }
+}
+
package Squirrel::Template::Expr::Tokenizer;
use constant TEXT => 0;
View
50 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.018";
+our $VERSION = "1.019";
use constant TOK => 0;
use constant TMPLT => 1;
@@ -516,21 +516,39 @@ sub _parse_define {
my $content = $self->_parse_content;
my $end = $self->[TOK]->get;
- my $error;
+ my @errors;
if ($end->[TOKEN_TYPE] eq 'end') {
if ($end->[TOKEN_END_TYPE] && $end->[TOKEN_END_TYPE] ne 'define') {
- $error = $self->_error($end, "Expected '.end' or '.end define' for .define started $define->[TOKEN_FILENAME]:$define->[TOKEN_LINE] but found '.end $end->[TOKEN_END_TYPE]'");
+ push @errors, $self->_error($end, "Expected '.end' or '.end define' for .define started $define->[TOKEN_FILENAME]:$define->[TOKEN_LINE] but found '.end $end->[TOKEN_END_TYPE]'");
}
}
else {
$self->[TOK]->unget($end);
- $error = $self->_error($end, "Expected '.end' for .define started $define->[TOKEN_FILENAME]:$define->[TOKEN_LINE] but found $end->[TOKEN_TYPE]");
+ push @errors, $self->_error($end, "Expected '.end' for .define started $define->[TOKEN_FILENAME]:$define->[TOKEN_LINE] but found $end->[TOKEN_TYPE]");
$end = $self->_empty($end);
}
- @{$define}[NODE_DEFINE_END, NODE_DEFINE_CONTENT] = ( $end, $content );
- if ($error) {
- return $self->_comp($define, $error);
+ my $text = $define->[NODE_DEFINE_NAME];
+ my $name;
+ if ($text =~ s(^([^;\s]+))()) {
+ $name = $1;
+ }
+ my $defaults;
+ my %seen_args;
+ if ($text =~ s/^\s*;\s*// && $text ne "") {
+ my $tokens = Squirrel::Template::Expr::Tokenizer->new($text);
+ my $parser = Squirrel::Template::Expr::Parser->new;
+ $defaults = $parser->parse_pairs($tokens);
+ $tokens->peektype eq 'eof'
+ or push @errors, $self->_error($end, "Defaults list for .define started $define->[TOKEN_FILENAME]:$define->[TOKEN_LINE] has extra junk");
+ }
+ $define->[NODE_DEFINE_NAME] = $name;
+
+ @{$define}[NODE_DEFINE_END, NODE_DEFINE_CONTENT, NODE_DEFINE_DEFAULTS] =
+ ( $end, $content, $defaults );
+
+ if (@errors) {
+ return $self->_comp($define, @errors);
}
else {
return $define;
@@ -552,22 +570,12 @@ sub _parse_call {
my @result;
my $next = $tokens->get;
- my @args;
+ my $args = [];
if ($next->[0] eq 'op,') {
unless (eval {
- while ($next->[0] eq 'op,') {
- my $key;
- my $value;
- $key = $parser->parse_tokens($tokens);
- my $colon = $tokens->get;
- $colon->[0] eq 'op:'
- or die [ error => "Expected : but found $colon->[0]" ];
- $value = $parser->parse_tokens($tokens);
- push @args, [ $key, $value ];
- $next = $tokens->get;
- }
+ $args = $parser->parse_pairs($tokens);
- if ($next->[0] ne 'eof') {
+ if ($tokens->peektype ne 'eof') {
die [ error => "Expected , or eof but found $next->[0]" ];
}
1;
@@ -579,7 +587,7 @@ sub _parse_call {
$error = $self->_error($call, "Expected , or end of expression but found $next->[0]");
}
- @{$call}[NODE_CALL_NAME, NODE_CALL_LIST] = ( $name_expr, \@args );
+ @{$call}[NODE_CALL_NAME, NODE_CALL_LIST] = ( $name_expr, $args );
return $error ? $self->_comp($call, $error) : $call;
}
View
17 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.024";
+our $VERSION = "1.025";
use constant ACTS => 0;
use constant TMPLT => 1;
@@ -158,7 +158,7 @@ sub _process_set {
sub _process_define {
my ($self, $define) = @_;
- $self->[TMPLT]->define_macro($define->[NODE_DEFINE_NAME], $define->[NODE_DEFINE_CONTENT]);
+ $self->[TMPLT]->define_macro($define->[NODE_DEFINE_NAME], $define->[NODE_DEFINE_CONTENT], $define->[NODE_DEFINE_DEFAULTS]);
return;
}
@@ -169,6 +169,7 @@ sub _process_call {
my $parsed;
my %args;
my @result;
+ my $defaults;
my $name;
if (eval {
$name = $self->[EVAL]->process($node->[NODE_CALL_NAME]);
@@ -178,7 +179,7 @@ sub _process_call {
$args{$key} = $value;
}
- $parsed = $self->[TMPLT]->get_macro($name);
+ ($parsed, $defaults) = $self->[TMPLT]->get_macro($name);
if (!$parsed) {
($parsed, my $message) = $self->[TMPLT]->parse_file($name);
unless ($parsed) {
@@ -190,6 +191,16 @@ sub _process_call {
}) {
my $ctx = ".call '$name' from $node->[NODE_FILENAME]:$node->[NODE_LINE]";
if (eval { $self->[TMPLT]->start_scope($ctx, \%args), 1 }) {
+ if ($defaults) {
+ for my $entry (@$defaults) {
+ my ($name_expr, $value_expr)= @$entry;
+ my $name = $self->[EVAL]->process($name_expr);
+ unless (exists $args{$name}) {
+ my $value = $self->[EVAL]->process($value_expr);
+ $self->[TMPLT]->set_var($name, $value);
+ }
+ }
+ }
@result = $self->process($parsed);
$self->[TMPLT]->end_scope();
}
View
52 site/templates/preload.tmpl
@@ -1,11 +1,8 @@
<:# see preload.pod for documentation -:>
-<:.set groups = 0 -:>
-<:.set grouplabel = "label" -:>
-<:.set groupid = "id" -:>
-<:.set itemgroupid = "groupid" -:>
<:.set dist_image_uri = cfg.entryIfVar("uri", "dist_images", "/images") -:>
<:# utility definitions :>
-<:-.define make_select-:>
+<:-.define make_select; groups: 0, grouplabel: "label", groupid: "id",
+ itemgroupid: "groupid" -:>
<:-.if !default.defined -:>
<:-.set default = "" -:>
<:.end if:>
@@ -50,7 +47,7 @@ make_multicheck expects:
name - the name of the input elements
readonly - true to make it readonly
-:>
-<:-.define make_multicheck-:>
+<:-.define make_multicheck; readonly: 0-:>
<:.if !readonly -:>
<input type="hidden" name="_save_<:= name -:>" value="1">
<:.end if -:>
@@ -137,7 +134,7 @@ Page <:= pages.page :> of <:= pages.pagecount :>
<:.end define -:>
<:.define error_img -:>
-<:.call "error_img_n", "index":0 -:>
+<:.call "error_img_n", index:0 -:>
<:.end define -:>
<:.define input -:>
@@ -175,22 +172,21 @@ Page <:= pages.page :> of <:= pages.pagecount :>
<:.set values = values.is_code ? values() : values -:>
<:.set default = cgi.param("_save_" _ name) ? [ cgi.param(name) ] : default -:>
<:.call "make_multicheck",
- "id":field.select.id,
- "desc":field.select.label,
- "readonly":0 -:>
+ id:field.select.id,
+ desc:field.select.label -:>
<: .elsif field.htmltype eq "select" -:>
<:.set values = field.select["values"] -:>
<:.set values = values.is_code ? values() : values -:>
<:.call "make_select",
- "name":name,
- "default":default,
- "list":values,
- "id":field.select.id,
- "desc":field.select.label,
- "groupid": (field.select.groupid or "id"),
- "itemgroupid": (field.select.itemgroupid or "groupid"),
- "groups": field.select.groups ? (field.select.groups.is_code ? (field.select.groups)() : field.select.groups ) : 0,
- "grouplabel": (field.select.grouplabel or "label")
+ name: name,
+ default: default,
+ list: values,
+ id: field.select.id,
+ desc: field.select.label,
+ groupid : (field.select.groupid or "id"),
+ itemgroupid: (field.select.itemgroupid or "groupid"),
+ groups: field.select.groups ? (field.select.groups.is_code ? (field.select.groups)() : field.select.groups ) : 0,
+ grouplabel: (field.select.grouplabel or "label")
-:>
<: .else -:>
<input id="<:= name | html :>" type="text" name="<:= name | html :>" value="<:= default | html :>"
@@ -207,7 +203,7 @@ Page <:= pages.page :> of <:= pages.pagecount :>
<:.if fields.is_hash -:>
<:.set f = fields[name] -:>
<:.if f -:>
- <:.call "inlinefield", "field":f, "name":name -:>
+ <:.call "inlinefield", field:f, name:name -:>
<:.else -:>
<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
<:.end if -:>
@@ -226,9 +222,9 @@ Page <:= pages.page :> of <:= pages.pagecount :>
<label for="<:= name | html :>"><:= field.nolabel ? "" : field.description | html :>:</label>
<span>
<:-.if field.readonly -:>
-<:-.call "display", "name":name -:>
+<:-.call "display", name:name -:>
<:.else -:>
-<:-.call "input", "name":name -:><:.call "error_img", "field":name :>
+<:-.call "input", name:name -:><:.call "error_img", field:name :>
<:-.end if -:>
<:-.if field.units -:>
<:-= field.units | html -:>
@@ -250,7 +246,7 @@ parameters:
<:.if !f.nolabel -:>
<legend><:= f.description :></legend>
<:.end if -:>
- <:.call "input", "name":name, "field":f -:>
+ <:.call "input", name: name, field: f -:>
</fieldset>
<:.elsif fields.is_hash -:>
<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
@@ -284,9 +280,9 @@ parameters:
<:.set values = field.select["values"] -:>
<:.set values = values.is_code ? values() : values -:>
<:.call "make_multicheck",
- "id":field.select.id,
- "desc":field.select.label,
- "readonly":1 -:>
+ id: field.select.id,
+ desc: field.select.label,
+ readonly: 1 -:>
<: .elsif field.htmltype eq "select" -:>
<:.set values = field.select["values"] -:>
<:.set values = values.is_code ? values() : values -:>
@@ -312,7 +308,7 @@ parameters:
<:.if field.is_hash -:>
<div>
<label for="<:= name :>"><:= field.nolabel ? "" : field.description :>:</label>
- <span><:.call "display", "name":name -:>
+ <span><:.call "display", name:name -:>
<:-.if field.units -:>
<:-= field.units -:>
<:-.end if -:>
@@ -326,7 +322,7 @@ parameters:
<:.if fields.is_hash -:>
<:.set f = fields[name] -:>
<:.if f -:>
- <:.call "inlinefieldro", "field":f, "name":name -:>
+ <:.call "inlinefieldro", field:f, name:name -:>
<:.else -:>
<p>Unknown field id '<b><:= name :></b>', available fields are '<:= fields.keys.join("', '") :>'</p>
<:.end if -:>
View
13 t/020-templater/040-original.t
@@ -1,7 +1,7 @@
#!perl -w
# Basic tests for Squirrel::Template
use strict;
-use Test::More tests => 185;
+use Test::More tests => 186;
use HTML::Entities;
sub template_test($$$$;$$);
@@ -624,9 +624,16 @@ IN
<:-.define foo:>
<:-= avar -:>
<:.end-:>
-<:.call "foo", "avar":"avalue"-:>
+<:.call "foo", avar:"avalue"-:>
<:.call "foo",
- "avar":"bvalue"-:>
+ avar:"bvalue"-:>
+IN
+ template_test(<<IN, "2716", "define defaults with call", \%acts, "both", \%vars);
+<:-.define foo; abc:1, def:abc+5 :>
+<:-= abc -:><:= def -:>
+<:.end-:>
+<:.call "foo", "abc":"2"-:>
+<:.call "foo" -:>
IN
template_test(<<IN, "other value", "external call", \%acts, "", \%vars);
<:.call "called.tmpl", "avar":"other value"-:>

No commit comments for this range

Something went wrong with that request. Please try again.