]> mj.ucw.cz Git - temple.git/blobdiff - UCW/Temple.pm
The argument of UCW::Temple::start() is no longer mandatory
[temple.git] / UCW / Temple.pm
old mode 100755 (executable)
new mode 100644 (file)
index 41af968..1a3dc97
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 # A really simple template engine
-# (c) 2004 Martin Mares <mj@ucw.cz>
+# (c) 2004--2008 Martin Mares <mj@ucw.cz>
 
 package UCW::Temple;
 
@@ -8,10 +8,27 @@ use strict;
 use warnings;
 no strict 'vars';
 
+require Exporter;
+our $VERSION = 1.0;
+our @ISA = qw(Exporter);
+our @EXPORT = qw(out);
+our @EXPORT_OK = qw();
+
 use IO::File;
 
+our $arguments;
 our @cond;
-our $temp;
+
+sub out {
+       $T::out_func->(@_);
+       return;
+}
+
+our %deps = ();
+
+sub add_depend($) {
+       $deps{$_[0]} = 1;
+}
 
 sub get_nested($$$) {
        my ($r,$left,$right) = @_;
@@ -35,7 +52,7 @@ sub get_nested($$$) {
 sub eval_if_ok($) {
        if ($cond[0] > 0) {
                my $x = shift;
-               my $res = eval $x;
+               my $res = eval "package T; $x";
                return $res unless $@;
                die "Error evaluating $x: $@";
        } else {
@@ -73,7 +90,8 @@ sub eval_func($$) {
                }
                # print "Cond stack: @cond\n";
        } else {
-               eval_if_ok("$f($a)");
+               my $res = eval_if_ok("$f $a");
+               out $res if defined $res;
        }
 }
 
@@ -82,21 +100,26 @@ sub parse_string($) {
        pos $t = 0;
        for(;;) {
                if ($t =~ /\G([^\@]+)/cgs) {
-                       print $1 if $cond[0] > 0;
+                       out $1 if $cond[0] > 0;
                } elsif ($t =~ /\G\@\s*\n/cgs) {
                        # @ at end of line is ignored and eats the end of line
                } elsif ($t =~ /\G\@#[^\n]*\n/cgs) {
                        # a comment, which is ignored
                } elsif ($t =~ /\G\@\@/cgs) {
-                       print "\@";
+                       out "\@" if $cond[0] > 0;
                } elsif ($t =~ /\G\@{/cgs) {
                        my $x = get_nested(\$t, "{", "}");
-                       print eval_if_ok($x);
+                       out eval_if_ok($x);
                } elsif ($t =~ /\G\@\[/cgs) {
                        my $x = get_nested(\$t, '\[', '\]');
                        $x =~ s/^\[//;
-                       $x =~ s/$\]//;
+                       $x =~ s/\]$//;
                        eval_if_ok($x);
+               } elsif ($t =~ /\G\@\(/cgs) {
+                       my $x = get_nested(\$t, '\(', '\)');
+                       $x =~ s/^\(//;
+                       $x =~ s/\)$//;
+                       out (defined($arguments->{$x}) ? $arguments->{$x} : "");
                } elsif ($t =~ /\G\@(\w+)\(/cgs) {
                        my $func = $1;
                        my $args = get_nested(\$t, '(', ')');
@@ -104,7 +127,7 @@ sub parse_string($) {
                } elsif ($t =~ /\G\@(\w+)([^\n]*)\n/cgs) {
                        eval_func($1, "($2)");
                } elsif ($t =~ /\G\@(\$\w+)/cgs) {
-                       print eval_if_ok($1);
+                       out eval_if_ok($1);
                } elsif ($t =~ /\G(\@[^\n]*)/cgs) {
                        die "Unknown control sequence $1";
                } elsif ($t =~ /\G$/cgs) {
@@ -117,6 +140,7 @@ sub parse_string($) {
 
 sub parse_file($) {
        my ($name) = @_;
+       add_depend($name);
        my $fh = new IO::File $name;
        die "Unable to open $name: $!" unless defined $fh;
        my $text;
@@ -125,8 +149,9 @@ sub parse_file($) {
        parse_string($text);
 }
 
-sub start()
+sub start(;$)
 {
+       $arguments = $_[0];
        @cond = (1);
 }
 
@@ -135,34 +160,46 @@ sub finish()
        $#cond and die "Unterminated \@if (depth $#cond)";
 }
 
-sub process_file($) {
-       start();
-       parse_file($_[0]);
+sub process_file($;$) {
+       my ($name, $args) = @_;
+       start($args);
+       parse_file($name);
        finish();
 }
 
-sub process_string($) {
-       start();
-       parse_string($_[0]);
+sub process_string($;$) {
+       my ($string, $args) = @_;
+       start($args);
+       parse_string($string);
        finish();
 }
 
-### Commands available from the templates
+### Perl commands embedded in the templates are evaluated in this package ###
+
+package T;
+
+import UCW::Temple;
+
+our $temp;
+our $out_func = sub { print @_; };
 
 sub include {
        my $fn = shift @_;
        while (@_) {
                my $v = shift @_;
                $temp = shift @_;
-               eval_if_ok("\$$v = \$temp");
+               UCW::Temple::eval_if_ok("\$$v = \$temp");
        }
-       parse_file($fn);
+       UCW::Temple::parse_file($fn);
+       return;
 }
 
 sub load {
        my $f = shift @_;
-       (!defined $f || @_) and die "\@load requires only one argument";
+       (!defined($f) || @_) and die "\@load requires only one argument";
+       UCW::Temple::add_depend($f);
        require $f;
+       return;
 }
 
 1;