Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
328 changes: 150 additions & 178 deletions elixir-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -208,193 +208,165 @@

(defvar elixir-mode--eval-filename "elixir-mode-tmp-eval-file.exs")

(defvar elixir-mode-define-names
'("def"
"defdelegate"
"defmacro"
"defmacrop"
"defoverridable"
"defp"
"defmacrop")
"Elixir mode def-like keywords.")
(defvar elixir-mode-keyword-names
'("->"
"bc"
"lc"
"in"
"inbits"
"inlist"
"quote"
"unquote"
"unquote_splicing"
"var"
"do"
"after"
"for"
"def"
"defdelegate"
"defimpl"
"defmacro"
"defmacrop"
"defmodule"
"defoverridable"
"defp"
"defprotocol"
"defrecord"
"defstruct"
"destructure"
"alias"
"require"
"import"
"use"
"if"
"unless"
"true"
"false"
"when"
"case"
"cond"
"throw"
"then"
"else"
"elsif"
"try"
"catch"
"rescue"
"fn"
"function"
"receive"
"end")
"Elixir mode keywords.")
(defvar elixir-mode-module-names
'("Agent"
"Base"
"Behavior"
"Binary"
"Bitwise"
"Builtin"
"Elixir"
"Code"
"EEx"
"Enum"
"ExUnit"
"Exception"
"File"
"GenServer"
"Function"
"GenServer"
"GenTCP"
"HashDict"
"IO"
"Keyword"
"List"
"Math"
"Module"
"Node"
"OptionParser"
"OrdDict"
"Port"
"Process"
"Record"
"Regexp"
"System"
"Task"
"Tuple"
"URI"
"UnboundMethod")
"Elixir mode modules.")
(defvar elixir-mode-builtin-names
'("Erlang"
"__MODULE__"
"__LINE__"
"__FILE__"
"__ENV__")
"Elixir mode builtins.")
(defvar elixir-mode-operator-names
'("+"
"++"
"<>"
"-"
"/"
"*"
"div"
"rem"
"=="
"!="
"<="
"<"
">="
">"
"==="
"!=="
"and"
"or"
"not"
"&&"
"||"
"!"
"."
"#"
"="
":="
"<-")
"Elixir mode operators.")

(defvar elixir-mode-sigils '("B" "C" "R" "b" "c" "r")
"~-prefixed sigils that are understood by `elixir-mode'.")

(defvar elixir-basic-offset 2)
(defvar elixir-key-label-offset 0)
(defvar elixir-match-label-offset 2)

