summaryrefslogtreecommitdiff
path: root/lisp/progmodes/cc-cmds.el
diff options
context:
space:
mode:
authorAlan Mackenzie <acm@muc.de>2019-01-15 15:54:02 +0000
committerAlan Mackenzie <acm@muc.de>2019-01-15 15:54:02 +0000
commit223e7b87872d4a010ae1c9a6f09a9c15aee46692 (patch)
tree609573333dd10bdce35efc2cfff7ca7b4ea643df /lisp/progmodes/cc-cmds.el
parent9530108fbc8bbf1ad5c1debe4b4f21da1238325b (diff)
downloademacs-223e7b87872d4a010ae1c9a6f09a9c15aee46692.tar.gz
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.
Diffstat (limited to 'lisp/progmodes/cc-cmds.el')
-rw-r--r--lisp/progmodes/cc-cmds.el312
1 files changed, 183 insertions, 129 deletions
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index a07527e4b8b..78677fefadb 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.