;;; electric.el --- window maker and Command loop for `electric' modes
-;; Copyright (C) 1985-1986, 1995, 2001-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1995, 2001-2013 Free Software Foundation,
+;; Inc.
;; Author: K. Shane Hartman
;; Maintainer: FSF
;;; Code:
-(eval-when-compile (require 'cl))
-
;; This loop is the guts for non-standard modes which retain control
;; until some event occurs. It is a `do-forever', the only way out is
;; to throw. It assumes that you have set up the keymap, window, and
:version "24.1"
:type 'boolean)
+(defun electric-pair-syntax (command-event)
+ (and electric-pair-mode
+ (let ((x (assq command-event electric-pair-pairs)))
+ (cond
+ (x (if (eq (car x) (cdr x)) ?\" ?\())
+ ((rassq command-event electric-pair-pairs) ?\))
+ (t (char-syntax command-event))))))
+
(defun electric-pair-post-self-insert-function ()
(let* ((syntax (and (eq (char-before) last-command-event) ; Sanity check.
- electric-pair-mode
- (let ((x (assq last-command-event electric-pair-pairs)))
- (cond
- (x (if (eq (car x) (cdr x)) ?\" ?\())
- ((rassq last-command-event electric-pair-pairs) ?\))
- (t (char-syntax last-command-event))))))
+ (electric-pair-syntax last-command-event)))
;; FIXME: when inserting the closer, we should maybe use
;; self-insert-command, although it may prove tricky running
;; post-self-insert-hook recursively, and we wouldn't want to trigger
((and (memq syntax '(?\( ?\" ?\$)) (use-region-p))
(if (> (mark) (point))
(goto-char (mark))
- ;; We already inserted the open-paren but at the end of the region,
- ;; so we have to remove it and start over.
- (delete-char -1)
- (save-excursion
+ ;; We already inserted the open-paren but at the end of the
+ ;; region, so we have to remove it and start over.
+ (delete-char -1)
+ (save-excursion
(goto-char (mark))
- (insert last-command-event)))
+ ;; Do not insert after `save-excursion' marker (Bug#11520).
+ (insert-before-markers last-command-event)))
(insert closer))
;; Backslash-escaped: no pairing, no skipping.
((save-excursion
(eq (char-syntax (following-char)) ?w)))
(save-excursion (insert closer))))))
+(defun electric-pair-will-use-region ()
+ (and (use-region-p)
+ (memq (electric-pair-syntax last-command-event) '(?\( ?\" ?\$))))
+
;;;###autoload
(define-minor-mode electric-pair-mode
"Toggle automatic parens pairing (Electric Pair mode).
:global t
:group 'electricity
(if electric-pair-mode
- (add-hook 'post-self-insert-hook
- #'electric-pair-post-self-insert-function)
+ (progn
+ (add-hook 'post-self-insert-hook
+ #'electric-pair-post-self-insert-function)
+ (add-hook 'self-insert-uses-region-functions
+ #'electric-pair-will-use-region))
(remove-hook 'post-self-insert-hook
- #'electric-pair-post-self-insert-function)))
+ #'electric-pair-post-self-insert-function)
+ (remove-hook 'self-insert-uses-region-functions
+ #'electric-pair-will-use-region)))
;; Automatically add newlines after/before/around some chars.
(not (nth 8 (save-excursion (syntax-ppss pos)))))
(let ((end (copy-marker (point) t)))
(goto-char pos)
- (case (if (functionp rule) (funcall rule) rule)
+ (pcase (if (functionp rule) (funcall rule) rule)
;; FIXME: we used `newline' down here which called
;; self-insert-command and ran post-self-insert-hook recursively.
;; It happened to make electric-indent-mode work automatically with
;; electric-layout-mode (at the cost of re-indenting lines
;; multiple times), but I'm not sure it's what we want.
- (before (goto-char (1- pos)) (skip-chars-backward " \t")
+ (`before (goto-char (1- pos)) (skip-chars-backward " \t")
(unless (bolp) (insert "\n")))
- (after (insert "\n")) ; FIXME: check eolp before inserting \n?
- (around (save-excursion
+ (`after (insert "\n")) ; FIXME: check eolp before inserting \n?
+ (`around (save-excursion
(goto-char (1- pos)) (skip-chars-backward " \t")
(unless (bolp) (insert "\n")))
(insert "\n"))) ; FIXME: check eolp before inserting \n?