X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/ab1dc14b220747e527d507d40905a24ba5c692d9..becf0483bf5ca42b0aab7533ed02ff21cc509c1a:/lisp/delsel.el diff --git a/lisp/delsel.el b/lisp/delsel.el index a643567220..1ada02705f 100644 --- a/lisp/delsel.el +++ b/lisp/delsel.el @@ -1,9 +1,10 @@ ;;; delsel.el --- delete selection if you insert -;; Copyright (C) 1992, 1997-1998, 2001-2012 Free Software Foundation, Inc. +;; Copyright (C) 1992, 1997-1998, 2001-2014 Free Software Foundation, +;; Inc. ;; Author: Matthieu Devin -;; Maintainer: FSF +;; Maintainer: emacs-devel@gnu.org ;; Created: 14 Jul 92 ;; Keywords: convenience emulations @@ -44,9 +45,12 @@ ;; `kill-region' is used on the selection, rather than ;; `delete-region'. (Text selected with the mouse will typically ;; be yankable anyhow.) -;; non-nil +;; t ;; The normal case: delete the active region prior to executing ;; the command which will insert replacement text. +;; +;; For commands which need to dynamically determine this behavior. +;; The function should return one of the above values or nil. ;;; Code: @@ -60,88 +64,131 @@ With a prefix argument ARG, enable Delete Selection mode if ARG is positive, and disable it otherwise. If called from Lisp, enable the mode if ARG is omitted or nil. -When Delete Selection mode is enabled, Transient Mark mode is also -enabled and typed text replaces the selection if the selection is -active. Otherwise, typed text is just inserted at point regardless of -any selection." +When Delete Selection mode is enabled, typed text replaces the selection +if the selection is active. Otherwise, typed text is just inserted at +point regardless of any selection." :global t :group 'editing-basics (if (not delete-selection-mode) (remove-hook 'pre-command-hook 'delete-selection-pre-hook) - (add-hook 'pre-command-hook 'delete-selection-pre-hook) - (transient-mark-mode t))) + (add-hook 'pre-command-hook 'delete-selection-pre-hook))) (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))) + ;; Don't allow `kill-region' to change the value of `this-command'. + (let (this-command) + (kill-region (point) (mark) t)) + (funcall region-extract-function 'delete-only)) t) +(defun delete-selection-helper (type) + "Delete 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.) + t + The normal case: delete the active region prior to executing + the command which will insert replacement text. + FUNCTION + For commands which need to dynamically determine this behavior. + FUNCTION should take no argument and return one of the above values or nil." + (condition-case data + (cond ((eq type 'kill) + (delete-active-region t) + (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)))) + ((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)) + (let ((pos (copy-marker (region-beginning)))) + (delete-active-region) + ;; If the region was, say, rectangular, make sure we yank + ;; from the top, to "replace". + (goto-char pos))) + ((eq type 'supersede) + (let ((empty-region (= (point) (mark)))) + (delete-active-region) + (unless empty-region + (setq this-command 'ignore)))) + ((functionp type) (delete-selection-helper (funcall 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 () - (when (and delete-selection-mode transient-mark-mode mark-active + "Function run before commands that delete selections are executed. +Commands which will delete the selection need a `delete-selection' +property on their symbol; commands which insert text but don't +have this property won't delete the selection. +See `delete-selection-helper'." + (when (and delete-selection-mode (use-region-p) (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)))))) - -(put 'self-insert-command 'delete-selection t) -(put 'self-insert-iso 'delete-selection t) + (delete-selection-helper (and (symbolp this-command) + (get this-command 'delete-selection))))) + +(put 'self-insert-command 'delete-selection + (lambda () + (not (run-hook-with-args-until-success + 'self-insert-uses-region-functions)))) + +(put 'insert-char 'delete-selection t) +(put 'quoted-insert 'delete-selection t) (put 'yank 'delete-selection 'yank) (put 'clipboard-yank 'delete-selection 'yank) (put 'insert-register 'delete-selection t) - -(put 'delete-backward-char 'delete-selection 'supersede) -(put 'backward-delete-char-untabify 'delete-selection 'supersede) +;; delete-backward-char and delete-forward-char already delete the selection by +;; default, but not delete-char. (put 'delete-char 'delete-selection 'supersede) +(put 'reindent-then-newline-and-indent 'delete-selection t) (put 'newline-and-indent 'delete-selection t) (put 'newline 'delete-selection t) +(put 'electric-newline-and-maybe-indent 'delete-selection t) (put 'open-line 'delete-selection 'kill) ;; This is very useful for canceling a selection in the minibuffer without @@ -151,7 +198,7 @@ any selection." In Delete Selection mode, if the mark is active, just deactivate it; then it takes a second \\[keyboard-quit] to abort the minibuffer." (interactive) - (if (and delete-selection-mode transient-mark-mode mark-active) + (if (and delete-selection-mode (region-active-p)) (setq deactivate-mark t) (abort-recursive-edit))) @@ -168,9 +215,9 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer." (define-key minibuffer-local-completion-map "\C-g" 'abort-recursive-edit) (define-key minibuffer-local-must-match-map "\C-g" 'abort-recursive-edit) (define-key minibuffer-local-isearch-map "\C-g" 'abort-recursive-edit) - (dolist (sym '(self-insert-command self-insert-iso yank clipboard-yank - insert-register delete-backward-char backward-delete-char-untabify - delete-char newline-and-indent newline open-line)) + (dolist (sym '(self-insert-command insert-char quoted-insert yank + clipboard-yank insert-register newline-and-indent + reindent-then-newline-and-indent newline open-line)) (put sym 'delete-selection nil)) ;; continue standard unloading nil)