--- NEWS.~1.660.~ Sat Apr 27 17:20:39 2002 +++ NEWS Sun Apr 28 14:43:43 2002 @@ -49,6 +48,13 @@ * Changes in Emacs 21.4 + ++++ +** The key `M-y' has been extended to display a menu of kill ring +entries, if the previous command was not a 'C-y'. Previously, `M-y' +ran the command `yank-pop'. Now it runs `yank-previous', which will +either display a menu (`kill-ring-menu') or call `yank-pop'. See the +node "Yanking Earlier Kills" in the Emacs manual for more information. --- ** The new options `buffers-menu-show-directories' and --- killing.texi.~1.26.~ Wed Sep 12 17:01:34 2001 +++ killing.texi Sun Apr 28 13:08:24 2002 @@ -270,8 +270,7 @@ @item C-y Yank last killed text (@code{yank}). @item M-y -Replace text just yanked with an earlier batch of killed text -(@code{yank-pop}). +Choose previously yanked text to insert (@code{yank-pop}). @item M-w Save region as last killed text without actually killing it (@code{kill-ring-save}). @@ -374,49 +373,92 @@ @cindex yanking previous kills @kindex M-y address@hidden yank-pop - To recover killed text that is no longer the most recent kill, use the address@hidden command (@code{yank-pop}). It takes the text previously -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} or another address@hidden - - You can understand @kbd{M-y} in terms of a ``last yank'' pointer which -points at an entry in the kill ring. Each time you kill, the ``last -yank'' pointer moves to the newly made entry at the front of the ring. address@hidden yanks the entry which the ``last yank'' pointer points to. address@hidden moves the ``last yank'' pointer to a different entry, and the -text in the buffer changes to match. Enough @kbd{M-y} commands can move -the pointer to any entry in the ring, so you can get any entry into the address@hidden yank-previous + To recover killed text that is no longer the most recent kill, use +the @kbd{M-y} command (@code{yank-previous}). This command can act in +two different ways. If the previous command was not a yank, then address@hidden will display a menu of kill ring entries, which you can +choose from (@code{kill-ring-menu}). If the previous command was a +yank, then @kbd{M-y} will replace the previously yanked text with the +text from an earlier kill (@code{yank-pop}). + address@hidden The Kill Ring Menu +If you are not sure how long ago you killed the piece of text you're +loooking for, it can often be easiest to use the kill ring menu. +Simply type @kbd{M-y} (which was not preceeded by a @kbd{C-y}), and a +window should pop up, which will display the text previously killed, +one entry on each line. In this special mode, keys do not insert +themselves; instead, they choose actions to perform. + address@hidden @kbd address@hidden RET +Choose the text at point to yank (@code{kill-ring-menu-insert}). address@hidden n +Move point forward by one kill ring entry +(@code{kill-ring-menu-forward}). address@hidden p +Move point backwards by one kill ring entry +(@code{kill-ring-menu-backward}). address@hidden q +Quit the kill ring menu without yanking any text +(@code{kill-ring-menu-quit}). address@hidden d +Remove the text at point from the kill ring +(@code{kill-ring-menu-delete}). address@hidden table + +The kill ring menu can display multi-line text; In the default display +style, all text is shown on one line, and newlines are shown as a address@hidden + address@hidden Cycling Through Yanked Text + +If you know precisely where the text you previously yanked is in the address@hidden, or it was very recently yanked, you may find using +the @code{yank-pop} functionality of @kbd{M-y} to be faster than the +kill ring menu. For example, to recover the text of the +next-to-the-last kill, you could first use @kbd{C-y} to yank the last +kill, and then type @kbd{M-y} to replace it with the previous kill. + + You can understand @code{yank-pop} in terms of a ``last yank'' +pointer which points at an entry in the kill ring. Each time you +kill, the ``last yank'' pointer moves to the newly made entry at the +front of the ring. @kbd{C-y} yanks the entry which the ``last yank'' +pointer points to. After that, typing @kbd{M-y} moves the ``last +yank'' pointer to a different entry, and the text in the buffer +changes to match. Enough @code{yank-pop} commands can move the +pointer to any entry in the ring, so you can get any entry into the buffer. Eventually the pointer reaches the end of the ring; the next @kbd{M-y} loops back around to the first entry again. - @kbd{M-y} moves the ``last yank'' pointer around the ring, but it does -not change the order of the entries in the ring, which always runs from -the most recent kill at the front to the oldest one still remembered. - - @kbd{M-y} can take a numeric argument, which tells it how many entries -to advance the ``last yank'' pointer by. A negative argument moves the -pointer toward the front of the ring; from the front of the ring, it -moves ``around'' to the last entry and continues forward from there. - - Once the text you are looking for is brought into the buffer, you can -stop doing @kbd{M-y} commands and it will stay there. It's just a copy -of the kill ring entry, so editing it in the buffer does not change -what's in the ring. As long as no new killing is done, the ``last -yank'' pointer remains at the same place in the kill ring, so repeating address@hidden will yank another copy of the same previous kill. - - If you know how many @kbd{M-y} commands it would take to find the -text you want, you can yank that text in one step using @kbd{C-y} with -a numeric argument. @kbd{C-y} with an argument restores the text from -the specified kill ring entry, counting back from the most recent as -1. Thus, @kbd{C-u 2 C-y} gets the next-to-the-last block of killed + @code{yank-pop} moves the ``last yank'' pointer around the ring, but +it does not change the order of the entries in the ring, which always +runs from the most recent kill at the front to the oldest one still +remembered. + + @code{yank-pop} can take a numeric argument, which tells it how many +entries to advance the ``last yank'' pointer by. A negative argument +moves the pointer toward the front of the ring; from the front of the +ring, it moves ``around'' to the last entry and continues forward from +there. + + Once the text you are looking for is brought into the buffer, you +can stop doing @code{yank-pop} commands and it will stay there. It's +just a copy of the kill ring entry, so editing it in the buffer does +not change what's in the ring. As long as no new killing is done, the +``last yank'' pointer remains at the same place in the kill ring, so +repeating @kbd{C-y} will yank another copy of the same previous kill. + + If you know how many @code{yank-pop} commands it would take to find +the text you want, you can yank that text in one step using @kbd{C-y} +with a numeric argument. @kbd{C-y} with an argument restores the text +from the specified kill ring entry, counting back from the most recent +as 1. Thus, @kbd{C-u 2 C-y} gets the next-to-the-last block of killed text---it is equivalent to @kbd{C-y M-y}. @kbd{C-y} with a numeric argument starts counting from the ``last yank'' pointer, and sets the ``last yank'' pointer to the entry that it yanks. + address@hidden The Kill Ring Data @vindex kill-ring-max The length of the kill ring is controlled by the variable +there. + + Once the text you are looking for is brought into the buffer, you +can stop doing @code{yank-pop} commands and it will stay there. It's +just a copy of the kill ring entry, so editing it in the buffer does +not change what's in the ring. As long as no new killing is done, the +``last yank'' pointer remains at the same place in the kill ring, so +repeating @kbd{C-y} will yank another copy of the same previous kill. + + If you know how many @code{yank-pop} commands it would take to find +the text you want, you can yank that text in one step using @kbd{C-y} +with a numeric argument. @kbd{C-y} with an argument restores the text +from the specified kill ring entry, counting back from the most recent +as 1. Thus, @kbd{C-u 2 C-y} gets the next-to-the-last block of killed text---it is equivalent to @kbd{C-y M-y}. @kbd{C-y} with a numeric argument starts counting from the ``last yank'' pointer, and sets the ``last yank'' pointer to the entry that it yanks. + address@hidden The Kill Ring Data @vindex kill-ring-max The length of the kill ring is controlled by the variable --- simple.el 27 Apr 2002 23:16:18 -0000 1.539 +++ simple.el 28 Apr 2002 19:28:53 -0000 @@ -32,11 +32,6 @@ (autoload 'shell-mode "shell") (require 'cl)) - -(defgroup killing nil - "Killing and yanking commands" - :group 'editing) - (defgroup paren-matching nil "Highlight (un)matching of parens and expressions." :group 'matching) @@ -1656,334 +1651,6 @@ unread-command-events))) (reset-this-command-lengths) (setq overriding-terminal-local-map nil)) - -;;;; Window system cut and paste hooks. - -(defvar interprogram-cut-function nil - "Function to call to make a killed region available to other programs. - -Most window systems provide some sort of facility for cutting and -pasting text between the windows of different programs. -This variable holds a function that Emacs calls whenever text -is put in the kill ring, to make the new kill available to other -programs. - -The function takes one or two arguments. -The first argument, TEXT, is a string containing -the text which should be made available. -The second, PUSH, if non-nil means this is a \"new\" kill; -nil means appending to an \"old\" kill.") - -(defvar interprogram-paste-function nil - "Function to call to get text cut from other programs. - -Most window systems provide some sort of facility for cutting and -pasting text between the windows of different programs. -This variable holds a function that Emacs calls to obtain -text that other programs have provided for pasting. - -The function should be called with no arguments. If the function -returns nil, then no other program has provided such text, and the top -of the Emacs kill ring should be used. If the function returns a -string, that string should be put in the kill ring as the latest kill. - -Note that the function should return a string only if a program other -than Emacs has provided a string for pasting; if Emacs provided the -most recent string, the function should return nil. If it is -difficult to tell whether Emacs or some other program provided the -current string, it is probably good enough to return nil if the string -is equal (according to `string=') to the last text Emacs provided.") - - - -;;;; The kill ring data structure. - -(defvar kill-ring nil - "List of killed text sequences. -Since the kill ring is supposed to interact nicely with cut-and-paste -facilities offered by window systems, use of this variable should -interact nicely with `interprogram-cut-function' and -`interprogram-paste-function'. The functions `kill-new', -`kill-append', and `current-kill' are supposed to implement this -interaction; you may want to use them instead of manipulating the kill -ring directly.") - -(defcustom kill-ring-max 60 - "*Maximum length of kill ring before oldest elements are thrown away." - :type 'integer - :group 'killing) - -(defvar kill-ring-yank-pointer nil - "The tail of the kill ring whose car is the last thing yanked.") - -(defun kill-new (string &optional replace) - "Make STRING the latest kill in the kill ring. -Set `kill-ring-yank-pointer' to point to it. -If `interprogram-cut-function' is non-nil, apply it to STRING. -Optional second argument REPLACE non-nil means that STRING will replace -the front of the kill ring, rather than being added to the list." - (and (fboundp 'menu-bar-update-yank-menu) - (menu-bar-update-yank-menu string (and replace (car kill-ring)))) - (if (and replace kill-ring) - (setcar kill-ring string) - (setq kill-ring (cons string kill-ring)) - (if (> (length kill-ring) kill-ring-max) - (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))) - (setq kill-ring-yank-pointer kill-ring) - (if interprogram-cut-function - (funcall interprogram-cut-function string (not replace)))) - -(defun kill-append (string before-p) - "Append STRING to the end of the latest kill in the kill ring. -If BEFORE-P is non-nil, prepend STRING to the kill. -If `interprogram-cut-function' is set, pass the resulting kill to -it." - (kill-new (if before-p - (concat string (car kill-ring)) - (concat (car kill-ring) string)) - t)) - -(defun current-kill (n &optional do-not-move) - "Rotate the yanking point by N places, and then return that kill. -If N is zero, `interprogram-paste-function' is set, and calling it -returns a string, then that string is added to the front of the -kill ring and returned as the latest kill. -If optional arg DO-NOT-MOVE is non-nil, then don't actually move the -yanking point; just return the Nth kill forward." - (let ((interprogram-paste (and (= n 0) - interprogram-paste-function - (funcall interprogram-paste-function)))) - (if interprogram-paste - (progn - ;; Disable the interprogram cut function when we add the new - ;; text to the kill ring, so Emacs doesn't try to own the - ;; selection, with identical text. - (let ((interprogram-cut-function nil)) - (kill-new interprogram-paste)) - interprogram-paste) - (or kill-ring (error "Kill ring is empty")) - (let ((ARGth-kill-element - (nthcdr (mod (- n (length kill-ring-yank-pointer)) - (length kill-ring)) - kill-ring))) - (or do-not-move - (setq kill-ring-yank-pointer ARGth-kill-element)) - (car ARGth-kill-element))))) - - - -;;;; Commands for manipulating the kill ring. - -(defcustom kill-read-only-ok nil - "*Non-nil means don't signal an error for killing read-only text." - :type 'boolean - :group 'killing) - -(put 'text-read-only 'error-conditions - '(text-read-only buffer-read-only error)) -(put 'text-read-only 'error-message "Text is read-only") - -(defun kill-region (beg end) - "Kill between point and mark. -The text is deleted but saved in the kill ring. -The command \\[yank] can retrieve it from there. -\(If you want to kill and then yank immediately, use \\[kill-ring-save].) - -If you want to append the killed region to the last killed text, -use \\[append-next-kill] before \\[kill-region]. - -If the buffer is read-only, Emacs will beep and refrain from deleting -the text, but put the text in the kill ring anyway. This means that -you can use the killing commands to copy text from a read-only buffer. - -This is the primitive for programs to kill text (as opposed to deleting it). -Supply two arguments, character numbers indicating the stretch of text - to be killed. -Any command that calls this function is a \"kill command\". -If the previous command was also a kill command, -the text killed this time appends to the text killed last time -to make one entry in the kill ring." - (interactive "r") - (condition-case nil - (let ((string (delete-and-extract-region beg end))) - (when string ;STRING is nil if BEG = END - ;; Add that string to the kill ring, one way or another. - (if (eq last-command 'kill-region) - (kill-append string (< end beg)) - (kill-new string))) - (setq this-command 'kill-region)) - ((buffer-read-only text-read-only) - ;; The code above failed because the buffer, or some of the characters - ;; in the region, are read-only. - ;; We should beep, in case the user just isn't aware of this. - ;; However, there's no harm in putting - ;; the region's text in the kill ring, anyway. - (copy-region-as-kill beg end) - ;; Set this-command now, so it will be set even if we get an error. - (setq this-command 'kill-region) - ;; This should barf, if appropriate, and give us the correct error. - (if kill-read-only-ok - (message "Read only text copied to kill ring") - ;; Signal an error if the buffer is read-only. - (barf-if-buffer-read-only) - ;; If the buffer isn't read-only, the text is. - (signal 'text-read-only (list (current-buffer))))))) - -;; copy-region-as-kill no longer sets this-command, because it's confusing -;; to get two copies of the text when the user accidentally types M-w and -;; then corrects it with the intended C-w. -(defun copy-region-as-kill (beg end) - "Save the region as if killed, but don't kill it. -In Transient Mark mode, deactivate the mark. -If `interprogram-cut-function' is non-nil, also save the text for a window -system cut and paste." - (interactive "r") - (if (eq last-command 'kill-region) - (kill-append (buffer-substring beg end) (< end beg)) - (kill-new (buffer-substring beg end))) - (if transient-mark-mode - (setq deactivate-mark t)) - nil) - -(defun kill-ring-save (beg end) - "Save the region as if killed, but don't kill it. -In Transient Mark mode, deactivate the mark. -If `interprogram-cut-function' is non-nil, also save the text for a window -system cut and paste. - -If you want to append the killed line to the last killed text, -use \\[append-next-kill] before \\[kill-ring-save]. - -This command is similar to `copy-region-as-kill', except that it gives -visual feedback indicating the extent of the region being copied." - (interactive "r") - (copy-region-as-kill beg end) - (if (interactive-p) - (let ((other-end (if (= (point) beg) end beg)) - (opoint (point)) - ;; Inhibit quitting so we can make a quit here - ;; look like a C-g typed as a command. - (inhibit-quit t)) - (if (pos-visible-in-window-p other-end (selected-window)) - (unless transient-mark-mode - ;; Swap point and mark. - (set-marker (mark-marker) (point) (current-buffer)) - (goto-char other-end) - (sit-for 1) - ;; Swap back. - (set-marker (mark-marker) other-end (current-buffer)) - (goto-char opoint) - ;; If user quit, deactivate the mark - ;; as C-g would as a command. - (and quit-flag mark-active - (deactivate-mark))) - (let* ((killed-text (current-kill 0)) - (message-len (min (length killed-text) 40))) - (if (= (point) beg) - ;; Don't say "killed"; that is misleading. - (message "Saved text until \"%s\"" - (substring killed-text (- message-len))) - (message "Saved text from \"%s\"" - (substring killed-text 0 message-len)))))))) - -(defun append-next-kill (&optional interactive) - "Cause following command, if it kills, to append to previous kill. -The argument is used for internal purposes; do not supply one." - (interactive "p") - ;; We don't use (interactive-p), since that breaks kbd macros. - (if interactive - (progn - (setq this-command 'kill-region) - (message "If the next command is a kill, it will append")) - (setq last-command 'kill-region))) - -;; Yanking. - -;; This is actually used in subr.el but defcustom does not work there. -(defcustom yank-excluded-properties - '(read-only invisible intangible field mouse-face local-map keymap) - "*Text properties to discard when yanking." - :type '(choice (const :tag "All" t) (repeat symbol)) - :group 'editing - :version 21.4) - -(defun yank-pop (arg) - "Replace just-yanked stretch of killed text with a different stretch. -This command is allowed only 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. - -With no argument, the previous kill is inserted. -With argument N, insert the Nth previous kill. -If N is negative, this is a more recent kill. - -The sequence of kills wraps around, so that after the oldest one -comes the newest one." - (interactive "*p") - (if (not (eq last-command 'yank)) - (error "Previous command was not a yank")) - (setq this-command 'yank) - (let ((inhibit-read-only t) - (before (< (point) (mark t)))) - (delete-region (point) (mark t)) - (set-marker (mark-marker) (point) (current-buffer)) - (insert-for-yank (current-kill arg)) - (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 the last stretch of killed text. -More precisely, reinsert the stretch of killed text most recently -killed OR yanked. Put point at end, and set mark at beginning. -With just C-u as argument, same but put point at beginning (and mark at end). -With argument N, reinsert the Nth most recently killed stretch of killed -text. -See also the command \\[yank-pop]." - (interactive "*P") - ;; If we don't get all the way thru, make last-command indicate that - ;; for the following command. - (setq this-command t) - (push-mark (point)) - (insert-for-yank (current-kill (cond - ((listp arg) 0) - ((eq arg '-) -1) - (t (1- arg))))) - (if (consp arg) - ;; 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))))) - ;; If we do get all the way thru, make this-command indicate that. - (setq this-command 'yank) - nil) - -(defun rotate-yank-pointer (arg) - "Rotate the yanking point in the kill ring. -With argument, rotate that many kills forward (or backward, if negative)." - (interactive "p") - (current-kill arg)) - -;; Some kill commands. - -;; Internal subroutine of delete-char -(defun kill-forward-chars (arg) - (if (listp arg) (setq arg (car arg))) - (if (eq arg '-) (setq arg -1)) - (kill-region (point) (forward-point arg))) - -;; Internal subroutine of backward-delete-char -(defun kill-backward-chars (arg) - (if (listp arg) (setq arg (car arg))) - (if (eq arg '-) (setq arg -1)) - (kill-region (point) (forward-point (- arg)))) - (defcustom backward-delete-char-untabify-method 'untabify "*The method for untabifying when deleting backward. Can be `untabify' -- turn a tab to many spaces, then delete one space; @@ -2033,53 +1700,6 @@ (search-forward (char-to-string char) nil nil arg) ; (goto-char (if (> arg 0) (1- (point)) (1+ (point)))) (point)))) - -;; kill-line and its subroutines. - -(defcustom kill-whole-line nil - "*If non-nil, `kill-line' with no arg at beg of line kills the whole line." - :type 'boolean - :group 'killing) - -(defun kill-line (&optional arg) - "Kill the rest of the current line; if no nonblanks there, kill thru newline. -With prefix argument, kill that many lines from point. -Negative arguments kill lines backward. -With zero argument, kills the text before point on the current line. - -When calling from a program, nil means \"no arg\", -a number counts as a prefix arg. - -To kill a whole line, when point is not at the beginning, type \ -\\[beginning-of-line] \\[kill-line] \\[kill-line]. - -If `kill-whole-line' is non-nil, then this command kills the whole line -including its terminating newline, when used at the beginning of a line -with no argument. As a consequence, you can always kill a whole line -by typing \\[beginning-of-line] \\[kill-line]. - -If you want to append the killed line to the last killed text, -use \\[append-next-kill] before \\[kill-line]. - -If the buffer is read-only, Emacs will beep and refrain from deleting -the line, but put the line in the kill ring anyway. This means that -you can use this command to copy text from a read-only buffer." - (interactive "P") - (kill-region (point) - ;; It is better to move point to the other end of the kill - ;; before killing. That way, in a read-only buffer, point - ;; moves across the text that is copied to the kill ring. - ;; The choice has no effect on undo now that undo records - ;; the value of point from before the command was run. - (progn - (if arg - (forward-visible-line (prefix-numeric-value arg)) - (if (eobp) - (signal 'end-of-buffer nil)) - (if (or (looking-at "[ \t]*$") (and kill-whole-line (bolp))) - (forward-visible-line 1) - (end-of-visible-line))) - (point)))) (defun forward-visible-line (arg) "Move forward by ARG lines, ignoring currently invisible newlines only. --- /dev/null Wed Dec 31 19:00:00 1969 +++ kill-ring.el Sun Apr 28 14:27:12 2002 @@ -0,0 +1,723 @@ +;;; kill-ring.el --- killing, yanking, and kill ring browsing + +;; Copyright (C) 1985, 86, 87, 93, 94, 95, 96, 97, 98, 99, 2000, 2001, 2002 +;; Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; 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. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;;; Code: + +(eval-when-compile + (require 'cl) + (require 'derived)) + +(defgroup killing nil + "Killing and yanking commands" + :group 'editing) + + +;;;; Window system cut and paste hooks. + +(defvar interprogram-cut-function nil + "Function to call to make a killed region available to other programs. + +Most window systems provide some sort of facility for cutting and +pasting text between the windows of different programs. +This variable holds a function that Emacs calls whenever text +is put in the kill ring, to make the new kill available to other +programs. + +The function takes one or two arguments. +The first argument, TEXT, is a string containing +the text which should be made available. +The second, PUSH, if non-nil means this is a \"new\" kill; +nil means appending to an \"old\" kill.") + +(defvar interprogram-paste-function nil + "Function to call to get text cut from other programs. + +Most window systems provide some sort of facility for cutting and +pasting text between the windows of different programs. +This variable holds a function that Emacs calls to obtain +text that other programs have provided for pasting. + +The function should be called with no arguments. If the function +returns nil, then no other program has provided such text, and the top +of the Emacs kill ring should be used. If the function returns a +string, that string should be put in the kill ring as the latest kill. + +Note that the function should return a string only if a program other +than Emacs has provided a string for pasting; if Emacs provided the +most recent string, the function should return nil. If it is +difficult to tell whether Emacs or some other program provided the +current string, it is probably good enough to return nil if the string +is equal (according to `string=') to the last text Emacs provided.") + + +;;;; The kill ring data structure. + +(defvar kill-ring nil + "List of killed text sequences. +Since the kill ring is supposed to interact nicely with cut-and-paste +facilities offered by window systems, use of this variable should +interact nicely with `interprogram-cut-function' and +`interprogram-paste-function'. The functions `kill-new', +`kill-append', and `current-kill' are supposed to implement this +interaction; you may want to use them instead of manipulating the kill +ring directly.") + +(defcustom kill-ring-max 60 + "*Maximum length of kill ring before oldest elements are thrown away." + :type 'integer + :group 'killing) + +(defcustom kill-ring-menu-display-style 'one-line + "How to display the kill ring menu items. + +If `one-line', then replace newlines with \"\\n\" for display. + +If `separated', then display `kill-ring-menu-separator' between +entries." + :type '(choice (const :tag "One line" one-line) + (const :tag "Separated" separated)) + :group 'killing) + +(defcustom kill-ring-menu-quit-action 'bury-and-delete-window + "What action to take when `kill-ring-menu-quit' is called. + +If `bury-buffer', then simply bury the *Kill Ring* buffer, but keep +the window. + +If `bury-and-delete-window', then bury the buffer, and (if there is +more than one window) delete the window. This is the default. + +If `kill-and-delete-window', then kill the *Kill Ring* buffer, and +delete the window on close. + +Otherwise, it should be a function to call." + :type '(choice (const :tag "Bury buffer" :value bury-buffer) + (const :tag "Delete window" :value delete-window) + (const :tag "Bury buffer and delete window" :value bury-and-delete-window) + (const :tag "Kill buffer and delete window" :value kill-and-delete-window)) + :group 'killing) + +(defcustom kill-ring-menu-maximum-display-length nil + "Whether or not to limit the length of displayed items. + +If this variable is an integer, the display of `kill-ring' will be +limited to that many characters. +Setting this variable to nil means no limit." + :type '(choice (const :tag "None" nil) + integer) + :group 'browse-kill-ring) + +(defcustom kill-ring-menu-separator "-------" + "The string separating entries in the `separated' style. +See `kill-ring-menu-display-style'." + :type 'string + :group 'killing) + +(defcustom kill-ring-menu-highlight-current-entry nil + "If non-nil, highlight the currently selected `kill-ring' entry." + :type 'boolean + :group 'killing) + +(defcustom kill-ring-menu-separator-face 'bold + "The face in which to highlight the `kill-ring-menu-separator'." + :type 'face + :group 'killing) + +(defvar kill-ring-yank-pointer nil + "The tail of the kill ring whose car is the last thing yanked.") + +(defvar kill-ring-menu-original-window nil + "The window in which chosen kill ring data will be inserted. +It is probably not a good idea to set this variable directly; simply +call `kill-ring-menu' again.") + +(defun kill-new (string &optional replace) + "Make STRING the latest kill in the kill ring. +Set `kill-ring-yank-pointer' to point to it. +If `interprogram-cut-function' is non-nil, apply it to STRING. +Optional second argument REPLACE non-nil means that STRING will replace +the front of the kill ring, rather than being added to the list." + (and (fboundp 'menu-bar-update-yank-menu) + (menu-bar-update-yank-menu string (and replace (car kill-ring)))) + (if (and replace kill-ring) + (setcar kill-ring string) + (setq kill-ring (cons string kill-ring)) + (if (> (length kill-ring) kill-ring-max) + (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))) + (setq kill-ring-yank-pointer kill-ring) + (if interprogram-cut-function + (funcall interprogram-cut-function string (not replace)))) + +(defun kill-append (string before-p) + "Append STRING to the end of the latest kill in the kill ring. +If BEFORE-P is non-nil, prepend STRING to the kill. +If `interprogram-cut-function' is set, pass the resulting kill to +it." + (kill-new (if before-p + (concat string (car kill-ring)) + (concat (car kill-ring) string)) + t)) + +(defun current-kill (n &optional do-not-move) + "Rotate the yanking point by N places, and then return that kill. +If N is zero, `interprogram-paste-function' is set, and calling it +returns a string, then that string is added to the front of the +kill ring and returned as the latest kill. +If optional arg DO-NOT-MOVE is non-nil, then don't actually move the +yanking point; just return the Nth kill forward." + (let ((interprogram-paste (and (= n 0) + interprogram-paste-function + (funcall interprogram-paste-function)))) + (if interprogram-paste + (progn + ;; Disable the interprogram cut function when we add the new + ;; text to the kill ring, so Emacs doesn't try to own the + ;; selection, with identical text. + (let ((interprogram-cut-function nil)) + (kill-new interprogram-paste)) + interprogram-paste) + (or kill-ring (error "Kill ring is empty")) + (let ((ARGth-kill-element + (nthcdr (mod (- n (length kill-ring-yank-pointer)) + (length kill-ring)) + kill-ring))) + (or do-not-move + (setq kill-ring-yank-pointer ARGth-kill-element)) + (car ARGth-kill-element))))) + +;;;; Commands for manipulating the kill ring. + +(defcustom kill-read-only-ok nil + "*Non-nil means don't signal an error for killing read-only text." + :type 'boolean + :group 'killing) + +(put 'text-read-only 'error-conditions + '(text-read-only buffer-read-only error)) +(put 'text-read-only 'error-message "Text is read-only") + +(defun kill-region (beg end) + "Kill between point and mark. +The text is deleted but saved in the kill ring. +The command \\[yank] can retrieve it from there. +\(If you want to kill and then yank immediately, use \\[kill-ring-save].) + +If you want to append the killed region to the last killed text, +use \\[append-next-kill] before \\[kill-region]. + +If the buffer is read-only, Emacs will beep and refrain from deleting +the text, but put the text in the kill ring anyway. This means that +you can use the killing commands to copy text from a read-only buffer. + +This is the primitive for programs to kill text (as opposed to deleting it). +Supply two arguments, character numbers indicating the stretch of text + to be killed. +Any command that calls this function is a \"kill command\". +If the previous command was also a kill command, +the text killed this time appends to the text killed last time +to make one entry in the kill ring." + (interactive "r") + (condition-case nil + (let ((string (delete-and-extract-region beg end))) + (when string ;STRING is nil if BEG = END + ;; Add that string to the kill ring, one way or another. + (if (eq last-command 'kill-region) + (kill-append string (< end beg)) + (kill-new string))) + (setq this-command 'kill-region)) + ((buffer-read-only text-read-only) + ;; The code above failed because the buffer, or some of the characters + ;; in the region, are read-only. + ;; We should beep, in case the user just isn't aware of this. + ;; However, there's no harm in putting + ;; the region's text in the kill ring, anyway. + (copy-region-as-kill beg end) + ;; Set this-command now, so it will be set even if we get an error. + (setq this-command 'kill-region) + ;; This should barf, if appropriate, and give us the correct error. + (if kill-read-only-ok + (message "Read only text copied to kill ring") + ;; Signal an error if the buffer is read-only. + (barf-if-buffer-read-only) + ;; If the buffer isn't read-only, the text is. + (signal 'text-read-only (list (current-buffer))))))) + +;; copy-region-as-kill no longer sets this-command, because it's confusing +;; to get two copies of the text when the user accidentally types M-w and +;; then corrects it with the intended C-w. +(defun copy-region-as-kill (beg end) + "Save the region as if killed, but don't kill it. +In Transient Mark mode, deactivate the mark. +If `interprogram-cut-function' is non-nil, also save the text for a window +system cut and paste." + (interactive "r") + (if (eq last-command 'kill-region) + (kill-append (buffer-substring beg end) (< end beg)) + (kill-new (buffer-substring beg end))) + (if transient-mark-mode + (setq deactivate-mark t)) + nil) + +(defun kill-ring-save (beg end) + "Save the region as if killed, but don't kill it. +In Transient Mark mode, deactivate the mark. +If `interprogram-cut-function' is non-nil, also save the text for a window +system cut and paste. + +If you want to append the killed line to the last killed text, +use \\[append-next-kill] before \\[kill-ring-save]. + +This command is similar to `copy-region-as-kill', except that it gives +visual feedback indicating the extent of the region being copied." + (interactive "r") + (copy-region-as-kill beg end) + (if (interactive-p) + (let ((other-end (if (= (point) beg) end beg)) + (opoint (point)) + ;; Inhibit quitting so we can make a quit here + ;; look like a C-g typed as a command. + (inhibit-quit t)) + (if (pos-visible-in-window-p other-end (selected-window)) + (unless transient-mark-mode + ;; Swap point and mark. + (set-marker (mark-marker) (point) (current-buffer)) + (goto-char other-end) + (sit-for 1) + ;; Swap back. + (set-marker (mark-marker) other-end (current-buffer)) + (goto-char opoint) + ;; If user quit, deactivate the mark + ;; as C-g would as a command. + (and quit-flag mark-active + (deactivate-mark))) + (let* ((killed-text (current-kill 0)) + (message-len (min (length killed-text) 40))) + (if (= (point) beg) + ;; Don't say "killed"; that is misleading. + (message "Saved text until \"%s\"" + (substring killed-text (- message-len))) + (message "Saved text from \"%s\"" + (substring killed-text 0 message-len)))))))) + +(defun append-next-kill (&optional interactive) + "Cause following command, if it kills, to append to previous kill. +The argument is used for internal purposes; do not supply one." + (interactive "p") + ;; We don't use (interactive-p), since that breaks kbd macros. + (if interactive + (progn + (setq this-command 'kill-region) + (message "If the next command is a kill, it will append")) + (setq last-command 'kill-region))) + +;; Yanking. + +;; This is actually used in subr.el but defcustom does not work there. +(defcustom yank-excluded-properties + '(read-only invisible intangible field mouse-face local-map keymap) + "*Text properties to discard when yanking." + :type '(choice (const :tag "All" t) (repeat symbol)) + :group 'editing + :version 21.4) + +(defun yank-pop (arg) + "Replace just-yanked stretch of killed text with a different stretch. +This command is allowed only 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. + +With no argument, the previous kill is inserted. +With argument N, insert the Nth previous kill. +If N is negative, this is a more recent kill. + +The sequence of kills wraps around, so that after the oldest one +comes the newest one." + (interactive "*p") + (setq this-command 'yank) + (let ((inhibit-read-only t) + (before (< (point) (mark t)))) + (delete-region (point) (mark t)) + (set-marker (mark-marker) (point) (current-buffer)) + (insert-for-yank (current-kill arg)) + (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-previous (arg) + "Replace previously yanked text, or display a kill ring menu. +If the last command was a `yank', `yank-previous', or `yank-pop', then +this command will replace a just-yanked section of text with a prevous +entry in the kill ring, using ARG. See `yank-pop'. +Otherwise, this command will display a menu of kill ring entries; see +`kill-ring-menu'." + (interactive "*p") + (if (not (memq last-command '(yank yank-previous))) + (kill-ring-menu) + (yank-pop arg))) + +(defun yank (&optional arg) + "Reinsert the last stretch of killed text. +More precisely, reinsert the stretch of killed text most recently +killed OR yanked. Put point at end, and set mark at beginning. +With just C-u as argument, same but put point at beginning (and mark at end). +With argument N, reinsert the Nth most recently killed stretch of killed +text. +See also the command \\[yank-pop]." + (interactive "*P") + ;; If we don't get all the way thru, make last-command indicate that + ;; for the following command. + (setq this-command t) + (push-mark (point)) + (insert-for-yank (current-kill (cond + ((listp arg) 0) + ((eq arg '-) -1) + (t (1- arg))))) + (if (consp arg) + ;; 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))))) + ;; If we do get all the way thru, make this-command indicate that. + (setq this-command 'yank) + nil) + +(defun rotate-yank-pointer (arg) + "Rotate the yanking point in the kill ring. +With argument, rotate that many kills forward (or backward, if negative)." + (interactive "p") + (current-kill arg)) + +;; Some kill commands. + +;; Internal subroutine of delete-char +(defun kill-forward-chars (arg) + (if (listp arg) (setq arg (car arg))) + (if (eq arg '-) (setq arg -1)) + (kill-region (point) (forward-point arg))) + +;; Internal subroutine of backward-delete-char +(defun kill-backward-chars (arg) + (if (listp arg) (setq arg (car arg))) + (if (eq arg '-) (setq arg -1)) + (kill-region (point) (forward-point (- arg)))) + +;; kill-line and its subroutines. + +(defcustom kill-whole-line nil + "*If non-nil, `kill-line' with no arg at beg of line kills the whole line." + :type 'boolean + :group 'killing) + +(defun kill-line (&optional arg) + "Kill the rest of the current line; if no nonblanks there, kill thru newline. +With prefix argument, kill that many lines from point. +Negative arguments kill lines backward. +With zero argument, kills the text before point on the current line. + +When calling from a program, nil means \"no arg\", +a number counts as a prefix arg. + +To kill a whole line, when point is not at the beginning, type \ +\\[beginning-of-line] \\[kill-line] \\[kill-line]. + +If `kill-whole-line' is non-nil, then this command kills the whole line +including its terminating newline, when used at the beginning of a line +with no argument. As a consequence, you can always kill a whole line +by typing \\[beginning-of-line] \\[kill-line]. + +If you want to append the killed line to the last killed text, +use \\[append-next-kill] before \\[kill-line]. + +If the buffer is read-only, Emacs will beep and refrain from deleting +the line, but put the line in the kill ring anyway. This means that +you can use this command to copy text from a read-only buffer." + (interactive "P") + (kill-region (point) + ;; It is better to move point to the other end of the kill + ;; before killing. That way, in a read-only buffer, point + ;; moves across the text that is copied to the kill ring. + ;; The choice has no effect on undo now that undo records + ;; the value of point from before the command was run. + (progn + (if arg + (forward-visible-line (prefix-numeric-value arg)) + (if (eobp) + (signal 'end-of-buffer nil)) + (if (or (looking-at "[ \t]*$") (and kill-whole-line (bolp))) + (forward-visible-line 1) + (end-of-visible-line))) + (point)))) + +(put 'kill-ring-menu-mode 'mode-class 'special) +(define-derived-mode kill-ring-menu-mode fundamental-mode + "Kill Ring" + "A major mode for browsing the `kill-ring'. +You most likely do not want to call `kill-ring-menu-mode' directly; use +`kill-ring-menu' instead. + +\\{kill-ring-menu-mode-map}" + (set (make-local-variable 'kill-ring-menu-original-window) nil) + (set (make-local-variable 'font-lock-defaults) + '(nil t nil nil nil + (font-lock-fontify-region-function . kill-ring-menu-fontify-region-function) + (font-lock-unfontify-region-function . kill-ring-menu-unfontify-region-function))) + (define-key kill-ring-menu-mode-map (kbd "q") 'kill-ring-menu-quit) + (define-key kill-ring-menu-mode-map (kbd "C-g") 'kill-ring-menu-quit) + (define-key kill-ring-menu-mode-map (kbd "d") 'kill-ring-menu-delete) + (define-key kill-ring-menu-mode-map (kbd "g") 'kill-ring-menu-update) + (define-key kill-ring-menu-mode-map (kbd "n") 'kill-ring-menu-forward) + (define-key kill-ring-menu-mode-map (kbd "p") 'kill-ring-menu-backward) + (define-key kill-ring-menu-mode-map [(mouse-2)] 'kill-ring-menu-mouse-insert) + (define-key kill-ring-menu-mode-map (kbd "?") 'describe-mode) + (define-key kill-ring-menu-mode-map (kbd "h") 'describe-mode) + (define-key kill-ring-menu-mode-map (kbd "RET") 'kill-ring-menu-insert)) + +(defun kill-ring-menu-fontify-region-function (beg end &optional verbose) + (when verbose (message "Fontifying...")) + (let ((inhibit-read-only t)) + (font-lock-fontify-on-text-properties + beg end 'kill-ring-menu-special 'bold) + (when verbose (message "Fontifying...done")))) + +(defun kill-ring-menu-unfontify-region-function (beg end) + (let ((inhibit-read-only t)) + (remove-text-properties beg end '(face nil)))) + +(defun kill-ring-menu-elide (str) + (if (and kill-ring-menu-maximum-display-length + (> (length str) + kill-ring-menu-maximum-display-length)) + (concat (substring str 0 (- kill-ring-menu-maximum-display-length 3)) + (propertize "..." 'kill-ring-menu-special t))) + str) + +(defmacro kill-ring-menu-add-overlays-for (item &rest body) + (let ((beg (gensym "kill-ring-menu-add-overlays-")) + (end (gensym "kill-ring-menu-add-overlays-"))) + `(let ((,beg (point)) + (,end + (progn + ,@body + (point)))) + (let ((o (make-overlay ,beg ,end))) + (overlay-put o 'kill-ring-menu-target ,item) + (overlay-put o 'mouse-face 'highlight))))) +;; (put 'kill-ring-menu-add-overlays-for 'lisp-indent-function 1) + +(defun kill-ring-menu-insert-as-one-line (items) + (dolist (item items) + (kill-ring-menu-add-overlays-for item + (let* ((item (kill-ring-menu-elide item)) + (len (length item)) + (start 0) + (newl (propertize "\\n" 'kill-ring-menu-special t))) + (while (and (< start len) + (string-match "\n" item start)) + (insert (substring item start (match-beginning 0)) + newl) + (setq start (match-end 0))) + (insert (substring item start len)))) + (insert "\n"))) + +(defun kill-ring-menu-insert-as-separated (items) + (while (cdr items) + (kill-ring-menu-insert-as-separated-1 (car items) t) + (setq items (cdr items))) + (when items + (kill-ring-menu-insert-as-separated-1 (car items) nil))) + +(defun kill-ring-menu-insert-as-separated-1 (origitem separatep) + (let* ((item (kill-ring-menu-elide origitem)) + (len (length item))) + (kill-ring-menu-add-overlays-for origitem + (insert item)) + (insert "\n") + (when separatep + (insert (propertize kill-ring-menu-separator + 'kill-ring-menu-special t)) + (insert "\n")))) + +;; (unintern 'kill-ring-menu-add-overlays-for) + +(defun kill-ring-menu-quit () + "Take the action specified by `kill-ring-menu-quit-action'." + (interactive) + (case kill-ring-menu-quit-action + (kill-and-delete-window + (kill-buffer (current-buffer)) + (unless (= (count-windows) 1) + (delete-window))) + (bury-and-delete-window + (bury-buffer) + (unless (= (count-windows) 1) + (delete-window))) + (t + (funcall kill-ring-menu-quit-action)))) + +(defun kill-ring-menu-forward (&optional arg) + "Move forward by ARG `kill-ring' entries." + (interactive "p") + (beginning-of-line) + (while (not (zerop arg)) + (if (< arg 0) + (progn + (incf arg) + (if (overlays-at (point)) + (progn + (goto-char (overlay-start (car (overlays-at (point))))) + (goto-char (previous-overlay-change (point))) + (goto-char (previous-overlay-change (point)))) + (progn + (goto-char (1- (previous-overlay-change (point)))) + (unless (bobp) + (goto-char (overlay-start (car (overlays-at (point))))))))) + (progn + (decf arg) + (if (overlays-at (point)) + (progn + (goto-char (overlay-end (car (overlays-at (point))))) + (goto-char (next-overlay-change (point)))) + (goto-char (next-overlay-change (point))) + (unless (eobp) + (goto-char (overlay-start (car (overlays-at (point)))))))))) + ;; This could probably be implemented in a more intelligent manner. + ;; Perhaps keep track over the overlay we started from? That would + ;; break when the user moved manually, though. + (when (and kill-ring-menu-highlight-current-entry + (overlays-at (point))) + (let ((overs (overlay-lists)) + (current-overlay (car (overlays-at (point))))) + (mapcar #'(lambda (o) + (overlay-put o 'face nil)) + (nconc (car overs) (cdr overs))) + (overlay-put current-overlay 'face 'highlight)))) + +(defun kill-ring-menu-backward (&optional arg) + "Move backward by ARG `kill-ring' entries." + (interactive "p") + (kill-ring-menu-forward (- arg))) + +(defun kill-ring-menu-do-insert (buf pt) + (let ((str (with-current-buffer buf + (let ((overs (overlays-at pt))) + (or (and overs + (overlay-get (car overs) 'kill-ring-menu-target)) + (error "No kill ring item here")))))) + (let ((orig (current-buffer))) + (unwind-protect + (progn + (unless (window-live-p kill-ring-menu-original-window) + (kill-ring-menu-quit) + (error (substitute-command-keys "Window %s has been deleted; Try calling '\\[yank-previous]' again") + kill-ring-menu-original-window)) + (set-buffer (window-buffer kill-ring-menu-original-window)) + (save-excursion + (insert str))) + (set-buffer orig))))) + +(defun kill-ring-menu-mouse-insert (e) + "Insert the chosen text in the last selected buffer." + (interactive "e") + (let* ((end (event-end e)) + (win (posn-window end)) + (buf (window-buffer win))) + (select-window win) + (kill-ring-menu-do-insert buf (posn-point end)) + (kill-ring-menu-quit))) + +(defun kill-ring-menu-insert (&optional noquit) + "Insert the kill ring item at point, and close the kill ring menu. +If optional argument NOQUIT is non-nil, don't close the menu." + (interactive "P") + (kill-ring-menu-do-insert (current-buffer) (point)) + (unless noquit + (kill-ring-menu-quit))) + +(defun kill-ring-menu-update () + "Update the buffer to reflect outside changes to `kill-ring'." + (interactive) + (assert (eq major-mode 'kill-ring-menu-mode)) + (kill-ring-menu-setup (current-buffer) + kill-ring-menu-original-window)) + +(defun kill-ring-menu-setup (buf window &optional regexp) + (with-current-buffer buf + (unwind-protect + (progn + (kill-ring-menu-mode) + (setq buffer-read-only nil) + (when (eq kill-ring-menu-display-style + 'one-line) + (setq truncate-lines t)) + (erase-buffer) + (setq kill-ring-menu-original-window window) + (let ((kill-ring-menu-maximum-display-length + (if (and kill-ring-menu-maximum-display-length + (<= kill-ring-menu-maximum-display-length 3)) + 4 + kill-ring-menu-maximum-display-length)) + (items (mapcar #'copy-sequence kill-ring))) +;; (when (not kill-ring-menu-display-duplicates) +;; (setq items (delete-duplicates items :test #'equal))) + (when (stringp regexp) + (setq items (delq nil + (mapcar + #'(lambda (item) + (when (string-match regexp item) + item)) + items)))) + (funcall (intern + (concat "kill-ring-menu-insert-as-" + (symbol-name kill-ring-menu-display-style))) + items) + (if (not regexp) + (message "%s entries in the kill ring" (length kill-ring)) + (message "%s (of %s) entries in the kill ring shown" + (length items) (length kill-ring))) + (set-buffer-modified-p nil) + (goto-char (point-min)) + (kill-ring-menu-forward 0) + (when regexp + (setq mode-name (concat "Kill Ring [" regexp "]"))) + (run-hooks 'kill-ring-menu-hook))) + (progn + (setq buffer-read-only t))))) + +;;;###autoload +(defun kill-ring-menu () + "Display items in the `kill-ring' in another buffer." + (interactive) + (let ((orig-buf (current-buffer)) + (buf (get-buffer-create "*Kill Ring*"))) + (kill-ring-menu-setup buf (selected-window)) + (pop-to-buffer buf) + nil)) + +(provide 'kill-ring) --- killing.texi.~1.26.~ Wed Sep 12 17:01:34 2001 +++ killing.texi Sun Apr 28 13:08:24 2002 @@ -270,8 +270,7 @@ @item C-y Yank last killed text (@code{yank}). @item M-y -Replace text just yanked with an earlier batch of killed text -(@code{yank-pop}). +Choose previously yanked text to insert (@code{yank-pop}). @item M-w Save region as last killed text without actually killing it (@code{kill-ring-save}). @@ -374,49 +373,92 @@ @cindex yanking previous kills @kindex M-y address@hidden yank-pop - To recover killed text that is no longer the most recent kill, use the address@hidden command (@code{yank-pop}). It takes the text previously -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} or another address@hidden - - You can understand @kbd{M-y} in terms of a ``last yank'' pointer which -points at an entry in the kill ring. Each time you kill, the ``last -yank'' pointer moves to the newly made entry at the front of the ring. address@hidden yanks the entry which the ``last yank'' pointer points to. address@hidden moves the ``last yank'' pointer to a different entry, and the -text in the buffer changes to match. Enough @kbd{M-y} commands can move -the pointer to any entry in the ring, so you can get any entry into the address@hidden yank-previous + To recover killed text that is no longer the most recent kill, use +the @kbd{M-y} command (@code{yank-previous}). This command can act in +two different ways. If the previous command was not a yank, then address@hidden will display a menu of kill ring entries, which you can +choose from (@code{kill-ring-menu}). If the previous command was a +yank, then @kbd{M-y} will replace the previously yanked text with the +text from an earlier kill (@code{yank-pop}). + address@hidden The Kill Ring Menu +If you are not sure how long ago you killed the piece of text you're +loooking for, it can often be easiest to use the kill ring menu. +Simply type @kbd{M-y} (which was not preceeded by a @kbd{C-y}), and a +window should pop up, which will display the text previously killed, +one entry on each line. In this special mode, keys do not insert +themselves; instead, they choose actions to perform. + address@hidden @kbd address@hidden RET +Choose the text at point to yank (@code{kill-ring-menu-insert}). address@hidden n +Move point forward by one kill ring entry +(@code{kill-ring-menu-forward}). address@hidden p +Move point backwards by one kill ring entry +(@code{kill-ring-menu-backward}). address@hidden q +Quit the kill ring menu without yanking any text +(@code{kill-ring-menu-quit}). address@hidden d +Remove the text at point from the kill ring +(@code{kill-ring-menu-delete}). address@hidden table + +The kill ring menu can display multi-line text; In the default display +style, all text is shown on one line, and newlines are shown as a address@hidden + address@hidden Cycling Through Yanked Text + +If you know precisely where the text you previously yanked is in the address@hidden, or it was very recently yanked, you may find using +the @code{yank-pop} functionality of @kbd{M-y} to be faster than the +kill ring menu. For example, to recover the text of the +next-to-the-last kill, you could first use @kbd{C-y} to yank the last +kill, and then type @kbd{M-y} to replace it with the previous kill. + + You can understand @code{yank-pop} in terms of a ``last yank'' +pointer which points at an entry in the kill ring. Each time you +kill, the ``last yank'' pointer moves to the newly made entry at the +front of the ring. @kbd{C-y} yanks the entry which the ``last yank'' +pointer points to. After that, typing @kbd{M-y} moves the ``last +yank'' pointer to a different entry, and the text in the buffer +changes to match. Enough @code{yank-pop} commands can move the +pointer to any entry in the ring, so you can get any entry into the buffer. Eventually the pointer reaches the end of the ring; the next @kbd{M-y} loops back around to the first entry again. - @kbd{M-y} moves the ``last yank'' pointer around the ring, but it does -not change the order of the entries in the ring, which always runs from -the most recent kill at the front to the oldest one still remembered. - - @kbd{M-y} can take a numeric argument, which tells it how many entries -to advance the ``last yank'' pointer by. A negative argument moves the -pointer toward the front of the ring; from the front of the ring, it -moves ``around'' to the last entry and continues forward from there. - - Once the text you are looking for is brought into the buffer, you can -stop doing @kbd{M-y} commands and it will stay there. It's just a copy -of the kill ring entry, so editing it in the buffer does not change -what's in the ring. As long as no new killing is done, the ``last -yank'' pointer remains at the same place in the kill ring, so repeating address@hidden will yank another copy of the same previous kill. - - If you know how many @kbd{M-y} commands it would take to find the -text you want, you can yank that text in one step using @kbd{C-y} with -a numeric argument. @kbd{C-y} with an argument restores the text from -the specified kill ring entry, counting back from the most recent as -1. Thus, @kbd{C-u 2 C-y} gets the next-to-the-last block of killed + @code{yank-pop} moves the ``last yank'' pointer around the ring, but +it does not change the order of the entries in the ring, which always +runs from the most recent kill at the front to the oldest one still +remembered. + + @code{yank-pop} can take a numeric argument, which tells it how many +entries to advance the ``last yank'' pointer by. A negative argument +moves the pointer toward the front of the ring; from the front of the +ring, it moves ``around'' to the last entry and continues forward from --- font-lock.el.~1.195.~ Fri Apr 5 04:37:40 2002 +++ font-lock.el Sun Apr 28 03:41:17 2002 @@ -1358,6 +1358,32 @@ (put-text-property start next prop value object) (setq start (text-property-any next end prop nil object))))) +(defun font-lock-fontify-on-text-properties (beg end &rest plist) + "Match areas of text which have text properties with faces. +Only areas of text between BEG and END are considered. The remaining +arguments should form a property list which looks like + (PROPERTY FACE PROPERTY FACE ...)." + (save-excursion + (let ((change-end nil)) + (while plist + (goto-char beg) + (while (and plist + (setq change-end (font-lock-fontify-on-text-property + (car plist) (cadr plist) (point) end))) + (goto-char change-end)) + (setq plist (cddr plist)))))) + +(defun font-lock-fontify-on-text-property (prop face beg end) + "Add face FACE to areas of text which have text property PROP. +Only areas of text between BEG and END are considered." + (let ((prop-beg (or (and (get-text-property (point) prop) (point)) + (next-single-property-change (point) prop nil end)))) + (when (and prop-beg (not (= prop-beg end))) + (let ((prop-end (next-single-property-change beg prop nil end))) + (when (and prop-end (not (= prop-end end))) + (put-text-property prop-beg prop-end 'face face) + prop-end))))) + ;; For completeness: this is to `remove-text-properties' as `put-text-property' ;; is to `add-text-properties', etc. ;(defun remove-text-property (start end property &optional object)