| … | |
… | |
| 87 | # |
87 | # |
| 88 | sub template { |
88 | sub template { |
| 89 | my ($self, $templateFile) = (shift, shift); |
89 | my ($self, $templateFile) = (shift, shift); |
| 90 | my $r = $self->{r}; |
90 | my $r = $self->{r}; |
| 91 | my $courseEnvironment = $self->{courseEnvironment}; |
91 | my $courseEnvironment = $self->{courseEnvironment}; |
|
|
92 | my @ifstack = (1); # Start off in printing mode |
|
|
93 | # say $ifstack[-1] to get the result of the last <#!--if--> |
| 92 | |
94 | |
| 93 | # so even though the variable $/ APPEARS to contain a newline, |
95 | # so even though the variable $/ APPEARS to contain a newline, |
| 94 | # <TEMPLATE> is slurping the whole file into the first element of |
96 | # <TEMPLATE> is slurping the whole file into the first element of |
| 95 | # @template ONLY AFTER THE TRANSLATOR RUNS. WTF!!! |
97 | # @template ONLY AFTER THE TRANSLATOR RUNS. WTF!!! |
| 96 | # |
98 | # |
| 97 | #open(TEMPLATE, $templateFile) or die "Couldn't open template $templateFile"; |
99 | #open(TEMPLATE, $templateFile) or die "Couldn't open template $templateFile"; |
| 98 | #my @template = <TEMPLATE>; |
100 | #my @template = <TEMPLATE>; |
| 99 | #close TEMPLATE; |
101 | #close TEMPLATE; |
| 100 | # |
102 | # |
| 101 | # Let's try something else instead: |
103 | # Let's try something else instead: |
| 102 | local $/="\n"; |
|
|
| 103 | my @template = split /\n/, readFile($templateFile); |
104 | my @template = split /\n/, readFile($templateFile); |
| 104 | |
105 | |
| 105 | foreach my $line (@template) { |
106 | foreach my $line (@template) { |
| 106 | #warn "foo: $line\n"; |
107 | #warn "foo: $line\n"; |
| 107 | # This is incremental regex processing. |
108 | # This is incremental regex processing. |
| 108 | # the /c is so that pos($line) doesn't die when the regex fails. |
109 | # the /c is so that pos($line) doesn't die when the regex fails. |
| 109 | while ($line =~ m/\G(.*?)<!--#(\w*)((?:\s+.*?)?)-->/gc) { |
110 | while ($line =~ m/\G(.*?)<!--#(\w*)((?:\s+.*?)?)-->/gc) { |
| 110 | my ($before, $function, $raw_args) = ($1, $2, $3); |
111 | my ($before, $function, $raw_args) = ($1, $2, $3); |
| 111 | # $args here will be a hashref |
112 | # $args here will be a hashref |
| 112 | my $args = $raw_args =~ /\S/ ? cook_args($raw_args) : {}; |
113 | my @args = $raw_args =~ /\S/ ? cook_args($raw_args) : {}; |
|
|
114 | if ($ifstack[-1]) { |
| 113 | print $before; |
115 | print $before; |
| 114 | |
116 | } |
|
|
117 | |
| 115 | if ($self->can($function)) { |
118 | if ($self->can($function)) { |
|
|
119 | if ($function eq "if") { |
|
|
120 | push @ifstack, $self->$function(@_, [@args]); |
|
|
121 | } elsif ($function eq "else" and @ifstack > 1) { |
|
|
122 | $ifstack[-1] = not $ifstack[-1]; |
|
|
123 | } elsif ($function eq "endif" and @ifstack > 1) { |
|
|
124 | pop $ifstack; |
|
|
125 | } elsif ($ifstack[-1]) { |
| 116 | print $self->$function(@_, $args); |
126 | print $self->$function(@_, {@args}); |
|
|
127 | } |
| 117 | } |
128 | } |
| 118 | } |
129 | } |
| 119 | |
130 | |
|
|
131 | if ($ifstack[-1]) { |
| 120 | print substr $line, (defined pos $line) ? pos $line : 0); |
132 | print substr $line, (defined pos $line) ? pos $line : 0); |
|
|
133 | } |
| 121 | } |
134 | } |
| 122 | } |
135 | } |
| 123 | |
136 | |
| 124 | # cook_args(STRING) - parses a string of the form ARG1="FOO" ARG2="BAR". Returns |
137 | # cook_args(STRING) - parses a string of the form ARG1="FOO" ARG2="BAR". Returns |
| 125 | # a reference to a hash containing the parsed arguments. |
138 | # a list which pairs into key/values and fits nicely in {}s. |
| 126 | # |
139 | # |
| 127 | sub cook_args($) { |
140 | sub cook_args($) { |
| 128 | my ($raw_args) = @_; |
141 | my ($raw_args) = @_; |
| 129 | my $args = {}; |
142 | my @args = (); |
| 130 | |
143 | |
| 131 | # Boy I love m//g in scalar context! Go read the camel book, heathen. |
144 | # Boy I love m//g in scalar context! Go read the camel book, heathen. |
| 132 | # First, get the whole token with the quotes on both ends... |
145 | # First, get the whole token with the quotes on both ends... |
| 133 | while ($raw_args =~ m/\G\s*(\w*)="((?:[^"\\]|\\.)*)"/g) { |
146 | while ($raw_args =~ m/\G\s*(\w*)="((?:[^"\\]|\\.)*)"/g) { |
| 134 | my ($key, $value) = ($1, $2); |
147 | my ($key, $value) = ($1, $2); |
| 135 | # ... then, rip out all the protecty backspaces |
148 | # ... then, rip out all the protecty backspaces |
| 136 | $value =~ s/\(.)/$1/g; |
149 | $value =~ s/\(.)/$1/g; |
| 137 | $args->{$key} = $value; |
150 | push @args, $key => $value; |
| 138 | } |
151 | } |
| 139 | |
152 | |
| 140 | return $args; |
153 | return @args; |
| 141 | } |
154 | } |
| 142 | |
155 | |
| 143 | ################################################################################ |
156 | ################################################################################ |
| 144 | # Macros used by content generators to render common idioms |
157 | # Macros used by content generators to render common idioms |
| 145 | ################################################################################ |
158 | ################################################################################ |
| … | |
… | |
| 330 | # CGI::a({-href=>$help}, "Help"), CGI::br(), |
343 | # CGI::a({-href=>$help}, "Help"), CGI::br(), |
| 331 | CGI::a({-href=>$logout}, "Log Out"), CGI::br(), |
344 | CGI::a({-href=>$logout}, "Log Out"), CGI::br(), |
| 332 | ; |
345 | ; |
| 333 | } |
346 | } |
| 334 | |
347 | |
| 335 | sub title { |
348 | # This is different. It probably should print anything (except in debugging cases) |
| 336 | return "WeBWorK"; |
349 | # and it should return a boolean, not a string. &if is called in a nonstandard way |
| 337 | } |
350 | # by &template, with $args as an arrayref instead of a hashref. this is a hack! yay! |
|
|
351 | sub if { |
|
|
352 | my ($self, $args) = @_[0,-1]; |
|
|
353 | # A single if "or"s it's components. Nesting produces "and". |
|
|
354 | |
|
|
355 | my @args = @$args; # Hahahahaha, get it?! |
|
|
356 | |
|
|
357 | if (@args % 2 != 0) { |
|
|
358 | # flip out and kill people, but do not commit seppuku |
|
|
359 | print '<!--&if recieved an uneven number of arguments. This shouldn\'t happen, but I\'ll let it slide.-->\n'; |
|
|
360 | } |
|
|
361 | |
|
|
362 | while (@args > 1) { |
|
|
363 | my ($key, $value) = (shift @args, shift @args); |
|
|
364 | |
|
|
365 | if ($key eq "can" and $self->can($value)) { |
|
|
366 | return 1; |
|
|
367 | } |
| 338 | |
368 | |
| 339 | sub body { |
369 | # Other conditions go here, friend. |
| 340 | return "Generated content"; |
370 | } |
|
|
371 | |
|
|
372 | return 0; |
| 341 | } |
373 | } |
| 342 | |
374 | |
| 343 | 1; |
375 | 1; |
| 344 | |
376 | |
| 345 | __END__ |
377 | __END__ |