%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: Elm
file_extensions:
  - elm
scope: source.elm
contexts:
  main:
    - match: "(`)[a-zA-Z_']*?(`)"
      scope: keyword.operator.function.infix.elm
      captures:
        1: punctuation.definition.entity.elm
        2: punctuation.definition.entity.elm
    - match: \(\)
      scope: constant.language.unit.elm
    - match: ^\b((effect|port)\s+)?(module)\s+
      captures:
        1: keyword.other.elm
        3: keyword.other.elm
      push:
        - meta_scope: meta.declaration.module.elm
        - match: $|;
          captures:
            1: keyword.other.elm
          pop: true
        - include: module_name
        - match: '(where)\s*\{'
          captures:
            1: keyword.other.elm
          push:
            - match: '\}'
              pop: true
            - include: type_signature
        - match: (exposing)
          scope: keyword.other.elm
        - include: module_exports
        - match: (where)
          scope: keyword.other.elm
        - match: "[a-z]+"
          scope: invalid
    - match: ^\b(import)\s+((open)\s+)?
      captures:
        1: keyword.other.elm
        3: invalid
      push:
        - meta_scope: meta.import.elm
        - match: ($|;)
          pop: true
        - match: (as|exposing)
          scope: keyword.import.elm
        - include: module_name
        - include: module_exports
    - match: '(\[)(glsl)(\|)'
      captures:
        1: keyword.other.elm
        2: support.function.prelude.elm
        3: keyword.other.elm
      push:
        - meta_scope: entity.glsl.elm
        - match: '(\|\])'
          captures:
            1: keyword.other.elm
          pop: true
        - include: scope:source.glsl
    - match: \b(type alias|type|case|of|let|in|as)\s+
      scope: keyword.other.elm
    - match: \b(if|then|else)\s+
      scope: keyword.control.elm
    - match: '\b([0-9]+\.[0-9]+([eE][+-]?[0-9]+)?|[0-9]+[eE][+-]?[0-9]+)\b'
      comment: Floats are always decimal
      scope: constant.numeric.float.elm
    - match: '\b([0-9]+)\b'
      scope: constant.numeric.elm
    - match: '"""'
      captures:
        0: punctuation.definition.string.begin.elm
      push:
        - meta_scope: string.quoted.double.elm
        - match: '"""'
          captures:
            0: punctuation.definition.string.end.elm
          pop: true
        - match: '\\(NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\''\&])'
          scope: constant.character.escape.elm
        - match: '\^[A-Z@\[\]\\\^_]'
          scope: constant.character.escape.control.elm
    - match: '"'
      captures:
        0: punctuation.definition.string.begin.elm
      push:
        - meta_scope: string.quoted.double.elm
        - match: '"'
          captures:
            0: punctuation.definition.string.end.elm
          pop: true
        - match: '\\(NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\\"''\&])'
          scope: constant.character.escape.elm
        - match: '\^[A-Z@\[\]\\\^_]'
          scope: constant.character.escape.control.elm
    - match: |-
        (?x)
        (')
        (?:
          [\ -\[\]-~]               # Basic Char
          | (\\(?:NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE
            |DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS
            |US|SP|DEL|[abfnrtv\\\"'\&]))   # Escapes
          | (\^[A-Z@\[\]\\\^_])           # Control Chars
        )
        (')
      scope: string.quoted.single.elm
      captures:
        1: punctuation.definition.string.begin.elm
        2: constant.character.escape.elm
        3: punctuation.definition.string.end.elm
    - match: '^(port\s+)?([a-z_][a-zA-Z0-9_'']*|\([|!%$+\-.,=</>]+\))\s*((:)([:]+)?)'
      captures:
        1: keyword.other.port.elm
        2: entity.name.function.elm
        4: keyword.other.colon.elm
        5: invalid
      push:
        - meta_scope: meta.function.type-declaration.elm
        - match: $\n?
          pop: true
        - include: type_signature
    - match: \bport\s+
      scope: keyword.other.port.elm
    - match: '\b[A-Z]\w*\b'
      scope: constant.other.elm
    - include: comments
    - match: '^[a-z][A-Za-z0-9_'']*\s+'
      scope: entity.name.function.elm
    - include: infix_op
    - match: '[|!%$?~+:\-.=</>&\\*^]+'
      scope: keyword.operator.elm
    - match: '([\[\]\{\},])'
      scope: constant.language.delimiter.elm
      captures:
        1: support.function.delimiter.elm
    - match: '([\(\)])'
      scope: keyword.other.parenthesis.elm
  block_comment:
    - match: '\{-(?!#)'
      captures:
        0: punctuation.definition.comment.elm
      push:
        - meta_scope: comment.block.elm
        - include: block_comment
        - match: '-\}'
          captures:
            0: punctuation.definition.comment.elm
          pop: true
  comments:
    - match: (--).*$\n?
      scope: comment.line.double-dash.elm
      captures:
        1: punctuation.definition.comment.elm
    - include: block_comment
  infix_op:
    - match: '(\([|!%$+:\-.=</>]+\)|\(,+\))'
      scope: entity.name.function.infix.elm
  module_exports:
    - match: \(
      push:
        - meta_scope: meta.declaration.exports.elm
        - match: \)
          pop: true
        - match: '\b[a-z][a-zA-Z_''0-9]*'
          scope: entity.name.function.elm
        - match: '\b[A-Z][A-Za-z_''0-9]*'
          scope: storage.type.elm
        - match: ","
          scope: punctuation.separator.comma.elm
        - include: infix_op
        - match: \(.*?\)
          comment: So named because I don't know what to call this.
          scope: meta.other.unknown.elm
  module_name:
    - match: "[A-Z][A-Za-z._']*"
      scope: support.other.module.elm
  type_signature:
    - match: '\(\s*([A-Z][A-Za-z]*)\s+([a-z][A-Za-z_'']*)\)\s*(=>)'
      scope: meta.class-constraint.elm
      captures:
        1: entity.other.inherited-class.elm
        2: variable.other.generic-type.elm
        3: keyword.other.big-arrow.elm
    - match: "->"
      scope: keyword.other.arrow.elm
    - match: "=>"
      scope: keyword.other.big-arrow.elm
    - match: '\b[a-z][a-zA-Z0-9_'']*\b'
      scope: variable.other.generic-type.elm
    - match: '\b[A-Z][a-zA-Z0-9_'']*\b'
      scope: storage.type.elm
    - match: \(\)
      scope: support.constant.unit.elm
    - include: comments