; Punctuation [ "%" ] @punctuation [ "," ";" ] @punctuation.delimiter [ "(" ")" "[" "]" "{" "}" "<<" ">>" ] @punctuation.bracket ; Literals [ (boolean) (nil) ] @constant [ (integer) (float) ] @number (char) @constant ; Identifiers ; * regular (identifier) @variable ; * unused ( (identifier) @comment.unused (#match? @comment.unused "^_") ) ; * special ( (identifier) @constant.builtin (#match? @constant.builtin "^(__MODULE__|__DIR__|__ENV__|__CALLER__|__STACKTRACE__)$") ) ; Comment (comment) @comment ; Quoted content (interpolation "#{" @punctuation.special "}" @punctuation.special) @embedded (escape_sequence) @string.escape [ (string) (charlist) ] @string [ (atom) (quoted_atom) (keyword) (quoted_keyword) ] @string.special.symbol ; Note that we explicitly target sigil quoted start/end, so they are not overridden by delimiters (sigil (sigil_name) @__name__ quoted_start: _ @string.special quoted_end: _ @string.special) @string.special (sigil (sigil_name) @__name__ quoted_start: _ @string quoted_end: _ @string (#match? @__name__ "^[sS]$")) @string (sigil (sigil_name) @__name__ quoted_start: _ @string.regex quoted_end: _ @string.regex (#match? @__name__ "^[rR]$")) @string.regex ; Calls ; * local function call (call target: (identifier) @function) ; * remote function call (call target: (dot right: (identifier) @function)) ; * field without parentheses or block (call target: (dot right: (identifier) @property) .) ; * remote call without parentheses or block (overrides above) (call target: (dot left: [ (alias) (atom) ] right: (identifier) @function) .) ; * definition keyword (call target: (identifier) @keyword (#match? @keyword "^(def|defdelegate|defexception|defguard|defguardp|defimpl|defmacro|defmacrop|defmodule|defn|defnp|defoverridable|defp|defprotocol|defstruct)$")) ; * kernel or special forms keyword (call target: (identifier) @keyword (#match? @keyword "^(alias|case|cond|for|if|import|quote|raise|receive|require|reraise|super|throw|try|unless|unquote|unquote_splicing|use|with)$")) ; * just identifier in function definition (call target: (identifier) @keyword (arguments [ (identifier) @function (binary_operator left: (identifier) @function operator: "when") ]) (#match? @keyword "^(def|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defp)$")) ; * pipe into identifier (function call) (binary_operator operator: "|>" right: (identifier) @function) ; * pipe into identifier (definition) (call target: (identifier) @keyword (arguments (binary_operator operator: "|>" right: (identifier) @variable)) (#match? @keyword "^(def|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defp)$")) ; * pipe into field without parentheses (function call) (binary_operator operator: "|>" right: (call target: (dot right: (identifier) @function))) ; Operators ; * capture operand (unary_operator operator: "&" operand: (integer) @operator) (operator_identifier) @operator (unary_operator operator: _ @operator) (binary_operator operator: _ @operator) (dot operator: _ @operator) (stab_clause operator: _ @operator) ; * module attribute (unary_operator operator: "@" @attribute operand: [ (identifier) @attribute (call target: (identifier) @attribute) (boolean) @attribute (nil) @attribute ]) ; * doc string (unary_operator operator: "@" @comment.doc operand: (call target: (identifier) @comment.doc.__attribute__ (arguments [ (string) @comment.doc (charlist) @comment.doc (sigil quoted_start: _ @comment.doc quoted_end: _ @comment.doc) @comment.doc (boolean) @comment.doc ])) (#match? @comment.doc.__attribute__ "^(moduledoc|typedoc|doc)$")) ; Module (alias) @module (call target: (dot left: (atom) @module)) ; Reserved keywords ["when" "and" "or" "not" "in" "not in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword