{
  "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
  "name": "El",
  "scopeName": "source.el",
  "fileTypes": ["el"],
  "patterns": [
    { "include": "#comments" },
    { "include": "#strings" },
    { "include": "#function-definition" },
    { "include": "#builtin-functions" },
    { "include": "#keywords-control" },
    { "include": "#keywords-declaration" },
    { "include": "#keywords-other" },
    { "include": "#types" },
    { "include": "#type-annotations" },
    { "include": "#constants" },
    { "include": "#numbers" },
    { "include": "#operators" },
    { "include": "#range-operator" },
    { "include": "#function-call" },
    { "include": "#identifiers" }
  ],
  "repository": {

    "comments": {
      "name": "comment.line.double-slash.el",
      "match": "//.*$"
    },

    "strings": {
      "name": "string.quoted.double.el",
      "begin": "\"",
      "end": "\"",
      "patterns": [
        {
          "name": "constant.character.escape.el",
          "match": "\\\\[nrt\\\\\"'0]"
        },
        {
          "name": "constant.character.escape.hex.el",
          "match": "\\\\x[0-9a-fA-F]{2}"
        }
      ]
    },

    "function-definition": {
      "comment": "fn keyword + function name — name gets entity.name.function",
      "match": "\\b(fn)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?=\\()",
      "captures": {
        "1": { "name": "keyword.declaration.function.el" },
        "2": { "name": "entity.name.function.el" }
      }
    },

    "builtin-functions": {
      "comment": "Well-known El builtins get support.function scope for distinct colour",
      "name": "support.function.builtin.el",
      "match": "\\b(println|print|readline|str_eq|str_len|str_concat|str_slice|str_contains|str_starts_with|str_ends_with|str_replace|str_to_upper|str_to_lower|str_trim|str_lstrip|str_rstrip|str_index_of|str_last_index_of|str_split|str_split_lines|str_split_n|str_join|str_char_at|str_char_code|str_pad_left|str_pad_right|str_repeat|str_reverse|str_strip_prefix|str_strip_suffix|str_strip_chars|str_count|str_count_lines|str_find_chars|str_upper|str_lower|int_to_str|str_to_int|float_to_str|str_to_float|int_to_float|float_to_int|format_float|decimal_round|bool_to_str|el_abs|el_max|el_min|math_sqrt|math_log|math_ln|math_sin|math_cos|math_pi|el_list_empty|el_list_append|el_list_len|el_list_get|el_list_clone|list_push|list_push_front|list_join|list_range|el_map_get|el_map_set|el_get_field|state_set|state_get|state_del|state_keys|json_get|json_get_string|json_get_int|json_get_float|json_get_bool|json_get_raw|json_set|json_parse|json_stringify|json_array_len|json_array_get|json_array_get_string|fs_read|fs_write|fs_list|fs_exists|fs_mkdir|http_get|http_post|http_post_json|http_get_with_headers|http_post_with_headers|http_serve|http_serve_v2|http_response|url_encode|url_decode|time_now|time_now_utc|sleep_secs|sleep_ms|time_format|time_add|time_diff|now|unix_seconds|unix_millis|uuid_new|uuid_v4|env|args|exit_program|exec_command|exec_capture|sha256_hex|hmac_sha256_hex|base64_encode|base64_decode|base64url_encode|base64url_decode|llm_call|llm_call_system|llm_call_agentic|llm_vision|llm_models|llm_register_tool|engram_node|engram_get_node|engram_strengthen|engram_forget|engram_search|engram_connect|engram_activate|engram_save|engram_load|engram_node_count|engram_edge_count|engram_neighbors|engram_search_json|engram_stats_json|dharma_connect|dharma_send|dharma_activate|dharma_emit|dharma_field|dharma_peers|native_list_empty|native_list_append|native_list_len|native_list_get|native_list_clone|native_string_chars|native_int_to_str)\\b(?=\\s*\\()"
    },

    "keywords-control": {
      "name": "keyword.control.el",
      "match": "\\b(if|else|while|for|in|return|match|break|continue)\\b"
    },

    "keywords-declaration": {
      "name": "keyword.declaration.el",
      "match": "\\b(fn|let|type|enum|import|from|as|extern)\\b"
    },

    "keywords-other": {
      "name": "keyword.other.el",
      "match": "\\b(cgi|vessel|activate|where|sealed|with|test|seed|assert|protocol|impl|retry|times|fallback|reason|parallel|trace|requires|deploy|to|via|target|manager|engine|accessor)\\b"
    },

    "types": {
      "comment": "Built-in El primitive types",
      "name": "support.type.primitive.el",
      "match": "\\b(String|Int|Float|Bool|Void|Any|Instant|Duration|Map|List)\\b"
    },

    "type-annotations": {
      "comment": "Highlight type annotations after : in let and fn params",
      "patterns": [
        {
          "match": ":\\s*([A-Z][a-zA-Z0-9_<>, ]*)(?=\\s*[,)={\\]]|\\s*->)",
          "captures": {
            "1": { "name": "support.type.el" }
          }
        },
        {
          "match": "->\\s*([A-Z][a-zA-Z0-9_<>, ]*)",
          "captures": {
            "0": { "name": "keyword.operator.arrow.el" },
            "1": { "name": "support.type.return.el" }
          }
        }
      ]
    },

    "constants": {
      "patterns": [
        {
          "name": "constant.language.boolean.el",
          "match": "\\b(true|false)\\b"
        },
        {
          "name": "constant.language.null.el",
          "match": "\\bnull\\b"
        }
      ]
    },

    "numbers": {
      "patterns": [
        {
          "name": "constant.numeric.float.el",
          "match": "-?\\b[0-9]+\\.[0-9]+\\b"
        },
        {
          "name": "constant.numeric.integer.el",
          "match": "-?\\b[0-9]+\\b"
        }
      ]
    },

    "range-operator": {
      "name": "keyword.operator.range.el",
      "match": "\\.\\."
    },

    "operators": {
      "patterns": [
        {
          "name": "keyword.operator.comparison.el",
          "match": "(==|!=|<=|>=)"
        },
        {
          "name": "keyword.operator.comparison.el",
          "match": "(?<![<>-])([<>])(?![>=])"
        },
        {
          "name": "keyword.operator.logical.el",
          "match": "(&&|\\|\\||!(?!=))"
        },
        {
          "name": "keyword.operator.assignment.el",
          "match": "(?<![=!<>])=(?!=)"
        },
        {
          "name": "keyword.operator.arithmetic.el",
          "match": "[+\\-*/%]"
        },
        {
          "name": "keyword.operator.arrow.el",
          "match": "->"
        }
      ]
    },

    "function-call": {
      "comment": "Function calls: identifier immediately followed by (",
      "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?=\\()",
      "captures": {
        "1": { "name": "entity.name.function.call.el" }
      }
    },

    "identifiers": {
      "comment": "Catch-all for remaining identifiers",
      "name": "variable.other.el",
      "match": "\\b[a-zA-Z_][a-zA-Z0-9_]*\\b"
    }
  }
}
