1993-05-19 19:08:12 +00:00
|
|
|
;;; delsel.el --- delete selection if you insert
|
1993-03-17 17:17:05 +00:00
|
|
|
|
2015-01-01 22:26:41 +00:00
|
|
|
;; Copyright (C) 1992, 1997-1998, 2001-2015 Free Software Foundation,
|
2013-01-01 09:11:05 +00:00
|
|
|
;; Inc.
|
1993-03-17 17:17:05 +00:00
|
|
|
|
|
|
|
;; Author: Matthieu Devin <devin@lucid.com>
|
2014-02-10 01:34:22 +00:00
|
|
|
;; Maintainer: emacs-devel@gnu.org
|
1993-03-17 17:17:05 +00:00
|
|
|
;; Created: 14 Jul 92
|
2000-05-24 15:24:37 +00:00
|
|
|
;; Keywords: convenience emulations
|
1993-03-09 05:27:35 +00:00
|
|
|
|
1996-01-14 07:34:30 +00:00
|
|
|
;; This file is part of GNU Emacs.
|
1993-03-09 05:27:35 +00:00
|
|
|
|
2008-05-06 08:06:51 +00:00
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
1996-01-14 07:34:30 +00:00
|
|
|
;; it under the terms of the GNU General Public License as published by
|
2008-05-06 08:06:51 +00:00
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
;; (at your option) any later version.
|
1993-03-09 05:27:35 +00:00
|
|
|
|
1996-01-14 07:34:30 +00:00
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
;; GNU General Public License for more details.
|
1993-03-09 05:27:35 +00:00
|
|
|
|
1996-01-14 07:34:30 +00:00
|
|
|
;; You should have received a copy of the GNU General Public License
|
2008-05-06 08:06:51 +00:00
|
|
|
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
1993-03-09 05:27:35 +00:00
|
|
|
|
1993-03-17 17:17:05 +00:00
|
|
|
;;; Commentary:
|
1993-03-09 05:27:35 +00:00
|
|
|
|
1996-01-14 07:34:30 +00:00
|
|
|
;; This file makes the active region be pending delete, meaning that
|
|
|
|
;; text inserted while the region is active will replace the region contents.
|
|
|
|
;; This is a popular behavior of personal computers text editors.
|
1993-03-09 05:27:35 +00:00
|
|
|
|
1998-04-23 18:00:06 +00:00
|
|
|
;; Interface:
|
|
|
|
|
|
|
|
;; Commands which will delete the selection need a 'delete-selection
|
|
|
|
;; property on their symbols; commands which insert text but don't
|
2007-10-31 00:30:54 +00:00
|
|
|
;; have this property won't delete the selection. It can be one of
|
1998-04-23 18:00:06 +00:00
|
|
|
;; the values:
|
|
|
|
;; '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.)
|
2012-10-22 12:43:54 +00:00
|
|
|
;; t
|
1998-04-23 18:00:06 +00:00
|
|
|
;; The normal case: delete the active region prior to executing
|
|
|
|
;; the command which will insert replacement text.
|
2012-10-22 12:43:54 +00:00
|
|
|
;; <function>
|
2014-01-05 02:56:08 +00:00
|
|
|
;; For commands which need to dynamically determine this behavior.
|
2012-10-22 12:43:54 +00:00
|
|
|
;; The function should return one of the above values or nil.
|
1993-03-17 17:17:05 +00:00
|
|
|
|
1998-04-23 18:00:06 +00:00
|
|
|
;;; Code:
|
1997-07-15 07:45:25 +00:00
|
|
|
|
2014-10-30 19:19:49 +00:00
|
|
|
(defvar delete-selection-save-to-register nil
|
|
|
|
"If non-nil, deleted region text is stored in this register.
|
|
|
|
Value must be the register (key) to use.")
|
|
|
|
|
1997-07-15 07:45:25 +00:00
|
|
|
;;;###autoload
|
|
|
|
(defalias 'pending-delete-mode 'delete-selection-mode)
|
|
|
|
|
|
|
|
;;;###autoload
|
2000-10-01 00:25:27 +00:00
|
|
|
(define-minor-mode delete-selection-mode
|
1997-07-15 07:45:25 +00:00
|
|
|
"Toggle Delete Selection mode.
|
Fix minor mode docstrings for the new meaning of a nil ARG.
* abbrev.el (abbrev-mode):
* allout.el (allout-mode):
* autoinsert.el (auto-insert-mode):
* autoarg.el (autoarg-mode, autoarg-kp-mode):
* autorevert.el (auto-revert-mode, auto-revert-tail-mode)
(global-auto-revert-mode):
* battery.el (display-battery-mode):
* composite.el (global-auto-composition-mode)
(auto-composition-mode):
* delsel.el (delete-selection-mode):
* desktop.el (desktop-save-mode):
* dired-x.el (dired-omit-mode):
* dirtrack.el (dirtrack-mode):
* doc-view.el (doc-view-minor-mode):
* double.el (double-mode):
* electric.el (electric-indent-mode, electric-pair-mode):
* emacs-lock.el (emacs-lock-mode):
* epa-hook.el (auto-encryption-mode):
* follow.el (follow-mode):
* font-core.el (font-lock-mode):
* frame.el (auto-raise-mode, auto-lower-mode, blink-cursor-mode):
* help.el (temp-buffer-resize-mode):
* hilit-chg.el (highlight-changes-mode)
(highlight-changes-visible-mode):
* hi-lock.el (hi-lock-mode):
* hl-line.el (hl-line-mode, global-hl-line-mode):
* icomplete.el (icomplete-mode):
* ido.el (ido-everywhere):
* image-file.el (auto-image-file-mode):
* image-mode.el (image-minor-mode):
* iswitchb.el (iswitchb-mode):
* jka-cmpr-hook.el (auto-compression-mode):
* linum.el (linum-mode):
* longlines.el (longlines-mode):
* master.el (master-mode):
* mb-depth.el (minibuffer-depth-indicate-mode):
* menu-bar.el (menu-bar-mode):
* minibuf-eldef.el (minibuffer-electric-default-mode):
* mouse-sel.el (mouse-sel-mode):
* msb.el (msb-mode):
* mwheel.el (mouse-wheel-mode):
* outline.el (outline-minor-mode):
* paren.el (show-paren-mode):
* recentf.el (recentf-mode):
* reveal.el (reveal-mode, global-reveal-mode):
* rfn-eshadow.el (file-name-shadow-mode):
* ruler-mode.el (ruler-mode):
* savehist.el (savehist-mode):
* scroll-all.el (scroll-all-mode):
* scroll-bar.el (scroll-bar-mode):
* server.el (server-mode):
* shell.el (shell-dirtrack-mode):
* simple.el (auto-fill-mode, transient-mark-mode)
(visual-line-mode, overwrite-mode, binary-overwrite-mode)
(line-number-mode, column-number-mode, size-indication-mode)
(auto-save-mode, normal-erase-is-backspace-mode, visible-mode):
* strokes.el (strokes-mode):
* time.el (display-time-mode):
* t-mouse.el (gpm-mouse-mode):
* tool-bar.el (tool-bar-mode):
* tooltip.el (tooltip-mode):
* type-break.el (type-break-mode-line-message-mode)
(type-break-query-mode):
* view.el (view-mode):
* whitespace.el (whitespace-mode, whitespace-newline-mode)
(global-whitespace-mode, global-whitespace-newline-mode):
* xt-mouse.el (xterm-mouse-mode): Doc fix.
* emacs-lisp/easy-mmode.el (define-globalized-minor-mode): Fix
autogenerated docstring.
2011-10-19 12:54:24 +00:00
|
|
|
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.
|
1997-07-15 07:45:25 +00:00
|
|
|
|
2014-01-31 07:28:17 +00:00
|
|
|
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."
|
2000-11-03 22:13:18 +00:00
|
|
|
:global t :group 'editing-basics
|
1997-07-15 07:45:25 +00:00
|
|
|
(if (not delete-selection-mode)
|
|
|
|
(remove-hook 'pre-command-hook 'delete-selection-pre-hook)
|
2013-12-11 14:42:34 +00:00
|
|
|
(add-hook 'pre-command-hook 'delete-selection-pre-hook)))
|
1997-07-15 07:45:25 +00:00
|
|
|
|
2014-10-30 19:19:49 +00:00
|
|
|
(defvar delsel--replace-text-or-position nil)
|
|
|
|
|
1993-03-09 05:27:35 +00:00
|
|
|
(defun delete-active-region (&optional killp)
|
2012-10-22 03:15:44 +00:00
|
|
|
"Delete the active region.
|
|
|
|
If KILLP in not-nil, the active region is killed instead of deleted."
|
2014-10-30 19:19:49 +00:00
|
|
|
(cond
|
|
|
|
(killp
|
|
|
|
;; Don't allow `kill-region' to change the value of `this-command'.
|
|
|
|
(let (this-command)
|
|
|
|
(kill-region (point) (mark) t)))
|
|
|
|
(delete-selection-save-to-register
|
|
|
|
(set-register delete-selection-save-to-register
|
|
|
|
(funcall region-extract-function t))
|
|
|
|
(setq delsel--replace-text-or-position
|
|
|
|
(cons (current-buffer)
|
|
|
|
(and (consp buffer-undo-list) (car buffer-undo-list)))))
|
|
|
|
(t
|
|
|
|
(funcall region-extract-function 'delete-only)))
|
1993-03-09 05:37:50 +00:00
|
|
|
t)
|
1993-03-09 05:27:35 +00:00
|
|
|
|
2014-10-30 19:19:49 +00:00
|
|
|
(defun delete-selection-repeat-replace-region (arg)
|
|
|
|
"Repeat replacing text of highlighted region with typed text.
|
|
|
|
Search for the next stretch of text identical to the region last replaced
|
|
|
|
by typing text over it and replaces it with the same stretch of text.
|
|
|
|
With ARG, repeat that many times. `C-u' means until end of buffer."
|
|
|
|
(interactive "P")
|
|
|
|
(let ((old-text (and delete-selection-save-to-register
|
|
|
|
(get-register delete-selection-save-to-register)))
|
|
|
|
(count (if (consp arg) (point-max)
|
|
|
|
(prefix-numeric-value current-prefix-arg))))
|
|
|
|
(if (not (and old-text
|
|
|
|
(> (length old-text) 0)
|
|
|
|
(or (stringp delsel--replace-text-or-position)
|
|
|
|
(buffer-live-p (car delsel--replace-text-or-position)))))
|
|
|
|
(message "No known previous replacement")
|
|
|
|
;; If this is the first use after overwriting regions,
|
|
|
|
;; find the replacement text by looking at the undo list.
|
|
|
|
(when (consp delsel--replace-text-or-position)
|
|
|
|
(let ((buffer (car delsel--replace-text-or-position))
|
|
|
|
(elt (cdr delsel--replace-text-or-position)))
|
|
|
|
(setq delsel--replace-text-or-position nil)
|
|
|
|
(with-current-buffer buffer
|
|
|
|
(save-restriction
|
|
|
|
(widen)
|
|
|
|
;; Find the text that replaced the region via the undo list.
|
|
|
|
(let ((ul buffer-undo-list) u s e)
|
|
|
|
(when elt
|
|
|
|
(while (consp ul)
|
|
|
|
(setq u (car ul) ul (cdr ul))
|
|
|
|
(cond
|
|
|
|
((eq u elt) ;; got it
|
|
|
|
(setq ul nil))
|
|
|
|
((and (consp u) (integerp (car u)) (integerp (cdr u)))
|
|
|
|
(if (and s (= (cdr u) s))
|
|
|
|
(setq s (car u))
|
|
|
|
(setq s (car u) e (cdr u)))))))
|
|
|
|
(cond ((and s e (<= s e) (= s (mark t)))
|
|
|
|
(setq delsel--replace-text-or-position
|
|
|
|
(filter-buffer-substring s e))
|
|
|
|
(set-text-properties
|
|
|
|
0 (length delsel--replace-text-or-position)
|
|
|
|
nil delsel--replace-text-or-position))
|
|
|
|
((and (null s) (eq u elt)) ;; Nothing inserted.
|
|
|
|
(setq delsel--replace-text-or-position ""))
|
|
|
|
(t
|
|
|
|
(message "Cannot locate replacement text"))))))))
|
|
|
|
(while (and (> count 0)
|
|
|
|
delsel--replace-text-or-position
|
|
|
|
(search-forward old-text nil t))
|
|
|
|
(replace-match delsel--replace-text-or-position nil t)
|
|
|
|
(setq count (1- count))))))
|
|
|
|
|
2012-10-22 03:15:44 +00:00
|
|
|
(defun delete-selection-helper (type)
|
2012-10-22 12:43:54 +00:00
|
|
|
"Delete selection according to TYPE:
|
|
|
|
`yank'
|
2012-10-22 03:15:44 +00:00
|
|
|
For commands which do a yank; ensures the region about to be
|
|
|
|
deleted isn't yanked.
|
2012-10-22 12:43:54 +00:00
|
|
|
`supersede'
|
2012-10-22 03:15:44 +00:00
|
|
|
Delete the active region and ignore the current command,
|
|
|
|
i.e. the command will just delete the region.
|
2012-10-22 12:43:54 +00:00
|
|
|
`kill'
|
2012-10-22 03:15:44 +00:00
|
|
|
`kill-region' is used on the selection, rather than
|
|
|
|
`delete-region'. (Text selected with the mouse will typically
|
|
|
|
be yankable anyhow.)
|
2012-10-22 12:43:54 +00:00
|
|
|
t
|
2012-10-22 03:15:44 +00:00
|
|
|
The normal case: delete the active region prior to executing
|
|
|
|
the command which will insert replacement text.
|
2012-10-22 12:43:54 +00:00
|
|
|
FUNCTION
|
2014-01-05 02:56:08 +00:00
|
|
|
For commands which need to dynamically determine this behavior.
|
2012-10-22 12:43:54 +00:00
|
|
|
FUNCTION should take no argument and return one of the above values or nil."
|
2012-10-22 03:15:44 +00:00
|
|
|
(condition-case data
|
|
|
|
(cond ((eq type 'kill)
|
2013-12-11 01:11:24 +00:00
|
|
|
(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))))
|
2012-10-22 03:15:44 +00:00
|
|
|
((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))
|
2013-12-11 14:42:34 +00:00
|
|
|
(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)))
|
2012-10-22 03:15:44 +00:00
|
|
|
((eq type 'supersede)
|
|
|
|
(let ((empty-region (= (point) (mark))))
|
|
|
|
(delete-active-region)
|
|
|
|
(unless empty-region
|
|
|
|
(setq this-command 'ignore))))
|
2012-10-22 12:43:54 +00:00
|
|
|
((functionp type) (delete-selection-helper (funcall type)))
|
2012-10-22 03:15:44 +00:00
|
|
|
(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))))
|
|
|
|
|
1993-05-19 19:08:12 +00:00
|
|
|
(defun delete-selection-pre-hook ()
|
2012-10-22 12:43:54 +00:00
|
|
|
"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
|
2012-10-22 03:15:44 +00:00
|
|
|
have this property won't delete the selection.
|
2012-10-22 12:43:54 +00:00
|
|
|
See `delete-selection-helper'."
|
|
|
|
(when (and delete-selection-mode (use-region-p)
|
1997-07-15 07:45:25 +00:00
|
|
|
(not buffer-read-only))
|
2012-10-22 12:43:54 +00:00
|
|
|
(delete-selection-helper (and (symbolp this-command)
|
|
|
|
(get this-command 'delete-selection)))))
|
2012-10-22 03:15:44 +00:00
|
|
|
|
2012-10-22 12:43:54 +00:00
|
|
|
(put 'self-insert-command 'delete-selection
|
|
|
|
(lambda ()
|
|
|
|
(not (run-hook-with-args-until-success
|
|
|
|
'self-insert-uses-region-functions))))
|
2012-10-22 03:15:44 +00:00
|
|
|
|
2013-12-11 01:11:24 +00:00
|
|
|
(put 'insert-char 'delete-selection t)
|
|
|
|
(put 'quoted-insert 'delete-selection t)
|
|
|
|
|
1995-08-06 07:18:06 +00:00
|
|
|
(put 'yank 'delete-selection 'yank)
|
1995-09-25 18:21:48 +00:00
|
|
|
(put 'clipboard-yank 'delete-selection 'yank)
|
1993-05-20 14:02:07 +00:00
|
|
|
(put 'insert-register 'delete-selection t)
|
2014-02-18 18:14:36 +00:00
|
|
|
;; delete-backward-char and delete-forward-char already delete the selection by
|
|
|
|
;; default, but not delete-char.
|
|
|
|
(put 'delete-char 'delete-selection 'supersede)
|
1993-03-09 05:27:35 +00:00
|
|
|
|
2013-12-11 01:11:24 +00:00
|
|
|
(put 'reindent-then-newline-and-indent 'delete-selection t)
|
1998-04-23 18:00:06 +00:00
|
|
|
(put 'newline-and-indent 'delete-selection t)
|
1993-05-19 19:08:12 +00:00
|
|
|
(put 'newline 'delete-selection t)
|
2014-06-17 13:40:03 +00:00
|
|
|
(put 'electric-newline-and-maybe-indent 'delete-selection t)
|
1998-04-23 18:00:06 +00:00
|
|
|
(put 'open-line 'delete-selection 'kill)
|
|
|
|
|
2011-12-04 08:02:42 +00:00
|
|
|
;; This is very useful for canceling a selection in the minibuffer without
|
1993-03-09 05:27:35 +00:00
|
|
|
;; aborting the minibuffer.
|
|
|
|
(defun minibuffer-keyboard-quit ()
|
|
|
|
"Abort recursive edit.
|
1998-04-23 18:00:06 +00:00
|
|
|
In Delete Selection mode, if the mark is active, just deactivate it;
|
|
|
|
then it takes a second \\[keyboard-quit] to abort the minibuffer."
|
1993-03-09 05:27:35 +00:00
|
|
|
(interactive)
|
2013-12-11 14:42:34 +00:00
|
|
|
(if (and delete-selection-mode (region-active-p))
|
1993-05-20 14:02:07 +00:00
|
|
|
(setq deactivate-mark t)
|
1993-03-09 05:27:35 +00:00
|
|
|
(abort-recursive-edit)))
|
|
|
|
|
2000-08-15 14:20:14 +00:00
|
|
|
(define-key minibuffer-local-map "\C-g" 'minibuffer-keyboard-quit)
|
|
|
|
(define-key minibuffer-local-ns-map "\C-g" 'minibuffer-keyboard-quit)
|
|
|
|
(define-key minibuffer-local-completion-map "\C-g" 'minibuffer-keyboard-quit)
|
|
|
|
(define-key minibuffer-local-must-match-map "\C-g" 'minibuffer-keyboard-quit)
|
|
|
|
(define-key minibuffer-local-isearch-map "\C-g" 'minibuffer-keyboard-quit)
|
|
|
|
|
2007-10-31 00:30:54 +00:00
|
|
|
(defun delsel-unload-function ()
|
|
|
|
"Unload the Delete Selection library."
|
2000-08-15 14:20:14 +00:00
|
|
|
(define-key minibuffer-local-map "\C-g" 'abort-recursive-edit)
|
|
|
|
(define-key minibuffer-local-ns-map "\C-g" 'abort-recursive-edit)
|
|
|
|
(define-key minibuffer-local-completion-map "\C-g" 'abort-recursive-edit)
|
|
|
|
(define-key minibuffer-local-must-match-map "\C-g" 'abort-recursive-edit)
|
2007-10-31 00:30:54 +00:00
|
|
|
(define-key minibuffer-local-isearch-map "\C-g" 'abort-recursive-edit)
|
2013-12-11 14:42:34 +00:00
|
|
|
(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))
|
2008-01-24 11:13:45 +00:00
|
|
|
(put sym 'delete-selection nil))
|
2007-10-31 00:30:54 +00:00
|
|
|
;; continue standard unloading
|
|
|
|
nil)
|
2004-10-17 06:51:48 +00:00
|
|
|
|
1993-05-20 14:02:07 +00:00
|
|
|
(provide 'delsel)
|
1993-03-09 05:27:35 +00:00
|
|
|
|
1993-05-20 14:02:07 +00:00
|
|
|
;;; delsel.el ends here
|