Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Preserving whitespace prefix in multiline strings #178

Open
ttsiodras opened this Issue Feb 16, 2013 · 7 comments

Comments

Projects
None yet
8 participants

In the StringTemplate engine - which I've used in some projects to emit C code - whitespace prefixes are automatically added in the output lines:

PrintCFunction(linesGlobal, linesLocal) ::= <<
void foo() {
    if (someRuntimeFlag) {
        <linesGlobal>
        if (anotherRuntimeFlag) {
            <linesLocal>
        }
    }
}
>>

When this template is rendered in StringTemplate, the whitespace prefixing the multilined linesGlobal and linesLocal strings, is copied for all the lines emitted. The generated C code is e.g.:

void foo() {
    if (someRuntimeFlag) {
        int i;
        i=1;   // <=== whitespace prefix copied in 2nd
        i++;   // <=== and 3rd line
        if (anotherRuntimeFlag) {
            int j=i;
            j++; //  <=== ditto
        }
    }
}

I am new to Jinja2 - and tried to replicate this:

#!/usr/bin/env python
from jinja2 import Template

linesGlobal='\n'.join(['int i;', 'i=1;'])
linesLocal='\n'.join(['int j=i;', 'j++;'])

tmpl = Template(u'''\
void foo() {
    if (someRuntimeFlag) {
        {{linesGlobal}}
        if (anotherRuntimeFlag) {
            {{linesLocal}}
        }
    }
}
''')

print tmpl.render(
    linesGlobal=linesGlobal,
    linesLocal=linesLocal)

...but saw it produce this:

void foo() {
    if (someRuntimeFlag) {
        int i;
i=1;
        if (anotherRuntimeFlag) {
            int j=i;
j++;
        }
    }
}

...which is not what I want. I managed to make the output emit proper whitespace prefixes with this:

...
if (someRuntimeFlag) {
    {{linesGlobal|indent(8)}}
    if (anotherRuntimeFlag) {
        {{linesLocal|indent(12)}}
    }
}

...but this is arguably bad, since I need to manually count whitespace for every string I emit...

Is there a better way that I am missing?

jgehrcke commented Mar 4, 2013

I am interested in basically the same thing. The issue has also come up at stackoverflow: http://stackoverflow.com/questions/10821539/jinja-keep-indentation-on-include-or-macro

+1

Also true when using the form:

    {{linesGlobal|join('\n')}}

This form does not behave as one would expect - since jinja2 is the one emmitting the newlines, it should make sure that they remain aligned with the last indentation level.

fmarczin commented Nov 7, 2014

This would be very nice to have! It would lead to much nicer templates and rendered output at the same time.

Why not create another whitespace option similar to {%+ and {%- that prepends the current indentation on whatever it evaluates to? Could be {%= or {%|

+1

mpaolini commented Dec 3, 2014

+1

needed here for templating API blueprint documentation:

{% macro entity_one() -%}
{
    "one": 1,
    "two": 2
}
{% endmacro -%}

+ Response 200 (application/json):

        {
            "entity": [
                {{ entity_one() }}
            ]
        }

is rendered now :

+ Response 200 (application/json):

        {
            "entity": [
                {
    "one": 1,
    "two": 2

}

            ]
        }

inducer commented Dec 21, 2014

When emitting YAML or Python, this becomes pretty crucial.

Ran into the same problem.

Is there a workaround for now other than defining a macro for every included tempkate and manually entering the indentation?

Sorry for reviving this old issue, I just came across the same problem and googling brought me here. After some more looking around I found that by now there is a nice way to achieve this through the indent filter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment