8

I often seem to want to copy paste multiple columns, for example, I paste one column

line one
line two
line three

Now I'd like to be able to yank another column behind it. Assuming my kill buffer has the following:

added to one
added to two
added to three

Which command would I need to invoke to get the following:

line one added to one
line two added to two
line three added to three

Update

Using the rectangles functionality of Emacs helps quite a bit, but is still suboptimal. For instance, if using Emacs in graphical mode and you are yanking from external programs, i.e. using the Copy-paste functionality from your OS, the kill-buffer has no rectangular meta info, so rectangular yank does not work. Another issue is if you are having a columns with varying internal width:

short line                        *
a much larger line which goes on
short line again

And you want to rectangular yank, you'll have to place your pointer at the marked spot (*). Although this is trivial with three lines, it can be quite cumbersome to make sure you are placing the pointer at the most outer edge of the first column.

Drew
  • 75,699
  • 9
  • 109
  • 225
hbogert
  • 191
  • 1
  • 6
  • Not quite sure I understand, but I think you want to work with [rectangles](http://www.gnu.org/software/emacs/manual/html_node/emacs/Rectangles.html). – Dan Nov 18 '15 at 11:45
  • Not sure there is a straightforward answer to this. Once the text is copied to the clipboard, any information about columns has been lost. I think you would probably need to do something outside Emacs, in order to preserve this "column" info. – Drew Nov 18 '15 at 16:02
  • If only i was more proficient with elisp, i expect this to be just a few lines, but actually expected this to be an existing function – hbogert Nov 18 '15 at 21:09
  • You can do this with a macro pretty easy. Yank your second column text beneath the first column text. Then record a macro that moves the top value of column two data to the end of the first row of column one data then moves down the the next value of column two data and execute it until it all lines up. – Jordon Biondo Nov 19 '15 at 21:37

2 Answers2

6

Here is a one-off command you can use to yank the each line of the current kill on the end of each subsequent line, starting on the current line.

(defun yank-append-lines (&optional without-space)
  "Yank each line of the current kill at the end of each subsequent line.

A space will be added between each line unless WITHOUT-SPACE which can
be passed in via a prefix arg."
  (interactive "P")
  (save-excursion
    (let ((lines (split-string (current-kill 0) "\n")))
      (dolist (line lines)
        (goto-char (line-end-position))
        (unless without-space
          (just-one-space))
        (insert line)
        (unless (zerop (forward-line))
          (insert "\n"))))))

The implementation is fairly simple. Take the current-kill, split it by line. Then for each split line: go to the end of the split line, insert a space, insert a line then move forward one line.

This could also be done with a repeatable macro that moves a line from one place in the buffer to the end of a line in another part of the buffer.

Jordon Biondo
  • 12,332
  • 2
  • 41
  • 62
0

I have a little helper that I use that lets me copy a column of lines from any program and paste it into Emacs as if I had obtained it through copy-rectangle-as-kill. Very useful for doing the equivalent of the CLI program paste (or the equivalent of pasting lines into a fresh column in a spreadsheet).

(defun my-yank-as-rectangle ()
  "Yank the current kill as if it were a rectangle region."
  (interactive)
  (let* ((lines (split-string (current-kill 0) "\n"))
         (longest (apply #'max (mapcar #'length lines)))
         (as-rect (with-temp-buffer
                    (insert (current-kill 0))
                    (indent-to-column longest)
                    (extract-rectangle (point-min) (point)))))
    (insert-rectangle
     (mapcar #'string-trim-right as-rect))))
(keymap-global-set "C-x r Y" #'my-yank-as-rectangle)
unhammer
  • 1,127
  • 8
  • 22