2 # A really simple template engine
3 # (c) 2004--2008 Martin Mares <mj@ucw.cz>
13 our @ISA = qw(Exporter);
14 our @EXPORT = qw(out);
15 our @EXPORT_OK = qw();
27 my ($r,$left,$right) = @_;
32 if ($$r =~ /\G([^$left$right]+)/cgs) {
33 } elsif ($$r =~ /\G([$left])/cgs) {
35 } elsif ($$r =~ /\G([$right])/cgs) {
38 die "File ended when looking for matching $right";
48 my $res = eval "package T; $x";
49 return $res unless $@;
50 die "Error evaluating $x: $@";
58 if ($f =~ /^(if|fi|else|elif)$/) {
60 $a ne "()" or die "\@if requires an argument";
62 unshift @cond, (eval_if_ok($a) ? 1 : -1);
66 } elsif ($f eq "fi") {
67 $a eq "()" or die "\@fi takes no arguments";
68 $#cond or die "\@fi without \@if";
70 } elsif ($f eq "else") {
71 $a eq "()" or die "\@else takes no arguments";
72 $#cond or die "\@else without \@if";
74 } elsif ($f eq "elif") {
75 $a ne "()" or die "\@elif requires an argument";
76 $#cond or die "\@elif without \@if";
79 } elsif ($cond[0] < 0) {
81 $cond[0] = (eval_if_ok($a) ? 1 : -1);
84 # print "Cond stack: @cond\n";
86 my $res = eval_if_ok("$f($a)");
87 out $res if defined $res;
95 if ($t =~ /\G([^\@]+)/cgs) {
96 out $1 if $cond[0] > 0;
97 } elsif ($t =~ /\G\@\s*\n/cgs) {
98 # @ at end of line is ignored and eats the end of line
99 } elsif ($t =~ /\G\@#[^\n]*\n/cgs) {
100 # a comment, which is ignored
101 } elsif ($t =~ /\G\@\@/cgs) {
103 } elsif ($t =~ /\G\@{/cgs) {
104 my $x = get_nested(\$t, "{", "}");
106 } elsif ($t =~ /\G\@\[/cgs) {
107 my $x = get_nested(\$t, '\[', '\]');
111 } elsif ($t =~ /\G\@(\w+)\(/cgs) {
113 my $args = get_nested(\$t, '(', ')');
114 eval_func($func, $args);
115 } elsif ($t =~ /\G\@(\w+)([^\n]*)\n/cgs) {
116 eval_func($1, "($2)");
117 } elsif ($t =~ /\G\@(\$\w+)/cgs) {
119 } elsif ($t =~ /\G(\@[^\n]*)/cgs) {
120 die "Unknown control sequence $1";
121 } elsif ($t =~ /\G$/cgs) {
123 } elsif ($t =~ /\G([^\n]*)/cgs) {
124 die "Internal parser error at $1 (pos " . pos($t) . ")";
131 my $fh = new IO::File $name;
132 die "Unable to open $name: $!" unless defined $fh;
134 { local $/; undef $/; $text = <$fh>; }
146 $#cond and die "Unterminated \@if (depth $#cond)";
149 sub process_file($) {
155 sub process_string($) {
161 ### Perl commands embedded in the templates are evaluated in this package ###
168 our $out_func = sub { print @_; };
175 UCW::Temple::eval_if_ok("\$$v = \$temp");
177 UCW::Temple::parse_file($fn);
183 (!defined($f) || @_) and die "\@load requires only one argument";