%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Jinja2
file_extensions:
  - j2
  - jinja2
scope: text.html.jinja2
contexts:
  main:
    - include: scope:text.html.basic
    - match: '({%)\s*(raw)\s*(%})'
      captures:
        1: entity.other.jinja2.delimiter.tag
        2: keyword.control.jinja2
        3: entity.other.jinja2.delimiter.tag
      push:
        - meta_scope: comment.block.jinja2.raw
        - match: '({%)\s*(endraw)\s*(%})'
          captures:
            1: entity.other.jinja2.delimiter.tag
            2: keyword.control.jinja2
            3: entity.other.jinja2.delimiter.tag
          pop: true
    - match: "{#-?"
      captures:
        0: entity.other.jinja2.delimiter.comment
      push:
        - meta_scope: comment.block.jinja2
        - match: "-?#}"
          captures:
            0: entity.other.jinja2.delimiter.comment
          pop: true
    - match: "{{-?"
      captures:
        0: entity.other.jinja2.delimiter.variable
      push:
        - meta_scope: meta.scope.jinja2.variable
        - match: "-?}}"
          captures:
            0: entity.other.jinja2.delimiter.variable
          pop: true
        - include: expression
    - match: "{%-?"
      captures:
        0: entity.other.jinja2.delimiter.tag
      push:
        - meta_scope: meta.scope.jinja2.tag
        - match: "-?%}"
          captures:
            0: entity.other.jinja2.delimiter.tag
          pop: true
        - include: expression
  escaped_char:
    - match: '\\x[0-9A-F]{2}'
      scope: constant.character.escape.hex.jinja2
  escaped_unicode_char:
    - match: '(\\U[0-9A-Fa-f]{8})|(\\u[0-9A-Fa-f]{4})|(\\N\{[a-zA-Z ]+\})'
      captures:
        1: constant.character.escape.unicode.16-bit-hex.jinja2
        2: constant.character.escape.unicode.32-bit-hex.jinja2
        3: constant.character.escape.unicode.name.jinja2
  expression:
    - match: '\s*\b(macro)\s+([a-zA-Z_][a-zA-Z0-9_]*)\b'
      captures:
        1: keyword.control.jinja2
        2: variable.other.jinja2.macro
    - match: '\s*\b(block)\s+([a-zA-Z_][a-zA-Z0-9_]*)\b'
      captures:
        1: keyword.control.jinja2
        2: variable.other.jinja2.block
    - match: '\s*\b(filter)\s+([a-zA-Z_][a-zA-Z0-9_]*)\b'
      captures:
        1: keyword.control.jinja2
        2: variable.other.jinja2.filter
    - match: '\s*\b(is)\s+([a-zA-Z_][a-zA-Z0-9_]*)\b'
      captures:
        1: keyword.control.jinja2
        2: variable.other.jinja2.test
    - match: '(?<=\{\%-|\{\%)\s*\b([a-zA-Z_][a-zA-Z0-9_]*)\b(?!\s*[,=])'
      captures:
        1: keyword.control.jinja2
    - match: \b(and|else|if|in|import|not|or|recursive|with(out)?\s+context)\b
      scope: keyword.control.jinja2
    - match: '\b([Tt]rue|[Ff]alse|[Nn]one)\b'
      scope: constant.language.jinja2
    - match: \b(loop|super|self|varargs|kwargs)\b
      scope: variable.language.jinja2
    - match: "[a-zA-Z_][a-zA-Z0-9_]*"
      scope: variable.other.jinja2
    - match: (\+|\-|\*\*|\*|//|/|%)
      scope: keyword.operator.arithmetic.jinja2
    - match: '(\|)([a-zA-Z_][a-zA-Z0-9_]*)'
      captures:
        1: punctuation.other.jinja2
        2: variable.other.jinja2.filter
    - match: '(\.)([a-zA-Z_][a-zA-Z0-9_]*)'
      captures:
        1: punctuation.other.jinja2
        2: variable.other.jinja2.attribute
    - match: '\['
      captures:
        0: punctuation.other.jinja2
      push:
        - match: '\]'
          captures:
            0: punctuation.other.jinja2
          pop: true
        - include: expression
    - match: \(
      captures:
        0: punctuation.other.jinja2
      push:
        - match: \)
          captures:
            0: punctuation.other.jinja2
          pop: true
        - include: expression
    - match: '\{'
      captures:
        0: punctuation.other.jinja2
      push:
        - match: '\}'
          captures:
            0: punctuation.other.jinja2
          pop: true
        - include: expression
    - match: (\.|:|\||,)
      scope: punctuation.other.jinja2
    - match: (==|<=|=>|<|>|!=)
      scope: keyword.operator.comparison.jinja2
    - match: "="
      scope: keyword.operator.assignment.jinja2
    - match: '"'
      captures:
        0: punctuation.definition.string.begin.jinja2
      push:
        - meta_scope: string.quoted.double.jinja2
        - match: '"'
          captures:
            0: punctuation.definition.string.end.jinja2
          pop: true
        - include: string
    - match: "'"
      captures:
        0: punctuation.definition.string.begin.jinja2
      push:
        - meta_scope: string.quoted.single.jinja2
        - match: "'"
          captures:
            0: punctuation.definition.string.end.jinja2
          pop: true
        - include: string
    - match: "@/"
      captures:
        0: punctuation.definition.regexp.begin.jinja2
      push:
        - meta_scope: string.regexp.jinja2
        - match: /
          captures:
            0: punctuation.definition.regexp.end.jinja2
          pop: true
        - include: simple_escapes
  simple_escapes:
    - match: (\\\n)|(\\\\)|(\\\")|(\\')|(\\a)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(\\v)
      captures:
        1: constant.character.escape.newline.jinja2
        2: constant.character.escape.backlash.jinja2
        3: constant.character.escape.double-quote.jinja2
        4: constant.character.escape.single-quote.jinja2
        5: constant.character.escape.bell.jinja2
        6: constant.character.escape.backspace.jinja2
        7: constant.character.escape.formfeed.jinja2
        8: constant.character.escape.linefeed.jinja2
        9: constant.character.escape.return.jinja2
        10: constant.character.escape.tab.jinja2
        11: constant.character.escape.vertical-tab.jinja2
  string:
    - include: simple_escapes
    - include: escaped_char
    - include: escaped_unicode_char