Commit 223e7b87 authored by Alan Mackenzie's avatar Alan Mackenzie
Browse files

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.
parent 9530108f
Pipeline #530 failed with stage
in 47 minutes and 37 seconds
......@@ -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.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment