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();
26 my ($r,$left,$right) = @_;
31 if ($$r =~ /\G([^$left$right]+)/cgs) {
32 } elsif ($$r =~ /\G([$left])/cgs) {
34 } elsif ($$r =~ /\G([$right])/cgs) {
37 die "File ended when looking for matching $right";
47 my $res = eval "package T; $x";
48 return $res unless $@;
49 die "Error evaluating $x: $@";
57 if ($f =~ /^(if|fi|else|elif)$/) {
59 $a ne "()" or die "\@if requires an argument";
61 unshift @cond, (eval_if_ok($a) ? 1 : -1);
65 } elsif ($f eq "fi") {
66 $a eq "()" or die "\@fi takes no arguments";
67 $#cond or die "\@fi without \@if";
69 } elsif ($f eq "else") {
70 $a eq "()" or die "\@else takes no arguments";
71 $#cond or die "\@else without \@if";
73 } elsif ($f eq "elif") {
74 $a ne "()" or die "\@elif requires an argument";
75 $#cond or die "\@elif without \@if";
78 } elsif ($cond[0] < 0) {
80 $cond[0] = (eval_if_ok($a) ? 1 : -1);
83 # print "Cond stack: @cond\n";
85 my $res = eval_if_ok("$f($a)");
86 out $res if defined $res;
94 if ($t =~ /\G([^\@]+)/cgs) {
95 out $1 if $cond[0] > 0;
96 } elsif ($t =~ /\G\@\s*\n/cgs) {
97 # @ at end of line is ignored and eats the end of line
98 } elsif ($t =~ /\G\@#[^\n]*\n/cgs) {
99 # a comment, which is ignored
100 } elsif ($t =~ /\G\@\@/cgs) {
102 } elsif ($t =~ /\G\@{/cgs) {
103 my $x = get_nested(\$t, "{", "}");
105 } elsif ($t =~ /\G\@\[/cgs) {
106 my $x = get_nested(\$t, '\[', '\]');
110 } elsif ($t =~ /\G\@(\w+)\(/cgs) {
112 my $args = get_nested(\$t, '(', ')');
113 eval_func($func, $args);
114 } elsif ($t =~ /\G\@(\w+)([^\n]*)\n/cgs) {
115 eval_func($1, "($2)");
116 } elsif ($t =~ /\G\@(\$\w+)/cgs) {
118 } elsif ($t =~ /\G(\@[^\n]*)/cgs) {
119 die "Unknown control sequence $1";
120 } elsif ($t =~ /\G$/cgs) {
122 } elsif ($t =~ /\G([^\n]*)/cgs) {
123 die "Internal parser error at $1 (pos " . pos($t) . ")";
130 my $fh = new IO::File $name;
131 die "Unable to open $name: $!" unless defined $fh;
133 { local $/; undef $/; $text = <$fh>; }
145 $#cond and die "Unterminated \@if (depth $#cond)";
148 sub process_file($) {
154 sub process_string($) {
160 ### Perl commands embedded in the templates are evaluated in this package ###
167 our $out_func = sub { print @_; };
174 UCW::Temple::eval_if_ok("\$$v = \$temp");
176 UCW::Temple::parse_file($fn);
182 (!defined($f) || @_) and die "\@load requires only one argument";