В движке 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)}}
}
}
... но это, возможно, плохо, так как мне нужно вручную подсчитывать пробелы для каждой строки, которую я испускаю ...
Есть ли лучший способ, который мне не хватает?
Меня интересует в основном то же самое. Проблема также возникла в stackoverflow: http://stackoverflow.com/questions/10821539/jinja-keep-indentation-on-include-or-macro
+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 и ручного ввода отступа?
Извините за возрождение этой старой проблемы, я столкнулся с той же проблемой, и поиск в Google привел меня сюда. Еще немного осмотревшись, я обнаружил, что к настоящему времени есть хороший способ добиться этого с помощью фильтра отступа.
@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. Однако мне бы очень хотелось, чтобы эта функция была реализована в моем любимом движке шаблонов.
Если это все еще то, что основные разработчики хотели бы видеть реализованным (сообщество определенно хочет этого, поскольку это PR и открытая проблема с большим количеством пальцев), я был бы рад помочь и, возможно, даже попытался бы реализовать это самостоятельно.
Также хотелось бы увидеть эту функцию. Замечу, что обходной путь indent
нельзя использовать, если уровень отступа неизвестен. например:
{{field.type}} {{field.name}}; {{field.comment|indent(??)}}
Сохранение уровня отступа зависит от длины первых двух значений.
У меня есть одна гипотеза. А как насчет обрезки слева 1-го уровня отступа в объявлении блока?
Пример:
{%- 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:
newline_sequence
Environment.Если позже вам потребуется включить этот блок с каким-то определенным отступом, все, что вам нужно, это назвать его как some_yaml_block|indent
. Поскольку отступ был нормализован при объявлении блока, вы можете без проблем указать его позже. И блок будет вести себя одинаково во всех вызовах.
Самый полезный комментарий
При передаче YAML или Python это становится очень важным.