mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2026-09-10 07:46:51 -04:00
Yank items selected from kill-ring using completion and minibuffer history
* doc/emacs/killing.texi (Earlier Kills): Document standalone M-y. * doc/emacs/search.texi (Isearch Yank): Explain standalone M-y. * doc/lispref/text.texi (Yank Commands): Soften the wording of yank after another yank. * lisp/delsel.el: Put 'yank' property on yank-pop and yank-from-kill-ring. * lisp/isearch.el (isearch-yank-pop): Use with-isearch-suspended and read-from-kill-ring to read a string from the kill-ring and append it to the search string. * lisp/simple.el (yank-pop): Call yank-from-kill-ring and read-from-kill-ring when last-command is not 'yank' instead of signaling an error. Remove "*" from interactive spec. Update docstring. (read-from-kill-ring): New function. (yank-from-kill-ring): New command. https://lists.gnu.org/archive/html/emacs-devel/2020-11/msg00801.html
This commit is contained in:
parent
2490ba0eb0
commit
83b5fcb001
|
|
@ -362,7 +362,7 @@ through the possibilities.
|
|||
that was yanked and replaces it with the text from an earlier kill.
|
||||
So, to recover the text of the next-to-the-last kill, first use
|
||||
@kbd{C-y} to yank the last kill, and then use @kbd{M-y} to replace it
|
||||
with the previous kill. @kbd{M-y} is allowed only after a @kbd{C-y}
|
||||
with the previous kill. This works only after a @kbd{C-y}
|
||||
or another @kbd{M-y}.
|
||||
|
||||
You can understand @kbd{M-y} in terms of a last-yank pointer which
|
||||
|
|
@ -394,6 +394,15 @@ pointer remains at the same place in the kill ring, so repeating
|
|||
When you call @kbd{C-y} with a numeric argument, that also sets the
|
||||
last-yank pointer to the entry that it yanks.
|
||||
|
||||
Alternatively, when the previous command was not a yank command,
|
||||
@kbd{M-y} activates the minibuffer where you can browse previous kills
|
||||
using the minibuffer history commands (@pxref{Minibuffer History}), or
|
||||
you can use completion commands (@pxref{Completion}) on a list of
|
||||
previously killed blocks of text from the kill ring. Exiting the
|
||||
minibuffer will insert the selected text to the buffer. With a plain
|
||||
prefix argument (@kbd{C-u M-y}), this command leaves the cursor in
|
||||
front of the inserted text, and sets the mark at the end.
|
||||
|
||||
@node Appending Kills
|
||||
@subsection Appending Kills
|
||||
|
||||
|
|
|
|||
|
|
@ -295,9 +295,12 @@ from point to the @var{n}th occurrence of the specified character.
|
|||
appends the current kill to the search string. @kbd{M-y}
|
||||
(@code{isearch-yank-pop}), if called after @kbd{C-y}, replaces that
|
||||
appended text with an earlier kill, similar to the usual @kbd{M-y}
|
||||
(@code{yank-pop}) command (@pxref{Yanking}). Clicking @kbd{mouse-2}
|
||||
in the echo area appends the current X selection (@pxref{Primary
|
||||
Selection}) to the search string (@code{isearch-yank-x-selection}).
|
||||
(@code{yank-pop}) command. When @kbd{M-y} is called not after
|
||||
@kbd{C-y}, then it activates the minibuffer where you can select
|
||||
a previous kill to append to the search string (@pxref{Earlier
|
||||
Kills}). Clicking @kbd{mouse-2} in the echo area appends the current
|
||||
X selection (@pxref{Primary Selection}) to the search string
|
||||
(@code{isearch-yank-x-selection}).
|
||||
|
||||
@kindex C-M-d @r{(Incremental search)}
|
||||
@kindex C-M-y @r{(Incremental search)}
|
||||
|
|
|
|||
|
|
@ -1100,7 +1100,7 @@ one, it rotates the kill ring to place the yanked string at the front.
|
|||
This command replaces the just-yanked entry from the kill ring with a
|
||||
different entry from the kill ring.
|
||||
|
||||
This is allowed only immediately after a @code{yank} or another
|
||||
This works only immediately after a @code{yank} or another
|
||||
@code{yank-pop}. At such a time, the region contains text that was just
|
||||
inserted by yanking. @code{yank-pop} deletes that text and inserts in
|
||||
its place a different piece of killed text. It does not add the deleted
|
||||
|
|
|
|||
7
etc/NEWS
7
etc/NEWS
|
|
@ -208,6 +208,13 @@ This command would previously not redefine values defined by these
|
|||
forms, but this command has now been changed to work more like
|
||||
'eval-defun', and reset the values as specified.
|
||||
|
||||
+++
|
||||
** Standalone 'M-y' uses the minibuffer to complete previous kills.
|
||||
When 'M-y' is typed not after a yank command, it activates the minibuffer
|
||||
where you can browse previous kills using the minibuffer history or
|
||||
completion. In Isearch 'C-s M-y' uses the minibuffer with completion
|
||||
on previous kills to read a string and append it to the search string.
|
||||
|
||||
---
|
||||
** New user options 'copy-region-blink-delay' and 'delete-pair-blink-delay'.
|
||||
'copy-region-blink-delay' specifies a delay to indicate the region
|
||||
|
|
|
|||
|
|
@ -274,6 +274,8 @@ to `delete-selection-mode'."
|
|||
(put 'quoted-insert 'delete-selection t)
|
||||
|
||||
(put 'yank 'delete-selection 'yank)
|
||||
(put 'yank-pop 'delete-selection 'yank)
|
||||
(put 'yank-from-kill-ring 'delete-selection 'yank)
|
||||
(put 'clipboard-yank 'delete-selection 'yank)
|
||||
(put 'insert-register 'delete-selection t)
|
||||
;; delete-backward-char and delete-forward-char already delete the selection by
|
||||
|
|
|
|||
|
|
@ -2500,11 +2500,18 @@ If search string is empty, just beep."
|
|||
"Replace just-yanked search string with previously killed string."
|
||||
(interactive)
|
||||
(if (not (memq last-command '(isearch-yank-kill isearch-yank-pop)))
|
||||
;; Fall back on `isearch-yank-kill' for the benefits of people
|
||||
;; who are used to the old behavior of `M-y' in isearch mode. In
|
||||
;; future, this fallback may be changed if we ever change
|
||||
;; `yank-pop' to do something like the kill-ring-browser.
|
||||
(isearch-yank-kill)
|
||||
;; Yank string from kill-ring-browser.
|
||||
(with-isearch-suspended
|
||||
(let ((string (read-from-kill-ring)))
|
||||
(if (and isearch-case-fold-search
|
||||
(eq 'not-yanks search-upper-case))
|
||||
(setq string (downcase string)))
|
||||
(if isearch-regexp (setq string (regexp-quote string)))
|
||||
(setq isearch-yank-flag t)
|
||||
(setq isearch-new-string (concat isearch-string string)
|
||||
isearch-new-message (concat isearch-message
|
||||
(mapconcat 'isearch-text-char-description
|
||||
string "")))))
|
||||
(isearch-pop-state)
|
||||
(isearch-yank-string (current-kill 1))))
|
||||
|
||||
|
|
|
|||
124
lisp/simple.el
124
lisp/simple.el
|
|
@ -5344,7 +5344,7 @@ Normally set from the UNDO element of a yank-handler; see `insert-for-yank'.")
|
|||
|
||||
(defun yank-pop (&optional arg)
|
||||
"Replace just-yanked stretch of killed text with a different stretch.
|
||||
This command is allowed only immediately after a `yank' or a
|
||||
The main use of this command is immediately after a `yank' or a
|
||||
`yank-pop'. At such a time, the region contains a stretch of
|
||||
reinserted previously-killed text. `yank-pop' deletes that text
|
||||
and inserts in its place a different stretch of killed text by
|
||||
|
|
@ -5359,30 +5359,36 @@ comes the newest one.
|
|||
|
||||
This command honors the `yank-handled-properties' and
|
||||
`yank-excluded-properties' variables, and the `yank-handler' text
|
||||
property, in the way that `yank' does."
|
||||
(interactive "*p")
|
||||
property, in the way that `yank' does.
|
||||
|
||||
When this command is called not immediately after a `yank' or a
|
||||
`yank-pop', then it activates the minibuffer with its completion
|
||||
and history filled with previously-killed items from the
|
||||
`kill-ring' variable, and reads a string to yank at point.
|
||||
See `yank-from-kill-ring' for more details."
|
||||
(interactive "p")
|
||||
(if (not (eq last-command 'yank))
|
||||
(user-error "Previous command was not a yank"))
|
||||
(setq this-command 'yank)
|
||||
(unless arg (setq arg 1))
|
||||
(let ((inhibit-read-only t)
|
||||
(before (< (point) (mark t))))
|
||||
(if before
|
||||
(funcall (or yank-undo-function 'delete-region) (point) (mark t))
|
||||
(funcall (or yank-undo-function 'delete-region) (mark t) (point)))
|
||||
(setq yank-undo-function nil)
|
||||
(set-marker (mark-marker) (point) (current-buffer))
|
||||
(insert-for-yank (current-kill arg))
|
||||
;; Set the window start back where it was in the yank command,
|
||||
;; if possible.
|
||||
(set-window-start (selected-window) yank-window-start t)
|
||||
(if before
|
||||
;; This is like exchange-point-and-mark, but doesn't activate the mark.
|
||||
;; It is cleaner to avoid activation, even though the command
|
||||
;; loop would deactivate the mark because we inserted text.
|
||||
(goto-char (prog1 (mark t)
|
||||
(set-marker (mark-marker) (point) (current-buffer))))))
|
||||
nil)
|
||||
(yank-from-kill-ring (read-from-kill-ring) current-prefix-arg)
|
||||
(setq this-command 'yank)
|
||||
(unless arg (setq arg 1))
|
||||
(let ((inhibit-read-only t)
|
||||
(before (< (point) (mark t))))
|
||||
(if before
|
||||
(funcall (or yank-undo-function 'delete-region) (point) (mark t))
|
||||
(funcall (or yank-undo-function 'delete-region) (mark t) (point)))
|
||||
(setq yank-undo-function nil)
|
||||
(set-marker (mark-marker) (point) (current-buffer))
|
||||
(insert-for-yank (current-kill arg))
|
||||
;; Set the window start back where it was in the yank command,
|
||||
;; if possible.
|
||||
(set-window-start (selected-window) yank-window-start t)
|
||||
(if before
|
||||
;; This is like exchange-point-and-mark, but doesn't activate the mark.
|
||||
;; It is cleaner to avoid activation, even though the command
|
||||
;; loop would deactivate the mark because we inserted text.
|
||||
(goto-char (prog1 (mark t)
|
||||
(set-marker (mark-marker) (point) (current-buffer))))))
|
||||
nil))
|
||||
|
||||
(defun yank (&optional arg)
|
||||
"Reinsert (\"paste\") the last stretch of killed text.
|
||||
|
|
@ -5449,6 +5455,76 @@ See also the command `yank-pop' (\\[yank-pop])."
|
|||
With ARG, rotate that many kills forward (or backward, if negative)."
|
||||
(interactive "p")
|
||||
(current-kill arg))
|
||||
|
||||
(defvar read-from-kill-ring-history)
|
||||
(defun read-from-kill-ring ()
|
||||
"Read a string from `kill-ring' using completion and minibuffer history."
|
||||
(let* ((history-add-new-input nil)
|
||||
(ellipsis (if (char-displayable-p ?…) "…" "..."))
|
||||
;; Remove keymaps from text properties of copied string,
|
||||
;; because typing RET in the minibuffer might call
|
||||
;; an irrelevant command from the map of copied string.
|
||||
(read-from-kill-ring-history
|
||||
(mapcar (lambda (s)
|
||||
(remove-list-of-text-properties
|
||||
0 (length s)
|
||||
'(
|
||||
keymap local-map action mouse-action
|
||||
button category help-args)
|
||||
s)
|
||||
s)
|
||||
kill-ring))
|
||||
(completions
|
||||
(mapcar (lambda (s)
|
||||
(let* ((s (query-replace-descr s))
|
||||
(b 0))
|
||||
;; Add ellipsis on leading whitespace
|
||||
(when (string-match "\\`[[:space:]]+" s)
|
||||
(setq b (match-end 0))
|
||||
(add-text-properties 0 b `(display ,ellipsis) s))
|
||||
;; Add ellipsis at the end of a long string
|
||||
(when (> (length s) (+ 40 b))
|
||||
(add-text-properties
|
||||
(min (+ 40 b) (length s)) (length s)
|
||||
`(display ,ellipsis) s))
|
||||
s))
|
||||
read-from-kill-ring-history)))
|
||||
(minibuffer-with-setup-hook
|
||||
(lambda ()
|
||||
;; Allow ‘SPC’ to be self-inserting
|
||||
(use-local-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent map (current-local-map))
|
||||
(define-key map " " nil)
|
||||
(define-key map "?" nil)
|
||||
map)))
|
||||
(completing-read
|
||||
"Yank from kill-ring: "
|
||||
(lambda (string pred action)
|
||||
(if (eq action 'metadata)
|
||||
;; Keep sorted by recency
|
||||
'(metadata (display-sort-function . identity))
|
||||
(complete-with-action action completions string pred)))
|
||||
nil nil nil
|
||||
'read-from-kill-ring-history))))
|
||||
|
||||
(defun yank-from-kill-ring (string &optional arg)
|
||||
"Insert the `kill-ring' item selected from the minibuffer history.
|
||||
Use minibuffer navigation and search commands to browse the
|
||||
previously-killed items from the `kill-ring' variable in the
|
||||
minibuffer history before typing RET to insert the selected item,
|
||||
or use completion on the elements of `kill-ring'. You can edit
|
||||
the item in the minibuffer before inserting it.
|
||||
|
||||
With \\[universal-argument] as argument, put point at beginning,
|
||||
and mark at end, like `yank' does."
|
||||
(interactive (list (read-from-kill-ring) current-prefix-arg))
|
||||
(push-mark)
|
||||
(insert-for-yank string)
|
||||
(if (consp arg)
|
||||
;; Swap point and mark like in `yank'.
|
||||
(goto-char (prog1 (mark t)
|
||||
(set-marker (mark-marker) (point) (current-buffer))))))
|
||||
|
||||
;; Some kill commands.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue