aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Law2012-10-21 23:15:44 -0400
committerStefan Monnier2012-10-21 23:15:44 -0400
commitb1d39ccce419eeec83a4bc723f6c9daf4ffb2be4 (patch)
treeab245066cbdda726e5f4b667f03d01182a761911
parent4ee8774065666426cda990f91fdec8fe343bdf30 (diff)
downloademacs-b1d39ccce419eeec83a4bc723f6c9daf4ffb2be4.tar.gz
emacs-b1d39ccce419eeec83a4bc723f6c9daf4ffb2be4.zip
* 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
-rw-r--r--lisp/ChangeLog19
-rw-r--r--lisp/delsel.el143
-rw-r--r--lisp/electric.el33
3 files changed, 134 insertions, 61 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 7d532ba899f..6edf13719ce 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,18 @@
12012-10-22 Simon Law <sfllaw@sfllaw.ca> (tiny change)
2
3 * delsel.el (delete-selection-helper): New function, extracted from
4 delete-selection-pre-hook.
5 (delete-selection-pre-hook): Use it.
6 (delete-selection-self-insert-function): New function.
7 (delete-selection-self-insert-hooks): New hook.
8 (self-insert-command, self-insert-iso): Use it.
9 * electric.el (electric-pair-syntax): New function, extracted from
10 electric-pair-post-self-insert-function.
11 (electric-pair-post-self-insert-function): Use it.
12 (electric-pair-delete-selection-self-insert-function): New function.
13 (electric-pair-mode): Require delsel and setup
14 delete-selection-self-insert-hooks (bug#11520).
15
12012-10-20 Chong Yidong <cyd@gnu.org> 162012-10-20 Chong Yidong <cyd@gnu.org>
2 17
3 * vc/vc.el (vc-diff-internal): Set up Diff mode even if there are 18 * vc/vc.el (vc-diff-internal): Set up Diff mode even if there are
@@ -8,8 +23,8 @@
8 23
92012-10-20 Arne Jørgensen <arne@arnested.dk> 242012-10-20 Arne Jørgensen <arne@arnested.dk>
10 25
11 * progmodes/flymake.el (flymake-create-temp-inplace): Use 26 * progmodes/flymake.el (flymake-create-temp-inplace):
12 file-truename. 27 Use file-truename.
13 28
142012-10-20 Eli Zaretskii <eliz@gnu.org> 292012-10-20 Eli Zaretskii <eliz@gnu.org>
15 30
diff --git a/lisp/delsel.el b/lisp/delsel.el
index a6435672201..09f58e086a2 100644
--- a/lisp/delsel.el
+++ b/lisp/delsel.el
@@ -47,6 +47,9 @@
47;; non-nil 47;; non-nil
48;; The normal case: delete the active region prior to executing 48;; The normal case: delete the active region prior to executing
49;; the command which will insert replacement text. 49;; the command which will insert replacement text.
50;; hooks
51;; For commands which need to dynamically determine this behaviour.
52;; Each hook should return one of the above values or nil.
50 53
51;;; Code: 54;;; Code:
52 55
@@ -71,66 +74,106 @@ any selection."
71 (transient-mark-mode t))) 74 (transient-mark-mode t)))
72 75
73(defun delete-active-region (&optional killp) 76(defun delete-active-region (&optional killp)
77 "Delete the active region.
78If KILLP in not-nil, the active region is killed instead of deleted."
74 (if killp 79 (if killp
75 (kill-region (point) (mark)) 80 (kill-region (point) (mark))
76 (delete-region (point) (mark))) 81 (delete-region (point) (mark)))
77 t) 82 t)
78 83
84(defun delete-selection-helper (type)
85 "Deletes selection according to TYPE:
86 'yank
87 For commands which do a yank; ensures the region about to be
88 deleted isn't yanked.
89 'supersede
90 Delete the active region and ignore the current command,
91 i.e. the command will just delete the region.
92 'kill
93 `kill-region' is used on the selection, rather than
94 `delete-region'. (Text selected with the mouse will typically
95 be yankable anyhow.)
96 non-nil
97 The normal case: delete the active region prior to executing
98 the command which will insert replacement text.
99 hooks
100 For commands which need to dynamically determine this behaviour.
101 Each hook should return one of the above values or nil."
102 (condition-case data
103 (cond ((eq type 'kill)
104 (delete-active-region t))
105 ((eq type 'yank)
106 ;; Before a yank command, make sure we don't yank the
107 ;; head of the kill-ring that really comes from the
108 ;; currently active region we are going to delete.
109 ;; That would make yank a no-op.
110 (when (and (string= (buffer-substring-no-properties
111 (point) (mark))
112 (car kill-ring))
113 (fboundp 'mouse-region-match)
114 (mouse-region-match))
115 (current-kill 1))
116 (delete-active-region))
117 ((eq type 'supersede)
118 (let ((empty-region (= (point) (mark))))
119 (delete-active-region)
120 (unless empty-region
121 (setq this-command 'ignore))))
122 ((and (symbolp type) (not (booleanp type)))
123 (delete-selection-helper
124 (run-hook-with-args-until-success type)))
125 (type
126 (delete-active-region)
127 (if (and overwrite-mode
128 (eq this-command 'self-insert-command))
129 (let ((overwrite-mode nil))
130 (self-insert-command
131 (prefix-numeric-value current-prefix-arg))
132 (setq this-command 'ignore)))))
133 ;; If ask-user-about-supersession-threat signals an error,
134 ;; stop safe_run_hooks from clearing out pre-command-hook.
135 (file-supersession (message "%s" (cadr data)) (ding))
136 (text-read-only
137 ;; This signal may come either from `delete-active-region' or
138 ;; `self-insert-command' (when `overwrite-mode' is non-nil).
139 ;; To avoid clearing out `pre-command-hook' we handle this case
140 ;; by issuing a simple message. Note, however, that we do not
141 ;; handle all related problems: When read-only text ends before
142 ;; the end of the region, the latter is not deleted but any
143 ;; subsequent insertion will succeed. We could avoid this case
144 ;; by doing a (setq this-command 'ignore) here. This would,
145 ;; however, still not handle the case where read-only text ends
146 ;; precisely where the region starts: In that case the deletion
147 ;; would succeed but the subsequent insertion would fail with a
148 ;; text-read-only error. To handle that case we would have to
149 ;; investigate text properties at both ends of the region and
150 ;; skip the deletion when inserting text is forbidden there.
151 (message "Text is read-only") (ding))))
152
79(defun delete-selection-pre-hook () 153(defun delete-selection-pre-hook ()
154 "Normal hook run before commands that delete selections are executed.
155Commands which will delete the selection need a 'delete-selection
156property on their symbols; commands which insert text but don't
157have this property won't delete the selection.
158
159See `delete-selection-helper'.
160"
80 (when (and delete-selection-mode transient-mark-mode mark-active 161 (when (and delete-selection-mode transient-mark-mode mark-active
81 (not buffer-read-only)) 162 (not buffer-read-only))
82 (let ((type (and (symbolp this-command) 163 (let ((type (and (symbolp this-command)
83 (get this-command 'delete-selection)))) 164 (get this-command 'delete-selection))))
84 (condition-case data 165 (delete-selection-helper type))))
85 (cond ((eq type 'kill) 166
86 (delete-active-region t)) 167(defun delete-selection-self-insert-function ()
87 ((eq type 'yank) 168 t)
88 ;; Before a yank command, make sure we don't yank the 169
89 ;; head of the kill-ring that really comes from the 170(defvar delete-selection-self-insert-hooks
90 ;; currently active region we are going to delete. 171 '(delete-selection-self-insert-function)
91 ;; That would make yank a no-op. 172 "Abnormal hook run before commands that insert characters.
92 (when (and (string= (buffer-substring-no-properties 173This hook should return a TYPE that `delete-selection-helper' understands.")
93 (point) (mark)) 174
94 (car kill-ring)) 175(put 'self-insert-command 'delete-selection 'delete-selection-self-insert-hooks)
95 (fboundp 'mouse-region-match) 176(put 'self-insert-iso 'delete-selection 'delete-selection-self-insert-hooks)
96 (mouse-region-match))
97 (current-kill 1))
98 (delete-active-region))
99 ((eq type 'supersede)
100 (let ((empty-region (= (point) (mark))))
101 (delete-active-region)
102 (unless empty-region
103 (setq this-command 'ignore))))
104 (type
105 (delete-active-region)
106 (if (and overwrite-mode
107 (eq this-command 'self-insert-command))
108 (let ((overwrite-mode nil))
109 (self-insert-command
110 (prefix-numeric-value current-prefix-arg))
111 (setq this-command 'ignore)))))
112 ;; If ask-user-about-supersession-threat signals an error,
113 ;; stop safe_run_hooks from clearing out pre-command-hook.
114 (file-supersession (message "%s" (cadr data)) (ding))
115 (text-read-only
116 ;; This signal may come either from `delete-active-region' or
117 ;; `self-insert-command' (when `overwrite-mode' is non-nil).
118 ;; To avoid clearing out `pre-command-hook' we handle this case
119 ;; by issuing a simple message. Note, however, that we do not
120 ;; handle all related problems: When read-only text ends before
121 ;; the end of the region, the latter is not deleted but any
122 ;; subsequent insertion will succeed. We could avoid this case
123 ;; by doing a (setq this-command 'ignore) here. This would,
124 ;; however, still not handle the case where read-only text ends
125 ;; precisely where the region starts: In that case the deletion
126 ;; would succeed but the subsequent insertion would fail with a
127 ;; text-read-only error. To handle that case we would have to
128 ;; investigate text properties at both ends of the region and
129 ;; skip the deletion when inserting text is forbidden there.
130 (message "Text is read-only") (ding))))))
131
132(put 'self-insert-command 'delete-selection t)
133(put 'self-insert-iso 'delete-selection t)
134 177
135(put 'yank 'delete-selection 'yank) 178(put 'yank 'delete-selection 'yank)
136(put 'clipboard-yank 'delete-selection 'yank) 179(put 'clipboard-yank 'delete-selection 'yank)
diff --git a/lisp/electric.el b/lisp/electric.el
index 3108a0ed4c0..e6fa1df914f 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -301,14 +301,17 @@ This can be convenient for people who find it easier to hit ) than C-f."
301 :version "24.1" 301 :version "24.1"
302 :type 'boolean) 302 :type 'boolean)
303 303
304(defun electric-pair-syntax (command-event)
305 (and electric-pair-mode
306 (let ((x (assq command-event electric-pair-pairs)))
307 (cond
308 (x (if (eq (car x) (cdr x)) ?\" ?\())
309 ((rassq command-event electric-pair-pairs) ?\))
310 (t (char-syntax command-event))))))
311
304(defun electric-pair-post-self-insert-function () 312(defun electric-pair-post-self-insert-function ()
305 (let* ((syntax (and (eq (char-before) last-command-event) ; Sanity check. 313 (let* ((syntax (and (eq (char-before) last-command-event) ; Sanity check.
306 electric-pair-mode 314 (electric-pair-syntax last-command-event)))
307 (let ((x (assq last-command-event electric-pair-pairs)))
308 (cond
309 (x (if (eq (car x) (cdr x)) ?\" ?\())
310 ((rassq last-command-event electric-pair-pairs) ?\))
311 (t (char-syntax last-command-event))))))
312 ;; FIXME: when inserting the closer, we should maybe use 315 ;; FIXME: when inserting the closer, we should maybe use
313 ;; self-insert-command, although it may prove tricky running 316 ;; self-insert-command, although it may prove tricky running
314 ;; post-self-insert-hook recursively, and we wouldn't want to trigger 317 ;; 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."
355 (eq (char-syntax (following-char)) ?w))) 358 (eq (char-syntax (following-char)) ?w)))
356 (save-excursion (insert closer)))))) 359 (save-excursion (insert closer))))))
357 360
361(defun electric-pair-delete-selection-self-insert-function ()
362 (let ((syntax (electric-pair-syntax last-command-event)))
363 (if (and (memq syntax '(?\( ?\" ?\$)) (use-region-p))
364 'keep
365 t)))
366
358;;;###autoload 367;;;###autoload
359(define-minor-mode electric-pair-mode 368(define-minor-mode electric-pair-mode
360 "Toggle automatic parens pairing (Electric Pair mode). 369 "Toggle automatic parens pairing (Electric Pair mode).
@@ -370,10 +379,16 @@ See options `electric-pair-pairs' and `electric-pair-skip-self'."
370 :global t 379 :global t
371 :group 'electricity 380 :group 'electricity
372 (if electric-pair-mode 381 (if electric-pair-mode
373 (add-hook 'post-self-insert-hook 382 (progn
374 #'electric-pair-post-self-insert-function) 383 (require 'delsel)
384 (add-hook 'post-self-insert-hook
385 #'electric-pair-post-self-insert-function)
386 (add-hook 'delete-selection-self-insert-hooks
387 #'electric-pair-delete-selection-self-insert-function))
375 (remove-hook 'post-self-insert-hook 388 (remove-hook 'post-self-insert-hook
376 #'electric-pair-post-self-insert-function))) 389 #'electric-pair-post-self-insert-function)
390 (remove-hook 'delete-selection-self-insert-hooks
391 #'electric-pair-delete-selection-self-insert-function)))
377 392
378;; Automatically add newlines after/before/around some chars. 393;; Automatically add newlines after/before/around some chars.
379 394