FAQ
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).

--

Search Discussions

  • Itmitica at Dec 11, 2012 at 11:09 pm
    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 at Dec 11, 2012 at 11:15 pm
    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.
    --
  • Itmitica at Dec 11, 2012 at 11:28 pm
    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.

    --
  • Itmitica at Dec 11, 2012 at 11:25 pm
    I haven't programmed for tabular/aligned plain text since the days of
    FoxPro for DOS and dot matrix printers, but I remember the pain it was
    every single time the boilerplate/reports changed. Not the way to go.

    --
  • Kevin Gillette at Dec 11, 2012 at 11:49 pm
    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.
    --
  • Itmitica at Dec 12, 2012 at 12:04 am
    You can simply achieve clarity in the way the template reads if you are
    generating it with some Go code, instead of editing it as a plain text
    document.

    Or you could write a preprocessor like HAML for HTML or LESS for CSS, where
    you write the text templates according to your rules, pass the text
    document through the preprocessor, and you end up with vanilla Go text
    template which doesn't have to be readable, since you'll always work with
    your own version.

    To be short:

    1. Write the template the way you want

    {{.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 \}}

    2. Write a Go preprocessor to "fix" your interpretation for the '\'
    modifier output vanilla Go text template


    --
  • Kyle Lemons at Dec 12, 2012 at 3:37 am
    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.


    On Tue, Dec 11, 2012 at 5:14 PM, Kevin Gillette
    wrote:
    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 at Dec 12, 2012 at 8:19 am
    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.
    On Tuesday, December 11, 2012 8:37:30 PM UTC-7, Kyle Lemons wrote:

    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.
    --
  • Itmitica at Dec 12, 2012 at 7:34 am
    By generating it with some Go code, I meant write it in Go, the way it's
    clearer for you:


    package main

    import (

    "fmt"

    )

    func main() {

    var txttmpl string

    txttmpl = "----------------------------" + "\n\n"

    txttmpl += "{{.Activity}} Scorecard for {{.Person.Name}}" + "\n\n"

    txttmpl += "{{range .Person.Groups}}"

    txttmpl += "{{.Name}}:"

    txttmpl += "{{range .CurrScores}}" + "\n"

    txttmpl += "{{/*tab*/}} {{score .Score .Scored}} {{.Name}}"

    txttmpl += "{{end}}" + "\n"

    txttmpl += "----------" + "\n"

    txttmpl += "{{/*tab*/}} {{score .CurrTotal true}} Total"

    txttmpl += "{{else}}"

    txttmpl += "No groups found"

    txttmpl += "{{end}}" + "\n\n"

    txttmpl += "Some blurb, with precisely one line separating it from the previous text," + "\n"

    txttmpl += "regardless of the branch taken." + "\n\n"

    txttmpl += "----------------------------" + "\n\n"

    fmt.Println(txttmpl)

    }



    and when saved to a file, it should now be vanilla Go text template again:


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

    {{.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.

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

    --
  • Itmitica at Dec 12, 2012 at 7:47 am
    That's how we did it in the days of text only dot printers and FoxPro for
    DOS anyway.

    With the risk of sounding like a broken record, you mentioned machine
    readable. Usually this means more standard structures: csv, json, xml. At
    one point you may have to use this data with standard mediums, databases,
    standard parsers, and then you'd have to follow a two step, rather than
    just the import/transfer, you'd have to convert your custom plain text
    structure to csv, json or xml.

    --
  • David DENG at Dec 12, 2012 at 8:42 am
    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
    On Wednesday, December 12, 2012 6:14:41 AM UTC+8, Kevin Gillette wrote:

    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).
    --
  • Itmitica at Dec 12, 2012 at 10:14 am
    Here's a more complete example for generating vanilla Go text templates
    from custom displayed and organized text templates using Go:

    package main

    import (

    "fmt"

    "io"

    "os"

    )

    func main() {

    tmpl := txtTmpl()

    err := writeTmpl("tmpl.txt", tmpl)

    if err != nil {

    fmt.Println("There was an error: ", err)

    }

    }

    func txtTmpl() string {

    s := "----------------------------" + "\n\n"


    s += "{{.Activity}} Scorecard for {{.Person.Name}}" + "\n\n"


    s += "{{range .Person.Groups}}"

    s += "{{.Name}}:"

    s += "{{range .CurrScores}}" + "\n"

    s += "{{/*tab*/}} {{score .Score .Scored}} {{.Name}}"

    s += "{{end}}" + "\n"

    s += "----------" + "\n"

    s += "{{/*tab*/}} {{score .CurrTotal true}} Total"

    s += "{{else}}"

    s += "No groups found"

    s += "{{end}}" + "\n\n"

    s += "Some blurb, with precisely one line separating it from the previous text," + "\n"

    s += "regardless of the branch taken." + "\n\n"

    s += "----------------------------" + "\n\n"

    return s

    }

    func writeTmpl(filename, txttmpl string) (err error) {

    f, err := os.Create(filename)

    if err != nil {

    return err

    }

    _, err = io.WriteString(f, txttmpl)

    if err != nil {

    return err

    }

    f.Close()

    return

    }


    OUTPUT

    tmpl.txt


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

    {{.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.

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



    --
  • Lucio at Dec 12, 2012 at 12:41 pm
    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.

    --

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedDec 11, '12 at 10:14p
activeDec 12, '12 at 12:41p
posts14
users5
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase