Jinja: ์—ฌ๋Ÿฌ ์ค„ ๋ฌธ์ž์—ด์—์„œ ๊ณต๋ฐฑ ์ ‘๋‘์‚ฌ ์œ ์ง€

์— ๋งŒ๋“  2013๋…„ 02์›” 16์ผ  ยท  12์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: pallets/jinja

์ผ๋ถ€ ํ”„๋กœ์ ํŠธ์—์„œ C ์ฝ”๋“œ๋ฅผ ๋‚ด๋ณด๋‚ด๋Š” ๋ฐ ์‚ฌ์šฉํ•œ StringTemplate ์—”์ง„์—์„œ ๊ณต๋ฐฑ ์ ‘๋‘์‚ฌ๊ฐ€ ์ถœ๋ ฅ ๋ผ์ธ์— ์ž๋™์œผ๋กœ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

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://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์— ๋Œ€ํ•ด ๋งคํฌ๋กœ๋ฅผ ์ •์˜ํ•˜๊ณ  ์ˆ˜๋™์œผ๋กœ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ ์™ธ์— ํ˜„์žฌ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ด ์˜ค๋ž˜๋œ ๋ฌธ์ œ๋ฅผ ๋˜์‚ด๋ ค์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๋ฐฉ๊ธˆ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์ธํ„ฐ๋„ท ๊ฒ€์ƒ‰์„ ํ†ตํ•ด ์—ฌ๊ธฐ๋กœ ์™”์Šต๋‹ˆ๋‹ค. ์ข€ ๋” ๋‘˜๋Ÿฌ๋ณธ ํ›„ ๋“ค์—ฌ์“ฐ๊ธฐ ํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด ์ด๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

@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>
        }
    }
}
>>

๋ถ„๋ช…ํžˆ PR์˜ ์ผ๋ถ€ ์ฃผ์š” ๋ฆฌํŒฉํ† ๋ง์ด ํ•„์š”ํ•œ ์ฝ”๋“œ ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•ด #919๊ฐ€ ๋‹ซํ˜”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ €๋Š” ์ด ๊ธฐ๋Šฅ์ด ์ œ๊ฐ€ ๊ฐ€์žฅ ์ข‹์•„ํ•˜๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„์—์„œ ๊ตฌํ˜„๋˜๋Š” ๊ฒƒ์„ ๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์—ฌ์ „ํžˆ ํ•ต์‹ฌ ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ตฌํ˜„๋˜๊ธฐ๋ฅผ ๋ฐ”๋ผ๋Š” ๊ฒƒ์ด๋ผ๋ฉด(์ปค๋ฎค๋‹ˆํ‹ฐ๋Š” ์ด๊ฒƒ์ด 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๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. newline_sequence ํ™˜๊ฒฝ ๋งค๊ฐœ๋ณ€์ˆ˜์— ํ‘œ์‹œ๋œ ๋Œ€๋กœ EOL ์‹œํ€€์Šค์ธ ๊ฒฝ์šฐ ์ฒซ ๋ฒˆ์งธ ๋ฌธ์ž๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
  2. ์ฝ˜ํ…์ธ ๋ฅผ ๋‚ด๋ถ€์ ์œผ๋กœ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.
  3. ๋ Œ๋”๋ง๋œ ์ค„์— ์ ‘๋‘์–ด๊ฐ€ ๋ถ™๋Š” ์ผ๋ฐ˜์ ์ธ ๊ณต๋ฐฑ ๋ฌธ์ž์˜ ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.
  4. ๊ฐ ์ค„์˜ ์‹œ์ž‘ ๋ถ€๋ถ„์—์„œ ์ œ๊ฑฐํ•˜์‹ญ์‹œ์˜ค.

๋‚˜์ค‘์— ํŠน์ • ๋“ค์—ฌ์“ฐ๊ธฐ์™€ ํ•จ๊ป˜ ์ด ๋ธ”๋ก์„ ํฌํ•จํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ some_yaml_block|indent ์™€ ๊ฐ™์ด ํ˜ธ์ถœํ•˜๊ธฐ

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