Skip to content

Commit 26c17f2

Browse files
committed
Merge pull request #91 from elixir-lang/lexeme-regex-updates
Updates to regexes for various lexemes
2 parents 5256ad2 + 6498fe3 commit 26c17f2

File tree

2 files changed

+126
-91
lines changed

2 files changed

+126
-91
lines changed

elixir-mode.el

Lines changed: 108 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -220,45 +220,49 @@
220220
(((class color) (background dark))
221221
(:foreground "#ff4500"))
222222
(t nil))
223-
"For use with escape characters."
223+
"For use with standalone \"?\" to indicate code point."
224224
:group 'font-lock-faces)
225225

226+
(defvar elixir-attribute-face 'elixir-attribute-face)
227+
(defface elixir-attribute-face
228+
'((((class color) (min-colors 88) (background light))
229+
:foreground "MediumPurple4")
230+
(((class color) (background dark))
231+
(:foreground "thistle"))
232+
(t nil))
233+
"For use with module attribute tokens."
234+
:group 'font-lock-faces)
235+
236+
(defvar elixir-atom-face 'elixir-atom-face)
237+
(defface elixir-atom-face
238+
'((((class color) (min-colors 88) (background light))
239+
:foreground "RoyalBlue4")
240+
(((class color) (background dark))
241+
(:foreground "light sky blue"))
242+
(t nil))
243+
"For use with atoms & map keys."
244+
:group 'font-lock-faces)
245+
246+
226247
(eval-when-compile
227248
(defconst elixir-rx-constituents
228249
`(
229-
;; Match `@doc' or `@moduledoc' syntax, with or without triple quotes.
230-
(heredocs . ,(rx symbol-start
231-
(or "@doc" "@moduledoc" "~s")
232-
symbol-end))
233-
(keywords . ,(rx symbol-start
234-
(or "->" "bc" "lc" "in" "inbits" "inlist" "quote"
235-
"unquote" "unquote_splicing" "var" "do" "after" "for"
236-
"def" "defdelegate" "defimpl" "defmacro" "defmacrop"
237-
"defmodule" "defoverridable" "defp" "defprotocol"
238-
"defrecord" "defstruct" "destructure" "alias"
239-
"require" "import" "use" "if" "unless" "when" "case"
240-
"cond" "throw" "then" "else" "elsif" "try" "catch"
241-
"rescue" "fn" "function" "receive" "end")
242-
symbol-end))
243-
(imports . ,(rx symbol-start
244-
(or "use" "require" "import")
245-
symbol-end))
246-
(bool-and-nil . ,(rx symbol-start
247-
(or "true" "false" "nil")
248-
symbol-end))
249-
(builtins . ,(rx symbol-start
250-
(or "_" "Erlang" "__MODULE__" "__LINE__" "__FILE__"
251-
"__ENV__" "__DIR__")
252-
symbol-end))
253-
(sigils . ,(rx "~" (or "B" "C" "R" "S" "b" "c" "r" "s" "w")))
254-
(method-defines . ,(rx symbol-start
255-
(or "def" "defdelegate" "defmacro" "defmacrop"
256-
"defoverridable" "defp" "defmacrop")
250+
(atoms . ,(rx ":"
251+
(or
252+
(one-or-more (any "a-z" "A-Z" "_" "\"" "'"))
253+
(and "\"" (one-or-more (not (any "\""))) "\"")
254+
(and "'" (one-or-more (not (any "'"))) "'"))))
255+
(builtin . ,(rx symbol-start
256+
(or "case" "cond" "for" "if" "unless" "try" "receive"
257+
"raise" "quote" "unquote" "unquote_splicing" "throw"
258+
"super")
257259
symbol-end))
258-
(module-defines . ,(rx symbol-start
259-
(or "defmodule" "defprotocol" "defimpl"
260-
"defrecord")
261-
symbol-end))
260+
(builtin-declaration . ,(rx symbol-start
261+
(or "def" "defp" "defmodule" "defprotocol"
262+
"defmacro" "defmacrop" "defdelegate"
263+
"defexception" "defstruct" "defimpl"
264+
"defcallback")
265+
symbol-end))
262266
(builtin-modules . ,(rx symbol-start
263267
(or "Agent" "Application" "Atom" "Base"
264268
"Behaviour" "Bitwise" "Builtin" "Code" "Dict"
@@ -278,10 +282,33 @@
278282
"Task.Supervisor" "Tuple" "URI"
279283
"UnboundMethod" "Version")
280284
symbol-end))
281-
(operators . ,(rx symbol-start
282-
(or "+" "++" "<>" "-" "/" "*" "div" "rem" "==" "!=" "<="
283-
"<" ">=" ">" "===" "!==" "and" "or" "not" "&&" "||"
284-
"!" "." "#" "=" ":=" "<-")))
285+
(builtin-namespace . ,(rx symbol-start
286+
(or "import" "require" "use" "alias")
287+
symbol-end))
288+
;; Set aside code point syntax for `elixir-negation-face'.
289+
(code-point . ,(rx symbol-start
290+
"?"
291+
anything
292+
symbol-end))
293+
(function-declaration . ,(rx symbol-start
294+
(or "def" "defp")
295+
symbol-end))
296+
;; Match `@doc' or `@moduledoc' syntax, with or without triple quotes.
297+
(heredocs . ,(rx symbol-start
298+
(or "@doc" "@moduledoc" "~s")
299+
symbol-end))
300+
;; The first character of an identifier must be a letter or an underscore.
301+
;; After that, they may contain any alphanumeric character + underscore.
302+
;; Additionally, the final character may be either `?' or `!'.
303+
(identifiers . ,(rx (one-or-more (any "A-Z" "a-z""_"))
304+
(zero-or-more (any "A-Z" "a-z" "0-9" "_"))
305+
(optional (or "?" "!"))))
306+
(keyword . ,(rx symbol-start
307+
(or "fn" "do" "end" "after" "else" "rescue" "catch")
308+
symbol-end))
309+
(keyword-operator . ,(rx symbol-start
310+
(or "not" "and" "or" "when" "in")
311+
symbol-end))
285312
;; Module and submodule names start with upper case letter or `_'. This
286313
;; can then be followed by any combination of alphanumeric chars + `_'.
287314
;; In turn, this can be followed by a `.' which begins the notation of
@@ -297,23 +324,25 @@
297324
(zero-or-more (any "A-Z" "a-z" "_" "0-9"))))
298325
(optional (or "!" "?"))
299326
symbol-end))
300-
;; The first character of an identifier must be a letter or an underscore.
301-
;; After that, they may contain any alphanumeric character + underscore.
302-
;; Additionally, the final character may be either `?' or `!'.
303-
(identifiers . ,(rx symbol-start
304-
(one-or-more (any "A-Z" "a-z""_"))
305-
(zero-or-more (any "A-Z" "a-z" "0-9" "_"))
306-
(optional (or "?" "!"))
327+
(operators1 . ,(rx symbol-start
328+
(or "<" ">" "+" "-" "*" "/" "!" "^" "&")
329+
symbol-end))
330+
(operators2 . ,(rx symbol-start
331+
(or
332+
"==" "!=" "<=" ">=" "&&" "||" "<>" "++" "--" "|>" "=~"
333+
"->" "<-" "|" "." "=")
334+
symbol-end))
335+
(operators3 . ,(rx symbol-start
336+
(or "<<<" ">>>" "|||" "&&&" "^^^" "~~~" "===" "!==")
337+
symbol-end))
338+
(pseudo-var . ,(rx symbol-start
339+
(or "_" "__MODULE__" "__DIR__" "__ENV__" "__CALLER__"
340+
"__block__" "__aliases__")
341+
symbol-end))
342+
(punctuation . ,(rx symbol-start
343+
(or "\\" "<<" ">>" "=>" "(" ")" ":" ";" "" "[" "]")
307344
symbol-end))
308-
(atoms . ,(rx ":"
309-
(or
310-
(one-or-more (any "a-z" "A-Z" "0-9" "_"))
311-
(and "\"" (one-or-more (not (any "\""))) "\"")
312-
(and "'" (one-or-more (not (any "'"))) "'"))))
313-
(code-point . ,(rx symbol-start
314-
"?"
315-
anything
316-
symbol-end))))
345+
(sigils . ,(rx "~" (or "B" "C" "R" "S" "b" "c" "r" "s" "w")))))
317346

318347
(defmacro elixir-rx (&rest sexps)
319348
(let ((rx-constituents (append elixir-rx-constituents rx-constituents)))
@@ -327,24 +356,26 @@
327356
(defconst elixir-mode-font-lock-defaults
328357
`(
329358
;; Module-defining & namespace builtins
330-
(,(elixir-rx (or module-defines imports)
359+
(,(elixir-rx (or builtin-declaration builtin-namespace)
331360
space
332361
(group module-names))
333362
1 font-lock-type-face)
334363

335-
;; Heredoc
336-
(,(elixir-rx (group heredocs))
337-
1 font-lock-builtin-face)
364+
;; Module attributes
365+
(,(elixir-rx (group (or heredocs
366+
(and "@" (1+ identifiers)))))
367+
1 elixir-attribute-face)
338368

339369
;; Keywords
340-
(,(elixir-rx (group keywords))
370+
(,(elixir-rx (group (or builtin builtin-declaration builtin-namespace
371+
keyword keyword-operator)))
341372
1 font-lock-keyword-face)
342373

343-
;; Method names, i.e. `def foo do'
344-
(,(elixir-rx method-defines
374+
;; Function names, i.e. `def foo do'.
375+
(,(elixir-rx (group function-declaration)
345376
space
346377
(group identifiers))
347-
1 font-lock-function-name-face)
378+
2 font-lock-function-name-face)
348379

349380
;; Variable definitions
350381
(,(elixir-rx (group identifiers)
@@ -353,10 +384,6 @@
353384
(one-or-more space))
354385
1 font-lock-variable-name-face)
355386

356-
;; Built-in constants
357-
(,(elixir-rx (group builtins))
358-
1 font-lock-builtin-face)
359-
360387
;; Sigils
361388
(,(elixir-rx (group sigils))
362389
1 font-lock-builtin-face)
@@ -367,38 +394,41 @@
367394
(and "/" (group (one-or-more (not (any "/")))) "/"))
368395
1 font-lock-string-face)
369396
(,(elixir-rx "~r"
370-
(and "[" (group (one-or-more (not (any "]")))) "]"))
397+
(and "[" (group (one-or-more (not (any "]")))) "]"))
371398
1 font-lock-string-face)
372399
(,(elixir-rx "~r"
373-
(and "{" (group (one-or-more (not (any "}")))) "}"))
400+
(and "{" (group (one-or-more (not (any "}")))) "}"))
374401
1 font-lock-string-face)
375402
(,(elixir-rx "~r"
376-
(and "(" (group (one-or-more (not (any ")")))) ")"))
403+
(and "(" (group (one-or-more (not (any ")")))) ")"))
377404
1 font-lock-string-face)
378405
(,(elixir-rx "~r"
379-
(and "|" (group (one-or-more (not (any "|")))) "|"))
406+
(and "|" (group (one-or-more (not (any "|")))) "|"))
380407
1 font-lock-string-face)
381408
(,(elixir-rx "~r"
382-
(and "\"" (group (one-or-more (not (any "\"")))) "\""))
409+
(and "\"" (group (one-or-more (not (any "\"")))) "\""))
383410
1 font-lock-string-face)
384411
(,(elixir-rx "~r"
385-
(and "'" (group (one-or-more (not (any "'")))) "'"))
412+
(and "'" (group (one-or-more (not (any "'")))) "'"))
386413
1 font-lock-string-face)
387414
(,(elixir-rx "~r"
388-
(and "<" (group (one-or-more (not (any ">")))) ">"))
415+
(and "<" (group (one-or-more (not (any ">")))) ">"))
389416
1 font-lock-string-face)
390417

391-
;; TODO: Figure out why atoms are not being colored with `reference-face'
392418
;; Atoms and singleton-like words like true/false/nil.
393-
(,(elixir-rx (or (group atoms) (group bool-and-nil)))
394-
1 font-lock-reference-face)
419+
(,(elixir-rx (group atoms))
420+
1 elixir-atom-face)
421+
422+
;; Map keys
423+
(,(elixir-rx (group (and (one-or-more identifiers) ":")))
424+
1 elixir-atom-face)
395425

396-
;; Built-in modules
397-
(,(elixir-rx (group builtin-modules))
426+
;; Built-in modules and pseudovariables
427+
(,(elixir-rx (group (or builtin-modules pseudo-var)))
398428
1 font-lock-constant-face)
399429

400430
;; Operators
401-
(,(elixir-rx (group operators))
431+
(,(elixir-rx (group (or operators1 operators2 operators3)))
402432
1 elixir-operator-face)
403433

404434
;; Code points

test/elixir-mode-font-tests.el

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -104,36 +104,41 @@ end"
104104
:tags '(fontification heredoc syntax-table)
105105
(elixir-test-with-temp-buffer
106106
"@doc \"\"\""
107-
(should (eq (elixir-test-face-at 1) 'font-lock-builtin-face))
108-
(should (eq (elixir-test-face-at 2) 'font-lock-builtin-face))
107+
(should (eq (elixir-test-face-at 1) 'elixir-attribute-face))
108+
(should (eq (elixir-test-face-at 2) 'elixir-attribute-face))
109109
(should (eq (elixir-test-face-at 6) 'font-lock-string-face))))
110110

111111
(ert-deftest elixir-mode-syntax-table/fontify-heredoc/2 ()
112112
:tags '(fontification heredoc syntax-table)
113113
(elixir-test-with-temp-buffer
114114
"@moduledoc \"\"\""
115-
(should (eq (elixir-test-face-at 1) 'font-lock-builtin-face))
116-
(should (eq (elixir-test-face-at 2) 'font-lock-builtin-face))
115+
(should (eq (elixir-test-face-at 1) 'elixir-attribute-face))
116+
(should (eq (elixir-test-face-at 2) 'elixir-attribute-face))
117117
(should (eq (elixir-test-face-at 12) 'font-lock-string-face))))
118118

119119
(ert-deftest elixir-mode-syntax-table/fontify-heredoc/3 ()
120120
:tags '(fontification heredoc syntax-table)
121121
(elixir-test-with-temp-buffer
122122
"~s\"\"\""
123-
(should (eq (elixir-test-face-at 1) 'font-lock-builtin-face))
124-
(should (eq (elixir-test-face-at 2) 'font-lock-builtin-face))
123+
(should (eq (elixir-test-face-at 1) 'elixir-attribute-face))
124+
(should (eq (elixir-test-face-at 2) 'elixir-attribute-face))
125125
(should (eq (elixir-test-face-at 3) 'font-lock-string-face))))
126126

127127
(ert-deftest elixir-mode-syntax-table/fontify-atoms ()
128128
:tags '(fontification atom syntax-table)
129129
(elixir-test-with-temp-buffer
130130
":oriole
131131
:andale"
132-
;; This is actually the wrong face. I thought I had set these up
133-
;; to use `font-lock-reference-face' but apparently not. See the
134-
;; TODO in `elixir-mode.el' on this.
135-
(should (eq (elixir-test-face-at 3) 'font-lock-constant-face))
136-
(should (eq (elixir-test-face-at 5) 'font-lock-constant-face))
137-
(should (eq (elixir-test-face-at 10) 'font-lock-constant-face))
138-
(should (eq (elixir-test-face-at 13) 'font-lock-constant-face))))
132+
(should (eq (elixir-test-face-at 3) 'elixir-atom-face))
133+
(should (eq (elixir-test-face-at 5) 'elixir-atom-face))
134+
(should (eq (elixir-test-face-at 10) 'elixir-atom-face))
135+
(should (eq (elixir-test-face-at 13) 'elixir-atom-face))))
139136

137+
(ert-deftest elixir-mode-syntax-table/fontify-map-keys ()
138+
:tags '(fontification map syntax-table)
139+
(elixir-test-with-temp-buffer
140+
"%{a: 1, b: 2}"
141+
(should (eq (elixir-test-face-at 3) 'elixir-atom-face))
142+
(should (eq (elixir-test-face-at 4) 'elixir-atom-face))
143+
(should (eq (elixir-test-face-at 9) 'elixir-atom-face))
144+
(should (eq (elixir-test-face-at 10) 'elixir-atom-face))))

0 commit comments

Comments
 (0)