emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master b25d58c: CC Mode: Improve handling of unbalanced st


From: Alan Mackenzie
Subject: [Emacs-diffs] master b25d58c: CC Mode: Improve handling of unbalanced strings
Date: Tue, 2 Jul 2019 08:34:26 -0400 (EDT)

branch: master
commit b25d58c956a9fcd2b81b804699573ea851bd8fde
Author: Alan Mackenzie <address@hidden>
Commit: Alan Mackenzie <address@hidden>

    CC Mode: Improve handling of unbalanced strings
    
    * lisp/progmodes/cc-fonts.el (c-before-font-lock-functions): Add function
    c-after-change-escape-NL-in-string into value for most languages.
    
    * lisp/progmodes/cc-mode.el (c-after-change-escape-NL-in-string): New
    function.
    (c-before-change-check-unbalanced-strings): Handle the making and breaking 
of
    escaped newlines, by removal or addition of text.
---
 lisp/progmodes/cc-langs.el |  6 +++-
 lisp/progmodes/cc-mode.el  | 78 +++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 78 insertions(+), 6 deletions(-)

diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 2fcd6ac..153d3fc 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -478,7 +478,7 @@ so that all identifiers are recognized as words.")
                    (list fs)))
   "If non-nil, a list of functions called from c-before-change-hook.
 Typically these will record enough state to allow
-`c-before-font-lock-function' to extend the region to fontify,
+`c-before-font-lock-functions' to extend the region to fontify,
 and may do such things as removing text-properties which must be
 recalculated.
 
@@ -497,15 +497,18 @@ parameters \(point-min) and \(point-max).")
   ;; For documentation see the following c-lang-defvar of the same name.
   ;; The value here may be a list of functions or a single function.
   t '(c-depropertize-new-text
+      c-after-change-escape-NL-in-string
       c-after-change-mark-abnormal-strings
       c-change-expand-fl-region)
   (c objc) '(c-depropertize-new-text
+            c-after-change-escape-NL-in-string
             c-parse-quotes-after-change
             c-after-change-mark-abnormal-strings
             c-extend-font-lock-region-for-macros
             c-neutralize-syntax-in-CPP
             c-change-expand-fl-region)
   c++ '(c-depropertize-new-text
+       c-after-change-escape-NL-in-string
        c-after-change-unmark-raw-strings
        c-parse-quotes-after-change
        c-after-change-mark-abnormal-strings
@@ -514,6 +517,7 @@ parameters \(point-min) and \(point-max).")
        c-restore-<>-properties
        c-change-expand-fl-region)
   java '(c-depropertize-new-text
+        c-after-change-escape-NL-in-string
         c-parse-quotes-after-change
         c-after-change-mark-abnormal-strings
         c-restore-<>-properties
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 5c18879..8f4bb34 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1262,11 +1262,31 @@ Note that the style variables are always made local to 
the buffer."
          (setq c-new-BEG (min (car beg-limits) c-new-BEG))))
 
      ((< end (point-max))
-      (goto-char (1+ end))     ; might be a newline.
-      ;; In the following regexp, the initial \n caters for a newline getting
-      ;; joined to a preceding \ by the removal of what comes between.
-      (re-search-forward "[\n\r]?\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*"
-                        nil t)
+      ;; Have we just escaped a newline by deleting characters?
+      (if (and (eq end-literal-type 'string)
+              (memq (char-after end) '(?\n ?\r)))
+         (cond
+          ;; Are we escaping a newline by deleting stuff between \ and \n?
+          ((and (> end beg)
+                (progn
+                  (goto-char end)
+                  (eq (logand (skip-chars-backward "\\\\" beg) 1) 1)))
+           (c-clear-char-property end 'syntax-table)
+           (c-truncate-lit-pos-cache end)
+           (goto-char (1+ end)))
+          ;; Are we unescaping a newline by inserting stuff between \ and \n?
+          ((and (eq end beg)
+                (progn
+                  (goto-char end)
+                  (eq (logand (skip-chars-backward "\\\\") 1) 1)))
+           (goto-char (1+ end))) ; To after the NL which is being unescaped.
+          (t
+           (goto-char end)))
+       (goto-char end))
+
+      ;; Move to end of logical line (as it will be after the change, or as it
+      ;; was before unescaping a NL.)
+      (re-search-forward "\\(\\\\\\(.\\|\n\\|\r\\)\\|[^\\\n\r]\\)*" nil t)
       ;; We're at an EOLL or point-max.
       (if (equal (c-get-char-property (point) 'syntax-table) '(15))
          (if (memq (char-after) '(?\n ?\r))
@@ -1426,6 +1446,54 @@ Note that the style variables are always made local to 
the buffer."
          (goto-char (min (1+ (match-end 0)) (point-max))))
        (setq s nil)))))
 
+(defun c-after-change-escape-NL-in-string (beg end _old_len)
+  ;; If a backslash has just been inserted into a string, and this quotes an
+  ;; existing newline, remove the string fence syntax-table text properties
+  ;; on what has become the tail of the string.
+  ;;
+  ;; POINT is undefined both at entry to and exit from this function, the
+  ;; buffer will have been widened, and match data will have been saved.
+  ;;
+  ;; This function is called exclusively as an after-change function via
+  ;; `c-before-font-lock-functions'.  In C++ Mode, it should come before
+  ;; `c-after-change-unmark-raw-strings' in that lang variable.
+  (let (lit-start)                    ; Don't calculate this till we have to.
+    (when
+       (and (> end beg)
+            (memq (char-after end) '(?\n ?\r))
+            (progn (goto-char end)
+                   (eq (logand (skip-chars-backward "\\\\") 1) 1))
+            (progn (goto-char end)
+                   (setq lit-start (c-literal-start)))
+            (memq (char-after lit-start) c-string-delims)
+            (or (not (c-major-mode-is 'c++-mode))
+                (progn
+                  (goto-char lit-start)
+                  (and (not (and (eq (char-before) ?R)
+                                 (looking-at c-c++-raw-string-opener-1-re)))
+                       (not (and (eq (char-after) ?\()
+                                 (equal (c-get-char-property
+                                         (point) 'syntax-table)
+                                        '(15))))))
+                (save-excursion
+                  (c-beginning-of-macro))))
+      (goto-char (1+ end))             ; After the \
+      ;; Search forward for a closing ".
+      (when (and (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\"\\\n\r]\\)*"
+                                   nil t)
+                (eq (char-after) ?\")
+                (equal (c-get-char-property (point) 'syntax-table) '(15)))
+       (c-clear-char-property end 'syntax-table)
+       (c-truncate-lit-pos-cache end)
+       (c-clear-char-property (point) 'syntax-table)
+       (forward-char)                  ; to after the "
+       (when
+           (and
+            ;; Search forward for an end of logical line.
+            (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*" nil t)
+            (memq (char-after) '(?\n ?\r)))
+         (c-clear-char-property (point) 'syntax-table))))))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Parsing of quotes.
 ;;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]