emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] master 223e7b8: Make CC Mode and electric-pair-mode work t


From: Alan Mackenzie
Subject: [Emacs-diffs] master 223e7b8: Make CC Mode and electric-pair-mode work together. This fixes bug #33794
Date: Tue, 15 Jan 2019 11:08:13 -0500 (EST)

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

    Make CC Mode and electric-pair-mode work together.  This fixes bug #33794
    
    * lisp/progmodes/cc-cmds.el (c-electric-pound, c-electric-slash)
    (c-electric-star, c-electric-semi&comma, c-electric-colon, 
c-electric-lt-gt):
    Bind post-self-insert-hook to nil around calls to self-insert-command to
    protect against arbitrary functionality confusing CC Mode.
    (c-do-brace-electrics): New function, extracted from c-electric-brace and
    enhanced.
    (c-electric-brace): Bind post-self-insert-hook to nil around the call to
    self-insert-command.  When electric-pair-mode is configured, call
    electric-pair-post-self-insert-function.  Handle any deletion done by this
    function.  Call c-do-brace-electrics for the inserted brace, and perhaps 
for a
    brace inserted by electric-pair-self-insert-function.
    (c-electric-paren): Bind post-self-insert-hook to nil around the call to
    self-insert-command.  When electric-pair-mode is configured, call
    electric-pair-post-self-insert-function.
---
 lisp/progmodes/cc-cmds.el | 312 +++++++++++++++++++++++++++-------------------
 1 file changed, 183 insertions(+), 129 deletions(-)

diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index a07527e..78677fe 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -47,6 +47,7 @@
 ;; Silence the compiler.
 (cc-bytecomp-defvar filladapt-mode)    ; c-fill-paragraph contains a kludge
                                        ; which looks at this.
+(cc-bytecomp-defun electric-pair-post-self-insert-function)
 
 ;; Indentation / Display syntax functions
 (defvar c-fix-backslashes t)
@@ -503,7 +504,8 @@ inside a literal or a macro, nothing special happens."
                          (eq (char-before) ?\\))))
            (c-in-literal)))
       ;; do nothing special
-      (self-insert-command (prefix-numeric-value arg))
+      (let (post-self-insert-hook)     ; Disable random functionality.
+       (self-insert-command (prefix-numeric-value arg)))
     ;; place the pound character at the left edge
     (let ((pos (- (point-max) (point)))
          (bolp (bolp)))
@@ -694,6 +696,134 @@ inside a literal or a macro, nothing special happens."
                            t))))
          (goto-char (- (point-max) pos))))))
 
