From 0c2d921a75375e5667224bfd92b28be3b77977b3 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Thu, 25 Apr 2019 18:00:15 +0000 Subject: [PATCH] Restore fontification of delimiters of multiline CC Mode strings. E.g., on typing the closing delimiter of a string continued onto a second line, the opening delimiter retained its font-lock-warning-face. * lisp/progmodes/cc-defs.el (c-c++-raw-string-opener-re) (c-c++-raw-string-opener-1-re): New constants. (c-sub-at-c++-raw-string-opener, c-at-c++-raw-string-opener): New macros. * lisp/progmodes/cc-engine.el (c-raw-string-pos) (c-depropertize-raw-strings-in-region, c-after-change-unmark-raw-strings): Replace uses of open-coded raw string regexps by the new constants and macros in cc-defs.el. * lisp/progmodes/cc-fonts.el (c-font-lock-raw-strings): Ditto * lisp/progmodes/cc-mode.el (c-before-change-check-unbalanced-strings): Set c-new-BEG to the beginning of the string when we encounter its closing ". When not in a raw string, but in a string, clear syntax-table properties from its delimiters and set c-new-BEG/END to its limits. (c-after-change-mark-abnormal-strings): When applying syntax-table properties to string delimiters, also set c-new-BEG/END to ensure subsequent fontification. --- lisp/progmodes/cc-defs.el | 25 +++++++++++++++++++++++++ lisp/progmodes/cc-engine.el | 18 ++++++++---------- lisp/progmodes/cc-fonts.el | 7 ++----- lisp/progmodes/cc-mode.el | 28 +++++++++++++++++++++------- 4 files changed, 56 insertions(+), 22 deletions(-) diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el index 87ddf3ac1e2..cd4ed6b352e 100644 --- a/lisp/progmodes/cc-defs.el +++ b/lisp/progmodes/cc-defs.el @@ -503,6 +503,31 @@ to it is returned. This function does not modify the point or the mark." ;; Emacs <22 + XEmacs '(default-value 'sentence-end))) +(defconst c-c++-raw-string-opener-re "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(") +;; Matches a C++ raw string opener. Submatch 1 is its identifier. + +(defconst c-c++-raw-string-opener-1-re "\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(") +;; Matches a C++ raw string opener starting after the initial R. + +(defmacro c-sub-at-c++-raw-string-opener () + `(save-excursion + (and + (if (eq (char-after) ?R) + (progn (forward-char) t) + (eq (char-before) ?R)) + (looking-at c-c++-raw-string-opener-1-re)))) + +(defmacro c-at-c++-raw-string-opener (&optional pos) + ;; Return non-nil if POS (default point) is either at the start of a C++ raw + ;; string opener, or after the introductory R of one. The match data is + ;; overwritten. On success the opener's identifier will be (match-string + ;; 1). Text properties on any characters are ignored. + (if pos + `(save-excursion + (goto-char ,pos) + (c-sub-at-c++-raw-string-opener)) + `(c-sub-at-c++-raw-string-opener))) + ;; The following is essentially `save-buffer-state' from lazy-lock.el. ;; It ought to be a standard macro. (defmacro c-save-buffer-state (varlist &rest body) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 6b44aae0884..242954dbf25 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -6607,15 +6607,14 @@ comment at the start of cc-engine.el for more info." (while (and (search-forward-regexp - "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" + c-c++-raw-string-opener-re (1+ here) 'limit) (< (point) here))) (and (eq (point) (1+ here)) (match-beginning 1) (goto-char (1- (match-beginning 1))))))) (not (bobp))))) - (eq (char-before) ?R) - (looking-at "\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(")) + (c-at-c++-raw-string-opener)) (setq open-quote-pos (point) open-paren-pos (match-end 1) id (match-string-no-properties 1)) @@ -6733,7 +6732,7 @@ comment at the start of cc-engine.el for more info." (concat "\\(" ; 1 c-anchored-cpp-prefix ; 2 "\\)\\|\\(" ; 3 - "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" ; 4 + c-c++-raw-string-opener-re ; 4 "\\)") finish t)) (when (save-excursion @@ -6752,7 +6751,7 @@ comment at the start of cc-engine.el for more info." (goto-char (match-end 2)) ; after the "#". (while (and (< (point) eom) (c-syntactic-re-search-forward - "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" eom t)) + c-c++-raw-string-opener-re eom t)) (c-depropertize-raw-string (match-string-no-properties 1) ; id (1+ (match-beginning 0)) ; open quote @@ -6931,8 +6930,7 @@ comment at the start of cc-engine.el for more info." (goto-char end) (setq eoll (c-point 'eoll)) (when (and (null c-old-END-literality) - (search-forward-regexp "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" - eoll t)) + (search-forward-regexp c-c++-raw-string-opener-re eoll t)) (setq state (c-state-semi-pp-to-literal end)) (when (eq (cadr state) 'string) (unwind-protect @@ -6969,7 +6967,7 @@ comment at the start of cc-engine.el for more info." (while (and (setq found - (search-forward-regexp "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" + (search-forward-regexp c-c++-raw-string-opener-re c-new-END 'bound)) (<= (match-end 0) beg))) (when (and found (<= (match-beginning 0) end)) @@ -6983,7 +6981,7 @@ comment at the start of cc-engine.el for more info." 'syntax-table) '(1))) (goto-char (1- (cadr c-old-beg-rs))) - (unless (looking-at "R\"[^ ()\\\n\r\t]\\{0,16\\}(") + (unless (looking-at c-c++-raw-string-opener-re) (c-clear-char-property (1+ (point)) 'syntax-table) (c-truncate-semi-nonlit-pos-cache (1+ (point))) (if (c-search-forward-char-property 'syntax-table '(15) @@ -6998,7 +6996,7 @@ comment at the start of cc-engine.el for more info." (and c-old-beg-rs (eq (car c-old-beg-rs) 'open-delim))) (goto-char (cadr c-old-beg-rs)) - (when (looking-at "\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(") + (when (looking-at c-c++-raw-string-opener-1-re) (setq id (match-string-no-properties 1)) (when (re-search-forward (concat ")" id "\"") nil t) ; No bound. (setq c-new-END (point-max)) diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index 4a5cf5719be..831fa308866 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1684,11 +1684,8 @@ casts and declarations are fontified. Used on level 2 and higher." (string-start (and (eq (cadr state) 'string) (car (cddr state)))) (raw-id (and string-start - (save-excursion - (goto-char string-start) - (and (eq (char-before) ?R) - (looking-at "\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(") - (match-string-no-properties 1))))) + (c-at-c++-raw-string-opener string-start) + (match-string-no-properties 1))) (content-start (and raw-id (point)))) ;; We go round the next loop twice per raw string, once for each "end". (while (< (point) limit) diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 27ed04fea52..1a360048752 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1261,7 +1261,8 @@ Note that the style variables are always made local to the buffer." (memq (char-after) c-string-delims)) ; Ignore an unterminated raw string's (. ;; Opening " on last line of text (without EOL). (c-clear-char-property (point) 'syntax-table) - (c-truncate-semi-nonlit-pos-cache (point))))) + (c-truncate-semi-nonlit-pos-cache (point)) + (setq c-new-BEG (min c-new-BEG (point)))))) (t (goto-char end) ; point-max (when @@ -1271,17 +1272,24 @@ Note that the style variables are always made local to the buffer." (c-clear-char-property (point) 'syntax-table) (c-truncate-semi-nonlit-pos-cache (point))))) - (unless (and c-multiline-string-start-char - (not (c-characterp c-multiline-string-start-char))) + (unless + (or (and + ;; Don't set c-new-BEG/END if we're in a raw string. + (eq beg-literal-type 'string) + (c-at-c++-raw-string-opener (car beg-limits))) + (and c-multiline-string-start-char + (not (c-characterp c-multiline-string-start-char)))) (when (and (eq end-literal-type 'string) (not (eq (char-before (cdr end-limits)) ?\())) (c-clear-char-property (1- (cdr end-limits)) 'syntax-table) - (c-truncate-semi-nonlit-pos-cache (1- (cdr end-limits)))) + (c-truncate-semi-nonlit-pos-cache (1- (cdr end-limits))) + (setq c-new-END (max c-new-END (cdr end-limits)))) (when (and (eq beg-literal-type 'string) (memq (char-after (car beg-limits)) c-string-delims)) (c-clear-char-property (car beg-limits) 'syntax-table) - (c-truncate-semi-nonlit-pos-cache (car beg-limits)))))) + (c-truncate-semi-nonlit-pos-cache (car beg-limits)) + (setq c-new-BEG (min c-new-BEG (car beg-limits))))))) (defun c-after-change-mark-abnormal-strings (beg end _old-len) ;; Mark any unbalanced strings in the region (c-new-BEG c-new-END) with @@ -1352,6 +1360,7 @@ Note that the style variables are always made local to the buffer." (car beg-limits)) (t ; comment (cdr beg-limits)))) + ;; Handle one string each time around the next while loop. (while (and (< (point) c-new-END) @@ -1373,10 +1382,15 @@ Note that the style variables are always made local to the buffer." (cond ((memq (char-after (match-end 0)) '(?\n ?\r)) (c-put-char-property (1- (point)) 'syntax-table '(15)) - (c-put-char-property (match-end 0) 'syntax-table '(15))) + (c-put-char-property (match-end 0) 'syntax-table '(15)) + (setq c-new-BEG (min c-new-BEG (point)) + c-new-END (max c-new-END (match-end 0)))) ((or (eq (match-end 0) (point-max)) (eq (char-after (match-end 0)) ?\\)) ; \ at EOB - (c-put-char-property (1- (point)) 'syntax-table '(15)))) + (c-put-char-property (1- (point)) 'syntax-table '(15)) + (setq c-new-BEG (min c-new-BEG (point)) + c-new-END (max c-new-END (match-end 0))) ; Do we need c-new-END? + )) (goto-char (min (1+ (match-end 0)) (point-max)))) (setq s nil))))) -- 2.39.2