2 # A really simple template engine
3 # (c) 2004--2008 Martin Mares <mj@ucw.cz>
16 my ($r,$left,$right) = @_;
21 if ($$r =~ /\G([^$left$right]+)/cgs) {
22 } elsif ($$r =~ /\G([$left])/cgs) {
24 } elsif ($$r =~ /\G([$right])/cgs) {
27 die "File ended when looking for matching $right";
37 my $res = eval "package T; $x";
38 return $res unless $@;
39 die "Error evaluating $x: $@";
47 if ($f =~ /^(if|fi|else|elif)$/) {
49 $a ne "()" or die "\@if requires an argument";
51 unshift @cond, (eval_if_ok($a) ? 1 : -1);
55 } elsif ($f eq "fi") {
56 $a eq "()" or die "\@fi takes no arguments";
57 $#cond or die "\@fi without \@if";
59 } elsif ($f eq "else") {
60 $a eq "()" or die "\@else takes no arguments";
61 $#cond or die "\@else without \@if";
63 } elsif ($f eq "elif") {
64 $a ne "()" or die "\@elif requires an argument";
65 $#cond or die "\@elif without \@if";
68 } elsif ($cond[0] < 0) {
70 $cond[0] = (eval_if_ok($a) ? 1 : -1);
73 # print "Cond stack: @cond\n";
83 if ($t =~ /\G([^\@]+)/cgs) {
84 print $1 if $cond[0] > 0;
85 } elsif ($t =~ /\G\@\s*\n/cgs) {
86 # @ at end of line is ignored and eats the end of line
87 } elsif ($t =~ /\G\@#[^\n]*\n/cgs) {
88 # a comment, which is ignored
89 } elsif ($t =~ /\G\@\@/cgs) {
91 } elsif ($t =~ /\G\@{/cgs) {
92 my $x = get_nested(\$t, "{", "}");
94 } elsif ($t =~ /\G\@\[/cgs) {
95 my $x = get_nested(\$t, '\[', '\]');
99 } elsif ($t =~ /\G\@(\w+)\(/cgs) {
101 my $args = get_nested(\$t, '(', ')');
102 eval_func($func, $args);
103 } elsif ($t =~ /\G\@(\w+)([^\n]*)\n/cgs) {
104 eval_func($1, "($2)");
105 } elsif ($t =~ /\G\@(\$\w+)/cgs) {
106 print eval_if_ok($1);
107 } elsif ($t =~ /\G(\@[^\n]*)/cgs) {
108 die "Unknown control sequence $1";
109 } elsif ($t =~ /\G$/cgs) {
111 } elsif ($t =~ /\G([^\n]*)/cgs) {
112 die "Internal parser error at $1 (pos " . pos($t) . ")";
119 my $fh = new IO::File $name;
120 die "Unable to open $name: $!" unless defined $fh;
122 { local $/; undef $/; $text = <$fh>; }
134 $#cond and die "Unterminated \@if (depth $#cond)";
137 sub process_file($) {
143 sub process_string($) {
149 ### Perl commands embedded in the templates are evaluated in this package ###
160 UCW::Temple::eval_if_ok("\$$v = \$temp");
162 UCW::Temple::parse_file($fn);
167 (!defined($f) || @_) and die "\@load requires only one argument";