Forum OpenACS Q&A: if/else tags in adp

Collapse
Posted by Reuven Lerner on
Perhaps this is documented somewhere, but we were all a bit surprised
here to encounter some odd problems with the <if> and <else> tags.  In
particular, it seems that nothing may come between the (closing) </if>
and the (opening) <else> tags.  If you do this, the code within the
<else> tag is displayed.

I assume that we weren't the only ones to be bitten by this problem,
so I figured that others would be interested in hearing about it.  I
don't know if it's possible to fix the ADP parser to handle this.

Collapse
Posted by Lars Pind on
Reuven,

I didn't know about this. Thanks for catching and letting us know.

When troubleshooting things like this, I usually copy the packages/acs-templating/www/doc/demo/compile.tcl script to the directory where my templates are, and then request compile?file=foo.adp. This gives you the code being generated by from the ADP template, and makes it a lot easier to troubleshoot what's going on.

In this example, I have this template:

<% set foo 1 %>

<if @foo@ true>Something</if>

Here's a bit of html.

<else>Something else.</else>

Which is translated into:

set __adp_output ""

set foo 1

if {[template::util::is_true "${foo}"]} {

append __adp_output "Something"

}

append __adp_output "

Here's a bit of html.

" else {

append __adp_output "Something else."
}

set __adp_output

So you can see what's happening: The <else> tag just appends " else {...}" to whatever line happens to be the latest one written so far. Since that in this case is the "append __adp_output" command, the else block is simply appended.

Here's the implementation of the tag:

template_tag else { chunk params } {

  template::adp_append_code "else {" -nobreak

  template::adp_compile_chunk $chunk

  template::adp_append_code "}"

}

So what would it take to fix? We'd have to save either the expression or the result of evaluating the expression from the <if> tag onto some sort of stack, and then pop the stack in the else tag.

Not impossible. And the current implementation of the <else> tag is, to say the least, not very robust.

Of course, it's easy to change the ADP file to not do this. You can just have two <if> chunks with inverted arguments.

Comments, others?

/Lars

Collapse
Posted by Tom Jackson on

I don't think there is anything wrong with requiring only whitespace between an ending if tag and an associated else tag. I wonder if Reuven would provide a real world example where including text between if/else would be a good idea. The else tag is simply a way of extending the if tag, it is really one unit. If you need two separate conditionals, use two if tags.

One annoyance is that pages break in strange ways when you mess up the if/else tags. This can easily happen on a complex page where you remove or add an if/else incorrectly. I think that 'fixing' the current limitation might lead to even more difficult debugging of these mistakes.

Collapse
Posted by Reuven Lerner on
Tom,

I agree that there isn't any good reason to have text between the </if> and <else> tags.  But the graphic designer (who is the client) didn't know this, and reported that weird things were happening to her pages.

So I'm not really asking for ADP to allow random stuff between </if> and <else>.  Rather, I'm asking that (a) this restriction be made explicit in the documentation, and (b) the error message make the error more obvious, so that designers and programmers alike aren't confused and surprised when funny things happen.

Collapse
Posted by Tom Jackson on

Reuven,

I agree this is confusing. The graphic designer folks, with the least desire to debug scripts, are given misleading, or seemingly incorrect output from the adp templates. A lot of time you get no error at all generated. As Lars has pointed out, the template parser is little more than an appender. His trick of using compile.tcl looks like a great tool for debugging.

Collapse
Posted by Don Baccus on
Let's just agree it's a bug :)

Lars, did you dig into this enough to figure out how to fix it?  I think the fix is simple: whitespace followed by an optional tag (to account for ifs at the end of a script) are the only things that are legal after the close-if tag.

Collapse
Posted by Roberto Mello on
Just a reminder that we DO take patches for (or new) documentation and we love to have them. Send them away!

Those in a position to use some paid time to help with documentation also could take advantage of this opportunity 😊

Collapse
Posted by Michael A. Cleverly on
Here is a short shell script that can help identify problems with .adp's. (Improperly closed <if> & <else> tags, improperly nested tags, etc.) In fact, it's more rigorous about well-formed .adp code than the ACS code. I wrote it to help our graphic designer find a missing </if> in an .adp that had grown to several thousand lines long.

Usage: save as adp-validate, stick it somewhere in your $PATH and then run: adp-validate *.adp from a shell.

#!/bin/sh
# -*- tcl -*- 
exec tclsh "$0" "$@"

package require Tcl 8.3
 
package require nstcl-templating
package require fileutil
 
foreach file $argv {
    if [catch {
        ::nstcl::template::adp::adp_to_pseudo_code [fileutil::cat $file]
    } problem] {
        puts stderr "$file ==> $problem"
    } else {
        puts "$file ==> OK"
    }
}
Collapse
Posted by Michael A. Cleverly on
Argh... there is supposed to be a backslash on line two (that the shell doesn't care about, but that causes tclsh to skip line three)... but it looks like it gotten eaten by postgres. <sigh>