From e4b1445f4301a4a672442d29f93983d804a80982 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Sat, 24 Sep 2022 12:23:32 +0000 Subject: [PATCH] CC Mode. Make AWK Mode work with electric-pair-mode Also fix some minor anomalies with other CC Mode modes in electric-pair-mode. This fixes bug #53446. * lisp/progmodes/cc-mode.el (c-open-string-opener): New buffer local variable. (c-after-change-mark-abnormal-strings): Set c-open-string-opener when an unbalanced string is detected. (c-before-change): Initilize c-open-string-opener to nil, each buffer change. (c-electric-pair-inhibit-predicate): Use the value of c-open-string-opener to flag an unbalaced string rather than trying to calculate it again. * lisp/progmodes/cc-awk.el (c-awk-syntax-tablify-string): Set c-open-string-opener when an unbalanced string is detected. --- lisp/progmodes/cc-awk.el | 25 +++++++++++++++---------- lisp/progmodes/cc-mode.el | 27 +++++++++++++++------------ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/lisp/progmodes/cc-awk.el b/lisp/progmodes/cc-awk.el index 57750a2b394..089fa9ffe4f 100644 --- a/lisp/progmodes/cc-awk.el +++ b/lisp/progmodes/cc-awk.el @@ -56,6 +56,7 @@ ;; Silence the byte compiler. (cc-bytecomp-defvar c-new-BEG) (cc-bytecomp-defvar c-new-END) +(cc-bytecomp-defvar c-open-string-opener) (cc-bytecomp-defun c-restore-string-fences) (cc-bytecomp-defun c-clear-string-fences) @@ -777,16 +778,20 @@ ;; opener, t if it would be a division sign. ;; ;; This function does hidden buffer changes. - (search-forward-regexp c-awk-string-without-end-here-re nil t) ; a (possibly unterminated) string - (c-awk-set-string-regexp-syntax-table-properties - (match-beginning 0) (match-end 0)) - (cond ((looking-at "\"") - (forward-char) - t) ; In AWK, ("15" / 5) gives 3 ;-) - ((looking-at "[\n\r]") ; Unterminated string with EOL. - (forward-char) - nil) ; / on next line would start a regexp - (t nil))) ; Unterminated string at EOB + (let ((string-start (if (eq (char-after) ?_) (1+ (point)) (point)))) + (search-forward-regexp c-awk-string-without-end-here-re nil t) ; a (possibly unterminated) string + (c-awk-set-string-regexp-syntax-table-properties + (match-beginning 0) (match-end 0)) + (cond ((looking-at "\"") + (forward-char) + t) ; In AWK, ("15" / 5) gives 3 ;-) + ((looking-at "[\n\r]") ; Unterminated string with EOL. + (setq c-open-string-opener string-start) + (forward-char) + nil) ; / on next line would start a regexp + (t ; Unterminated string at EOB + (setq c-open-string-opener string-start) + nil)))) (defun c-awk-syntax-tablify-/ (anchor anchor-state-/div) ;; Point is at a /. Determine whether this is a division sign or a regexp diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 9309a546dbd..15dfdc4b0e5 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1421,6 +1421,13 @@ Note that the style variables are always made local to the buffer." (c-clear-syn-tab (point))) (t (c-benign-error "c-remove-string-fences: Wrong position"))))) +(defvar c-open-string-opener nil + "The position of the opening delimiter of an unterminated string or nil. +This is valid only immediately after a buffer change, and refers +only to an opener in the (logical) line containing the END +position of `after-change-functions'.") +(make-variable-buffer-local 'c-open-string-opener) + (defun c-before-change-check-unbalanced-strings (beg end) ;; If BEG or END is inside an unbalanced string, remove the syntax-table ;; text property from respectively the start or end of the string. Also @@ -1685,13 +1692,14 @@ Note that the style variables are always made local to the buffer." (c-put-syn-tab (1- (point)) '(15)) (c-put-syn-tab (match-end 0) '(15)) (setq c-new-BEG (min c-new-BEG (point)) - c-new-END (max c-new-END (match-end 0)))) + c-new-END (max c-new-END (match-end 0))) + (setq c-open-string-opener (1- (point)))) ((or (eq (match-end 0) (point-max)) (eq (char-after (match-end 0)) ?\\)) ; \ at EOB (c-put-syn-tab (1- (point)) '(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? - )) + (setq c-open-string-opener (1- (point))))) (goto-char (min (1+ (match-end 0)) (point-max)))) (setq s nil))))) @@ -2130,6 +2138,7 @@ with // and /*, not more generic line and block comments." ;; (c-new-BEG c-new-END) will be the region to fontify. (setq c-new-BEG beg c-new-END end) (setq c-maybe-stale-found-type nil) + (setq c-open-string-opener nil) ;; A workaround for syntax-ppss's failure to notice syntax-table text ;; property changes. (when (fboundp 'syntax-ppss) @@ -2698,11 +2707,9 @@ This function is called from `c-common-init', once per mode initialization." At the time of call, point is just after the newly inserted CHAR. When CHAR is \" and not within a comment, t will be returned if -the quotes on the current line are already balanced (i.e. if the -last \" is not marked with a string fence syntax-table text -property). For other cases, the default value of -`electric-pair-inhibit-predicate' is called and its value -returned. +the quotes on the current line are already balanced. For other +cases, the default value of `electric-pair-inhibit-predicate' is +called and its value returned. This function is the appropriate value of `electric-pair-inhibit-predicate' for CC Mode modes, which mark @@ -2710,11 +2717,7 @@ invalid strings with such a syntax table text property on the opening \" and the next unescaped end of line." (if (and (eq char ?\") (not (memq (cadr (c-semi-pp-to-literal (1- (point)))) '(c c++)))) - (let ((last-quote (save-match-data - (save-excursion - (goto-char (c-point 'eoll)) - (search-backward "\""))))) - (not (equal (c-get-char-property last-quote 'c-fl-syn-tab) '(15)))) + (not c-open-string-opener) (funcall (default-value 'electric-pair-inhibit-predicate) char))) -- 2.39.2