aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2019-01-15 15:54:02 +0000
committerAlan Mackenzie2019-01-15 15:54:02 +0000
commit223e7b87872d4a010ae1c9a6f09a9c15aee46692 (patch)
tree609573333dd10bdce35efc2cfff7ca7b4ea643df
parent9530108fbc8bbf1ad5c1debe4b4f21da1238325b (diff)
downloademacs-223e7b87872d4a010ae1c9a6f09a9c15aee46692.tar.gz
emacs-223e7b87872d4a010ae1c9a6f09a9c15aee46692.zip
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.
-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 @@
47;; Silence the compiler. 47;; Silence the compiler.
48(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge 48(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge
49 ; which looks at this. 49 ; which looks at this.
50(cc-bytecomp-defun electric-pair-post-self-insert-function)
50 51
51;; Indentation / Display syntax functions 52;; Indentation / Display syntax functions
52(defvar c-fix-backslashes t) 53(defvar c-fix-backslashes t)
@@ -503,7 +504,8 @@ inside a literal or a macro, nothing special happens."
503 (eq (char-before) ?\\)))) 504 (eq (char-before) ?\\))))
504 (c-in-literal))) 505 (c-in-literal)))
505 ;; do nothing special 506 ;; do nothing special
506 (self-insert-command (prefix-numeric-value arg)) 507 (let (post-self-insert-hook) ; Disable random functionality.
508 (self-insert-command (prefix-numeric-value arg)))
507 ;; place the pound character at the left edge 509 ;; place the pound character at the left edge
508 (let ((pos (- (point-max) (point))) 510 (let ((pos (- (point-max) (point)))
509 (bolp (bolp))) 511 (bolp (bolp)))
@@ -694,6 +696,134 @@ inside a literal or a macro, nothing special happens."
694 t)))) 696 t))))
695 (goto-char (- (point-max) pos)))))) 697 (goto-char (- (point-max) pos))))))
696 698
699(defun c-do-brace-electrics (before after)
700 ;; Point is just after a brace. Indent the various lines, add any required
701 ;; auto newlines, and apply pertinent clean ups. It is assumed that the
702 ;; caller has checked that point is at EOL if need be, and that the brace is
703 ;; not in a comment or string, and suchlike.
704 ;;
705 ;; BEFORE and AFTER qualify the newlines required before and after the
706 ;; brace as follows:
707 ;; If
708 ;; o - nil: insert a newline or not according to `c-hanging-braces-alist'.
709 ;; o - 'ignore: don't insert a newline.
710 ;; o - 'assume: insert a newline.
711 ;;
712 ;; The return value has no significance.
713 (let (;; shut this up too
714 (c-echo-syntactic-information-p nil)
715 newlines
716 ln-syntax br-syntax syntax) ; Syntactic context of the original line,
717 ; of the brace itself, of the line the
718 ; brace ends up on.
719 (c-save-buffer-state ((c-syntactic-indentation-in-macros t)
720 (c-auto-newline-analysis t))
721 (setq ln-syntax (c-guess-basic-syntax)))
722 (if c-syntactic-indentation
723 (c-indent-line ln-syntax))
724
725 (when c-auto-newline
726 (backward-char)
727 (setq br-syntax (c-point-syntax)
728 newlines (c-brace-newlines br-syntax))
729
730 ;; Insert the BEFORE newline, if wanted, and reindent the newline.
731 (if (or (and (null before) (memq 'before newlines)
732 (> (current-column) (current-indentation)))
733 (eq before 'assume))
734 (if c-syntactic-indentation
735 ;; Only a plain newline for now - it's indented
736 ;; after the cleanups when the line has its final
737 ;; appearance.
738 (newline)
739 (c-newline-and-indent)))
740 (forward-char)
741
742 ;; `syntax' is the syntactic context of the line which ends up
743 ;; with the brace on it.
744 (setq syntax (if (memq 'before newlines) br-syntax ln-syntax))
745
746 ;; Do all appropriate clean ups
747 (let ((here (point))
748 (pos (- (point-max) (point)))
749 mbeg mend
750 )
751
752 ;; `}': clean up empty defun braces
753 (when (c-save-buffer-state ()
754 (and (memq 'empty-defun-braces c-cleanup-list)
755 (eq (c-last-command-char) ?\})
756 (c-intersect-lists '(defun-close class-close inline-close)
757 syntax)
758 (progn
759 (forward-char -1)
760 (c-skip-ws-backward)
761 (eq (char-before) ?\{))
762 ;; make sure matching open brace isn't in a comment
763 (not (c-in-literal))))
764 (delete-region (point) (1- here))
765 (setq here (- (point-max) pos)))
766 (goto-char here)
767
768 ;; `}': compact to a one-liner defun?
769 (save-match-data
770 (when
771 (and (eq (c-last-command-char) ?\})
772 (memq 'one-liner-defun c-cleanup-list)
773 (c-intersect-lists '(defun-close) syntax)
774 (c-try-one-liner))
775 (setq here (- (point-max) pos))))
776
777 ;; `{': clean up brace-else-brace and brace-elseif-brace
778 (when (eq (c-last-command-char) ?\{)
779 (cond
780 ((and (memq 'brace-else-brace c-cleanup-list)
781 (re-search-backward
782 (concat "}"
783 "\\([ \t\n]\\|\\\\\n\\)*"
784 "else"
785 "\\([ \t\n]\\|\\\\\n\\)*"
786 "{"
787 "\\=")
788 nil t))
789 (delete-region (match-beginning 0) (match-end 0))
790 (insert-and-inherit "} else {"))
791 ((and (memq 'brace-elseif-brace c-cleanup-list)
792 (progn
793 (goto-char (1- here))
794 (setq mend (point))
795 (c-skip-ws-backward)
796 (setq mbeg (point))
797 (eq (char-before) ?\)))
798 (zerop (c-save-buffer-state nil (c-backward-token-2 1 t)))
799 (eq (char-after) ?\()
800 (re-search-backward
801 (concat "}"
802 "\\([ \t\n]\\|\\\\\n\\)*"
803 "else"
804 "\\([ \t\n]\\|\\\\\n\\)+"
805 "if"
806 "\\([ \t\n]\\|\\\\\n\\)*"
807 "\\=")
808 nil t))
809 (delete-region mbeg mend)
810 (goto-char mbeg)
811 (insert ?\ ))))
812
813 (goto-char (- (point-max) pos))
814
815 ;; Indent the line after the cleanups since it might
816 ;; very well indent differently due to them, e.g. if
817 ;; c-indent-one-line-block is used together with the
818 ;; one-liner-defun cleanup.
819 (when c-syntactic-indentation
820 (c-indent-line)))
821
822 ;; does a newline go after the brace?
823 (if (or (and (null after) (memq 'after newlines))
824 (eq after 'assume))
825 (c-newline-and-indent)))))
826
697(defun c-electric-brace (arg) 827(defun c-electric-brace (arg)
698 "Insert a brace. 828 "Insert a brace.
699 829
@@ -716,7 +846,10 @@ settings of `c-cleanup-list' are done."
716 ;; We want to inhibit blinking the paren since this would be 846 ;; We want to inhibit blinking the paren since this would be
717 ;; most disruptive. We'll blink it ourselves later on. 847 ;; most disruptive. We'll blink it ourselves later on.
718 (old-blink-paren blink-paren-function) 848 (old-blink-paren blink-paren-function)
719 blink-paren-function case-fold-search) 849 blink-paren-function case-fold-search
850 (at-eol (looking-at "[ \t]*\\\\?$"))
851 (active-region (and (fboundp 'use-region-p) (use-region-p)))
852 got-pair-} electric-pair-deletion)
720 853
721 (c-save-buffer-state () 854 (c-save-buffer-state ()
722 (setq safepos (c-safe-position (point) (c-parse-state)) 855 (setq safepos (c-safe-position (point) (c-parse-state))
@@ -724,128 +857,36 @@ settings of `c-cleanup-list' are done."
724 857
725 ;; Insert the brace. Note that expand-abbrev might reindent 858 ;; Insert the brace. Note that expand-abbrev might reindent
726 ;; the line here if there's a preceding "else" or something. 859 ;; the line here if there's a preceding "else" or something.
727 (self-insert-command (prefix-numeric-value arg)) 860 (let (post-self-insert-hook) ; the only way to get defined functionality
728 861 ; from `self-insert-command'.
729 (when (and c-electric-flag (not literal) (not arg)) 862 (self-insert-command (prefix-numeric-value arg)))
730 (if (not (looking-at "[ \t]*\\\\?$")) 863
731 (if c-syntactic-indentation 864 ;; Emulate `electric-pair-mode'.
732 (indent-according-to-mode)) 865 (when (and (boundp 'electric-pair-mode)
733 866 electric-pair-mode)
734 (let ( ;; shut this up too 867 (let ((size (buffer-size))
735 (c-echo-syntactic-information-p nil) 868 (c-in-electric-pair-functionality t)
736 newlines 869 post-self-insert-hook)
737 ln-syntax br-syntax syntax) ; Syntactic context of the original line, 870 (electric-pair-post-self-insert-function)
738 ; of the brace itself, of the line the brace ends up on. 871 (setq got-pair-} (and at-eol
739 (c-save-buffer-state ((c-syntactic-indentation-in-macros t) 872 (eq (c-last-command-char) ?{)
740 (c-auto-newline-analysis t)) 873 (eq (char-after) ?}))
741 (setq ln-syntax (c-guess-basic-syntax))) 874 electric-pair-deletion (< (buffer-size) size))))
742 (if c-syntactic-indentation 875
743 (c-indent-line ln-syntax)) 876 ;; Perform any required CC Mode electric actions.
744 877 (cond
745 (when c-auto-newline 878 ((or literal arg (not c-electric-flag) active-region))
746 (backward-char) 879 ((not at-eol)
747 (setq br-syntax (c-point-syntax) 880 (c-indent-line))
748 newlines (c-brace-newlines br-syntax)) 881 (electric-pair-deletion
749 882 (c-indent-line)
750 ;; Insert the BEFORE newline, if wanted, and reindent the newline. 883 (c-do-brace-electrics 'ignore nil))
751 (if (and (memq 'before newlines) 884 (t (c-do-brace-electrics nil nil)
752 (> (current-column) (current-indentation))) 885 (when got-pair-}
753 (if c-syntactic-indentation 886 (save-excursion
754 ;; Only a plain newline for now - it's indented
755 ;; after the cleanups when the line has its final
756 ;; appearance.
757 (newline)
758 (c-newline-and-indent)))
759 (forward-char) 887 (forward-char)
760 888 (c-do-brace-electrics 'assume 'ignore))
761 ;; `syntax' is the syntactic context of the line which ends up 889 (c-indent-line))))
762 ;; with the brace on it.
763 (setq syntax (if (memq 'before newlines) br-syntax ln-syntax))
764
765 ;; Do all appropriate clean ups
766 (let ((here (point))
767 (pos (- (point-max) (point)))
768 mbeg mend
769 )
770
771 ;; `}': clean up empty defun braces
772 (when (c-save-buffer-state ()
773 (and (memq 'empty-defun-braces c-cleanup-list)
774 (eq (c-last-command-char) ?\})
775 (c-intersect-lists '(defun-close class-close inline-close)
776 syntax)
777 (progn
778 (forward-char -1)
779 (c-skip-ws-backward)
780 (eq (char-before) ?\{))
781 ;; make sure matching open brace isn't in a comment
782 (not (c-in-literal))))
783 (delete-region (point) (1- here))
784 (setq here (- (point-max) pos)))
785 (goto-char here)
786
787 ;; `}': compact to a one-liner defun?
788 (save-match-data
789 (when
790 (and (eq (c-last-command-char) ?\})
791 (memq 'one-liner-defun c-cleanup-list)
792 (c-intersect-lists '(defun-close) syntax)
793 (c-try-one-liner))
794 (setq here (- (point-max) pos))))
795
796 ;; `{': clean up brace-else-brace and brace-elseif-brace
797 (when (eq (c-last-command-char) ?\{)
798 (cond
799 ((and (memq 'brace-else-brace c-cleanup-list)
800 (re-search-backward
801 (concat "}"
802 "\\([ \t\n]\\|\\\\\n\\)*"
803 "else"
804 "\\([ \t\n]\\|\\\\\n\\)*"
805 "{"
806 "\\=")
807 nil t))
808 (delete-region (match-beginning 0) (match-end 0))
809 (insert-and-inherit "} else {"))
810 ((and (memq 'brace-elseif-brace c-cleanup-list)
811 (progn
812 (goto-char (1- here))
813 (setq mend (point))
814 (c-skip-ws-backward)
815 (setq mbeg (point))
816 (eq (char-before) ?\)))
817 (zerop (c-save-buffer-state nil (c-backward-token-2 1 t)))
818 (eq (char-after) ?\()
819 ; (progn
820 ; (setq tmp (point))
821 (re-search-backward
822 (concat "}"
823 "\\([ \t\n]\\|\\\\\n\\)*"
824 "else"
825 "\\([ \t\n]\\|\\\\\n\\)+"
826 "if"
827 "\\([ \t\n]\\|\\\\\n\\)*"
828 "\\=")
829 nil t);)
830 ;(eq (match-end 0) tmp);
831 )
832 (delete-region mbeg mend)
833 (goto-char mbeg)
834 (insert ?\ ))))
835
836 (goto-char (- (point-max) pos))
837
838 ;; Indent the line after the cleanups since it might
839 ;; very well indent differently due to them, e.g. if
840 ;; c-indent-one-line-block is used together with the
841 ;; one-liner-defun cleanup.
842 (when c-syntactic-indentation
843 (c-indent-line)))
844
845 ;; does a newline go after the brace?
846 (if (memq 'after newlines)
847 (c-newline-and-indent))
848 ))))
849 890
850 ;; blink the paren 891 ;; blink the paren
851 (and (eq (c-last-command-char) ?\}) 892 (and (eq (c-last-command-char) ?\})
@@ -903,7 +944,8 @@ is inhibited."
903 c-electric-flag 944 c-electric-flag
904 (eq (c-last-command-char) ?/) 945 (eq (c-last-command-char) ?/)
905 (eq (char-before) (if literal ?* ?/)))) 946 (eq (char-before) (if literal ?* ?/))))
906 (self-insert-command (prefix-numeric-value arg)) 947 (let (post-self-insert-hook) ; Disable random functionality.
948 (self-insert-command (prefix-numeric-value arg)))
907 (if indentp 949 (if indentp
908 (indent-according-to-mode)))) 950 (indent-according-to-mode))))
909 951
@@ -916,7 +958,8 @@ supplied, point is inside a literal, or `c-syntactic-indentation' is nil,
916this indentation is inhibited." 958this indentation is inhibited."
917 959
918 (interactive "*P") 960 (interactive "*P")
919 (self-insert-command (prefix-numeric-value arg)) 961 (let (post-self-insert-hook) ; Disable random functionality.
962 (self-insert-command (prefix-numeric-value arg)))
920 ;; if we are in a literal, or if arg is given do not reindent the 963 ;; if we are in a literal, or if arg is given do not reindent the
921 ;; current line, unless this star introduces a comment-only line. 964 ;; current line, unless this star introduces a comment-only line.
922 (if (c-save-buffer-state () 965 (if (c-save-buffer-state ()
@@ -963,7 +1006,8 @@ settings of `c-cleanup-list'."
963 (setq lim (c-most-enclosing-brace (c-parse-state)) 1006 (setq lim (c-most-enclosing-brace (c-parse-state))
964 literal (c-in-literal lim))) 1007 literal (c-in-literal lim)))
965 1008
966 (self-insert-command (prefix-numeric-value arg)) 1009 (let (post-self-insert-hook) ; Disable random functionality.
1010 (self-insert-command (prefix-numeric-value arg)))
967 1011
968 (if (and c-electric-flag (not literal) (not arg)) 1012 (if (and c-electric-flag (not literal) (not arg))
969 ;; do all cleanups and newline insertions if c-auto-newline is on. 1013 ;; do all cleanups and newline insertions if c-auto-newline is on.
@@ -1032,7 +1076,8 @@ reindented unless `c-syntactic-indentation' is nil.
1032 newlines is-scope-op 1076 newlines is-scope-op
1033 ;; shut this up 1077 ;; shut this up
1034 (c-echo-syntactic-information-p nil)) 1078 (c-echo-syntactic-information-p nil))
1035 (self-insert-command (prefix-numeric-value arg)) 1079 (let (post-self-insert-hook) ; Disable random functionality.
1080 (self-insert-command (prefix-numeric-value arg)))
1036 ;; Any electric action? 1081 ;; Any electric action?
1037 (if (and c-electric-flag (not literal) (not arg)) 1082 (if (and c-electric-flag (not literal) (not arg))
1038 ;; Unless we're at EOL, only re-indentation happens. 1083 ;; Unless we're at EOL, only re-indentation happens.
@@ -1125,7 +1170,8 @@ numeric argument is supplied, or the point is inside a literal."
1125 (let ((c-echo-syntactic-information-p nil) 1170 (let ((c-echo-syntactic-information-p nil)
1126 final-pos found-delim case-fold-search) 1171 final-pos found-delim case-fold-search)
1127 1172
1128 (self-insert-command (prefix-numeric-value arg)) 1173 (let (post-self-insert-hook) ; Disable random functionality.
1174 (self-insert-command (prefix-numeric-value arg)))
1129 (setq final-pos (point)) 1175 (setq final-pos (point))
1130 1176
1131;;;; 2010-01-31: There used to be code here to put a syntax-table text 1177;;;; 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'."
1190 ;; shut this up 1236 ;; shut this up
1191 (c-echo-syntactic-information-p nil) 1237 (c-echo-syntactic-information-p nil)
1192 case-fold-search) 1238 case-fold-search)
1193 (self-insert-command (prefix-numeric-value arg)) 1239 (let (post-self-insert-hook) ; The only way to get defined functionality
1240 ; from `self-insert-command'.
1241 (self-insert-command (prefix-numeric-value arg)))
1194 1242
1195 (if (and (not arg) (not literal)) 1243 (if (and (not arg) (not literal))
1196 (let* ( ;; We want to inhibit blinking the paren since this will 1244 (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'."
1239 (delete-region (match-beginning 0) (match-end 0)) 1287 (delete-region (match-beginning 0) (match-end 0))
1240 (insert-and-inherit "} catch ("))) 1288 (insert-and-inherit "} catch (")))
1241 1289
1290 ;; Apply `electric-pair-mode' stuff.
1291 (when (and (boundp 'electric-pair-mode)
1292 electric-pair-mode)
1293 (let (post-self-insert-hook)
1294 (electric-pair-post-self-insert-function)))
1295
1242 ;; Check for clean-ups at function calls. These two DON'T need 1296 ;; Check for clean-ups at function calls. These two DON'T need
1243 ;; `c-electric-flag' or `c-syntactic-indentation' set. 1297 ;; `c-electric-flag' or `c-syntactic-indentation' set.
1244 ;; Point is currently just after the inserted paren. 1298 ;; Point is currently just after the inserted paren.