|
1 |
| -;;; rust-mode.el --- A major emacs mode for editing Rust source code |
| 1 | +;;; rust-mode.el --- A major emacs mode for editing Rust source code -*-lexical-binding: t-*- |
2 | 2 |
|
3 | 3 | ;; Version: 0.2.0
|
4 | 4 | ;; Author: Mozilla
|
|
11 | 11 | ;;; Code:
|
12 | 12 |
|
13 | 13 | (eval-when-compile (require 'misc)
|
14 |
| - (require 'rx)) |
| 14 | + (require 'rx) |
| 15 | + (require 'compile) |
| 16 | + (require 'url-vars)) |
| 17 | + |
| 18 | +(defvar electric-pair-inhibit-predicate) |
15 | 19 |
|
16 | 20 | ;; for GNU Emacs < 24.3
|
17 | 21 | (eval-when-compile
|
|
20 | 24 | "Set variable VAR to value VAL in current buffer."
|
21 | 25 | (list 'set (list 'make-local-variable (list 'quote var)) val))))
|
22 | 26 |
|
| 27 | +(defconst rust-re-ident "[[:word:][:multibyte:]_][[:word:][:multibyte:]_[:digit:]]*") |
| 28 | + |
| 29 | +(defconst rust-re-non-standard-string |
| 30 | + (rx |
| 31 | + (or |
| 32 | + ;; Raw string: if it matches, it ends up with the starting character |
| 33 | + ;; of the string as group 1, any ending backslashes as group 4, and |
| 34 | + ;; the ending character as either group 5 or group 6. |
| 35 | + (seq |
| 36 | + ;; The "r" starts the raw string. Capture it as group 1 to mark it as such syntactically: |
| 37 | + (group "r") |
| 38 | + |
| 39 | + ;; Then either: |
| 40 | + (or |
| 41 | + ;; a sequence at least one "#" (followed by quote). Capture all |
| 42 | + ;; but the last "#" as group 2 for this case. |
| 43 | + (seq (group (* "#")) "#\"") |
| 44 | + |
| 45 | + ;; ...or a quote without any "#". Capture it as group 3. This is |
| 46 | + ;; used later to match the opposite quote only if this capture |
| 47 | + ;; occurred |
| 48 | + (group "\"")) |
| 49 | + |
| 50 | + ;; The contents of the string: |
| 51 | + (*? anything) |
| 52 | + |
| 53 | + ;; If there are any backslashes at the end of the string, capture |
| 54 | + ;; them as group 4 so we can suppress the normal escape syntax |
| 55 | + ;; parsing: |
| 56 | + (group (* "\\")) |
| 57 | + |
| 58 | + ;; Then the end of the string--the backreferences ensure that we |
| 59 | + ;; only match the kind of ending that corresponds to the beginning |
| 60 | + ;; we had: |
| 61 | + (or |
| 62 | + ;; There were "#"s - capture the last one as group 5 to mark it as |
| 63 | + ;; the end of the string: |
| 64 | + (seq "\"" (backref 2) (group "#")) |
| 65 | + |
| 66 | + ;; No "#"s - capture the ending quote (using a backref to group 3, |
| 67 | + ;; so that we can't match a quote if we had "#"s) as group 6 |
| 68 | + (group (backref 3)) |
| 69 | + |
| 70 | + ;; If the raw string wasn't actually closed, go all the way to the end |
| 71 | + string-end)) |
| 72 | + |
| 73 | + ;; Character literal: match the beginning ' of a character literal |
| 74 | + ;; as group 7, and the ending one as group 8 |
| 75 | + (seq |
| 76 | + (group "'") |
| 77 | + (or |
| 78 | + (seq |
| 79 | + "\\" |
| 80 | + (or |
| 81 | + (: "U" (= 8 xdigit)) |
| 82 | + (: "u" (= 4 xdigit)) |
| 83 | + (: "x" (= 2 xdigit)) |
| 84 | + (any "'nrt0\"\\"))) |
| 85 | + (not (any "'\\")) |
| 86 | + ) |
| 87 | + (group "'")) |
| 88 | + ) |
| 89 | + )) |
| 90 | + |
23 | 91 | (defun rust-looking-back-str (str)
|
24 | 92 | "Like `looking-back' but for fixed strings rather than regexps (so that it's not so slow)"
|
25 | 93 | (let ((len (length str)))
|
|
145 | 213 | (backward-up-list)
|
146 | 214 | (back-to-indentation))))
|
147 | 215 |
|
148 |
| -(defconst rust-re-ident "[[:word:][:multibyte:]_][[:word:][:multibyte:]_[:digit:]]*") |
149 |
| - |
150 | 216 | (defun rust-align-to-method-chain ()
|
151 | 217 | (save-excursion
|
152 | 218 | ;; for method-chain alignment to apply, we must be looking at
|
|
420 | 486 | ("fn" . font-lock-function-name-face)
|
421 | 487 | ("static" . font-lock-constant-face)))))
|
422 | 488 |
|
| 489 | +(defvar font-lock-beg) |
| 490 | +(defvar font-lock-end) |
| 491 | + |
423 | 492 | (defun rust-font-lock-extend-region ()
|
424 | 493 | "Extend the region given by `font-lock-beg' and `font-lock-end'
|
425 | 494 | to include the beginning of a string or comment if it includes
|
|
490 | 559 | (set-match-data (nth 1 ret-list))
|
491 | 560 | (nth 0 ret-list))))
|
492 | 561 |
|
493 |
| -(defconst rust-re-non-standard-string |
494 |
| - (rx |
495 |
| - (or |
496 |
| - ;; Raw string: if it matches, it ends up with the starting character |
497 |
| - ;; of the string as group 1, any ending backslashes as group 4, and |
498 |
| - ;; the ending character as either group 5 or group 6. |
499 |
| - (seq |
500 |
| - ;; The "r" starts the raw string. Capture it as group 1 to mark it as such syntactically: |
501 |
| - (group "r") |
502 |
| - |
503 |
| - ;; Then either: |
504 |
| - (or |
505 |
| - ;; a sequence at least one "#" (followed by quote). Capture all |
506 |
| - ;; but the last "#" as group 2 for this case. |
507 |
| - (seq (group (* "#")) "#\"") |
508 |
| - |
509 |
| - ;; ...or a quote without any "#". Capture it as group 3. This is |
510 |
| - ;; used later to match the opposite quote only if this capture |
511 |
| - ;; occurred |
512 |
| - (group "\"")) |
513 |
| - |
514 |
| - ;; The contents of the string: |
515 |
| - (*? anything) |
516 |
| - |
517 |
| - ;; If there are any backslashes at the end of the string, capture |
518 |
| - ;; them as group 4 so we can suppress the normal escape syntax |
519 |
| - ;; parsing: |
520 |
| - (group (* "\\")) |
521 |
| - |
522 |
| - ;; Then the end of the string--the backreferences ensure that we |
523 |
| - ;; only match the kind of ending that corresponds to the beginning |
524 |
| - ;; we had: |
525 |
| - (or |
526 |
| - ;; There were "#"s - capture the last one as group 5 to mark it as |
527 |
| - ;; the end of the string: |
528 |
| - (seq "\"" (backref 2) (group "#")) |
529 |
| - |
530 |
| - ;; No "#"s - capture the ending quote (using a backref to group 3, |
531 |
| - ;; so that we can't match a quote if we had "#"s) as group 6 |
532 |
| - (group (backref 3)) |
533 |
| - |
534 |
| - ;; If the raw string wasn't actually closed, go all the way to the end |
535 |
| - string-end)) |
536 |
| - |
537 |
| - ;; Character literal: match the beginning ' of a character literal |
538 |
| - ;; as group 7, and the ending one as group 8 |
539 |
| - (seq |
540 |
| - (group "'") |
541 |
| - (or |
542 |
| - (seq |
543 |
| - "\\" |
544 |
| - (or |
545 |
| - (: "U" (= 8 xdigit)) |
546 |
| - (: "u" (= 4 xdigit)) |
547 |
| - (: "x" (= 2 xdigit)) |
548 |
| - (any "'nrt0\"\\"))) |
549 |
| - (not (any "'\\")) |
550 |
| - ) |
551 |
| - (group "'")) |
552 |
| - ) |
553 |
| - )) |
554 |
| - |
555 | 562 | (defun rust-look-for-non-standard-string (bound)
|
556 | 563 | ;; Find a raw string or character literal, but only if it's not in the middle
|
557 | 564 | ;; of another string or a comment.
|
|
769 | 776 | ;; Otherwise, if the ident: appeared with anything other than , or {
|
770 | 777 | ;; before it, it can't be part of a struct initializer and therefore
|
771 | 778 | ;; must be denoting a type.
|
772 |
| - nil |
| 779 | + (t nil) |
773 | 780 | ))
|
774 | 781 | ))
|
775 | 782 |
|
@@ -1096,7 +1103,7 @@ This is written mainly to be used as `end-of-defun-function' for Rust."
|
1096 | 1103 | (progn
|
1097 | 1104 | (goto-char (match-beginning 0))
|
1098 | 1105 | ;; Go to the closing brace
|
1099 |
| - (condition-case err |
| 1106 | + (condition-case nil |
1100 | 1107 | (forward-sexp)
|
1101 | 1108 | (scan-error
|
1102 | 1109 | ;; The parentheses are unbalanced; instead of being unable to fontify, just jump to the end of the buffer
|
@@ -1169,7 +1176,7 @@ This is written mainly to be used as `end-of-defun-function' for Rust."
|
1169 | 1176 | (error-or-warning "\\(?:[Ee]rror\\|\\([Ww]arning\\)\\)"))
|
1170 | 1177 | (let ((re (concat "^" file ":" start-line ":" start-col
|
1171 | 1178 | ": " end-line ":" end-col
|
1172 |
| - " \\(?:[Ee]rror\\|\\([Ww]arning\\)\\):"))) |
| 1179 | + " " error-or-warning ":"))) |
1173 | 1180 | (cons re '(1 (2 . 4) (3 . 5) (6)))))
|
1174 | 1181 | "Specifications for matching errors in rustc invocations.
|
1175 | 1182 | See `compilation-error-regexp-alist' for help on their format.")
|
|
0 commit comments