[stringtemplate-interest] leading/trailing whitespace trimmed
Zenaan Harkness
zen at freedbms.net
Wed Apr 16 10:34:56 PDT 2008
> What I find frustrating is that it seems as though it can trim one OR
> two newlines.
I've just done some experimenting, and the problem is this. Here's my
test case, with three failed examples:
0) ----
# This is my getter template, the main parent template, which, when
# a.customGetter is true (as is in my case), then the subtemplate
# "getBody" is called.
# If the middle line wraps, pretend the following is three lines only:
attGet(a) ::= <<
public <a.type> get<a.name> () {<if(a.customGetter)><getBody(a)><else>return <a.name>;<endif>}
>>
1) ----
# Here's my first attempt to produce a nice (custom) getter method body.
# Clearly this example does not work, because there is no blank line
# at start or end of method:
getBody(a) ::= <<
return _param != null ? _param
: _returns != null ? _returns
: null;
>>
# As expected, the consumed blank lines show (by their lack) in my
# generated output; a nice template layout (just above), but an ugly
# result:
public String getParam () { return _param != null ? _param
: _returns != null ? _returns
: null;}
2) ----
# Take 2, my second attempt, following the ST docs, I insert a "<\n>":
getBody(a) ::= <<
<\n>
return _param != null ? _param
: _returns != null ? _returns
: null;
<\n>
>>
# Here's what my 2nd generated output looks like, template a bit ugly,
# reasonable layout (above), but a silly result:
public String getParam () {
return _param != null ? _param
: _returns != null ? _returns
: null;
}
3) ----
# So, I must have too many newlines. Easy! compress the <\n>s:
getBody(a) ::= << <\n>
return _param != null ? _param
: _returns != null ? _returns
: null;
<\n> >>
# This produces almost the same result as 2) above, except there are
# extra space characters lurking around (just after the first open
# brace, and just before the last open brace):
public String getParam () {
return _param != null ? _param
: _returns != null ? _returns
: null;
}
4) ----
# So, on to solution 4), where I take advantage of the first and
# last \n getting consumed, and have my template like so:
getBody(a) ::= <<
<\n> return _param != null ? _param
: _returns != null ? _returns
: null;<\n>
>>
# Finally, I have produced the result, character for character,
# that I wanted, albeit with a template that's a bit ugly:
public String getParam () {
return _param != null ? _param
: _returns != null ? _returns
: null;
}
5) ----
# Take 5 :), Ahah! I think I finally understand it, and I can try a
# slightly modified (and arguably prettier) template, to get the same
# result:
getBody(a) ::= <<
return _param != null ? _param
: _returns != null ? _returns
: null;
>>
# Hmm, this produces the same (correct) result:
public String getParam () {
return _param != null ? _param
: _returns != null ? _returns
: null;
}
So in conclusion, there are 5 ways to get the job done, 3 of which
simply don't work, and two of which work.
Given the goal of consuming leading and trailing template whitespace,
being to make the templates prettier (so they can be layed out nicely,
which is a goal I agree with by the way), neither of the two successful
templates are ideally layed out. One has ugly <\n>s squeezed into it,
the other has excess blank lines, which DON'T appear in the output.
I could modify my parent template like so:
attGet(a) ::= <<
public <a.type> get<a.name> () {<if(a.customGetter)>
<getBody(a)>
}<else>return <a.name>;}<endif>
>>
And take out the leading space in my sub-template like so:
getBody(a) ::= <<
return _param != null ? _param
: _returns != null ? _returns
: null;
>>
But this produces the following undesirable output (which is correct
except for the first line (first two lines joined):
public String getParam () {return _param != null ? _param
: _returns != null ? _returns
: null;
}
We can go through the same variations as above with <\n>, and come to
the conclusion that the (arguably) prettiest solution is an extra single
blank line in the parent template, like so:
attGet(a) ::= <<
public <a.type> get<a.name> () {<if(a.customGetter)>
<getBody(a)>
}<else>return <a.name>;}<endif>
>>
And again, this does the job.
So, where there's a will there's a way. Is there any such thing as
perfect, in the world of output grammar type template language? I don't
think so.
Would I change the current default choices of ST?
Perhaps quoted style templates should be absolutely literal (perhaps
they already are), and << >> bracketed templates stay as current.
Perhaps an option to turn off whitespace consumption. I know I would
continue to use the whitespace consumption as is.
Zen
--
Homepage: www.SoulSound.net -- Free Australia: www.UPMART.org
Please respect the confidentiality of this email as sensibly warranted.
More information about the stringtemplate-interest
mailing list