"clean" text/template block formatting

3,184 views
Skip to first unread message

Kevin Gillette

unread,
Dec 11, 2012, 5:14:41 PM12/11/12
to golan...@googlegroups.com
To build good line-oriented aligned output with text/template, as far as I can tell, I must do something like ('score' is a func):

----------------------------

{{.Activity}} Scorecard for {{.Person.Name}}

{{range .Person.Groups}}{{.Name}}:{{range .CurrScores}}
{{/*tab*/}} {{score .Score .Scored}} {{.Name}}{{end}}
----------
{{/*tab*/}} {{score .CurrTotal true}} Total{{else}}No groups found{{end}}

Some blurb, with precisely one line separating it from the previous text,
regardless of the branch taken.

----------------------------

This will produce output like:

----------------------------

Some Activity Scorecard for John Doe

Group One:
     15/ 15 Item One
      3/ 10 Item Two
    ----------
     18/ 25 Total

Group Two:
      -/150 Item Three
    ----------
      0/150 Total

Some blurb, with precisely one line separating it from the previous text,
regardless of the branch taken.

----------------------------

What would be rather useful is if the same output could be produced without having to hack at the template to get spacing and newlines right. In particular, in contrast to html/template (since html has collapsing whitespace rules), I find templates oriented for precise text output must by nature be extremely unreadable at times, and do not lend themselves to efficient line editing -- two unrelated pieces of template code often must share the same line. Newlines can sometimes be shifted from the inside of a block to the outside, or vice versa, but the readability of the template code is rarely cleaned up by doing so.

I would like to be able to write a template to produce the same output like so:

----------------------------

{{.Activity}} Scorecard for {{.Person.Name}}

{{range .Person.Groups \}}
{{.Name}}:
{{range .CurrScores \}}
{{/*tab*/}} {{score .Score .Scored}} {{.Name}}
{{end \}}
----------
{{/*tab*/}} {{score .CurrTotal true}} Total
{{else \}}
No groups found
{{end \}}

Some blurb, with precisely one line separating it from the previous text,
regardless of the branch taken.

----------------------------

Here, I'm using a hypothetical '\' modifier as the last character of a template action to signify that the following newline should be ignored. I don't really care about the mechanism, as long precise control can still be maintained, and a post-process step is not required (which usually sacrifices control, if the formatting requirements are more complex than "no more than one blank line between text blocks").

Even nicer would be a template flag (settable during parse) that causes the literal-text portion of an entire line to be ignored if it only contains whitespace and an action (allowing benign indentation of nested actions for clarity).

Kevin Gillette

unread,
Dec 11, 2012, 6:15:45 PM12/11/12
to golan...@googlegroups.com, itmi...@gmail.com
The target medium is plaintext, not html. CSS has absolutely nothing to do with it. In this case, content and presentation are inseparable.

On Tuesday, December 11, 2012 4:09:51 PM UTC-7, itmi...@gmail.com wrote:
According to the separation of content and presentation, this is a job for CSS.

You have various options, depending on what your target medium is. Non-breaking spaces, padding for specific elements, with specific class attribute, the use of lists, tab character content with :before pseudo-class etcetera.

Kevin Gillette

unread,
Dec 11, 2012, 6:49:21 PM12/11/12
to golan...@googlegroups.com, itmi...@gmail.com
Sigh. HTML is not an option for a great many tasks, period. The output requirement is invariant, and font/presentation concerns aside from what is mentioned in the original post are entirely irrelevant. If there are any doubts about why I'm not using html, imagine that this output must be machine parseable using a predefined, unchangable format. Thank you for your suggestions, but this is not a question about how to make output look a certain way when viewed on screen: this is intended to essentially be either a feature request for text/template, or a discussion of how text/template (again, in no way related to html/template) can already do what I want in a way that I didn't notice from the package documentation.

On Tuesday, December 11, 2012 4:20:05 PM UTC-7, itmi...@gmail.com wrote:
Are you guaranteed to always have a monospace font used by those that use the resulting plaintexts? Otherwise, all your efforts are easily defeated.

HTML/CSS is still your best best, I believe.

Kyle Lemons

unread,
Dec 11, 2012, 10:37:30 PM12/11/12
to Kevin Gillette, golang-nuts
I think the thought experiment has been undertaken a few times, but I haven't seen any CLs come out of it.  I believe there is general acknowledgement that text/template could use some nicer handling of newlines, but nobody's really sure how to do it.  The Go templates are pretty easy to understand as they are, and (while often annoying) it is usually pretty clear how you fix your template when you have output spacing issues.  When you start adding elision of newlines, especially in some automated fashion (like, if there are only templates in a line, pretend that the new line following them doesn't exist,) it starts to become a lot more difficult to reason about.


--
 
 

Kevin Gillette

unread,
Dec 12, 2012, 3:19:46 AM12/12/12
to golan...@googlegroups.com, Kevin Gillette
Okay, at least it's not just me.

I agree that the obvious solutions sacrifice simplicity in the grammar/semantics to gain line-level simplicity. That is certainly not a reasonable tradeoff. Thinking about it further, the plaintext-ready template systems I've used that can workaround this allow sh-style use of backslash as the last character of a line to escape it, though I much rather like that text/template only specially treats anything inside {{}} (or whatever it's configured for). I think if there's ever to be a clean solution, it would involve a new action (possibly a block), or some parser configuration, but not some new exterior-to-action syntax.

David DENG

unread,
Dec 12, 2012, 3:42:14 AM12/12/12
to golan...@googlegroups.com
It seems the problem happens on the new-line mark, which is ignored in HTML. A simple ways to solve this is to use a double new-line mark for a single new-line in the template. Then after excuting the template, try convert it back.

Your original template would look like this:

{{.Activity}} Scorecard for {{.Person.Name}}
 
 

{{range .Person.Groups}} 
{{.Name}}: 
{{range .CurrScores}}

{{/*tab*/}} {{score .Score .Scored}} {{.Name}} 
{{end}}
 
----------
 
{{/*tab*/}} {{score .CurrTotal true}} Total 
{{else}} 
No groups found 
{{end}}

David

Lucio

unread,
Dec 12, 2012, 7:41:40 AM12/12/12
to golan...@googlegroups.com
No one has mentioned m4's "dnl" feature, so I oblige.  Will it do what you want? Does it fit anywhere? I just thought prior art ought to be considered.  I haven't really used it much, so I'm no expert.

Reply all
Reply to author
Forward
0 new messages