Jinja: 在多行字符串中保留空白前缀

创建于 2013-02-16  ·  12评论  ·  资料来源: pallets/jinja

在 StringTemplate 引擎中——我在一些项目中使用它来发出 C 代码——空白前缀会自动添加到输出行中:

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

当在 StringTemplate 中呈现此模板时,会为所有发出的行复制多行 linesGlobal 和linesLocal 字符串的前缀空白。 生成的 C 代码是:

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

我是 Jinja2 的新手 - 并试图复制这个:

#!/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)

...但看到它产生了这个:

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

……这不是我想要的。 我设法使输出发出正确的空白前缀:

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

...但这可以说是糟糕的,因为我需要为我发出的每个字符串手动计算空格...

有没有更好的方法让我失踪?

最有用的评论

当发出 YAML 或 Python 时,这变得非常重要。

所有12条评论

我对基本相同的事情感兴趣。 这个问题也出现在 stackoverflow: http :

+1

使用表单时也是如此:

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

这种形式的行为不像人们预期的那样——因为 jinja2 是发出换行符的形式,它应该确保它们与最后一个缩进级别保持一致。

这将是非常好的! 这将导致更好的模板和同时呈现的输出。

为什么不创建另一个类似于 {%+ 和 {%- 的空白选项,将当前缩进放在它评估的任何内容之前? 可以是 {%= 或 {%|

+1

+1

这里需要模板 API 蓝图文档:

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

+ Response 200 (application/json):

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

现在呈现:

+ Response 200 (application/json):

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

}

            ]
        }

当发出 YAML 或 Python 时,这变得非常重要。

遇到了同样的问题。

除了为每个包含的 tempkate 定义一个宏并手动输入缩进之外,现在还有其他解决方法吗?

很抱歉重提这个老问题,我刚刚遇到了同样的问题,谷歌搜索把我带到了这里。 经过更多的环顾四周后,我发现现在有一个很好的方法可以通过缩进过滤器来实现这一点

@kaikuchn谢谢你,伙计! 有用。

@kaikuchn ,@Cigizmoond-Vyhuholev 伙计们,我不确定我是否遵循...正如您在顶部的原始报告中看到的那样,我确实提到了indent过滤器的解决方法 - 但也明确指出它并没有像 StringTemplate 那样以简单而强大的方式解决这个问题,因为它迫使你每次需要发出一行行时都要计算缩进空间......如果你必须这样做并且你正在生成代码任何形式(C、Python 等等),你很快就会完全放弃这个过程......

再说一次,我可能误解了你的意思......你能确切地分享一下你是如何实现我在顶部显示的原始要求的吗? 即使用 Jinja2 语法生成相同类型的输出? 这是我不喜欢的...

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

...因为我需要计算我发出代码的每个模板中的“8”和“12”。 相比之下,在 StringTemplate 中...

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

我注意到 #919 由于代码更改而关闭,这显然需要对 PR 进行一些重大重构。 然而,我真的很想看到这个功能在我最喜欢的模板引擎中实现。

如果这仍然是核心开发人员希望实现的东西(社区肯定想要它,因为它是公关和开放问题,获得最多的赞许)我会很乐意提供帮助,甚至可能尝试自己实现。

也很想看到这个功能。 我会注意到,当缩进级别未知时,不能使用indent解决方法。 例如:

{{field.type}} {{field.name}}; {{field.comment|indent(??)}}

要保留的缩进级别取决于前两个值的长度。

我有一个假设。 在块声明中左修剪第一级缩进怎么样?

例子:

{%- macro some_yaml_block(sub_block) ~%}
  label indented with how many spaces: 2
  amount of spaces that will be trimmed due to that "~" char above: 2
  {%- if sub_block ~%}
    "yay! we can indent ifs!": true
    the minimal indent in this if block is 2, so:
      this extra-indented value is still indented properly
  {%- endif %}
{%- endmacro -%}

now we invoke that here:
  {{ some_yaml_block(true) }}

渲染将是:

now we invoke that here:
  label indented with how many spaces: 2
  amount of spaces that will be trimmed due to that "~" char above: 2
  "yay! we can indent ifs!": true
  the minimal indent in this if block is 2, so:
    this extra-indented value is still indented properly

基本上,当用~%}完成一个块时,Jinja 会:

  1. 如果它是 EOL 序列,则删除第 1 个字符,如newline_sequence环境参数中所示。
  2. 在内部呈现内容。
  3. 计算这些渲染行的前缀有多少常见的空白字符。
  4. 从每行的开头剥离它们。

如果您稍后需要使用某些特定缩进包含此块,您只需将其命名为some_yaml_block|indent 。 由于缩进在块声明时被规范化,您可以稍后毫无问题地指定它。 并且该块将在调用之间保持一致。

此页面是否有帮助?
0 / 5 - 0 等级