1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-02-02 20:16:25 +00:00

* lisp/delsel.el (delete-selection-helper): New function, extracted from

delete-selection-pre-hook.
(delete-selection-pre-hook): Use it.
(delete-selection-self-insert-function): New function.
(delete-selection-self-insert-hooks): New hook.
(self-insert-command, self-insert-iso): Use it.
* lisp/electric.el (electric-pair-syntax): New function, extracted from
electric-pair-post-self-insert-function.
(electric-pair-post-self-insert-function): Use it.
(electric-pair-delete-selection-self-insert-function): New function.
(electric-pair-mode): Require delsel and setup
delete-selection-self-insert-hooks.

Fixes: debbugs:11520
This commit is contained in:
Simon Law 2012-10-21 23:15:44 -04:00 committed by Stefan Monnier
parent 4ee8774065
commit b1d39ccce4
3 changed files with 133 additions and 60 deletions

View File

@ -1,3 +1,18 @@
2012-10-22 Simon Law <sfllaw@sfllaw.ca> (tiny change)
* delsel.el (delete-selection-helper): New function, extracted from
delete-selection-pre-hook.
(delete-selection-pre-hook): Use it.
(delete-selection-self-insert-function): New function.
(delete-selection-self-insert-hooks): New hook.
(self-insert-command, self-insert-iso): Use it.
* electric.el (electric-pair-syntax): New function, extracted from
electric-pair-post-self-insert-function.
(electric-pair-post-self-insert-function): Use it.
(electric-pair-delete-selection-self-insert-function): New function.
(electric-pair-mode): Require delsel and setup
delete-selection-self-insert-hooks (bug#11520).
2012-10-20 Chong Yidong <cyd@gnu.org>
* vc/vc.el (vc-diff-internal): Set up Diff mode even if there are
@ -8,8 +23,8 @@
2012-10-20 Arne Jørgensen <arne@arnested.dk>
* progmodes/flymake.el (flymake-create-temp-inplace): Use
file-truename.
* progmodes/flymake.el (flymake-create-temp-inplace):
Use file-truename.
2012-10-20 Eli Zaretskii <eliz@gnu.org>

View File

@ -47,6 +47,9 @@
;; non-nil
;; The normal case: delete the active region prior to executing
;; the command which will insert replacement text.
;; hooks
;; For commands which need to dynamically determine this behaviour.
;; Each hook should return one of the above values or nil.
;;; Code:
@ -71,66 +74,106 @@ any selection."
(transient-mark-mode t)))
(defun delete-active-region (&optional killp)
"Delete the active region.
If KILLP in not-nil, the active region is killed instead of deleted."
(if killp
(kill-region (point) (mark))
(delete-region (point) (mark)))
t)
(defun delete-selection-helper (type)
"Deletes selection according to TYPE:
'yank
For commands which do a yank; ensures the region about to be
deleted isn't yanked.
'supersede
Delete the active region and ignore the current command,
i.e. the command will just delete the region.
'kill
`kill-region' is used on the selection, rather than
`delete-region'. (Text selected with the mouse will typically
be yankable anyhow.)
non-nil
The normal case: delete the active region prior to executing
the command which will insert replacement text.
hooks
For commands which need to dynamically determine this behaviour.
Each hook should return one of the above values or nil."
(condition-case data
(cond ((eq type 'kill)
(delete-active-region t))
((eq type 'yank)
;; Before a yank command, make sure we don't yank the
;; head of the kill-ring that really comes from the
;; currently active region we are going to delete.
;; That would make yank a no-op.
(when (and (string= (buffer-substring-no-properties
(point) (mark))
(car kill-ring))
(fboundp 'mouse-region-match)
(mouse-region-match))
(current-kill 1))
(delete-active-region))
((eq type 'supersede)
(let ((empty-region (= (point) (mark))))
(delete-active-region)
(unless empty-region
(setq this-command 'ignore))))
((and (symbolp type) (not (booleanp type)))
(delete-selection-helper
(run-hook-with-args-until-success type)))
(type
(delete-active-region)
(if (and overwrite-mode
(eq this-command 'self-insert-command))
(let ((overwrite-mode nil))
(self-insert-command
(prefix-numeric-value current-prefix-arg))
(setq this-command 'ignore)))))
;; If ask-user-about-supersession-threat signals an error,
;; stop safe_run_hooks from clearing out pre-command-hook.
(file-supersession (message "%s" (cadr data)) (ding))
(text-read-only
;; This signal may come either from `delete-active-region' or
;; `self-insert-command' (when `overwrite-mode' is non-nil).
;; To avoid clearing out `pre-command-hook' we handle this case
;; by issuing a simple message. Note, however, that we do not
;; handle all related problems: When read-only text ends before
;; the end of the region, the latter is not deleted but any
;; subsequent insertion will succeed. We could avoid this case
;; by doing a (setq this-command 'ignore) here. This would,
;; however, still not handle the case where read-only text ends
;; precisely where the region starts: In that case the deletion
;; would succeed but the subsequent insertion would fail with a
;; text-read-only error. To handle that case we would have to
;; investigate text properties at both ends of the region and
;; skip the deletion when inserting text is forbidden there.
(message "Text is read-only") (ding))))
(defun delete-selection-pre-hook ()
"Normal hook run before commands that delete selections are executed.
Commands which will delete the selection need a 'delete-selection
property on their symbols; commands which insert text but don't
have this property won't delete the selection.
See `delete-selection-helper'.
"
(when (and delete-selection-mode transient-mark-mode mark-active
(not buffer-read-only))
(let ((type (and (symbolp this-command)
(get this-command 'delete-selection))))
(condition-case data
(cond ((eq type 'kill)
(delete-active-region t))
((eq type 'yank)
;; Before a yank command, make sure we don't yank the
;; head of the kill-ring that really comes from the
;; currently active region we are going to delete.
;; That would make yank a no-op.
(when (and (string= (buffer-substring-no-properties
(point) (mark))
(car kill-ring))
(fboundp 'mouse-region-match)
(mouse-region-match))
(current-kill 1))
(delete-active-region))
((eq type 'supersede)
(let ((empty-region (= (point) (mark))))
(delete-active-region)
(unless empty-region
(setq this-command 'ignore))))
(type
(delete-active-region)
(if (and overwrite-mode
(eq this-command 'self-insert-command))
(let ((overwrite-mode nil))
(self-insert-command
(prefix-numeric-value current-prefix-arg))
(setq this-command 'ignore)))))
;; If ask-user-about-supersession-threat signals an error,
;; stop safe_run_hooks from clearing out pre-command-hook.
(file-supersession (message "%s" (cadr data)) (ding))
(text-read-only
;; This signal may come either from `delete-active-region' or
;; `self-insert-command' (when `overwrite-mode' is non-nil).
;; To avoid clearing out `pre-command-hook' we handle this case
;; by issuing a simple message. Note, however, that we do not
;; handle all related problems: When read-only text ends before
;; the end of the region, the latter is not deleted but any
;; subsequent insertion will succeed. We could avoid this case
;; by doing a (setq this-command 'ignore) here. This would,
;; however, still not handle the case where read-only text ends
;; precisely where the region starts: In that case the deletion
;; would succeed but the subsequent insertion would fail with a
;; text-read-only error. To handle that case we would have to
;; investigate text properties at both ends of the region and
;; skip the deletion when inserting text is forbidden there.
(message "Text is read-only") (ding))))))
(delete-selection-helper type))))
(put 'self-insert-command 'delete-selection t)
(put 'self-insert-iso 'delete-selection t)
(defun delete-selection-self-insert-function ()
t)
(defvar delete-selection-self-insert-hooks
'(delete-selection-self-insert-function)
"Abnormal hook run before commands that insert characters.
This hook should return a TYPE that `delete-selection-helper' understands.")
(put 'self-insert-command 'delete-selection 'delete-selection-self-insert-hooks)
(put 'self-insert-iso 'delete-selection 'delete-selection-self-insert-hooks)
(put 'yank 'delete-selection 'yank)
(put 'clipboard-yank 'delete-selection 'yank)

View File

@ -301,14 +301,17 @@ This can be convenient for people who find it easier to hit ) than C-f."
: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
@ -355,6 +358,12 @@ This can be convenient for people who find it easier to hit ) than C-f."
(eq (char-syntax (following-char)) ?w)))
(save-excursion (insert closer))))))
(defun electric-pair-delete-selection-self-insert-function ()
(let ((syntax (electric-pair-syntax last-command-event)))
(if (and (memq syntax '(?\( ?\" ?\$)) (use-region-p))
'keep
t)))
;;;###autoload
(define-minor-mode electric-pair-mode
"Toggle automatic parens pairing (Electric Pair mode).
@ -370,10 +379,16 @@ See options `electric-pair-pairs' and `electric-pair-skip-self'."
:global t
:group 'electricity
(if electric-pair-mode
(add-hook 'post-self-insert-hook
#'electric-pair-post-self-insert-function)
(progn
(require 'delsel)
(add-hook 'post-self-insert-hook
#'electric-pair-post-self-insert-function)
(add-hook 'delete-selection-self-insert-hooks
#'electric-pair-delete-selection-self-insert-function))
(remove-hook 'post-self-insert-hook
#'electric-pair-post-self-insert-function)))
#'electric-pair-post-self-insert-function)
(remove-hook 'delete-selection-self-insert-hooks
#'electric-pair-delete-selection-self-insert-function)))
;; Automatically add newlines after/before/around some chars.