in reply to Re: Templating suggestions for code generation
in thread Templating suggestions for code generation

Thank you. I don't know how I missed the "loop.last" property for the FOREACH directive, I clearly was looking at the wrong spot in the docs. It obviously is the right property to use to put text between items.

So, to answer my own question, for Template::Toolkit, this is a good way to do what I wanted in Template::Toolkit — though you're still free to suggest improvements :):

// BEGIN [% IF list -%] switch(x) { [% FOREACH item IN list -%] case [% item %]: // code for [% item %] [% UNLESS loop.last -%] break; [% END -%] [% END -%] } [% END -%] // END

Run together with the following code:

#! perl -w use Template; my $tt = Template->new(); foreach my $data ([undef => undef], [ empty => []], ['("foo", "bar", "baz")' => [qw(foo bar baz)]]) { print "// List is $data->[0]:\n"; $tt->process('tt2.tmpl', { list => $data->[1] }); print "\n\n"; }
I get the following output:
// List is undef: // BEGIN // END // List is empty: // BEGIN switch(x) { } // END // List is ("foo", "bar", "baz"): // BEGIN switch(x) { case foo: // code for foo break; case bar: // code for bar break; case baz: // code for baz } // END

It's what I wanted, except for when the array is present but empty. How can you get the number of items in an array in TT2? I couldn't find that in the docs. I'd like to avoid having to add Perl code, setting a new value to the count of list items, both in the template (I think the template small language should stay perl-free), as in the script (as it might at some point be forgotten).

Oh, and I feel that I had to tweak it quite a bit just to get the proper amount of whitespace, adding the hyphens just at the right spots (those -%] thingies). Either I'm missing something, or Template::Toolkit could use a touchup.

I'd also like to indent the loop control directives, without that the added leading whitespace shows up in the output. Can it be done? It seems like I have to choose between stripping all whitespace (including newlines) just in front or right after the directives, or no stripping at all. Can't I strip leading whitespace just up to, but excluding, the newline?

Replies are listed 'Best First'.
Re^3: Templating suggestions for code generation
by merlyn (Sage) on Feb 17, 2005 at 14:35 UTC
    // BEGIN [% IF list -%] switch(x) { [% FOREACH item IN list -%] case [% item %]: // code for [% item %] [% UNLESS loop.last -%] break; [% END -%] [% END -%] } [% END -%] // END
    With loop.first and loop.last (which I sometimes wish Perl had), you can simplify this even further by getting rid of the outer "if":
    [% FOREACH item IN list -%] [% IF loop.first -%] // BEGIN switch(x) { [% END %] case [% item %]: // code for [% item %] [% UNLESS loop.last -%] break; [% ELSE -%] } // END [% END -%]
    The loop won't be run if there are no elements, so you don't need to test if elements exist or not. Then, once in the loop, you put "ahead of first time" and "after last time" things inside the loop.first and loop.last conditionals. Nice pattern. In the abstract:
    [% FOR item IN list %] [% IF loop.first %] ... before first item .. [% END %] ... each item ... [% UNLESS loop.last %] ... between items ... [% ELSE %] ... after last item ... [% END; END %]

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re^3: Templating suggestions for code generation
by cbrandtbuffalo (Deacon) on Feb 17, 2005 at 16:24 UTC
    Oh, and I feel that I had to tweak it quite a bit just to get the proper amount of whitespace, adding the hyphens just at the right spots (those -%] thingies). Either I'm missing something, or Template::Toolkit could use a touchup.

    You can control this behavior in a more global manner with the chomping options PRE_CHOMP and POST_CHOMP which you can set when you create your Template object. You can find some details on the TT web site in the section on config options.

      I find in general that POST_CHOMP nearly always "does the right thing" for line-oriented output. I just have to remember the occasional "+" for those items that appear at the end of a line where I really do want to keep the newline.

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a reply.