+(defun c-do-brace-electrics (before after)
+  ;; Point is just after a brace.  Indent the various lines, add any required
+  ;; auto newlines, and apply pertinent clean ups.  It is assumed that the
+  ;; caller has checked that point is at EOL if need be, and that the brace is
+  ;; not in a comment or string, and suchlike.
+  ;;
+  ;; BEFORE and AFTER qualify the newlines required before and after the
+  ;; brace as follows:
+  ;; If
+  ;;  o - nil: insert a newline or not according to `c-hanging-braces-alist'.
+  ;;  o - 'ignore: don't insert a newline.
+  ;;  o - 'assume: insert a newline.
+  ;;
+  ;; The return value has no significance.
+  (let (;; shut this up too
+       (c-echo-syntactic-information-p nil)
+       newlines
+       ln-syntax br-syntax syntax)  ; Syntactic context of the original line,
+                                       ; of the brace itself, of the line the
+                                       ; brace ends up on.
+    (c-save-buffer-state ((c-syntactic-indentation-in-macros t)
+                         (c-auto-newline-analysis t))
+      (setq ln-syntax (c-guess-basic-syntax)))
+    (if c-syntactic-indentation
+       (c-indent-line ln-syntax))
+
+    (when c-auto-newline
+      (backward-char)
+      (setq br-syntax (c-point-syntax)
+           newlines (c-brace-newlines br-syntax))
+
+      ;; Insert the BEFORE newline, if wanted, and reindent the newline.
+      (if (or (and (null before) (memq 'before newlines)
+                  (> (current-column) (current-indentation)))
+             (eq before 'assume))
+         (if c-syntactic-indentation
+             ;; Only a plain newline for now - it's indented
+             ;; after the cleanups when the line has its final
+             ;; appearance.
+             (newline)
+           (c-newline-and-indent)))
+      (forward-char)
+
+      ;; `syntax' is the syntactic context of the line which ends up
+      ;; with the brace on it.
+      (setq syntax (if (memq 'before newlines) br-syntax ln-syntax))
+
+      ;; Do all appropriate clean ups
+      (let ((here (point))
+           (pos (- (point-max) (point)))
+           mbeg mend
+           )
+
+       ;; `}': clean up empty defun braces
+       (when (c-save-buffer-state ()
+               (and (memq 'empty-defun-braces c-cleanup-list)
+                    (eq (c-last-command-char) ?\})
+                    (c-intersect-lists '(defun-close class-close inline-close)
+                                       syntax)
+                    (progn
+                      (forward-char -1)
+                      (c-skip-ws-backward)
+                      (eq (char-before) ?\{))
+                    ;; make sure matching open brace isn't in a comment
+                    (not (c-in-literal))))
+         (delete-region (point) (1- here))
+         (setq here (- (point-max) pos)))
+       (goto-char here)
+
+       ;; `}': compact to a one-liner defun?
+       (save-match-data
+         (when
+             (and (eq (c-last-command-char) ?\})
+                  (memq 'one-liner-defun c-cleanup-list)
+                  (c-intersect-lists '(defun-close) syntax)
+                  (c-try-one-liner))
+           (setq here (- (point-max) pos))))
+
+       ;; `{': clean up brace-else-brace and brace-elseif-brace
+       (when (eq (c-last-command-char) ?\{)
+         (cond
+          ((and (memq 'brace-else-brace c-cleanup-list)
+                (re-search-backward
+                 (concat "}"
+                         "\\([ \t\n]\\|\\\\\n\\)*"
+                         "else"
+                         "\\([ \t\n]\\|\\\\\n\\)*"
+                         "{"
+                         "\\=")
+                 nil t))
+           (delete-region (match-beginning 0) (match-end 0))
+           (insert-and-inherit "} else {"))
+          ((and (memq 'brace-elseif-brace c-cleanup-list)
+                (progn
+                  (goto-char (1- here))
+                  (setq mend (point))
+                  (c-skip-ws-backward)
+                  (setq mbeg (point))
+                  (eq (char-before) ?\)))
+                (zerop (c-save-buffer-state nil (c-backward-token-2 1 t)))
+                (eq (char-after) ?\()
+                (re-search-backward
+                 (concat "}"
+                         "\\([ \t\n]\\|\\\\\n\\)*"
+                         "else"
+                         "\\([ \t\n]\\|\\\\\n\\)+"
+                         "if"
+                         "\\([ \t\n]\\|\\\\\n\\)*"
+                         "\\=")
+                 nil t))
+           (delete-region mbeg mend)
+           (goto-char mbeg)
+           (insert ?\ ))))
+
+       (goto-char (- (point-max) pos))
+
+       ;; Indent the line after the cleanups since it might
+       ;; very well indent differently due to them, e.g. if
+       ;; c-indent-one-line-block is used together with the
+       ;; one-liner-defun cleanup.
+       (when c-syntactic-indentation
+         (c-indent-line)))
+
+      ;; does a newline go after the brace?
+      (if (or (and (null after) (memq 'after newlines))
+             (eq after 'assume))
+         (c-newline-and-indent)))))
+
 (defun c-electric-brace (arg)
   "Insert a brace.
 
@@ -716,7 +846,10 @@ settings of `c-cleanup-list' are done."
        ;; We want to inhibit blinking the paren since this would be
        ;; most disruptive.  We'll blink it ourselves later on.
        (old-blink-paren blink-paren-function)
-       blink-paren-function case-fold-search)
+       blink-paren-function case-fold-search
+       (at-eol (looking-at "[ \t]*\\\\?$"))
+       (active-region (and (fboundp 'use-region-p) (use-region-p)))
+       got-pair-} electric-pair-deletion)
 
     (c-save-buffer-state ()
       (setq safepos (c-safe-position (point) (c-parse-state))
@@ -724,128 +857,36 @@ settings of `c-cleanup-list' are done."
 
     ;; Insert the brace.  Note that expand-abbrev might reindent
     ;; the line here if there's a preceding "else" or something.
-    (self-insert-command (prefix-numeric-value arg))
-
-    (when (and c-electric-flag (not literal) (not arg))
-      (if (not (looking-at "[ \t]*\\\\?$"))
-         (if c-syntactic-indentation
-             (indent-according-to-mode))
-
-       (let ( ;; shut this up too
-             (c-echo-syntactic-information-p nil)
-             newlines
-             ln-syntax br-syntax syntax) ; Syntactic context of the original 
line,
-                       ; of the brace itself, of the line the brace ends up on.
-         (c-save-buffer-state ((c-syntactic-indentation-in-macros t)
-                               (c-auto-newline-analysis t))
-           (setq ln-syntax (c-guess-basic-syntax)))
-         (if c-syntactic-indentation
-             (c-indent-line ln-syntax))
-
-         (when c-auto-newline
-           (backward-char)
-           (setq br-syntax (c-point-syntax)
-                 newlines (c-brace-newlines br-syntax))
-
-           ;; Insert the BEFORE newline, if wanted, and reindent the newline.
-           (if (and (memq 'before newlines)
-                    (> (current-column) (current-indentation)))
-               (if c-syntactic-indentation
-                   ;; Only a plain newline for now - it's indented
-                   ;; after the cleanups when the line has its final
-                   ;; appearance.
-                   (newline)
-                 (c-newline-and-indent)))
+    (let (post-self-insert-hook) ; the only way to get defined functionality
+                                ; from `self-insert-command'.
+      (self-insert-command (prefix-numeric-value arg)))
+
+    ;; Emulate `electric-pair-mode'.
+    (when (and (boundp 'electric-pair-mode)
+              electric-pair-mode)
+      (let ((size (buffer-size))
+           (c-in-electric-pair-functionality t)
+           post-self-insert-hook)
+       (electric-pair-post-self-insert-function)
+       (setq got-pair-} (and at-eol
+                             (eq (c-last-command-char) ?{)
+                             (eq (char-after) ?}))
+             electric-pair-deletion (< (buffer-size) size))))
+
+    ;; Perform any required CC Mode electric actions.
+    (cond
+     ((or literal arg (not c-electric-flag) active-region))
+     ((not at-eol)
+      (c-indent-line))
+     (electric-pair-deletion
+      (c-indent-line)
+      (c-do-brace-electrics 'ignore nil))
+     (t (c-do-brace-electrics nil nil)
+       (when got-pair-}
+         (save-excursion
            (forward-char)
-
-           ;; `syntax' is the syntactic context of the line which ends up
-           ;; with the brace on it.
-           (setq syntax (if (memq 'before newlines) br-syntax ln-syntax))
-
-           ;; Do all appropriate clean ups
-           (let ((here (point))
-                 (pos (- (point-max) (point)))
-                 mbeg mend
-                 )
-
-             ;; `}': clean up empty defun braces
-             (when (c-save-buffer-state ()
-                     (and (memq 'empty-defun-braces c-cleanup-list)
-                          (eq (c-last-command-char) ?\})
-                          (c-intersect-lists '(defun-close class-close 
inline-close)
-                                             syntax)
-                          (progn
-                            (forward-char -1)
-                            (c-skip-ws-backward)
-                            (eq (char-before) ?\{))
-                          ;; make sure matching open brace isn't in a comment
-                          (not (c-in-literal))))
-               (delete-region (point) (1- here))
-               (setq here (- (point-max) pos)))
-             (goto-char here)
-
-             ;; `}': compact to a one-liner defun?
-             (save-match-data
-               (when
-                   (and (eq (c-last-command-char) ?\})
-                        (memq 'one-liner-defun c-cleanup-list)
-                        (c-intersect-lists '(defun-close) syntax)
-                        (c-try-one-liner))
-                 (setq here (- (point-max) pos))))
-
-             ;; `{': clean up brace-else-brace and brace-elseif-brace
-             (when (eq (c-last-command-char) ?\{)
-               (cond
-                ((and (memq 'brace-else-brace c-cleanup-list)
-                      (re-search-backward
-                       (concat "}"
-                               "\\([ \t\n]\\|\\\\\n\\)*"
-                               "else"
-                               "\\([ \t\n]\\|\\\\\n\\)*"
-                               "{"
-                               "\\=")
-                       nil t))
-                 (delete-region (match-beginning 0) (match-end 0))
-                 (insert-and-inherit "} else {"))
-                ((and (memq 'brace-elseif-brace c-cleanup-list)
-                      (progn
-                        (goto-char (1- here))
-                        (setq mend (point))
-                        (c-skip-ws-backward)
-                        (setq mbeg (point))
-                        (eq (char-before) ?\)))
-                      (zerop (c-save-buffer-state nil (c-backward-token-2 1 
t)))
-                      (eq (char-after) ?\()
-                     ; (progn
-                       ; (setq tmp (point))
-                        (re-search-backward
-                         (concat "}"
-                                 "\\([ \t\n]\\|\\\\\n\\)*"
-                                 "else"
-                                 "\\([ \t\n]\\|\\\\\n\\)+"
-                                 "if"
-                                 "\\([ \t\n]\\|\\\\\n\\)*"
-                                 "\\=")
-                         nil t);)
-                      ;(eq (match-end 0) tmp);
-                        )
-                 (delete-region mbeg mend)
-                 (goto-char mbeg)
-                 (insert ?\ ))))
-
-             (goto-char (- (point-max) pos))
-
-             ;; Indent the line after the cleanups since it might
-             ;; very well indent differently due to them, e.g. if
-             ;; c-indent-one-line-block is used together with the
-             ;; one-liner-defun cleanup.
-             (when c-syntactic-indentation
-               (c-indent-line)))
-
-           ;; does a newline go after the brace?
-           (if (memq 'after newlines)
-               (c-newline-and-indent))
-           ))))
+           (c-do-brace-electrics 'assume 'ignore))
+         (c-indent-line))))
 
     ;; blink the paren
     (and (eq (c-last-command-char) ?\})
@@ -903,7 +944,8 @@ is inhibited."
                       c-electric-flag
                       (eq (c-last-command-char) ?/)
                       (eq (char-before) (if literal ?* ?/))))
-    (self-insert-command (prefix-numeric-value arg))
+    (let (post-self-insert-hook)       ; Disable random functionality.
+      (self-insert-command (prefix-numeric-value arg)))
     (if indentp
        (indent-according-to-mode))))
 
@@ -916,7 +958,8 @@ supplied, point is inside a literal, or 
`c-syntactic-indentation' is nil,
 this indentation is inhibited."
 
   (interactive "*P")
-  (self-insert-command (prefix-numeric-value arg))
+  (let (post-self-insert-hook)         ; Disable random functionality.
+    (self-insert-command (prefix-numeric-value arg)))
   ;; if we are in a literal, or if arg is given do not reindent the
   ;; current line, unless this star introduces a comment-only line.
   (if (c-save-buffer-state ()
@@ -963,7 +1006,8 @@ settings of `c-cleanup-list'."
       (setq lim (c-most-enclosing-brace (c-parse-state))
            literal (c-in-literal lim)))
 
-    (self-insert-command (prefix-numeric-value arg))
+    (let (post-self-insert-hook)       ; Disable random functionality.
+      (self-insert-command (prefix-numeric-value arg)))
 
     (if (and c-electric-flag (not literal) (not arg))
        ;; do all cleanups and newline insertions if c-auto-newline is on.
@@ -1032,7 +1076,8 @@ reindented unless `c-syntactic-indentation' is nil.
         newlines is-scope-op
         ;; shut this up
         (c-echo-syntactic-information-p nil))
-    (self-insert-command (prefix-numeric-value arg))
+    (let (post-self-insert-hook)       ; Disable random functionality.
+      (self-insert-command (prefix-numeric-value arg)))
     ;; Any electric action?
     (if (and c-electric-flag (not literal) (not arg))
        ;; Unless we're at EOL, only re-indentation happens.
@@ -1125,7 +1170,8 @@ numeric argument is supplied, or the point is inside a 
literal."
   (let ((c-echo-syntactic-information-p nil)
        final-pos found-delim case-fold-search)
 
-    (self-insert-command (prefix-numeric-value arg))
+    (let (post-self-insert-hook)       ; Disable random functionality.
+      (self-insert-command (prefix-numeric-value arg)))
     (setq final-pos (point))
 
 ;;;; 2010-01-31: There used to be code here to put a syntax-table text
@@ -1190,7 +1236,9 @@ newline cleanups are done if appropriate; see the 
variable `c-cleanup-list'."
        ;; shut this up
        (c-echo-syntactic-information-p nil)
        case-fold-search)
-    (self-insert-command (prefix-numeric-value arg))
+    (let (post-self-insert-hook) ; The only way to get defined functionality
+                                ; from `self-insert-command'.
+      (self-insert-command (prefix-numeric-value arg)))
 
     (if (and (not arg) (not literal))
        (let* ( ;; We want to inhibit blinking the paren since this will
@@ -1239,6 +1287,12 @@ newline cleanups are done if appropriate; see the 
variable `c-cleanup-list'."
              (delete-region (match-beginning 0) (match-end 0))
              (insert-and-inherit "} catch (")))
 
+         ;; Apply `electric-pair-mode' stuff.
+         (when (and (boundp 'electric-pair-mode)
+                    electric-pair-mode)
+           (let (post-self-insert-hook)
+             (electric-pair-post-self-insert-function)))
+
          ;; Check for clean-ups at function calls.  These two DON'T need
          ;; `c-electric-flag' or `c-syntactic-indentation' set.
          ;; Point is currently just after the inserted paren.



reply via email to

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