%YAML 1.2
---
version: 2
name: Elixir
scope: source.elixir
file_extensions: [ex, exs]
first_line_match: ^#!\s*/.*\b(?:elixirc?|iex)
authors:
- Aziz Köksal <aziz.koeksal@gmail.com>
- Po Chen <chenpaul914@gmail.com>
- José Valim <jose.valim@dashbit.co>
variables:
module_name: '[A-Z][a-zA-Z\d_]*+'
atom_id_suffix: '[\w@]*+[?!]?+'
atom_id: (?>[[:alpha:]_]{{atom_id_suffix}})
identifier: (?>[[:lower:]_]\w*+[?!]?+)
no_id_key_suffix: (?=\b(?!{{atom_id_suffix}}:(?!:)|[?!])|(?<=[?!])(?!:(?!:)))
no_key_suffix: (?!{{atom_id_suffix}}:(?!:))
no_colon_suffix: (?![:'"[:alpha:]])
closing_keyword: (?>end|else|after|rescue|catch){{no_id_key_suffix}}
closing_token: (?>[)}\];#]|>>(?!>)|%>|$|{{closing_keyword}})
binary_operator: |
(?x)(?>
(?<!\s)\[ | <?<~ | ~>>? | <~> | [*=/|\\>] | \.(?!\.\.) | <(?!<[^<~] | %=)
| \^{3} | && | (?<!\s)[-+]\S | [-+][-+>\s] | ::(?!:) | $ | !=
| (?>when|and|in|or|not\s+in){{no_id_key_suffix}}
)
operator: |
(?x)(?>
=~ | ={1,3} | @ | <?\|> | (?!<%=)[<-](?![~=] | < | --)[->]? | \|{1,3} | ::
| &{1,3} | \+{1,3} | \\\\ | \^{3} | \^ | \.{1,3} | !={0,2} | [<>]= | \*\*?
| >>> | >(?!>) | // | / | <<< | ~~~ | <~> | <?<~ | ~>>? | ---
)
has_arguments: |
(?x)(?=
\(
| \s* (?!\?:) (?>{{operator}}: {{no_colon_suffix}} | \\(?!\\))
| (?! \s* (?>, | {{closing_token}} | {{binary_operator}}) )
)
no_suffix_then_arguments: '{{no_id_key_suffix}}{{has_arguments}}'
atom_symbol: (?>{{atom_id}}|<<>>|\.\.//|{{operator}}|%?{}|%)
member: (?>{{identifier}}|{{operator}}|{})
is_markdown_elixir: |
(?x)
```\s*elixir\b
| (?<=\s{4})(?>
(?>iex|\.{3}).*?>
| (?>
def(?>module|impl|macro|guard|struct|delegate|protocol|p)?
| (?#if|for|)unless|case|cond|with|try|receive|quote|unquote(?:_splicing)?
){{no_id_key_suffix}}
(?>\(|.+\bdo\b)
)
contexts:
main:
- include: core_syntax
prototype:
- include: merge_conflict
core_syntax:
- include: atom_keyword - include: def_blocks - include: elixir_keywords - include: built_ins - include: alias - include: fn_block - include: elixir_functions - include: special_form - include: do_block - include: sql_or_fragment - include: modules_or_ids_or_calls - include: comma_and_skip_ws - include: operator - include: atom_symbol - include: string - include: dot_accessor - include: tuple - include: item_access - include: list - include: module_attribute - include: numeric - include: map - include: comment - include: capture - include: char_literal - include: paren - include: line_continuation
merge_conflict:
- match: ^(?=<{7}|={7}|>{7})
push:
- clear_scopes: true
- match: (?>(<+)(.*\n)|(=+)(.*\n)|(>+)(.*\n))
scope: text.git.conflict
captures:
1: punctuation.section.block.begin.git.conflict
2: comment.line.current.git.conflict
3: punctuation.section.block.middle.git.conflict
4: comment.line.middle.git.conflict
5: punctuation.section.block.end.git.conflict
6: comment.line.incoming.git.conflict
pop: 1
fn_block:
- match: fn{{no_id_key_suffix}}
scope: punctuation.section.block.begin.elixir keyword.other.fn.elixir
push: [fn_block_end_pop, arrow_clauses_body_pop, fn_single_body_or_pop]
fn_single_body_or_pop:
- match: (?=->)
set:
- match: (?=end{{no_id_key_suffix}})
pop: 1
- include: core_syntax
- include: if_non_space_or_eol_pop
fn_block_end_pop:
- include: block_end_pop
- include: if_closing_token_pop
- include: core_syntax
arrow_clauses_body_pop:
- match: (?=\S)
set:
- match: (?=->|when{{no_id_key_suffix}})
push: inlined_core_syntax_pop
- match: \\\\(?!:{{no_colon_suffix}})
scope: keyword.operator.default.elixir invalid.illegal.default-operator.elixir
- include: parameters_or_if_closing_pop
- match: $
set:
- include: if_closing_token_pop
- match: ^(\s*)(?=[^#\s])
push: [indented_core_syntax_pop, params_until_arrow_pop]
- include: core_syntax
inlined_core_syntax_pop:
- match: (?=;)
pop: 1
- include: core_syntax_or_if_closing_pop
params_until_arrow_pop:
- match: (?=->|when{{no_id_key_suffix}})
pop: 1
- include: parameters_or_if_closing_pop
indented_core_syntax_pop:
- match: ^(?=\1[^#\s]|(?!\1)(?!\s*(#|$)))
pop: 1
- include: core_syntax_or_if_closing_pop
function_header_pop:
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_closing_pop
- match: ''
push: function_header_args_pop
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_ws_closing_pop
- match: ''
push: function_header_args_pop
function_header_args_pop:
- match: (?={{atom_symbol}}:(?!:))|(?<=[^:]:)
set: arguments_ws_rest_pop
- match: (?=unquote\(\s*:(?!:(?!:)))
set: [function_params_or_eol_pop, function_atom_name_pop, unquote_pop]
- match: (?=unquote(?:_splicing)?\()
set: [function_params_or_eol_pop, arguments_pop, unquote_pop]
- match: not{{no_suffix_then_arguments}}
scope: entity.name.function.elixir
set: function_free_form_header_pop
- include: atom_keyword
- include: func_do_block_pop
- include: block_or_keyword
- include: paren_param
- match: '{{identifier}}(?=\s){{has_arguments}}'
scope: entity.name.function.elixir
set: function_free_form_header_pop
- match: '{{identifier}}(?=\s*([(),;]|do{{no_id_key_suffix}}|$))'
comment: e.g. "def func," OR "def func(a, b)" OR "def func do" OR "def func"
scope: entity.name.function.elixir
set: function_params_or_eol_pop
- match: (?=\S)
set:
- match: |
(?x)
(?>((?=_)(?<!%>){{identifier}})|({{identifier}}))?
\s*
({{operator}}|(?>and|in|or){{no_id_key_suffix}})
comment: e.g. x && y
captures:
1: variable.parameter.unused.elixir
2: variable.parameter.elixir
3: entity.name.function.elixir
set:
- match: (?=,|when{{no_id_key_suffix}})
set: arguments_ws_rest_pop
- include: func_do_block_pop
- include: if_ws_closing_token_or_eol_pop
- include: paren_param
- include: parameters_or_if_closing_pop
- include: if_non_space_pop
- include: if_ws_closing_token_or_eol_pop
- include: paren
- match: \{(?!}:(?!:(?!:)))
scope: entity.name.function.elixir
set:
- meta_scope: meta.function.parameters.elixir
- match: \}
scope: entity.name.function.elixir
set: arguments_ws_rest_pop
- include: parameters_or_if_closing_pop
- include: parameters_or_if_closing_pop
- include: function_params_or_eol_pop
function_free_form_header_pop:
- match: (?={{atom_symbol}}:(?!:))|(?<=[^:]:)|(?=when{{no_id_key_suffix}})
comment: break at first atom key (usually "do:")
set: arguments_ws_rest_pop
- include: arg_comma_and_skip_ws
- include: function_ws_params_pop
function_ws_params_pop:
- include: func_do_block_pop
- include: if_ws_closing_token_or_eol_pop
- include: paren
- include: parameters_or_if_closing_pop
- include: if_non_space_pop
function_params_or_eol_pop:
- match: \(
scope: punctuation.definition.parameters.begin.elixir
set:
- meta_scope: meta.function.parameters.elixir
- match: \)
scope: punctuation.definition.parameters.end.elixir
set: function_body_pop
- include: parameters_or_if_closing_pop
- match: (?=,)
set: arguments_ws_rest_pop
- include: func_do_block_pop
- include: if_ws_closing_token_or_eol_pop
- include: if_non_space_pop
function_body_pop:
- include: func_do_block_pop
- include: arguments_ws_rest_pop
function_atom_name_pop:
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_closing_pop
- match: ':'
scope: constant.other.symbol.elixir punctuation.definition.constant.begin.elixir
push:
- match: (?=<%)|{{atom_symbol}}
scope: constant.other.symbol.elixir entity.name.function.elixir
pop: 1
- match: (["'])
scope: punctuation.definition.constant.begin.elixir
set:
- meta_scope: constant.other.symbol.quoted.elixir
- match: \1
scope: punctuation.definition.constant.end.elixir
pop: 1
- include: interpolated_elixir
- match: \\?.|\n
scope: entity.name.function.elixir
- include: if_empty_pop
- include: core_syntax
parameters:
- include: block_or_keyword
- include: special_form
- match: (?=\^\s*{{identifier}}{{no_key_suffix}}(?!\s*\.(?!\.))(?!{{has_arguments}}))
push:
- include: operator
- include: identifier_pop
- match: |
(?x)
(?>((?=_)(?<!%>){{identifier}})|({{identifier}}))
(?=\s*(?>[,;)}\]=|\\]|\.\.|::|->|<-|<>|>>|(?>when|do){{no_id_key_suffix}}|$))
captures:
1: variable.parameter.unused.elixir
2: variable.parameter.elixir
- match: (?=\\\\(?!:{{no_colon_suffix}})|<-)
push:
- match: (?=,|(?>when|do){{no_id_key_suffix}}|do:(?!:))
pop: 1
- include: core_syntax_or_if_closing_pop
- include: paren_param
- include: list_param
- include: tuple_param
- include: map_param
- include: binary_string_param
- include: last_id_argument
- include: core_syntax
parameters_or_if_closing_pop:
- include: if_closing_token_pop
- include: parameters
paren_param:
- match: (?=\()
push: paren_param_pop
paren_param_pop:
- match: \(
scope: punctuation.definition.parameters.begin.elixir
set:
- meta_scope: meta.function.parameters.elixir
- match: \)
scope: punctuation.definition.parameters.end.elixir
pop: 1
- include: parameters_or_if_closing_pop
tuple_param:
- match: \{
scope: punctuation.section.sequence.begin.elixir
push:
- meta_scope: meta.sequence.tuple.elixir
- match: \}
scope: punctuation.section.sequence.end.elixir
pop: 1
- include: parameters_or_if_closing_pop
list_param:
- match: \[
scope: punctuation.section.brackets.begin.elixir
push:
- meta_scope: meta.brackets.elixir
- match: \]
scope: punctuation.section.brackets.end.elixir
pop: 1
- include: cons_operator
- include: parameters_or_if_closing_pop
map_param:
- match: \%
scope: punctuation.section.mapping.begin.elixir
push:
- meta_scope: meta.mapping.elixir
- match: (?=unquote\()
set: [map_param_body_pop, arguments_pop, unquote_pop]
- include: alias_names
- match: ((?=_)(?<!%>){{identifier}})|({{identifier}})
captures:
1: variable.parameter.unused.elixir
2: variable.parameter.elixir
set: map_param_body_pop
- include: map_param_body_pop
map_param_body_pop:
- match: \{
scope: punctuation.section.mapping.begin.elixir
set:
- include: map_closing_pop
- include: parameters_or_if_closing_pop
- include: if_closing_token_pop
- include: if_non_space_or_eol_pop
binary_string_param:
- include: stray_binary_end
- match: <<(?![<~])
scope: string.other.binary.elixir punctuation.definition.string.begin.elixir
push:
- meta_scope: meta.string.binary.elixir
- include: binary_string_body_pop
- include: parameters_or_if_closing_pop
spec_definition_pop:
- match: (?=\()
set: [type_definition_next_pop, type_arguments_or_pop]
- include: type_definition_next_pop
spec_op_definition_pop:
- meta_scope: meta.type.elixir
- match: (?x)((?!::|\.(?!\.)){{operator}} | (?>and|in|or|not){{no_id_key_suffix}})
scope: variable.other.spec.elixir
set: spec_op_definition_next_pop
- include: if_types_end_pop
- include: spec_op_definition_next_pop
spec_op_definition_next_pop:
- meta_scope: meta.type.elixir
- include: return_types_pop
- match: (?=[,;])
pop: 1
- include: types_or_if_closing_pop
- include: if_non_space_pop
type_definition_pop:
- meta_scope: meta.type.elixir
- match: (?=\()
set: [type_definition_next_pop, type_params_pop]
- include: type_definition_next_pop
type_params_pop:
- match: \(
scope: punctuation.definition.parameters.begin.elixir
set:
- meta_scope: meta.type.elixir meta.function.parameters.elixir
- match: \)
scope: punctuation.definition.parameters.end.elixir
pop: 1
- include: parameters_or_if_closing_pop
type_definition_next_pop:
- include: comments
- include: return_types_pop
- include: if_non_space_pop
types:
- match: (?=unquote(?:_splicing)?\()
push: [type_arguments_or_pop, arguments_pop, unquote_pop]
- include: block_or_keyword
- include: special_form
- match: |
(?x)(
(?> # Ordered by likeliness of occurrence.
binary|term|atom|any|integer|boolean|map|list|module
| (?>(?:non_)?neg_|pos_)?integer|no_return|pid|iodata
| number|float|keyword|timeout|tuple|reference|charlist
| fun(?:ction)?|char|struct|arity|port|identifier|none\b|mfa
| node|byte|as_boolean|bitstring|iolist|maybe_improper_list
| (?>
nonempty_char
| (?>(?:nonempty_)?maybe_|nonempty_)improper_|nonempty_
)?list
)
){{no_id_key_suffix}}
| (?>(optional)|(required)|(record))(?={{no_suffix_then_arguments}})
| ({{identifier}})
captures:
1: support.type.elixir
2: keyword.other.optional.elixir
3: keyword.other.required.elixir
4: keyword.other.record.elixir
5: storage.type.custom.elixir
push: type_arguments_or_pop
- include: list_type
- include: tuple_type
- include: module_name
- include: dot_type
- include: map_type
- include: binary_string_type
- include: paren_type
- include: comments
types_or_if_closing_pop:
- include: types
- include: if_closing_token_pop
- include: core_syntax
dot_type:
- match: \.(?!\.)
scope: punctuation.accessor.dot.elixir
push:
- include: unquote_call_pop
- match: '{{identifier}}{{no_id_key_suffix}}'
scope: storage.type.remote.elixir
set: type_arguments_or_pop
- include: if_non_space_or_eol_pop
type_arguments_or_pop:
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.type.elixir meta.function-call.arguments.elixir
- include: arguments_closing_pop
- include: arg_comma_and_skip_ws
- include: named_type
- include: types_or_if_closing_pop
- include: if_empty_pop
named_type:
- include: block_or_keyword
- match: '{{identifier}}(?=\s*::(?!:))'
scope: variable.other.named-type.elixir
return_types_pop:
- match: ::(?!:)
scope: meta.type.elixir keyword.operator.colon.elixir
set: [first_and_next_types_pop, if_non_space_pop]
if_types_end_pop:
- match: (?=when{{no_id_key_suffix}}|@?{{identifier}}{{no_id_key_suffix}}\s{{has_arguments}})
comment: no when clause directly after "::"
pop: 1
- include: if_closing_token_pop
first_and_next_types_pop:
- include: comments
- include: if_types_end_pop
- match: (?=\S)
set:
- meta_scope: meta.type.elixir
- match: (?=$|\|(?![:|>])|::(?!:)|when{{no_id_key_suffix}})
set: [next_types_pop, if_non_space_pop]
- match: (?=[,;])
pop: 1
- include: named_type
- include: types_or_if_closing_pop
next_types_pop:
- include: comments
- match: when{{no_id_key_suffix}}
scope: keyword.operator.when.elixir
set: [when_types_clause_pop, invalid_comma_or_non_space_pop]
- match: (\|(?![:|>]))|(::(?!:))
captures:
1: keyword.operator.union.elixir
2: keyword.operator.colon.elixir
push: [if_non_space_pop, union_types_eol_pop, if_non_space_pop]
- include: if_ws_closing_token_or_eol_pop
- include: if_non_space_or_eol_pop
union_types_eol_pop:
- meta_scope: meta.type.elixir
- include: comments
- match: |
(?x)(?=
[,;] | \|(?![:|>]) | ::(?!:) | when{{no_id_key_suffix}}
| @?{{identifier}}{{no_id_key_suffix}}\s{{has_arguments}}
)
pop: 1
- include: named_type
- include: types_or_if_closing_pop
- include: if_ws_closing_token_or_eol_pop
- include: if_non_space_or_eol_pop
when_types_clause_pop:
- meta_scope: meta.type.elixir
- include: comments
- include: atom_keyword
- match: (?<=[^:]:)
comment: skips to keyword value
push: [when_var_pop, invalid_comma_or_non_space_pop]
- include: comma_and_skip_ws
- include: if_ws_closing_token_or_eol_pop
- include: if_non_space_or_eol_pop
when_var_pop:
- match: var{{no_id_key_suffix}}(?!{{has_arguments}})
comment: "`var` is a particular support type. Elixir recognizes it only after a `when`."
scope: support.type.elixir
- include: first_and_next_types_pop
paren_type:
- match: \(
scope: punctuation.section.group.begin.elixir
push:
- meta_scope: meta.parens.elixir
- match: \)
scope: punctuation.section.group.end.elixir
pop: 1
- include: named_type
- include: types_or_if_closing_pop
tuple_type:
- match: \{
scope: punctuation.section.sequence.begin.elixir
push:
- meta_scope: meta.braces.elixir
- match: \}
scope: punctuation.section.sequence.end.elixir
pop: 1
- include: named_type
- include: types_or_if_closing_pop
list_type:
- match: \[
scope: punctuation.section.brackets.begin.elixir
push:
- meta_scope: meta.brackets.elixir
- match: \]
scope: punctuation.section.brackets.end.elixir
pop: 1
- include: named_type
- include: types_or_if_closing_pop
map_type:
- match: \%
scope: punctuation.section.mapping.begin.elixir
push:
- meta_scope: meta.mapping.elixir
- match: (?=unquote\()
set: [map_type_body_pop, arguments_pop, unquote_pop]
- include: alias_names
- match: _(?>{{module_name}}|{{identifier}})?
scope: variable.type.unused.elixir invalid.illegal.struct.elixir
set: map_type_body_pop
- include: map_type_body_pop
map_type_body_pop:
- match: \{
scope: punctuation.section.mapping.begin.elixir
set:
- include: map_closing_pop
- include: named_type
- include: types_or_if_closing_pop
- include: if_closing_token_pop
- include: if_non_space_or_eol_pop
binary_string_type:
- include: stray_binary_end
- match: <<(?![<~])
scope: string.other.binary.elixir punctuation.definition.string.begin.elixir
push:
- meta_scope: meta.string.binary.elixir
- include: binary_string_body_pop
- include: named_type
- include: types_or_if_closing_pop
numeric:
- match: |
(?x)(?>
(0 (x) \h (?:_?\h)*)
| (0 (b) [01] (?:_?[01])*)
| (0 (o) [0-7] (?:_?[0-7])*)
| (\d(?:_?\d)* (\.) \d(?:_?\d)* (?:[eE] [-+]? \d(?:_?\d)*)?)
| (\d(?:_?\d)*)
)([_\d]*)
comment: (?:_?\d)* because double or trailing '_' are invalid
captures:
1: constant.numeric.hex.elixir
2: punctuation.separator.numeric.elixir
3: constant.numeric.binary.elixir
4: punctuation.separator.numeric.elixir
5: constant.numeric.octal.elixir
6: punctuation.separator.numeric.elixir
7: constant.numeric.float.elixir
8: punctuation.separator.decimal.elixir
9: constant.numeric.integer.elixir
10: invalid.illegal.numeric.elixir
binary_string:
- include: stray_binary_end
- match: <<(?![<~])
scope: string.other.binary.elixir punctuation.definition.string.begin.elixir
push:
- meta_scope: meta.string.binary.elixir
- include: binary_string_body_pop
- include: core_syntax_or_if_closing_pop
stray_binary_end:
- match: '>>(?!>)'
scope: punctuation.definition.string.end.elixir invalid.illegal.stray-closing-binary.elixir
binary_string_body_pop:
- match: '>>(?!>)'
scope: string.other.binary.elixir punctuation.definition.string.end.elixir
pop: 1
- match: ::(?!:)
scope: keyword.operator.colon.elixir
push:
- meta_scope: meta.type.binary.elixir
- include: bitstring_type
- include: if_non_space_pop
bitstring_type:
- include: atom_symbol
- include: block_or_keyword
- include: unquote_call
- match: -(?![->])|\*|(?>\d(?:_?\d)*)
scope: storage.type.binary.elixir
- match: '{{identifier}}'
scope: storage.type.binary.elixir
push: arguments_or_pop
- include: paren_binary
paren_binary:
- match: \(
scope: punctuation.section.group.begin.elixir
push:
- meta_scope: meta.parens.elixir
- match: \)
scope: punctuation.section.group.end.elixir
pop: 1
- include: bitstring_type
- include: core_syntax_or_if_closing_pop
escaped_char:
- match: (?x) \\x (?> \h{2} | (?>\h|([^'"/\\)\]}>#])){1,2} | )
scope: constant.character.escape.hex.elixir
captures:
1: invalid.illegal.escape.hex.elixir
- match: (?x) \\u (?> (?>\h{4}|{\h{1,6}}) | ({}|{?[^'"/\\)\]}>#]{1,6}}?))
scope: constant.character.escape.unicode.elixir
captures:
1: invalid.illegal.escape.unicode.elixir
- match: \\.
scope: constant.character.escape.char.elixir
interpolated_elixir:
- match: (?=#{)
push:
- clear_scopes: true
- match: '#{'
scope: punctuation.section.interpolation.begin.elixir
set:
- clear_scopes: true
- meta_content_scope: source.elixir.embedded
- meta_scope: source.elixir meta.string.elixir meta.interpolation.elixir
- match: \}
scope: punctuation.section.interpolation.end.elixir
pop: 1
- include: core_syntax
escaped_or_interpolated:
- include: line_continuation
- include: escaped_char
- include: interpolated_elixir
pcre_erlang:
- include: scope:source.pcree
elixir_in_regex:
- include: line_continuation
- include: interpolated_elixir
simple_string:
- match: \'
comment: single quoted string (allows for interpolation)
scope: punctuation.definition.string.begin.elixir
push:
- meta_scope: meta.string.elixir string.quoted.single.elixir
- match: \'
scope: punctuation.definition.string.end.elixir
pop: 1
- include: escaped_or_interpolated
- match: \"
comment: double quoted string (allows for interpolation)
scope: punctuation.definition.string.begin.elixir
push:
- meta_scope: meta.string.elixir string.quoted.double.elixir
- match: \"
scope: punctuation.definition.string.end.elixir
pop: 1
- include: escaped_or_interpolated
heredoc_regex_interpolated:
- match: (""")(.*)\n
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
push:
- meta_scope: meta.string.elixir string.quoted.triple.double.elixir
- include: heredoc_string_closing_double_pop
- match: ''
push: pcre_erlang
with_prototype:
- include: elixir_in_regex
- match: (?=(?>\\.|[^"])*?""")
pop: 1
- match: (''')(.*)\n
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
push:
- meta_scope: meta.string.elixir string.quoted.triple.single.elixir
- include: heredoc_string_closing_single_pop
- match: ''
push: pcre_erlang
with_prototype:
- include: elixir_in_regex
- match: (?=^(?>\\.|[^'])*?''')
pop: 1
heredoc_regex_raw:
- match: (""")(.*)\n
comment: Triple-quoted heredocs
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
push:
- meta_scope: meta.string.elixir string.quoted.triple.double.elixir
- include: heredoc_string_closing_double_pop
- match: ''
push: pcre_erlang
with_prototype:
- match: (?=(?>\\.|[^"])*?""")
pop: 1
- match: (''')(.*)\n
comment: Triple-quoted heredocs
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
push:
- meta_scope: meta.string.elixir string.quoted.triple.single.elixir
- include: heredoc_string_closing_single_pop
- match: ''
push: pcre_erlang
with_prototype:
- match: (?=^(?>\\.|[^'])*?''')
pop: 1
heredoc_string_interpolated:
- match: (""")(.*)\n
comment: Triple-quoted heredocs
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
push:
- meta_scope: meta.string.elixir string.quoted.triple.double.elixir
- include: escaped_or_interpolated
- include: heredoc_string_closing_double_pop
- match: (''')(.*)\n
comment: Triple-quoted heredocs
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
push:
- meta_scope: meta.string.elixir string.quoted.triple.single.elixir
- include: escaped_or_interpolated
- include: heredoc_string_closing_single_pop
heredoc_string_raw:
- match: (""")(.*)\n
comment: Triple-quoted heredocs
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
push:
- meta_scope: meta.string.elixir string.quoted.triple.double.elixir
- match: \\"
scope: constant.character.escape.char.elixir
- include: heredoc_string_closing_double_pop
- match: (''')(.*)\n
comment: Triple-quoted heredocs
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
push:
- meta_scope: meta.string.elixir string.quoted.triple.single.elixir
- match: \\'
scope: constant.character.escape.char.elixir
- include: heredoc_string_closing_single_pop
heredoc_string_closing_double_pop:
- match: \s*((?>\\.|[^"])*?)\s*(""")
captures:
1: invalid.illegal.closing-heredoc.elixir
2: punctuation.definition.string.end.elixir
pop: 1
heredoc_string_closing_double_w_meta_pop:
- meta_scope: meta.string.elixir
- include: heredoc_string_closing_double_pop
heredoc_string_closing_single_pop:
- match: \s*((?>\\.|[^'])*?)\s*(''')
captures:
1: invalid.illegal.closing-heredoc.elixir
2: punctuation.definition.string.end.elixir
pop: 1
string:
- include: heredoc_string_interpolated
- include: simple_string
- include: binary_string
- match: (?x) (~[a-zA-Z])\n | ~[a-zA-Z]([^{\[<(/|"'])
comment: catch invalid sigils first
scope: meta.string.elixir storage.type.string.elixir
captures:
1: invalid.illegal.sigil-string.elixir
2: invalid.illegal.string-delimiter.elixir
- match: (?=~w([/|"'])(?>\\.|(?!\1).)*\1a)
comment: highlight words as atoms
push:
- match: (~w)(.)
captures:
1: storage.type.string.elixir
2: string.quoted.other.atom.elixir punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir
- meta_content_scope: string.quoted.other.atom.elixir constant.other.symbol.atom.elixir
- match: \s+
push:
- clear_scopes: 1
- include: if_empty_pop
- include: escaped_or_interpolated
- match: (\2)(a)
captures:
1: string.quoted.other.atom.elixir punctuation.definition.string.end.elixir
2: string.quoted.modifiers.elixir storage.type.string.elixir
pop: 1
- match: ~L(?=["'])(?!''')
comment: LiveView
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (""")(.*)\n
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
set:
- meta_scope: meta.string.elixir
- match: (?=""")
set: [string_modifiers_and_pop, heredoc_string_closing_double_w_meta_pop]
- match: \\"
scope: constant.character.escape.char.elixir
- include: scope:text.html.eex
apply_prototype: true
- match: \"
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir
- match: \\"
scope: constant.character.escape.char.elixir
- include: string_closing_dquote
- include: scope:text.html.eex
apply_prototype: true
- match: \'
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir
- match: \\'
scope: constant.character.escape.char.elixir
- include: string_closing_squote
- include: scope:text.html.eex
apply_prototype: true
- match: ~H(?=["'])(?!''')
comment: LiveView HEEx template
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (""")(.*)\n
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
set:
- meta_scope: meta.string.elixir
- match: (?=""")
set: [string_modifiers_and_pop, heredoc_string_closing_double_w_meta_pop]
- match: \\"
scope: constant.character.escape.char.elixir
- include: scope:text.html.heex
apply_prototype: true
- match: \"
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir
- match: \\"
scope: constant.character.escape.char.elixir
- include: string_closing_dquote
- include: scope:text.html.heex
apply_prototype: true
- match: \'
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir
- match: \\'
scope: constant.character.escape.char.elixir
- include: string_closing_squote
- include: scope:text.html.heex
apply_prototype: true
- match: ~F(?=["'])(?!''')
comment: Surface template
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (""")(.*)\n
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
set:
- meta_scope: meta.string.elixir
- match: (?=""")
set: [string_modifiers_and_pop, heredoc_string_closing_double_w_meta_pop]
- match: \\"
scope: constant.character.escape.char.elixir
- include: scope:text.html.surface
apply_prototype: true
- match: \"
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir
- match: \\"
scope: constant.character.escape.char.elixir
- include: string_closing_dquote
- include: scope:text.html.surface
apply_prototype: true
- match: \'
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir
- match: \\'
scope: constant.character.escape.char.elixir
- include: string_closing_squote
- include: scope:text.html.surface
apply_prototype: true
- match: ~y(?=""")
comment: YAML with interpolation
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (""")(.*)\n
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
set:
- meta_scope: meta.string.elixir
- match: (?=""")
set: [string_modifiers_and_pop, heredoc_string_closing_double_w_meta_pop]
- match: ''
push: scope:source.yaml
with_prototype:
- include: escaped_or_interpolated
- match: (?=""")
pop: 1
- match: ~Y(?=""")
comment: YAML raw
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (""")(.*)\n
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
set:
- meta_scope: meta.string.elixir
- match: (?=""")
set: [string_modifiers_and_pop, heredoc_string_closing_double_w_meta_pop]
- match: ''
push: scope:source.yaml
with_prototype:
- match: \\"
scope: constant.character.escape.char.elixir
- match: (?=""")
pop: 1
- match: ~j(?=")
comment: JSON with interpolation
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (""")(.*)\n
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
set:
- meta_scope: meta.string.elixir
- match: (?=""")
set: [string_modifiers_and_pop, heredoc_string_closing_double_w_meta_pop]
- match: ''
push: scope:source.json
with_prototype:
- include: escaped_or_interpolated
- match: (?=""")
pop: 1
- match: \"
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir
- include: string_closing_dquote
- match: ''
push: scope:source.json
with_prototype:
- include: escaped_or_interpolated
- match: (?=")
pop: 1
- match: ~J(?=")
comment: JSON raw
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (""")(.*)\n
captures:
1: punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
set:
- meta_scope: meta.string.elixir
- match: (?=""")
set: [string_modifiers_and_pop, heredoc_string_closing_double_w_meta_pop]
- match: ''
push: scope:source.json
with_prototype:
- match: \\"
scope: constant.character.escape.char.elixir
- match: (?=""")
pop: 1
- match: \"
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir
- include: string_closing_dquote
- match: ''
push: scope:source.json
with_prototype:
- match: \\"
scope: constant.character.escape.char.elixir
- match: (?=")
pop: 1
- match: ~r
comment: regex sigil string with interpolation
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (?="""|''')
set:
- match: (?<="""|''')
set: string_modifiers_and_pop
- include: heredoc_regex_interpolated
- match: \"
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_dquote
- match: ''
push: pcre_erlang
with_prototype:
- include: elixir_in_regex
- match: (?=")
pop: 1
- match: \'
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_squote
- match: ''
push: pcre_erlang
with_prototype:
- include: elixir_in_regex
- match: (?=')
pop: 1
- match: /
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_slash
- match: ''
push: pcre_erlang
with_prototype:
- include: elixir_in_regex
- match: (?=/)
pop: 1
- match: \|
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_pipe
- match: ''
push: pcre_erlang
with_prototype:
- include: elixir_in_regex
- match: (?=\|)
pop: 1
- match: \{
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_curly
- match: ''
push: pcre_erlang
with_prototype:
- include: elixir_in_regex
- match: (?=})
pop: 1
- match: \[
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_square
- match: ''
push: pcre_erlang
with_prototype:
- include: elixir_in_regex
- match: (?=])
pop: 1
- match: \<
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_angle
- match: ''
push: pcre_erlang
with_prototype:
- include: elixir_in_regex
- match: (?=>)
pop: 1
- match: \(
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_round
- match: ''
push: pcre_erlang
with_prototype:
- include: elixir_in_regex
- include: if_closing_paren_pop
- match: ~R
comment: regex sigil string without interpolation
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (?="""|''')
set:
- match: (?<="""|''')
set: string_modifiers_and_pop
- include: heredoc_regex_raw
- match: \"
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.regex.elixir
- include: string_closing_dquote
- match: ''
push: pcre_erlang
with_prototype:
- match: \\"
scope: constant.character.escape.pcree
- match: (?=")
pop: 1
- match: \'
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.regex.elixir
- include: string_closing_squote
- match: ''
push: pcre_erlang
with_prototype:
- match: \\'
scope: constant.character.escape.pcree
- match: (?=')
pop: 1
- match: /
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.regex.elixir
- include: string_closing_slash
- match: ''
push: pcre_erlang
with_prototype:
- match: \\/
scope: constant.character.escape.pcree
- match: (?=/)
pop: 1
- match: \|
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.regex.elixir
- include: string_closing_pipe
- match: ''
push: pcre_erlang
with_prototype:
- match: \\\|
scope: constant.character.escape.pcree
- match: (?=\|)
pop: 1
- match: \{
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.regex.elixir
- include: string_closing_curly
- match: ''
push: pcre_erlang
with_prototype:
- match: \\}
scope: constant.character.escape.pcree
- match: (?=})
pop: 1
- match: \[
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.regex.elixir
- include: string_closing_square
- match: ''
push: pcre_erlang
with_prototype:
- match: \\]
scope: constant.character.escape.pcree
- match: (?=])
pop: 1
- match: \<
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.regex.elixir
- include: string_closing_angle
- match: ''
push: pcre_erlang
with_prototype:
- match: \\>
scope: constant.character.escape.pcree
- match: (?=>)
pop: 1
- match: \(
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.regex.elixir
- include: string_closing_round
- match: ''
push: pcre_erlang
with_prototype:
- match: \\\)
scope: constant.character.escape.pcree
- include: if_closing_paren_pop
- match: ~[a-z]
comment: with sigil and with interpolation
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (?="""|''')
set:
- match: (?<="""|''')
set: string_modifiers_and_pop
- include: heredoc_string_interpolated
- match: (?=[/|"'])
set:
- meta_scope: meta.string.elixir
- match: (?<=[a-z])([/|"'])
captures:
1: string.quoted.other.literal.lower.elixir punctuation.definition.string.begin.elixir
push:
- meta_content_scope: string.quoted.other.literal.lower.elixir
- match: \1
scope: string.quoted.other.literal.lower.elixir punctuation.definition.string.end.elixir
pop: 1
- include: escaped_or_interpolated
- match: ''
set: string_modifiers_and_pop
- match: \{
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_curly
- include: escaped_or_interpolated
- match: \[
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_square
- include: escaped_or_interpolated
- match: \<
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_angle
- include: escaped_or_interpolated
- match: \(
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.interpolated.elixir
- include: string_closing_round
- include: escaped_or_interpolated
- match: ~[A-Z]
comment: with sigil and without interpolation
scope: meta.string.elixir storage.type.string.elixir
push:
- match: (?="""|''')
set:
- match: (?<="""|''')
set: string_modifiers_and_pop
- include: heredoc_string_raw
- match: (?=[/|"'])
set:
- meta_scope: meta.string.elixir
- match: (?<=[A-Z])([/|"'])
captures:
1: string.quoted.other.literal.upper.elixir punctuation.definition.string.begin.elixir
push:
- meta_content_scope: string.quoted.other.literal.upper.elixir
- match: \\.
- match: \1
scope: string.quoted.other.literal.upper.elixir punctuation.definition.string.end.elixir
pop: 1
- match: ''
set: string_modifiers_and_pop
- match: \{
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.upper.elixir
- include: string_closing_curly
- match: \[
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.upper.elixir
- include: string_closing_square
- match: \<
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.upper.elixir
- include: string_closing_angle
- match: \(
scope: punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir string.quoted.other.literal.upper.elixir
- include: string_closing_round
string_closing_dquote:
- match: \"
scope: punctuation.definition.string.end.elixir
set: string_modifiers_and_pop
string_closing_squote:
- match: \'
scope: punctuation.definition.string.end.elixir
set: string_modifiers_and_pop
string_closing_pipe:
- match: \|
scope: punctuation.definition.string.end.elixir
set: string_modifiers_and_pop
string_closing_slash:
- match: \/
scope: punctuation.definition.string.end.elixir
set: string_modifiers_and_pop
string_closing_curly:
- match: \\\}
scope: constant.character.escape.char.elixir
- match: \}
scope: punctuation.definition.string.end.elixir
set: string_modifiers_and_pop
string_closing_square:
- match: \\\]
scope: constant.character.escape.char.elixir
- match: \]
scope: punctuation.definition.string.end.elixir
set: string_modifiers_and_pop
string_closing_angle:
- match: \\\>
scope: constant.character.escape.char.elixir
- match: \>
scope: punctuation.definition.string.end.elixir
set: string_modifiers_and_pop
string_closing_round:
- match: \\\)
scope: constant.character.escape.char.elixir
- match: \)
scope: punctuation.definition.string.end.elixir
set: string_modifiers_and_pop
string_modifiers:
- match: '[a-zA-Z]+'
scope: meta.string.elixir string.quoted.modifiers.elixir storage.type.string.elixir
- match: \w+
scope: invalid.illegal.non-ascii-modifier.elixir
string_modifiers_and_pop:
- include: string_modifiers
- include: if_empty_pop
def_blocks:
- match: |
(?x)
(?>(def(?>macro|guard|n)?p) | (def(?>macro|delegate|guard|n)?))
{{no_suffix_then_arguments}}
captures:
1: keyword.declaration.function.private.elixir
2: keyword.declaration.function.public.elixir
push: function_header_pop
- match: defmodule{{no_suffix_then_arguments}}
scope: keyword.declaration.module.elixir
push:
- meta_scope: meta.namespace.module.elixir
- include: defmodule_body_pop
- match: defimpl{{no_suffix_then_arguments}}
scope: keyword.declaration.implementation.elixir
push:
- meta_scope: meta.namespace.implementation.elixir
- include: arguments_paren_or_ws_pop
- match: defprotocol{{no_suffix_then_arguments}}
scope: keyword.declaration.protocol.elixir
push:
- meta_scope: meta.namespace.protocol.elixir
- include: defmodule_body_pop
defmodule_body_pop:
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_closing_pop
- include: defmodule_arguments
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_ws_closing_pop
- include: defmodule_arguments
defmodule_arguments:
- match: (?={{atom_symbol}}:(?!:))|(?<=[^:]:)
push: arguments_ws_rest_pop
- include: block_or_keyword
- match: |
(?x)(?=
(?:(?<=%>)\.)? (?>{{module_name}}{{no_key_suffix}} | __MODULE__{{no_id_key_suffix}})
| :(?>{{atom_symbol}}|['"])
)
push:
- meta_scope: meta.namespace.elixir
- match: '{{module_name}}{{no_key_suffix}}(?!\s*\.(?!\.))'
scope: entity.name.namespace.elixir
- include: atom_namespace_entity
- include: special_form
- include: module_name
- include: atom_symbol
- include: unquote_call
- include: dot_operator
- include: if_non_space_or_eol_pop
- include: arg_comma_and_skip_ws
- include: core_syntax_or_if_closing_pop
defrecord:
- match: (?:(Record)\s*(\.)\s*)?(defrecordp?){{no_suffix_then_arguments}}
captures:
1: constant.other.module.elixir
2: punctuation.accessor.dot.elixir
3: keyword.declaration.elixir
push: defrecord_pop
defrecord_pop:
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_closing_pop
- include: defrecord_arguments
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_ws_closing_pop
- include: defrecord_arguments
defrecord_arguments:
- include: atom_function_entity
- match: (?=,)
push: arguments_ws_rest_pop
- include: arg_comma_and_skip_ws
- include: core_syntax_or_if_closing_pop
atom_function_entity:
- match: (:)({{atom_symbol}})(?!\s*\.(?!\.))
scope: constant.other.symbol.elixir
captures:
1: punctuation.definition.constant.begin.elixir
2: entity.name.function.elixir
atom_namespace_entity:
- match: (:)({{atom_symbol}})(?!\s*\.(?!\.))
scope: constant.other.symbol.elixir
captures:
1: punctuation.definition.constant.begin.elixir
2: entity.name.namespace.elixir
block_or_keyword:
- include: atom_keyword
- include: fn_block
- include: do_block
- include: elixir_keywords
do_block_pop:
- match: do{{no_id_key_suffix}}
scope: punctuation.section.block.begin.elixir keyword.context.block.do.elixir
set:
- meta_scope: meta.block.elixir
- match: else{{no_id_key_suffix}}
comment: the else-block contains arrow clauses only in error handling
scope: keyword.control.conditional.else.elixir
- match: (?=%>)
pop: 1
- include: error_handling_clauses
- include: core_syntax_or_block_end_pop
func_do_block_pop:
- match: do{{no_id_key_suffix}}
scope: punctuation.section.block.begin.elixir keyword.context.block.do.elixir
set:
- meta_scope: meta.block.elixir
- include: error_handling_clauses
- include: core_syntax_or_block_end_pop
error_handling_clauses:
- match: else{{no_id_key_suffix}}
scope: keyword.control.exception.else.elixir
push: arrow_clauses_body_pop
- match: after{{no_id_key_suffix}}
scope: keyword.control.exception.after.elixir
push: core_syntax_or_if_closing_pop
- match: rescue{{no_id_key_suffix}}
scope: keyword.control.exception.rescue.elixir
push: arrow_clauses_body_pop
- match: catch{{no_id_key_suffix}}
scope: keyword.control.exception.catch.elixir
push: arrow_clauses_body_pop
do_block:
- match: (?=do{{no_id_key_suffix}})
push: do_block_pop
block_end_pop:
- match: end{{no_id_key_suffix}}
scope: punctuation.section.block.end.elixir keyword.context.block.end.elixir
pop: 1
last_arg_block_end_pop:
- match: end{{no_id_key_suffix}}
scope: punctuation.section.block.end.elixir keyword.context.block.end.elixir
set:
- match: \s|\n|
scope: punctuation.section.arguments.end.elixir
pop: 1
core_syntax_or_block_end_pop:
- include: block_end_pop
- include: core_syntax
core_syntax_or_if_closing_pop:
- include: if_closing_token_pop
- include: core_syntax
module_name:
- match: '{{module_name}}{{no_key_suffix}}'
scope: constant.other.module.elixir
- match: (?x)(:(["'])) ((?>\\\\|\\\2|(?!\2).)*?) (\2) (?=\s*\.(?!\.))
captures:
1: punctuation.definition.constant.begin.elixir
3: constant.other.module.elixir
4: punctuation.definition.constant.end.elixir
- match: (:)({{atom_symbol}})(?=\s*\.(?!\.))
captures:
1: punctuation.definition.constant.begin.elixir
2: constant.other.module.elixir
module_name_pop:
- match: '{{module_name}}{{no_key_suffix}}'
scope: constant.other.module.elixir
pop: 1
module_function_call_pop:
- match: ({{module_name}})\s*(\.(?!\.))
comment: always a function call after a module
captures:
1: constant.other.module.elixir
2: punctuation.accessor.dot.elixir
set: member_call_pop
member_call_pop:
- include: quoted_remote_call_pop
- include: quoted_member_pop
- include: unquote_call_pop
- match: '{{member}}'
scope: variable.function.elixir
set: arguments_or_pop
- include: tuple_call_pop
- include: if_non_space_or_eol_pop
id_or_operator_call_pop:
- match: ({{member}})(?=\s*\.\s*\(|{{has_arguments}})
scope: variable.function.elixir
set: arguments_paren_or_ws_pop
quoted_remote_call_pop:
- match: \"(?=(?>\\[\\"]|.)*?"{{has_arguments}})
scope: punctuation.definition.constant.begin.elixir
set:
- meta_scope: meta.function-call.elixir
- match: \"
scope: punctuation.definition.constant.end.elixir
set: arguments_or_pop
- match: (\\[\\"])|[^"]
scope: variable.function.elixir
captures:
1: constant.character.escape.char.elixir
- match: \'(?=(?>\\[\\']|.)*?'{{has_arguments}})
scope: punctuation.definition.constant.begin.elixir
set:
- meta_scope: meta.function-call.elixir
- match: \'
scope: punctuation.definition.constant.end.elixir
set: arguments_or_pop
- match: (\\[\\'])|[^']
scope: variable.function.elixir
captures:
1: constant.character.escape.char.elixir
quoted_member_pop:
- match: \"
scope: punctuation.definition.constant.begin.elixir
set:
- meta_scope: meta.member.elixir
- match: \"
scope: punctuation.definition.constant.end.elixir
pop: 1
- match: (\\[\\"])|[^"]
scope: variable.other.member.elixir
captures:
1: constant.character.escape.char.elixir
- match: \'
scope: punctuation.definition.constant.begin.elixir
set:
- meta_scope: meta.member.elixir
- match: \'
scope: punctuation.definition.constant.end.elixir
pop: 1
- match: (\\[\\'])|[^']
scope: variable.other.member.elixir
captures:
1: constant.character.escape.char.elixir
modules_or_ids_or_calls:
- match: (?x)(:(["'])) ((?>\\\\|\\\2|(?!\2).)*?) (\2) (?=\s*\.(?!\.))
captures:
1: punctuation.definition.constant.begin.elixir
3: constant.other.module.elixir
4: punctuation.definition.constant.end.elixir
push: member_call_pop
- match: (:)({{atom_symbol}})\s*(\.(?!\.))
captures:
1: punctuation.definition.constant.begin.elixir
2: constant.other.module.elixir
3: punctuation.accessor.dot.elixir
push: member_call_pop
- match: (?={{module_name}}|{{identifier}})
push:
- include: module_function_call_pop
- include: id_or_operator_call_pop
- include: module_name_pop
- include: identifier_pop
identifier_pop:
- match: ((?=_)(?<!%>){{identifier}})|({{identifier}})
captures:
1: variable.other.unused.elixir
2: variable.other.elixir
pop: 1
id_member_pop:
- match: '{{member}}'
scope: variable.other.member.elixir
pop: 1
tuple_call_pop:
- match: \{
scope: punctuation.section.braces.begin.elixir
set:
- match: \}
scope: punctuation.section.braces.end.elixir
pop: 1
- include: core_syntax_or_if_closing_pop
dot_accessor:
- match: \.(?!\.)
scope: punctuation.accessor.dot.elixir
push:
- include: atom_keyword
- include: module_function_call_pop
- include: unquote_call_pop
- include: id_or_operator_call_pop
- include: id_member_pop
- include: module_name_pop
- include: arguments_pop
- include: quoted_remote_call_pop
- include: quoted_member_pop
- include: tuple_call_pop
- include: if_non_space_or_eol_pop
module_attribute:
- match: '@'
scope: keyword.operator.attribute.elixir
push: module_attribute_pop
module_attribute_pop:
- match: (?!{{identifier}}(?!{{atom_id_suffix}}:(?!:)))
set:
- match: '[A-Z]'
scope: invalid.illegal.attribute.elixir
- include: if_empty_pop
- match: (?>(?>module|type|short)?doc){{no_suffix_then_arguments}}
scope: support.attr.doc.elixir
set:
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.doc.elixir
- include: arguments_closing_pop
- match: ''
push:
- include: if_closing_token_pop
- include: arg_comma_and_skip_ws
- include: markdown_comment
- include: core_syntax
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.doc.elixir
- include: arguments_ws_closing_pop
- include: arg_comma_and_skip_ws
- include: markdown_comment
- include: core_syntax
- match: (?>spec|(?:macro)?callback)(?={{no_suffix_then_arguments}}|\s*{{operator}})
scope: keyword.declaration.type.elixir
set:
- meta_scope: meta.type.elixir
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- include: arguments_closing_pop
- match: ''
push:
- match: (?=not{{no_id_key_suffix}})
set: spec_header_pop
- include: block_or_keyword
- include: spec_header_pop
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- match: (?=not{{no_id_key_suffix}})
set: spec_header_pop
- include: block_or_keyword
- include: spec_header_pop
- include: if_non_space_pop
- match: (?>typep?|opaque){{no_suffix_then_arguments}}
scope: keyword.declaration.type.elixir
set:
- meta_scope: meta.type.elixir
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.type.elixir meta.function-call.arguments.elixir
- include: block_or_keyword
- match: (?=unquote\()
push: [type_definition_pop, arguments_pop, unquote_pop]
- match: '{{identifier}}'
scope: entity.name.type.elixir
push: type_definition_pop
- include: arguments_rest_pop
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.type.elixir meta.function-call.arguments.elixir
- include: block_or_keyword
- match: (?=unquote\()
set: [type_definition_pop, arguments_pop, unquote_pop]
- match: '{{identifier}}'
scope: entity.name.type.elixir
set: type_definition_pop
- include: if_non_space_pop
- match: |
(?x)(?>
impl | deprecated | (?>before_|after_)?compile | behaviour | enforce_keys
| fallback_to_any | optional_callbacks | file | dialyzer | derive
| external_resource | vsn | on_(?>definition|load)
){{no_suffix_then_arguments}}
scope: support.attr.elixir
set: arguments_paren_or_ws_pop
- include: block_or_keyword
- match: '{{identifier}}{{has_arguments}}'
comment: definition
scope: entity.name.constant.elixir
set: arguments_paren_or_ws_pop
- match: '{{identifier}}'
comment: reference
scope: variable.other.constant.elixir
pop: 1
spec_after_unquote_pop:
- match: (?=(?!::){{operator}})
set: spec_op_definition_pop
- match: ''
set: spec_definition_pop
spec_header_pop:
- match: (?=unquote\()
set: [spec_after_unquote_pop, if_non_space_or_eol_pop, arguments_pop, unquote_pop]
- match: '{{identifier}}(?!\s*(?!::){{operator}})'
scope: variable.other.spec.elixir
set: spec_definition_pop
- match: (?=\S)
set: spec_op_definition_pop
markdown_comment:
- match: (""")(.*)(\n)
captures:
1: string.quoted.triple.double.elixir punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
3: string.quoted.triple.double.elixir
push:
- meta_scope: meta.string.elixir
- match: (?=^\s*""")
set:
- meta_scope: meta.string.elixir string.quoted.triple.double.elixir
- include: heredoc_string_closing_double_pop
- include: escaped_or_interpolated
- match: ''
embed: scope:text.html.markdown
embed_scope: source.markdown.embedded.elixir
escape: (?=^\s*"""|\\|#{)
- match: \"
scope: string.quoted.double.elixir punctuation.definition.string.begin.elixir
push:
- meta_scope: meta.string.elixir
- match: \"
scope: string.quoted.double.elixir punctuation.definition.string.end.elixir
pop: 1
- include: escaped_or_interpolated
- match: ''
embed: scope:text.html.markdown
embed_scope: source.markdown.embedded.elixir
escape: (?="|\\|#{)
- match: (~S)(""")(.*)(\n)
captures:
1: storage.type.string.elixir
2: string.quoted.triple.double.elixir punctuation.definition.string.begin.elixir
3: invalid.illegal.opening-heredoc.elixir
4: string.quoted.triple.double.elixir
push:
- meta_scope: meta.string.elixir
- match: (?<=""")
set: string_modifiers_and_pop
- match: (?=^\s*""")
push:
- meta_scope: string.quoted.triple.double.elixir
- include: heredoc_string_closing_double_pop
- match: ''
embed: scope:text.html.markdown
embed_scope: source.markdown.embedded.elixir
escape: (?=^\s*""")
- match: (~S)(''')(.*)(\n)
captures:
1: storage.type.string.elixir
2: string.quoted.triple.single.elixir punctuation.definition.string.begin.elixir
3: invalid.illegal.opening-heredoc.elixir
4: string.quoted.triple.single.elixir
push:
- meta_scope: meta.string.elixir
- match: (?<=''')
set: string_modifiers_and_pop
- match: (?=^\s*''')
push:
- meta_scope: string.quoted.triple.single.elixir
- include: heredoc_string_closing_single_pop
- match: ''
embed: scope:text.html.markdown
embed_scope: source.markdown.embedded.elixir
escape: (?=^\s*''')
elixir_in_markdown:
- match: (?<=\s{4})(iex)(?:\((.*?)\))?(>)
captures:
1: keyword.other.iex.elixir
2: constant.other.elixir
3: keyword.other.iex-angle.elixir punctuation.definition.iex.begin.elixir
push:
- clear_scopes: true
- meta_scope: meta.interpolation.elixir markup.raw.block.markdown markup.raw.block.elixir
- match: \n|$
scope: punctuation.definition.iex.end.elixir
pop: 1
- include: core_syntax
- match: (?={{is_markdown_elixir}})
push:
- clear_scopes: true
- meta_scope: meta.interpolation.elixir markup.raw.block.markdown markup.raw.block.elixir
- match: \n|$
scope: punctuation.section.arguments.end.elixir
pop: 1
- include: core_syntax
iex_dots:
- match: ^(\s*)(\.{3})(?:\((.*?)\))?(>)
comment: iex prompt continuation
captures:
1: meta.string.elixir
2: keyword.other.iex-dots.elixir
3: constant.other.elixir
4: keyword.other.iex-angle.elixir punctuation.definition.iex.begin.elixir
comma_and_skip_ws:
- include: invalid_comma
- match: \,
scope: punctuation.separator.sequence.elixir
push: invalid_comma_or_non_space_pop
arg_comma_and_skip_ws:
- match: \,
scope: punctuation.separator.arguments.elixir
push: invalid_comma_or_non_space_pop
invalid_comma:
- match: (?=,\s*(?>[,;)]|%>|->(?!:)|(?>do|when){{no_id_key_suffix}}|{{closing_keyword}}))
push: invalid_comma_or_non_space_pop
invalid_comma_or_non_space_pop:
- include: comment
- match: \,
scope: invalid.illegal.separator.elixir
- include: if_non_space_pop
operator:
- match: |
(?x)(?> # Ordered by likeliness of occurrence.
(=(?![=>~]))
| (->|<-)
| (<?\|>|<~>|<?<~|~>>?) # Operators with pipe precedence.
| ((?>[!=]=|[<>])(?![<>])=?)
| (=>)
| (<>)
| (-(?!-)|\+(?!\+)|//?|\*\*?)
| (\+\+(?!\+))
| (\|(?!\|))
| (::(?!:))
| (\^(?!\^\^))
| (\|\|(?!\|)|&&(?!&)|!)
| (\.\.\.) # Can appear in @type declarations.
| (\.\.)
| (=~)
| (\\\\)
| (<<<|>>>|&&&|\|\|\||~~~|\^\^\^)
| (---|\+\+\+)
| (--(?!-))
| (;)
)
captures:
1: keyword.operator.match.elixir
2: keyword.operator.arrow.elixir
3: keyword.operator.pipe.elixir
4: keyword.operator.comparison.elixir
5: keyword.operator.map-pair.elixir
6: keyword.operator.binary-concat.elixir
7: keyword.operator.arithmetic.elixir
8: keyword.operator.list-concat.elixir
9: keyword.operator.union.elixir
10: keyword.operator.colon.elixir
11: keyword.operator.pin.elixir
12: keyword.operator.logical.elixir
13: keyword.operator.ellipsis.elixir
14: keyword.operator.range.elixir
15: keyword.operator.regex.elixir
16: keyword.operator.default.elixir
17: keyword.operator.bitwise.elixir
18: keyword.operator.reserved.elixir
19: keyword.operator.list-diff.elixir
20: keyword.operator.semicolon.elixir
cons_operator:
- match: \|(?![:|>])
scope: keyword.operator.cons.elixir
dot_operator:
- match: \.(?!\.)
scope: punctuation.accessor.dot.elixir
tuple:
- match: \}
scope: invalid.illegal.stray-closing-brace.elixir
- match: \{
scope: punctuation.section.sequence.begin.elixir
push:
- meta_scope: meta.sequence.tuple.elixir
- match: \}
scope: punctuation.section.sequence.end.elixir
pop: 1
- include: core_syntax_or_if_closing_pop
item_access:
- match: |
(?x)
(?<=["'\w\])}]|\w[?!]|%>)
(?<!\bdo|\bwhen|\band|\bin|\belse|\bafter|\bor|\brescue|\bnot|\bcatch)
\[
scope: punctuation.section.access.begin.elixir
push:
- meta_scope: meta.access.elixir
- match: \]
scope: punctuation.section.access.end.elixir
pop: 1
- include: core_syntax_or_if_closing_pop
list:
- match: \]
scope: invalid.illegal.stray-closing-bracket.elixir
- match: \[
scope: punctuation.section.brackets.begin.elixir
push:
- meta_scope: meta.brackets.elixir
- match: \]
scope: punctuation.section.brackets.end.elixir
pop: 1
- include: cons_operator
- include: core_syntax_or_if_closing_pop
map:
- match: \%
scope: punctuation.section.mapping.begin.elixir
push:
- meta_scope: meta.mapping.elixir
- match: (?=unquote\()
set: [map_body_pop, arguments_pop, unquote_pop]
- include: alias_names
- match: \^
scope: keyword.operator.pin.elixir
- match: ((?=_)(?<!%>){{identifier}})|({{identifier}})
captures:
1: variable.other.unused.elixir
2: variable.other.elixir
set: map_body_pop
- include: map_body_pop
map_body_pop:
- match: \{
scope: punctuation.section.mapping.begin.elixir
set:
- include: map_closing_pop
- include: cons_operator
- include: core_syntax_or_if_closing_pop
- include: if_closing_token_pop
- include: if_non_space_or_eol_pop
paren:
- match: (?<=%>)(?=\()
push: arguments_pop
- match: \)
scope: invalid.illegal.stray-closing-parenthesis.elixir
- match: \(
scope: punctuation.section.group.begin.elixir
push:
- meta_scope: meta.parens.elixir
- match: \)
scope: punctuation.section.group.end.elixir
pop: 1
- include: core_syntax_or_if_closing_pop
alias:
- match: (?>alias|require){{no_suffix_then_arguments}}
scope: keyword.control.import.elixir
push:
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_closing_pop
- include: alias_names
- match: (?=,)
set:
- include: alias_as_arg
- include: arguments_rest_pop
- include: core_syntax
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_ws_closing_pop
- match: ''
push:
- include: alias_names
- match: (?=,)
set:
- include: alias_as_arg
- include: arg_comma_and_skip_ws
- include: if_ws_closing_token_or_eol_pop
- include: core_syntax
- include: if_ws_closing_token_or_eol_pop
- include: core_syntax
alias_as_arg:
- match: as(:)(?!:)
scope: constant.other.keyword.elixir
captures:
1: punctuation.definition.constant.elixir
push: [alias_as_name_pop, invalid_comma_or_non_space_pop]
alias_as_name_pop:
- match: '{{module_name}}{{no_key_suffix}}'
scope: entity.name.namespace.elixir
- include: if_non_space_or_eol_pop
alias_names:
- match: |
(?x)(?=
(?:(?<=%>)\.)? (?>{{module_name}}{{no_key_suffix}} | __MODULE__{{no_id_key_suffix}})
| :(?>{{atom_symbol}}|['"])
)
push:
- include: module_name
- include: dot_accessor
- include: unquote_call_pop
- include: special_form
- include: atom_symbol
- include: if_non_space_or_eol_pop
atom_keyword:
- match: |
(?x)
(?! \?: | ::: | %:(?:{{atom_id}}|['"]) ) # No ::: and %:XYZ{} (it's a map)
(?>{{atom_symbol}}|(?<=%>)) (:) {{no_colon_suffix}}
comment: keyword symbol
scope: constant.other.keyword.elixir
captures:
1: punctuation.definition.constant.end.elixir
- match: (?x)(?=(["']) (?>\\. | (?!\1).)* \1:{{no_colon_suffix}})
comment: keyword string
push:
- match: (.)
scope: punctuation.definition.constant.begin.elixir
set:
- meta_scope: meta.string.elixir constant.other.keyword.elixir
- include: escaped_or_interpolated
- match: '\1:'
scope: punctuation.definition.constant.end.elixir
pop: 1
atom_symbol:
- match: :(?!:(?!:))
scope: constant.other.symbol.elixir punctuation.definition.constant.begin.elixir
push:
- match: (?=<%)|{{atom_symbol}}
scope: constant.other.symbol.elixir
pop: 1
- match: (["'])
scope: punctuation.definition.constant.begin.elixir
set:
- meta_scope: constant.other.symbol.quoted.elixir
- match: \1
scope: punctuation.definition.constant.end.elixir
pop: 1
- include: escaped_or_interpolated
- include: if_empty_pop
capture:
- match: (&)\s*(\d+)(?!\.(?![.\D]))
captures:
1: punctuation.definition.capture.elixir constant.other.capture.elixir
2: constant.other.capture.elixir
- match: \&
scope: keyword.operator.capture.elixir
push:
- match: (?=(?>do|fn|true|false|nil){{no_id_key_suffix}})
pop: 1
- include: if_closing_token_pop
- match: (?=\.(?!\.))
set:
- include: dot_operator
- include: arguments_pop
- include: capture_name_pop
- include: id_or_operator_call_pop
- include: quoted_remote_call_pop
- include: quoted_member_pop
- match: (?={{member}}{{no_id_key_suffix}})
push: id_member_pop
- include: tuple_call_pop
- include: if_closing_token_pop
- include: if_non_space_or_eol_pop
- include: capture_name_pop
- include: special_form
- match: (?={{identifier}}\s*\.(?!\.|\s*\())
push: identifier_pop
- include: if_non_space_or_eol_pop
capture_name_pop:
- match: |
(?x)(?=
(?>
{{module_name}}{{no_key_suffix}}
| :{{atom_symbol}}
| (?>:(["'])) (?>\\\\|\\\1|(?!\1).)*? (\1)
)
\s* (?!\. (?!\. | \s*\())
| (?>:{{atom_symbol}}) \s*\.\s* {{member}} \s*\(
)
comment: exit if module/atom is not followed by `.` or `.(`
pop: 1
- include: atom_symbol
- include: atom_keyword
- include: module_name
- include: unquote_call
- match: (/)\s*(\d+)(?!\.(?![.\D]))
captures:
1: punctuation.accessor.arity.elixir
2: constant.numeric.arity.elixir
pop: 1
- match: |
(?x)
(?>(/(?=/)|{{member}}) | (["'])((?>\\\\|\\\2|(?!\2).)*?)(\2))
(?=\s*(/)\s*(\d+)(?!\.(?![.\D])))
captures:
1: variable.other.capture.elixir
2: punctuation.definition.constant.begin.elixir
3: variable.other.capture.elixir
4: punctuation.definition.constant.end.elixir
sql_or_fragment:
- match: (?>(fragment)|(sql))(\()
captures:
1: support.function.elixir
2: variable.function.elixir
3: punctuation.section.arguments.begin.elixir
push:
- meta_scope: meta.function-call.arguments.elixir
- match: (?=unquote\()
set: [arguments_rest_pop, sql_unquote_pop, unquote_pop]
- include: sql_or_fragment_args_pop
sql_unquote_pop:
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: sql_or_fragment_args_pop
sql_or_fragment_args_pop:
- match: (?=")
set: [arguments_rest_pop, sql_string_pop]
- include: comment
- match: (?=\S)
set: arguments_rest_pop
sql_string_pop:
- match: (""")(.*)\n
captures:
1: string.quoted.triple.double.elixir punctuation.definition.string.begin.elixir
2: invalid.illegal.opening-heredoc.elixir
set:
- meta_scope: meta.string.elixir
- match: '"""'
scope: string.quoted.triple.double.elixir punctuation.definition.string.end.elixir
pop: 1
- match: ''
push: scope:source.ex.sql
with_prototype:
- match: (?=""")
pop: 1
- include: sql_or_elixir_escaped_pop
- match: \"
scope: string.quoted.double.elixir punctuation.definition.string.begin.elixir
set:
- meta_scope: meta.string.elixir
- match: \"
scope: string.quoted.double.elixir punctuation.definition.string.end.elixir
pop: 1
- match: ''
push: scope:source.ex.sql
with_prototype:
- match: (?=")
pop: 1
- include: sql_or_elixir_escaped_pop
sql_or_elixir_escaped_pop:
- include: interpolated_elixir
- include: line_continuation
- match: (?=\\(?!\\?\?))
push:
- meta_scope: source.ex.sql
- match: (?=\\\\?\?)
comment: let source.ex.sql match "\\?"
pop: 1
- include: escaped_char
- include: if_empty_pop
opaque_struct:
- match: '#(?={{module_name}}(?:\s*\.\s*{{module_name}})*<)'
scope: punctuation.section.mapping.elixir
comment: opaque struct
push:
- include: module_name
- include: dot_operator
- match: \<
scope: punctuation.section.mapping.begin.elixir
set:
- match: (?<=\S|^)\>
scope: punctuation.section.mapping.end.elixir
pop: 1
comment:
- match: \#
scope: punctuation.definition.comment.elixir
push:
- meta_scope: comment.line.number-sign.elixir
- match: \n
pop: 1
comments:
- match: (?=#)
push:
- include: comment
- include: if_non_space_pop
char_literal:
- match: (\?$)|(\?)(?>\\[\S\s]|\S|(\s))
comment: character literal as an integer
scope: constant.numeric.char.elixir
captures:
1: invalid.illegal.character-literal.elixir
2: punctuation.definition.numeric.elixir
3: invalid.illegal.character-literal.elixir
built_ins:
- match: |
(?x)(?> # Ordered by likeliness of occurrence.
is_(?>
binary|list|atom|integer|function|nil|map(?:_key)?|tuple|number
| boolean|float|bitstring|pid|exception|port|reference|struct
)
| inspect|to_string|elem|length|apply|self|byte_size|div|send|rem|put_(?>elem|in)
| (?>function|macro)_exported\?|update_in|binary_part|hd|struct!?|max|trunc|then
| to_charlist|get(?:_and_update)?_in|map_size|min|tl|node|make_ref|bit_size
| tuple_size|spawn(?>_link|_monitor)?|pop_in|abs|round|sum|floor|ceil|tap
){{no_suffix_then_arguments}}
scope: variable.function.built-in.elixir
push: arguments_paren_or_ws_pop
arguments_paren_or_ws_pop:
- include: arguments_pop
- match: ''
set: [arguments_ws_closing_or_empty_pop, arguments_ws_pop]
arguments_or_pop:
- match: '{{has_arguments}}'
set: arguments_paren_or_ws_pop
- include: if_empty_pop
arguments_pop:
- match: \(
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_rest_pop
arguments_closing_pop:
- match: \)
scope: punctuation.section.arguments.end.elixir
pop: 1
map_closing_pop:
- match: \}
scope: meta.mapping.elixir punctuation.section.mapping.end.elixir
pop: 1
arguments_rest_pop:
- include: arguments_closing_pop
- include: if_closing_token_pop
- include: arg_comma_and_skip_ws
- include: core_syntax
arguments_ws_closing_pop:
- match: |
(?x)
\n | \s? (?=\s*{{closing_token}})
| (?<=::\bend\b) | (?<=([^:])\bend\b) | (?<=^end\b)
scope: punctuation.section.arguments.end.elixir
pop: 1
arguments_ws_closing_or_empty_pop:
- include: arguments_ws_closing_pop
- include: if_empty_pop
arguments_ws:
- match: ''
push: arguments_ws_pop
arguments_ws_pop:
- match: \s?
comment: arguments list without parentheses
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- include: arguments_ws_rest_pop
arguments_ws_rest_pop:
- include: invalid_comma
- include: arg_comma_and_skip_ws
- match: (?=\?:\s*{{closing_token}})
set:
- include: char_literal
- include: if_ws_closing_token_or_eol_pop
- include: atom_keyword
- match: (?=(?>when|and|in|or|not){{no_id_key_suffix}})
push:
- include: if_closing_token_pop
- match: (?!(?>when|and|in|or|not){{no_id_key_suffix}}|[,\s]|(?<!,))
pop: 1
- include: elixir_keywords
- include: invalid_comma_or_non_space_pop
- match: (?x) (?=[-+*/=!|;] | && | \\\\ | ~(?![a-zA-Z]) | <(?!<(?!<)) | >(?!>(?!>)) | \.\.(?!\.) | ::(?!:))
push:
- include: if_closing_token_pop
- include: operator
- include: invalid_comma_or_non_space_pop
- match: (?<=[^:]:)\s
push: invalid_comma_or_non_space_pop
- include: do_block_pop
- include: fn_block
- include: if_ws_closing_token_or_eol_pop
- include: elixir_keywords
- include: special_form
- include: last_id_argument
- include: core_syntax
last_id_argument:
- match: |
(?x)(?=
(?>
(?:@\s*)?{{identifier}}
| \.\s*(?:{{member}} | "(?>\\[\\"]|.)*?" | '(?>\\[\\']|.)*?')
)
\s*do{{no_id_key_suffix}}
)
comment: prevent matching last argument as a function call, e.g. `func first, second, last do end`
push:
- match: (?=do{{no_id_key_suffix}})
pop: 1
- match: (@)\s*({{identifier}})
comment: reference
captures:
1: keyword.operator.attribute.elixir
2: variable.other.constant.elixir
- include: identifier_pop
- match: \.(?!\.)
scope: punctuation.accessor.dot.elixir
set:
- include: id_member_pop
- include: quoted_member_pop
- include: if_non_space_or_eol_pop
- include: if_non_space_or_eol_pop
special_form:
- match: __(?>MODULE|ENV|DIR|CALLER|STACKTRACE)__{{no_id_key_suffix}}
scope: variable.language.special-form.elixir
elixir_keywords:
- match: when\b(?![?!])
scope: keyword.operator.when.elixir
comment: for `when`-clauses that are placed below the function header
push:
- match: (?=(?><-|->)(?!:))
pop: 1
- include: arguments_ws_rest_pop
- match: |
(?x)(?> # Ordered by likeliness of occurrence.
# (do) | (fn) # Handled by do_block and fn_block.
# (when)
(true|false|nil)
| (and|in|or|not)
| (else)
| (after)
| (rescue)
| (catch)
| (end) # Normally in EEx: <% end %>
)\b(?![?!])
comment: fully reserved keywords
captures:
1: constant.language.elixir
2: keyword.operator.logical.elixir
3: keyword.control.conditional.else.elixir
4: keyword.control.exception.after.elixir
5: keyword.control.exception.rescue.elixir
6: keyword.control.exception.catch.elixir
7: keyword.context.block.end.elixir
case_macro_call:
- match: case(?!\(){{no_suffix_then_arguments}}
scope: keyword.control.conditional.elixir
push:
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- match: do{{no_id_key_suffix}}
scope: punctuation.section.block.begin.elixir keyword.context.block.do.elixir
push:
- meta_scope: meta.block.elixir
- include: arrow_clauses_body_pop
- include: last_arg_block_end_pop
- include: arguments_ws_rest_pop
one_left_arrow_clause:
- match: (?=\S)
push:
- match: (?=<-(?!:)|,|(?>when|do){{no_id_key_suffix}}|do:(?!:))
set:
- match: (?=,|do{{no_id_key_suffix}}|do:(?!:))
pop: 1
- include: arguments_ws_rest_pop
- include: parameters_or_if_closing_pop
with_macro_call:
- match: with(?!\(){{no_suffix_then_arguments}}
scope: keyword.control.conditional.elixir
push:
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- match: (?=do:(?!:))
set: [arguments_ws_closing_pop, arguments_ws_rest_pop]
- match: do{{no_id_key_suffix}}
scope: punctuation.section.block.begin.elixir keyword.context.block.do.elixir
set:
- meta_scope: meta.block.elixir
- match: else{{no_id_key_suffix}}
scope: keyword.control.conditional.else.elixir
push: arrow_clauses_body_pop
- include: last_arg_block_end_pop
- include: core_syntax
- include: arguments_ws_closing_pop
- include: arg_comma_and_skip_ws
- include: one_left_arrow_clause
for_macro_call:
- match: for(?!\(){{no_suffix_then_arguments}}
scope: keyword.control.loop.for.elixir
push:
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- match: (?=reduce:(?!:))
set:
- match: do{{no_id_key_suffix}}
scope: punctuation.section.block.begin.elixir keyword.context.block.do.elixir
set:
- meta_scope: meta.block.elixir
- include: last_arg_block_end_pop
- match: ''
push: arrow_clauses_body_pop
- include: arg_comma_and_skip_ws
- include: arguments_ws_rest_pop
- match: (?={{atom_symbol}}:(?!:))|(?<=[^:]:)
set: [arguments_ws_closing_pop, arguments_ws_rest_pop]
- include: arguments_ws_closing_pop
- include: arg_comma_and_skip_ws
- include: one_left_arrow_clause
try_macro_call:
- match: try(?!\(){{no_suffix_then_arguments}}
scope: keyword.control.exception.try.elixir
push:
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- match: do{{no_id_key_suffix}}
scope: punctuation.section.block.begin.elixir keyword.context.block.do.elixir
set:
- meta_scope: meta.block.elixir
- include: error_handling_clauses
- include: last_arg_block_end_pop
- include: core_syntax
- include: arguments_ws_closing_pop
- include: arg_comma_and_skip_ws
- include: core_syntax
receive_macro_call:
- match: receive(?!\(){{no_suffix_then_arguments}}
scope: keyword.control.loop.receive.elixir
push:
- match: \s?
scope: punctuation.section.arguments.begin.elixir
set:
- meta_scope: meta.function-call.arguments.elixir
- match: do{{no_id_key_suffix}}
scope: punctuation.section.block.begin.elixir keyword.context.block.do.elixir
set:
- meta_scope: meta.block.elixir
- match: after{{no_id_key_suffix}}
scope: keyword.control.exception.catch.elixir
push: arrow_clauses_body_pop
- include: last_arg_block_end_pop
- match: ''
push: arrow_clauses_body_pop
- include: arguments_ws_closing_pop
- include: arg_comma_and_skip_ws
- include: core_syntax
elixir_functions:
- include: unquote_call
- include: case_macro_call
- include: with_macro_call
- include: for_macro_call
- include: try_macro_call
- include: receive_macro_call
- match: |
(?x)(?> # Ordered by likeliness of occurrence.
(case|if|with|cond|unless)
| (use|import|require)
| (quote)
| (raise|reraise|throw)
| (for)
| (defstruct|defexception|defoverridable)
| (try)
| (receive)
| (exit)
| (super)
| (destructure)
){{no_suffix_then_arguments}}
captures:
1: keyword.control.conditional.elixir
2: keyword.control.import.elixir
3: keyword.other.quote.elixir
4: keyword.control.flow.throw.elixir
5: keyword.control.loop.for.elixir
6: keyword.declaration.elixir
7: keyword.control.exception.try.elixir
8: keyword.control.loop.receive.elixir
9: keyword.control.flow.exit.elixir
10: keyword.other.super.elixir
11: keyword.other.destructure.elixir
push: arguments_paren_or_ws_pop
- include: defrecord
unquote_pop:
- match: unquote(?:_splicing)?
scope: keyword.other.unquote.elixir
pop: 1
unquote_call_pop:
- match: (?=unquote(?:_splicing)?\()
set: [unquote_post_args_pop, arguments_pop, unquote_pop]
- match: (?=unquote(?:_splicing)?{{no_suffix_then_arguments}})
set: [arguments_ws_pop, unquote_pop]
unquote_post_args_pop:
- match: (?=\()
set: arguments_pop
- include: if_empty_pop
unquote_call:
- match: (?=unquote(?:_splicing)?{{no_suffix_then_arguments}})
push: unquote_call_pop
line_continuation:
- match: \\\n
scope: punctuation.separator.continuation.elixir
if_closing_token_pop:
- match: (?=[)}\]]|>>(?!>)|%>|{{closing_keyword}})
pop: 1
if_ws_closing_token_pop:
- match: (?=\s*(?>[)}\];]|>>(?!>)|%>|{{closing_keyword}}))
pop: 1
if_ws_closing_token_or_eol_pop:
- include: if_ws_closing_token_pop
- match: (?=\s*(?>#|$))
pop: 1
if_closing_paren_pop:
- match: (?=\))
pop: 1
if_non_space_pop:
- match: (?=\S)
pop: 1
if_non_space_or_eol_pop:
- match: (?=\S|$)
pop: 1
if_empty_pop:
- match: ''
pop: 1