|
10 | 10 |
|
11 | 11 | ;;; Code:
|
12 | 12 |
|
13 |
| -(eval-when-compile (require 'misc)) |
| 13 | +(eval-when-compile (require 'misc) |
| 14 | + (require 'rx)) |
14 | 15 |
|
15 | 16 | ;; for GNU Emacs < 24.3
|
16 | 17 | (eval-when-compile
|
|
51 | 52 |
|
52 | 53 | table))
|
53 | 54 |
|
54 |
| -(defvar rust-mode-inside-raw-string-syntax-table |
55 |
| - (let ((table (make-syntax-table rust-mode-syntax-table))) |
56 |
| - (modify-syntax-entry ?\" "_" table) |
57 |
| - (modify-syntax-entry ?\\ "_" table) |
58 |
| - |
59 |
| - table)) |
60 |
| - |
61 | 55 | (defgroup rust-mode nil
|
62 | 56 | "Support for Rust code."
|
63 | 57 | :link '(url-link "http://www.rust-lang.org/")
|
|
318 | 312 | ("fn" . font-lock-function-name-face)
|
319 | 313 | ("static" . font-lock-constant-face)))))
|
320 | 314 |
|
| 315 | +(defun rust-look-for-raw-string (bound) |
| 316 | + ;; Find a raw string, but only if it's not in the middle of another string or |
| 317 | + ;; a comment |
| 318 | + |
| 319 | + (let* ((raw-str-regexp |
| 320 | + (rx |
| 321 | + (seq |
| 322 | + ;; The "r" starts the raw string. Capture it as group 1 to mark it as such syntactically: |
| 323 | + (group "r") |
| 324 | + |
| 325 | + ;; Then either: |
| 326 | + (or |
| 327 | + ;; a sequence at least one "#" (followed by quote). Capture all |
| 328 | + ;; but the last "#" as group 2 for this case. |
| 329 | + (seq (group (* "#")) "#\"") |
| 330 | + |
| 331 | + ;; ...or a quote without any "#". Capture it as group 3. This is |
| 332 | + ;; used later to match the opposite quote only if this capture |
| 333 | + ;; occurred |
| 334 | + (group "\"")) |
| 335 | + |
| 336 | + ;; The contents of the string: |
| 337 | + (*? anything) |
| 338 | + |
| 339 | + ;; If there are any backslashes at the end of the string, capture |
| 340 | + ;; them as group 4 so we can suppress the normal escape syntax |
| 341 | + ;; parsing: |
| 342 | + (group (* "\\")) |
| 343 | + |
| 344 | + ;; Then the end of the string--the backreferences ensure that we |
| 345 | + ;; only match the kind of ending that corresponds to the beginning |
| 346 | + ;; we had: |
| 347 | + (or |
| 348 | + ;; There were "#"s - capture the last one as group 5 to mark it as |
| 349 | + ;; the end of the string: |
| 350 | + (seq "\"" (backref 2) (group "#")) |
| 351 | + |
| 352 | + ;; No "#"s - capture the ending quote (using a backref to group 3, |
| 353 | + ;; so that we can't match a quote if we had "#"s) as group 6 |
| 354 | + (group (backref 3)))))) |
| 355 | + ;; If it matches, it ends up with the starting character of the string |
| 356 | + ;; as group 1, any ending backslashes as group 4, and the ending |
| 357 | + ;; character as either group 5 or group 6. |
| 358 | + |
| 359 | + (ret-list (save-excursion |
| 360 | + (let* ((match-end (re-search-forward raw-str-regexp bound t)) |
| 361 | + (ret-list (and match-end (list match-end (match-beginning 0) (match-data) (point))))) |
| 362 | + (when (and ret-list |
| 363 | + (save-excursion |
| 364 | + (goto-char (nth 1 ret-list)) |
| 365 | + (not (rust-in-str-or-cmnt)))) |
| 366 | + ret-list))))) |
| 367 | + (when ret-list |
| 368 | + (goto-char (nth 3 ret-list)) |
| 369 | + (set-match-data (nth 2 ret-list)) |
| 370 | + (nth 0 ret-list)))) |
| 371 | + |
321 | 372 | (defvar rust-mode-font-lock-syntactic-keywords
|
322 | 373 | (append
|
323 | 374 | ;; Handle single quoted character literals:
|
|
328 | 379 | "\\('\\)\\\\u[[:xdigit:]]\\{4\\}\\('\\)"
|
329 | 380 | "\\('\\)\\\\U[[:xdigit:]]\\{8\\}\\('\\)"))
|
330 | 381 | ;; Handle raw strings:
|
331 |
| - `(("\\(r\\)\"\\([^\"]*\\)\\(\"\\)" (1 "|") (2 ,rust-mode-inside-raw-string-syntax-table) (3 "|")) |
332 |
| - ("\\(r\\)#\\(#*\\)\\(\"[^#]*\"\\2\\)\\(#\\)" (1 "|") (3 ,rust-mode-inside-raw-string-syntax-table) (4 "|"))))) |
| 382 | + `((rust-look-for-raw-string (1 "|") (4 "_" nil t) (5 "|" nil t) (6 "|" nil t))))) |
333 | 383 |
|
334 | 384 | (defun rust-fill-prefix-for-comment-start (line-start)
|
335 | 385 | "Determine what to use for `fill-prefix' based on what is at the beginning of a line."
|
|
0 commit comments