Skip to content

Commit 5ed4675

Browse files
committed
Merge pull request #73 from MicahChalmer/raw-string-multiline-edit-fix
Fix multi-line raw strings when editing
2 parents 86db9bd + 9d773b4 commit 5ed4675

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

rust-mode-tests.el

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,24 @@ this_is_not_a_string();)"
10671067
"r\" this is a comment\n" font-lock-comment-face
10681068
"\"this is a string\"" font-lock-string-face)))
10691069

1070+
(ert-deftest font-lock-raw-string-constant ()
1071+
;; There was an issue in which a multi-line raw string would be fontified
1072+
;; correctly if inserted, but then incorrectly if one of the lines was then
1073+
;; edited. This test replicates how font-lock responds when text in the
1074+
;; buffer is modified in order to reproduce it.
1075+
(with-temp-buffer
1076+
(rust-mode)
1077+
(font-lock-fontify-buffer)
1078+
(insert "const BOO:&str = r#\"\nBOO\"#;")
1079+
(beginning-of-buffer)
1080+
(insert " ")
1081+
(font-lock-after-change-function 1 2 0)
1082+
1083+
(should (equal 'font-lock-string-face (get-text-property 19 'face))) ;; Opening "r" of raw string
1084+
(should (equal 'font-lock-string-face (get-text-property 27 'face))) ;; Closing "#" of raw string
1085+
(should (equal nil (get-text-property 28 'face))) ;; Semicolon--should not be part of the string
1086+
))
1087+
10701088
(ert-deftest indent-method-chains-no-align ()
10711089
(let ((rust-indent-method-chain nil)) (test-indent
10721090
"

rust-mode.el

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,43 @@
374374
("fn" . font-lock-function-name-face)
375375
("static" . font-lock-constant-face)))))
376376

377+
(defun rust-extend-region-raw-string ()
378+
"Extend the region given by `font-lock-beg' and `font-lock-end'
379+
to include the beginning of a string if it includes part of it.
380+
Adjusts to include the r[#] of a raw string as well."
381+
382+
(let* ((orig-beg font-lock-beg)
383+
(orig-end font-lock-end)
384+
(beg-ppss (syntax-ppss font-lock-beg))
385+
(beg-in-str (nth 3 beg-ppss))
386+
(end-ppss (syntax-ppss font-lock-end))
387+
(end-in-str (nth 3 end-ppss)))
388+
389+
(when (and beg-in-str (> font-lock-beg (nth 8 beg-ppss)))
390+
(setq font-lock-beg str-beg)
391+
(while (equal ?# (char-before font-lock-beg))
392+
(setq font-lock-beg (1- font-lock-beg)))
393+
(when (equal ?r (char-before font-lock-beg))
394+
(setq font-lock-beg (1- font-lock-beg))))
395+
396+
(when end-in-str
397+
(save-excursion
398+
(goto-char (nth 8 end-ppss))
399+
(ignore-errors (forward-sexp))
400+
(setq font-lock-end (max font-lock-end (point)))))
401+
402+
;; If we have the beginning of a raw string in the region, make sure we have the end of
403+
;; it.
404+
(when (or beg-in-str end-in-str)
405+
(save-excursion
406+
(goto-char font-lock-beg)
407+
(while (and (< (point) font-lock-end) (ignore-errors (rust-look-for-raw-string (buffer-end 1)))))
408+
(setq font-lock-end (max font-lock-end (point)))))
409+
410+
(or (/= font-lock-beg orig-beg)
411+
(/= font-lock-end orig-end))
412+
))
413+
377414
(defun rust-look-for-raw-string (bound)
378415
;; Find a raw string, but only if it's not in the middle of another string or
379416
;; a comment
@@ -702,6 +739,7 @@ This is written mainly to be used as `end-of-defun-function' for Rust."
702739
(setq-local indent-line-function 'rust-mode-indent-line)
703740

704741
;; Fonts
742+
(add-to-list 'font-lock-extend-region-functions 'rust-extend-region-raw-string)
705743
(setq-local font-lock-defaults '(rust-mode-font-lock-keywords nil nil nil nil (font-lock-syntactic-keywords . rust-mode-font-lock-syntactic-keywords)))
706744

707745
;; Misc

0 commit comments

Comments
 (0)