I am looking for an easy way to gather blocks of text that are scattered throughout an emacs or org-mode document and move (or copy, but move would be preferred) them to a single location.

(For example, reorganizing thoughts in an org-mode outline, where items that had been sub-entries of various different sub-outlines are to be gathered under a new heading as a new point.)

I had thought I could use the kill ring to cut the kill the various items, knowing they would be stored successively in the kill ring, move point to the new location and then yank them back. That would copy, rather than move, but I thought I could start with that.

I don't see, however, how to get yank to continue appending entries from the kill ring at point. (I see I could accumulate in another buffer, but isn't there a default key binding just to yank successively at point?)

Any thoughts either on accomplishing the specific kill ring objective, or my ultimate goal of moving scattered text will be appreciated.

  • 1. Cutting doesn't just copy. It deletes from the original location. 2. C-y followed by repeated M-y yanks previous kill-ring entries. – Drew Jul 29 '17 at 0:33
  • @Drew: But repeating M-y replaces each yank with the previous one. In order to accumulate the yanks, you would need the growing sequence: C-y, C-y M-y, C-y M-y M-y, C-y M-y M-y M-y, etc. Alternatively, just repeat C-2 C-y, as per my answer. – deprecated Jul 29 '17 at 3:01
  • @deprecated: Yes, I know. Or use a prefix arg. Or use a prefix arg with C-y. Or use browse-kill-ring. Or use any number of other approaches. – Drew Jul 29 '17 at 4:42

A fourth option is optimized for ease of yanking, at the cost of a little forethought during the killing phase. We use append-next-kill (C-M-w) before the second and each subsequent kill operation. This means that all the killed text is amalgamated into the same entry in the kill ring. So a single C-y is all that is needed to yank it all back at the new location.

For instance, a sequence for moving 3 chunks to a common destination could be: C-k C-k to kill 1st chunk, move somewhere, select text, C-M-w C-w to kill 2nd chunk, move somewhere else, C-M-w C-k C-k C-k C-k to kill 3rd chunk, move to destination, C-y and done!

Note that only a single C-M-w is necessary before a sequence of several C-k. The same is true of other kill commands, such as M-d.

Here is the doc string for C-M-w:

C-M-w runs the command append-next-kill (found in global-map), which is an interactive compiled Lisp function in simple.el.

It is bound to C-M-w.

(append-next-kill &optional INTERACTIVE)

Cause following command, if it kills, to add to previous kill. If the next command kills forward from point, the kill is appended to the previous killed text. If the command kills backward, the kill is prepended. Kill commands that act on the region, such as kill-region, are regarded as killing forward if point is after mark, and killing backward if point is before mark.

If the next command is not a kill command, append-next-kill has no effect.

The argument is used for internal purposes; do not supply one.

  • Came here to suggest this. Glad you saved me the effort. – Omar Jul 29 '17 at 23:16

There are at least two ways of approaching this.

  1. To answer your specific about yanking back a sequence of previous kills, you can do this as follows. First, perform all your kills with a series of C-k or C-w (or whatever) in different places. Then, go to where you want to put them and type C-y to yank the last-killed item, followed by repeatedly typing C-2 C-y to access the previously killed items in turn (in reverse order). See Yanking Earlier Kills section of the manual for more details.

  2. However, since you mention specifically reorganizing an org-mode outline, you would probably be better off using org-refile (C-c C-w). By default, this only allows you to move sub-headings to a top-level heading in the same file. But if that is too limiting for you, you can customize the variable org-refile-targets. For instance (following a suggestion from Sacha Chua): (setq org-refile-targets '((org-agenda-files . (:maxlevel . 6))))

  • Wow, I stared at the "Yanking Earlier Kills" man page and tried nearly everything there - I simply did not get that that is what the numeric prefix would do. Thanks. I will also play with org-refile. (Want to wait and see if other suggestions are posted before accepting, but will return and do so.) – Will M Jul 29 '17 at 2:37
  • You shouldn't feel ashamed – I have been using Emacs for more than a quarter of a century, and I only really understood how the C-y numeric prefix worked today! I have some more suggestions, which I will write up as separate answers if I have time – deprecated Jul 29 '17 at 3:28

A third option is to use the Paste from Kill Menu item in the Edit menu. On macOS, with no customization, it looks like this

screenshot of Paste from Kill Menu on macOS

Personally, I hardly ever use the menus and have disabled most of them, but I do keep the Edit menu around especially for this, since it avoids having to remember where you are in the kill ring.

If you want to quickly and directly access any given element of the kill-ring and yank it then there are various options. I'll mention a few.

  1. Browse Kill Ring: That pops up a buffer showing the kill-ring entries and lets you pick one.

  2. Use command icicle-completing-yank (C-- C-y, by default) with Icicles. That offers completion against the kill-ring, yanking the entry (or entries) you choose.

    If you also use library browse-kill-ring+.el or library second-sel.el then an alternative selection ring is used if you provide a prefix argument: browse-kill-ring-alternative-ring or secondary-selection-ring. This gives you a way to yank chosen items from two different sets of selections.

  3. Use M-y, if you use both Icicles and library second-sel.el.

    • If the previous command was a kill-ring yank command then this does yank-pop -- it yanks the previous kill.

    • If the previous command was a yank-secondary command then this does yank-pop-secondary -- it yanks the previous secondary selection.

    • Otherwise, this does icicle-completing-yank - see #2.

For #2 and #3, during completion you can use:

  • C-, to sort the candidates to yank in different ways (repeat)
  • S-delete to remove a candidate entry from the selection ring
  • C-S-return to copy a candidate to the other selection ring (requires second-sel.el or browse-kill-ring+.el)

A fifth (and final, from me) option is to use mouse-drag-secondary-pasting from mouse-copy.el. Here is an animated demo:

animated gif demo of mouse-drag-secondary-pasting

You just select text with the mouse/trackpad while holding the meta key down, and on the up-click it automatically yanks itself at the point position. No need for any key stroke.

This is especially suited to macbook trackpads – it combines well with 2-fingered scrolling, which is a great way of navigating in the non-selected windows of a split frame (without selecting them). Here is an example of how it can be set up:

(require 'mouse-copy)

(defun wjh/mouse-drag-secondary-pasting (start-event)
  "Drag out a secondary selection, then paste it at the current point.

Just the same as the `mouse-drag-secondary-pasting` from
mouse-copy.el, with two exceptions: (1) It behaves the same way
as `yank' with respect to text properties (as in not copying
invisible properties that you probably don't want), and (2) it
deactivates the secondary selection when it has finished."
  (interactive "e")
  (cl-letf (((symbol-function 'insert) #'insert-for-yank-1))
    (mouse-drag-secondary-pasting start-event))
  (delete-overlay mouse-secondary-overlay))

(global-set-key [M-down-mouse-1] 'wjh/mouse-drag-secondary-pasting)
;; TODO 18 Feb 2016 - re-write this function too
(global-set-key [M-S-down-mouse-1] 'mouse-drag-secondary-moving)

Note that I modify the function to deal with a couple of minor annoyances with the original: (1) avoid copying invisible text properties; (2) remove the secondary selection overlay as soon as I am done.

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.