Skip to content

Commit 2a9fcd0

Browse files
committed
Add syntax highlighting and imenu support for union
`union` is a contextual keyword, so highlight it in the correct context. Otherwise, treat `union` similarly to `struct`.
1 parent 09efc45 commit 2a9fcd0

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

rust-mode-tests.el

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,19 @@ this_is_not_a_string();)"
15511551
"fn" font-lock-keyword-face
15521552
"f" font-lock-function-name-face)))
15531553

1554+
(ert-deftest rust-test-union-context-sensitive ()
1555+
(rust-test-font-lock
1556+
"let union = 7; union foo { x: &'union bar }"
1557+
'("let" font-lock-keyword-face
1558+
;; Ignore the first union, it's an unhighlighted variable.
1559+
;; The second union is a contextual keyword.
1560+
"union" font-lock-keyword-face
1561+
"foo" font-lock-type-face
1562+
"x" font-lock-variable-name-face
1563+
;; This union is the name of a lifetime.
1564+
"union" font-lock-variable-name-face
1565+
"bar" font-lock-type-face)))
1566+
15541567
(ert-deftest indent-method-chains-no-align ()
15551568
(let ((rust-indent-method-chain nil)) (test-indent
15561569
"

rust-mode.el

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,18 @@
3939
(defconst rust-re-vis "pub")
4040
(defconst rust-re-unsafe "unsafe")
4141
(defconst rust-re-extern "extern")
42+
(defconst rust-re-union
43+
(rx-to-string
44+
`(seq
45+
(or space line-start)
46+
(group symbol-start "union" symbol-end)
47+
(+ space) (regexp ,rust-re-ident))))
4248

4349
;;; Start of a Rust item
4450
(defvar rust-top-item-beg-re
4551
(concat "\\s-*\\(?:priv\\|pub\\)?\\s-*"
4652
(regexp-opt
47-
'("enum" "struct" "type" "mod" "use" "fn" "static" "impl"
53+
'("enum" "struct" "union" "type" "mod" "use" "fn" "static" "impl"
4854
"extern" "trait"))
4955
"\\_>"))
5056

@@ -577,9 +583,12 @@ the desired identifiers), but does not match type annotations \"foo::<\"."
577583
(append
578584
`(
579585
;; Keywords proper
580-
("\\_<\\(default\\)[[:space:]]+fn\\_>" 1 font-lock-keyword-face)
581586
(,(regexp-opt rust-mode-keywords 'symbols) . font-lock-keyword-face)
582587

588+
;; Contextual keywords
589+
("\\_<\\(default\\)[[:space:]]+fn\\_>" 1 font-lock-keyword-face)
590+
(,rust-re-union 1 font-lock-keyword-face)
591+
583592
;; Special types
584593
(,(regexp-opt rust-special-types 'symbols) . font-lock-type-face)
585594

@@ -613,12 +622,13 @@ the desired identifiers), but does not match type annotations \"foo::<\"."
613622
("\\?" . 'rust-question-mark-face)
614623
)
615624

616-
;; Item definitions
625+
;; Ensure we highlight `Foo` in `struct Foo` as a type.
617626
(mapcar #'(lambda (x)
618627
(list (rust-re-item-def (car x))
619628
1 (cdr x)))
620629
'(("enum" . font-lock-type-face)
621630
("struct" . font-lock-type-face)
631+
("union" . font-lock-type-face)
622632
("type" . font-lock-type-face)
623633
("mod" . font-lock-constant-face)
624634
("use" . font-lock-constant-face)
@@ -671,7 +681,7 @@ the desired identifiers), but does not match type annotations \"foo::<\"."
671681
(rust-rewind-irrelevant)
672682
(rust-rewind-type-param-list)
673683
(cond
674-
((rust-looking-back-symbols '("fn" "trait" "enum" "struct" "impl" "type")) ident-pos)
684+
((rust-looking-back-symbols '("fn" "trait" "enum" "struct" "union" "impl" "type")) ident-pos)
675685

676686
((equal 5 (rust-syntax-class-before-point))
677687
(backward-sexp)
@@ -758,7 +768,7 @@ the desired identifiers), but does not match type annotations \"foo::<\"."
758768
(not (and (rust-rewind-to-decl-name)
759769
(progn
760770
(rust-rewind-irrelevant)
761-
(rust-looking-back-symbols '("enum" "struct" "trait" "type"))))))
771+
(rust-looking-back-symbols '("enum" "struct" "union" "trait" "type"))))))
762772
))
763773

764774
((equal token 'ambiguous-operator)
@@ -1167,7 +1177,7 @@ raw string, or to `end', whichever comes first."
11671177
(defvar rust-imenu-generic-expression
11681178
(append (mapcar #'(lambda (x)
11691179
(list (capitalize x) (rust-re-item-def-imenu x) 1))
1170-
'("enum" "struct" "type" "mod" "fn" "trait" "impl"))
1180+
'("enum" "struct" "union" "type" "mod" "fn" "trait" "impl"))
11711181
`(("Macro" ,(rust-re-item-def-imenu "macro_rules!") 1)))
11721182
"Value for `imenu-generic-expression' in Rust mode.
11731183
@@ -1242,7 +1252,7 @@ This is written mainly to be used as `end-of-defun-function' for Rust."
12421252
(error "Rustfmt failed, see *rustfmt* buffer for details"))))
12431253
(delete-file tmpf))))
12441254

1245-
(defconst rust--format-word "\\b\\(else\\|enum\\|fn\\|for\\|if\\|let\\|loop\\|match\\|struct\\|unsafe\\|while\\)\\b")
1255+
(defconst rust--format-word "\\b\\(else\\|enum\\|fn\\|for\\|if\\|let\\|loop\\|match\\|struct\\|union\\|unsafe\\|while\\)\\b")
12461256
(defconst rust--format-line "\\([\n]\\)")
12471257

12481258
;; Counts number of matches of regex beginning up to max-beginning,

0 commit comments

Comments
 (0)