(defvar font-lock-operator-face 'font-lock-operator-face)
(defface font-lock-operator-face
'((((type tty) (class color)) nil)
(((class color) (background light))
(:foreground "darkred"))
(defvar elixir-operator-face 'elixir-operator-face)
(defface elixir-operator-face
'((((class color) (min-colors 88) (background light))
:foreground "darkred")
(((class color) (background dark))
(:foreground "lemonchiffon1"))
(t nil))
"For use with operators."
:group 'font-lock-faces)

(defconst elixir-mode-font-lock-defaults
(list
;; records and modules at point of definition:
'("^\\s *def\\(module\\|record\\|protocol\\|impl\\)\\s +\\([^( \t\n,]+\\)" 2 font-lock-type-face)

;; use/require/import:
'("^\\s *\\(use\\|require\\|import\\)\\s \\([^\n]+\\)" 2 font-lock-type-face)

;; methods:
`(,(concat "^\\s *\\<" (regexp-opt elixir-mode-define-names t) "\\>\\s +\\([^( \t\n]+\\)") 2 font-lock-function-name-face)

;; keywords:
`(,(concat "\\<" (regexp-opt elixir-mode-keyword-names t) "\\>") . font-lock-keyword-face)

;; ~ Sigils
`(,(concat "\\<~" (regexp-opt elixir-mode-sigils t) "\\>") . font-lock-builtin-face)

;; builtins:
`(,(concat "\\<" (regexp-opt elixir-mode-builtin-names t) "\\>") . font-lock-builtin-face)
(eval-when-compile
(defconst elixir-rx-constituents
`(
(keywords . ,(rx symbol-start
(or "->" "bc" "lc" "in" "inbits" "inlist" "quote"
"unquote" "unquote_splicing" "var" "do" "after" "for"
"def" "defdelegate" "defimpl" "defmacro" "defmacrop"
"defmodule" "defoverridable" "defp" "defprotocol"
"defrecord" "defstruct" "destructure" "alias"
"require" "import" "use" "if" "unless" "when" "case"
"cond" "throw" "then" "else" "elsif" "try" "catch"
"rescue" "fn" "function" "receive" "end")
symbol-end))
(imports . ,(rx symbol-start
(or "use" "require" "import")
symbol-end))
(bool-and-nil . ,(rx symbol-start
(or "true" "false" "nil")
symbol-end))
(builtins . ,(rx symbol-start
(or "Erlang" "__MODULE__" "__LINE__" "__FILE__"
"__ENV__" "__DIR__")
symbol-end))
(sigils . ,(rx "~" (or "B" "C" "R" "S" "b" "c" "r" "s" "w")))
(method-defines . ,(rx symbol-start
(or "def" "defdelegate" "defmacro" "defmacrop"
"defoverridable" "defp" "defmacrop")
symbol-end))
(module-defines . ,(rx symbol-start
(or "defmodule" "defprotocol" "defimpl"
"defrecord")
symbol-end))
(builtin-modules . ,(rx symbol-start
(or "Agent" "Base" "Behavior" "Binary" "Bitwise"
"Builtin" "Elixir" "Code" "EEx" "Enum"
"ExUnit" "Exception" "File" "GenServer"
"Function" "GenServer" "GenTCP" "HashDict"
"IO" "Keyword" "List" "Math" "Module" "Node"
"OptionParser" "OrdDict" "Port" "Process"
"Record" "Regexp" "System" "Task" "Tuple"
"URI" "UnboundMethod")
symbol-end))
(operators . ,(rx symbol-start
(or "+" "++" "<>" "-" "/" "*" "div" "rem" "==" "!=" "<="
"<" ">=" ">" "===" "!==" "and" "or" "not" "&&" "||"
"!" "." "#" "=" ":=" "<-")))
(resource-name . ,(rx symbol-start
(zero-or-more (any "A-Z")
(zero-or-more
(any "a-z"))
"."
(any "A-Z")
(zero-or-more
(any "a-z")))
symbol-end))
(variables . ,(rx symbol-start
(one-or-more (any "A-Z" "a-z" "0-9" "_"))
symbol-end))
(atoms . ,(rx ":"
(or
(one-or-more (any "a-z" "A-Z" "0-9" "_"))
(and "\"" (one-or-more (not (any "\""))) "\"")
(and "'" (one-or-more (not (any "'"))) "'"))))
(code-point . ,(rx "?" anything))))

(defmacro elixir-rx (&rest sexps)
(let ((rx-constituents (append elixir-rx-constituents rx-constituents)))
(cond ((null sexps)
(error "No regexp"))
((cdr sexps)
(rx-to-string `(and ,@sexps) t))
(t
(rx-to-string (car sexps) t))))))

;; core modules:
`(,(concat "\\<" (regexp-opt elixir-mode-module-names t) "\\>") . font-lock-type-face)

;; operators:
(when elixir-mode-highlight-operators
`(,(concat "\\<" (regexp-opt elixir-mode-operator-names t) "\\>") . font-lock-operator-face))

;; variables:
'("\\(\\w+\\)\\s-*:?=[^=]" 1 font-lock-variable-name-face)

;; regexes:
'("~r/\\(.*\\)/[, \n\t]*" 1 font-lock-string-face)

;; atoms, boolean:
'("\\<\\(true\\|false\\|nil\\)\\>" . font-lock-reference-face)

