diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index 40618e9ef38..1b5b6d401a9 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el @@ -528,71 +528,72 @@ electric-pair-post-self-insert-function and `electric-pair-skip-whitespace' (which see)." (let* ((pos (and electric-pair-mode (electric--after-char-pos))) (skip-whitespace-info)) - (pcase (electric-pair-syntax-info last-command-event) - (`(,syntax ,pair ,unconditional ,_) - (cond - ((null pos) nil) - ;; Wrap a pair around the active region. - ;; - ((and (memq syntax '(?\( ?\) ?\" ?\$)) (use-region-p)) - ;; FIXME: To do this right, we'd need a post-self-insert-function - ;; so we could add-function around it and insert the closer after - ;; all the rest of the hook has run. - (if (or (eq syntax ?\") - (and (eq syntax ?\)) - (>= (point) (mark))) - (and (not (eq syntax ?\))) - (>= (mark) (point)))) - (save-excursion - (goto-char (mark)) - (electric-pair--insert pair)) - (delete-region pos (1- pos)) - (electric-pair--insert pair) - (goto-char (mark)) - (electric-pair--insert last-command-event))) - ;; Backslash-escaped: no pairing, no skipping. - ((save-excursion - (goto-char (1- pos)) - (not (zerop (% (skip-syntax-backward "\\") 2)))) - nil) - ;; Skip self. - ((and (memq syntax '(?\) ?\" ?\$)) - (and (or unconditional - (if (functionp electric-pair-skip-self) - (electric-pair--save-literal-point-excursion - (goto-char pos) - (funcall electric-pair-skip-self last-command-event)) - electric-pair-skip-self)) - (save-excursion - (when (and (not (and unconditional - (eq syntax ?\"))) - (setq skip-whitespace-info - (if (and (not (eq electric-pair-skip-whitespace 'chomp)) - (functionp electric-pair-skip-whitespace)) - (funcall electric-pair-skip-whitespace) - electric-pair-skip-whitespace))) - (funcall electric-pair-skip-whitespace-function)) - (eq (char-after) last-command-event)))) - ;; This is too late: rather than insert&delete we'd want to only - ;; skip (or insert in overwrite mode). The difference is in what - ;; goes in the undo-log and in the intermediate state which might - ;; be visible to other post-self-insert-hook. We'll just have to - ;; live with it for now. - (when skip-whitespace-info - (funcall electric-pair-skip-whitespace-function)) - (delete-region (1- pos) (if (eq skip-whitespace-info 'chomp) - (point) - pos)) - (forward-char)) - ;; Insert matching pair. - ((and (memq syntax '(?\( ?\" ?\$)) - (not overwrite-mode) - (or unconditional - (not (electric-pair--save-literal-point-excursion - (goto-char pos) - (funcall electric-pair-inhibit-predicate - last-command-event))))) - (save-excursion (electric-pair--insert pair)))))))) + (when (characterp last-command-event) + (pcase (electric-pair-syntax-info last-command-event) + (`(,syntax ,pair ,unconditional ,_) + (cond + ((null pos) nil) + ;; Wrap a pair around the active region. + ;; + ((and (memq syntax '(?\( ?\) ?\" ?\$)) (use-region-p)) + ;; FIXME: To do this right, we'd need a post-self-insert-function + ;; so we could add-function around it and insert the closer after + ;; all the rest of the hook has run. + (if (or (eq syntax ?\") + (and (eq syntax ?\)) + (>= (point) (mark))) + (and (not (eq syntax ?\))) + (>= (mark) (point)))) + (save-excursion + (goto-char (mark)) + (electric-pair--insert pair)) + (delete-region pos (1- pos)) + (electric-pair--insert pair) + (goto-char (mark)) + (electric-pair--insert last-command-event))) + ;; Backslash-escaped: no pairing, no skipping. + ((save-excursion + (goto-char (1- pos)) + (not (zerop (% (skip-syntax-backward "\\") 2)))) + nil) + ;; Skip self. + ((and (memq syntax '(?\) ?\" ?\$)) + (and (or unconditional + (if (functionp electric-pair-skip-self) + (electric-pair--save-literal-point-excursion + (goto-char pos) + (funcall electric-pair-skip-self last-command-event)) + electric-pair-skip-self)) + (save-excursion + (when (and (not (and unconditional + (eq syntax ?\"))) + (setq skip-whitespace-info + (if (and (not (eq electric-pair-skip-whitespace 'chomp)) + (functionp electric-pair-skip-whitespace)) + (funcall electric-pair-skip-whitespace) + electric-pair-skip-whitespace))) + (funcall electric-pair-skip-whitespace-function)) + (eq (char-after) last-command-event)))) + ;; This is too late: rather than insert&delete we'd want to only + ;; skip (or insert in overwrite mode). The difference is in what + ;; goes in the undo-log and in the intermediate state which might + ;; be visible to other post-self-insert-hook. We'll just have to + ;; live with it for now. + (when skip-whitespace-info + (funcall electric-pair-skip-whitespace-function)) + (delete-region (1- pos) (if (eq skip-whitespace-info 'chomp) + (point) + pos)) + (forward-char)) + ;; Insert matching pair. + ((and (memq syntax '(?\( ?\" ?\$)) + (not overwrite-mode) + (or unconditional + (not (electric-pair--save-literal-point-excursion + (goto-char pos) + (funcall electric-pair-inhibit-predicate + last-command-event))))) + (save-excursion (electric-pair--insert pair))))))))) (defun electric-pair-open-newline-between-pairs-psif () "Honor `electric-pair-open-newline-between-pairs'.