allow alternate delimiters for tags
authorTony Cook <tony@develop-help.com>
Sun, 24 Aug 2014 04:41:52 +0000 (14:41 +1000)
committerTony Cook <tony@develop-help.com>
Sun, 24 Aug 2014 04:41:52 +0000 (14:41 +1000)
site/cgi-bin/modules/Squirrel/Template.pm
site/cgi-bin/modules/Squirrel/Template/Tokenizer.pm
t/020-templater/010-token.t

index 23193bb..d91bb59 100644 (file)
@@ -20,7 +20,7 @@ BEGIN {
 
 use constant DEBUG_GET_PARMS => 0;
 
-our $VERSION = "1.029";
+our $VERSION = "1.030";
 
 my %compile_cache;
 
@@ -35,6 +35,10 @@ sub new {
   $opts{wraps} = [];
   $opts{errors} = [];
   $opts{def_format} ||= "";
+  $opts{delimiters} ||=
+    [
+     [ "<:", ":>" ],
+    ];
 
   return bless \%opts, $class;
 }
@@ -414,7 +418,7 @@ sub parse {
   my ($self, $template, $name) = @_;
 
   my $t = Squirrel::Template::Tokenizer->new($template, $name || "<string>",
-                                            $self);
+                                            $self, $self->{delimiters});
   my $p = Squirrel::Template::Parser->new($t, $self);
 
   my $node = $p->parse;
index 4e151ec..4e6825d 100644 (file)
@@ -2,7 +2,7 @@ package Squirrel::Template::Tokenizer;
 use strict;
 use Squirrel::Template::Constants qw(:token);
 
-our $VERSION = "1.014";
+our $VERSION = "1.015";
 
 use constant QUEUE => 0;
 use constant TEXT => 1;
@@ -10,17 +10,32 @@ use constant LINE => 2;
 use constant NAME => 3;
 use constant TMPLT => 4;
 use constant INCLUDES => 5;
+use constant STARTS => 6;
+use constant ENDS => 7;
 
 use constant TRACE => 0;
 
 sub new {
-  my ($class, $text, $name, $templater) = @_;
+  my ($class, $text, $name, $templater, $ends) = @_;
 
-  return bless [ [], $text, 1, $name, $templater, [] ], $class;
-}
+  $ends ||= [ [ "<:", ":>" ] ];
+
+  my $end_res;
+  my @starts;
+  my %ends;
+  for my $end (@$ends) {
+    push @starts, $end->[0];
+    $ends{$end->[0]} = qr/(?:-\Q$end->[1]\E\s*|\Q$end->[1]\E)/;
+  }
+  my $head_match = join "|", map quotemeta, @starts;
+  my $match = qr/(?:$head_match)/;
+
+  my $self = bless [ [], $text, 1, $name, $templater, [] ], $class;
+  $self->[STARTS] = $match;
+  $self->[ENDS] = \%ends;
 
-my $tag_head = qr/(?:\s+<:-|<:-?)/;
-my $tag_tail = qr/(?:-:>\s*|:>)/;
+  $self;
+}
 
 # simple to tokenize directives
 my @simple = qw(endwrap switch endswitch eif or);
@@ -47,8 +62,18 @@ sub get {
     return;
   }
 
-  if ($self->[TEXT] =~ s/\A(.*?)(($tag_head)\s*)//s) {
-    my ($content, $tag_start, $head) = ($1, $2, $3);
+  if ($self->[TEXT] =~ s/\A(.*?)(\s*)($self->[STARTS])(-?)(\s*)//s) {
+    my ($content, $before_ws, $start, $dash, $more_ws) =
+      ($1, $2, $3, $4, $5);
+    my $head;
+    if ($dash) {
+      $head = $before_ws . $start . $dash;
+    }
+    else {
+      $content .= $before_ws;
+      $head = $start;
+    }
+    my $tag_start = $head . $more_ws;
 
     if (length $content) {
       push @$queue, [ "content", $content, $line, $name ];
@@ -56,6 +81,8 @@ sub get {
       $line = $self->[LINE];
     }
 
+    my $tag_tail = $self->[ENDS]{$start}
+      or die "No tail found for $start '$tag_start'";
     if ($self->[TEXT] =~ s/\A((.*?)\s*($tag_tail))//s) {
       my ($tag_end, $body, $tail) = ($1, $2, $3);
       my $tag = $tag_start . $tag_end;
index 7c00d20..0db3f30 100644 (file)
@@ -1,11 +1,16 @@
 #!perl -w
 use strict;
-use Test::More tests => 42;
+use Test::More tests => 44;
 use Squirrel::Template;
 use Squirrel::Template::Constants qw(:token);
 
 sub test_tokens($$$);
 
+my %opts =
+  (
+   template_dir=>'t/templates',
+  );
+
 # test the interface
 my $templater = Squirrel::Template->new();
 my $t = Squirrel::Template::Tokenizer->new("content\n<:sometag foo:>", "<test>", $templater);
@@ -330,11 +335,52 @@ EOS
             [ eof => "", 6, "<string>" ],
            ], "comment");
 
+{
+  local $opts{delimiters} =
+    [
+     [ "[:", ":]" ],
+    ];
+
+  test_tokens(<<EOS,
+[:.if foo -:]
+bar
+[:.end if-:]
+EOS
+             [
+              [ ext_if => "[:.if foo -:]\n", 1, "<string>", "foo" ],
+              [ content => "bar\n", 2, "<string>" ],
+              [ end => "[:.end if-:]\n", 3, "<string>", "if" ],
+              [ eof => "", 4, "<string>" ],
+             ], "alt delimters .if");
+}
+
+{
+{
+  local $opts{delimiters} =
+    [
+     [ "<:", ":>" ],
+     [ "[:", ":]" ],
+    ];
+
+  test_tokens(<<EOS,
+[:.if ":>" -:]
+bar
+<:.set bar = "[:" -:>
+EOS
+             [
+              [ ext_if => "[:.if \":>\" -:]\n", 1, "<string>", '":>"' ],
+              [ content => "bar\n", 2, "<string>" ],
+              [ set => "<:.set bar = \"[:\" -:>\n", 3, "<string>", "bar", '"[:"' ],
+              [ eof => "", 4, "<string>" ],
+             ], "alt delimters .if some more");
+}
+}
+
 sub test_tokens($$$) {
   my ($text, $tokens, $name) = @_;
 
-  my $tmpl = Squirrel::Template->new(template_dir=>'t/templates');
-  my $tok = Squirrel::Template::Tokenizer->new($text, "<string>", $tmpl);
+  my $tmpl = Squirrel::Template->new(%opts);
+  my $tok = Squirrel::Template::Tokenizer->new($text, "<string>", $tmpl, $opts{delimiters});
 
   my @rtokens;
   while (my $token = $tok->get) {