;; atoms, generic
'("[@:]\\w*\\|\\w*:\\s-" . font-lock-reference-face))
"Highlighting for Elixir mode.")
(defconst elixir-mode-font-lock-defaults
`(
;; Import, module- and method-defining keywords
(,(elixir-rx (or method-defines module-defines imports)
space
(group resource-name))
1 font-lock-type-face)

;; Keywords
(,(elixir-rx (group keywords))
1 font-lock-keyword-face)

;; Method names, i.e. `def foo do'
(,(elixir-rx method-defines
space
(group (one-or-more (any "a-z" "_"))))
1 font-lock-function-name-face)

;; Variable definitions
(,(elixir-rx (group variables)
(one-or-more space)
"="
(one-or-more space))
1 font-lock-variable-name-face)

;; Built-in constants
(,(elixir-rx (group builtins))
1 font-lock-builtin-face)

;; Sigils
(,(elixir-rx (group sigils))
1 font-lock-builtin-face)

;; Regex patterns. Elixir has support for eight different regex delimiters.
;; This isn't a very DRY approach here but it gets the job done.
(,(elixir-rx "~r"
(and "/" (group (one-or-more (not (any "/")))) "/"))
1 font-lock-string-face)
(,(elixir-rx "~r"
(and "[" (group (one-or-more (not (any "]")))) "]"))
1 font-lock-string-face)
(,(elixir-rx "~r"
(and "{" (group (one-or-more (not (any "}")))) "}"))
1 font-lock-string-face)
(,(elixir-rx "~r"
(and "(" (group (one-or-more (not (any ")")))) ")"))
1 font-lock-string-face)
(,(elixir-rx "~r"
(and "|" (group (one-or-more (not (any "|")))) "|"))
1 font-lock-string-face)
(,(elixir-rx "~r"
(and "\"" (group (one-or-more (not (any "\"")))) "\""))
1 font-lock-string-face)
(,(elixir-rx "~r"
(and "'" (group (one-or-more (not (any "'")))) "'"))
1 font-lock-string-face)
(,(elixir-rx "~r"
(and "<" (group (one-or-more (not (any ">")))) ">"))
1 font-lock-string-face)

;; Built-in modules
(,(elixir-rx (group builtin-modules))
1 font-lock-constant-face)

;; Operators
(,(elixir-rx (group operators))
1 elixir-operator-face)

;; Atoms and singleton-like words like true/false/nil.
(,(elixir-rx (group (or atoms bool-and-nil)))
1 font-lock-reference-face)))

(defun elixir-mode-cygwin-path (expanded-file-name)
"Elixir mode get Cygwin absolute path name.
Expand Down
34 changes: 17 additions & 17 deletions elixir-smie.el
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@
"Emit context information about the current syntax state.")

(defvar elixir-mode-syntax-table
(let ((elixir-mode-syntax-table (make-syntax-table)))
(let ((table (make-syntax-table)))

;; Note that ?_ might be better as class "_", but either seems to
;; work:
(modify-syntax-entry ?_ "w" elixir-mode-syntax-table)
(modify-syntax-entry ?? "w" elixir-mode-syntax-table)
(modify-syntax-entry ?~ "w" elixir-mode-syntax-table)
(modify-syntax-entry ?_ "w" table)
(modify-syntax-entry ?? "w" table)
(modify-syntax-entry ?~ "w" table)

(modify-syntax-entry ?' "\"'" elixir-mode-syntax-table)
(modify-syntax-entry ?\" "\"\"" elixir-mode-syntax-table)
(modify-syntax-entry ?# "<" elixir-mode-syntax-table)
(modify-syntax-entry ?\n ">" elixir-mode-syntax-table)
(modify-syntax-entry ?\( "()" elixir-mode-syntax-table)
(modify-syntax-entry ?\) ")(" elixir-mode-syntax-table)
(modify-syntax-entry ?\{ "(}" elixir-mode-syntax-table)
(modify-syntax-entry ?\} "){" elixir-mode-syntax-table)
(modify-syntax-entry ?\[ "(]" elixir-mode-syntax-table)
(modify-syntax-entry ?\] ")[" elixir-mode-syntax-table)
(modify-syntax-entry ?\: "'" elixir-mode-syntax-table)
(modify-syntax-entry ?\@ "'" elixir-mode-syntax-table)
elixir-mode-syntax-table)
(modify-syntax-entry ?' "\"'" table)
(modify-syntax-entry ?\" "\"\"" table)
(modify-syntax-entry ?# "<" table)
(modify-syntax-entry ?\n ">" table)
(modify-syntax-entry ?\( "()" table)
(modify-syntax-entry ?\) ")(" table)
(modify-syntax-entry ?\{ "(}" table)
(modify-syntax-entry ?\} "){" table)
(modify-syntax-entry ?\[ "(]" table)
(modify-syntax-entry ?\] ")[" table)
(modify-syntax-entry ?\: "'" table)
(modify-syntax-entry ?\@ "'" table)
table)
"Elixir mode syntax table.")

(defun elixir-syntax-propertize (start end)
Expand Down