CopyingWholeLines

Standard Emacs

There are various ways to copy the current line to the kill ring in vanilla GnuEmacs:

Using the mouse

You can also use either of these mouse selection methods to select whole lines as the SecondarySelection – just hold down the Meta key while you click.

Using the keyboard

In the key sequences above, ‘C-a’ goes to beginning of line, ‘C-e’ goes to the end of line, ‘C-n’ goes to the next line, ‘C-SPC’ sets the mark, ‘M-w’ saves the region, ‘C-k’ kills from point to the end of line, and ‘C-y’ yanks the last kill back.

You can also copy whole lines using Viper: yy (current line), yj (current + next etc.).

Enhancements

This section presents some additional ways to copy a line, besides those available out of the box.

  1. Define a new command for copying the current line. It can then be bound to a shorter key sequence, e.g., ‘C-c C-k’.
  2. Modify the vanilla commands, for some context-dependent behavior.

New commands

Best overall imo for adding to standard emacs

  (defun copy-line (arg)
    "Copy lines (as many as prefix argument) in the kill ring.
      Ease of use features:
      - Move to start of next line.
      - Appends the copy on sequential calls.
      - Use newline as last char even on the last line of the buffer.
      - If region is active, copy its lines."
    (interactive "p")
    (let ((beg (line-beginning-position))
          (end (line-end-position arg)))
      (when mark-active
        (if (> (point) (mark))
            (setq beg (save-excursion (goto-char (mark)) (line-beginning-position)))
          (setq end (save-excursion (goto-char (mark)) (line-end-position)))))
      (if (eq last-command 'copy-line)
          (kill-append (buffer-substring beg end) (< end beg))
        (kill-ring-save beg end)))
    (kill-append "\n" nil)
    (beginning-of-line (or (and arg (1+ arg)) 2))
    (if (and arg (not (= 1 arg))) (message "%d lines copied" arg)))
Simple copy line
    (defun copy-line (arg)
      "Copy lines (as many as prefix argument) in the kill ring"
      (interactive "p")
      (kill-ring-save (line-beginning-position)
                      (line-beginning-position (+ 1 arg)))
      (message "%d line%s copied" arg (if (= 1 arg) "" "s")))
   ;; optional key binding
   (global-set-key "\C-c\C-k" 'copy-line)

A copy-line that uses kill-line in a read-only context

Originally by GregReagle; improvements by Bodhi.

    (defun copy-line (&optional arg)
      "Do a kill-line but copy rather than kill.  This function directly calls
    kill-line, so see documentation of kill-line for how to use it including prefix
    argument and relevant variables.  This function works by temporarily making the
    buffer read-only."
      (interactive "P")
      (let ((buffer-read-only t)
            (kill-read-only-ok t))
        (kill-line arg)))
    ;; optional key binding
    (global-set-key "\C-c\C-k" 'copy-line)

quick-copy-line

Anonymous’s first EmacsLisp function.

    (defun quick-copy-line ()
      "Copy the whole line that point is on and move to the beginning of the next line.
    Consecutive calls to this command append each line to the
    kill-ring."
      (interactive)
      (let ((beg (line-beginning-position 1))
            (end (line-beginning-position 2)))
        (if (eq last-command 'quick-copy-line)
            (kill-append (buffer-substring beg end) (< end beg))
          (kill-new (buffer-substring beg end))))
      (beginning-of-line 2))

I bind this command to <f11>. Hitting <f11> multiple times appends each line to the kill ring (which is why the command moves to the beginning of the next line). This makes it really quick and easy to copy multiple lines.

quick-cut-line

(defun quick-cut-line ()
  "Cut the whole line that point is on.  Consecutive calls to this command append each line to the kill-ring."
  (interactive)
  (let ((beg (line-beginning-position 1))
	(end (line-beginning-position 2)))
    (if (eq last-command 'quick-cut-line)
	(kill-append (buffer-substring beg end) (< end beg))
      (kill-new (buffer-substring beg end)))
    (delete-region beg end))
  (beginning-of-line 1)
  (setq this-command 'quick-cut-line))

Similar to the quick-copy-line, I define the function quick-cut-line to quickly cut multiple lines and append them to the kill-ring. I bind it to \M-f11.

This is the same behavior as hitting `<C-S-backspace>’, the binding for ‘kill-whole-line’.

avi-kill-line-save

I too always wondered why stock Emacs didn’t have a convenient line copying keybinding, or even a function. There are C-w (kill-region) and M-w (kill-ring-save), but C-k (kill-line) doesn’t seem to have a counterpart that just saves the lines into the kill ring.

This one behaves the same way as ‘kill-line’, except that it doesn’t move point at all, because I felt that it suits me the best this way. What I’d like to expand it with is the possibillity to be able to call it consecutively and copy multiple lines one for one, as quick-copy-line does, and let this behaviour depend on a variable or a prefix. When I find time for that. As of now I use both functions with different keys, depending on the situation i need them. – avi

    (defun avi-kill-line-save (&optional arg)
      "Copy to the kill ring from point to the end of the current line.
    With a prefix argument, copy that many lines from point. Negative
    arguments copy lines backward. With zero argument, copies the
    text before point to the beginning of the current line."
      (interactive "p")
      (save-excursion
        (copy-region-as-kill
         (point)
         (progn (if arg (forward-visible-line arg)
                  (end-of-visible-line))
                (point)))))

duplicate-current-line

I (dim) am doing that instead:

    ;; duplicate current line
    (defun duplicate-current-line (&optional n)
      "duplicate current line, make more than 1 copy given a numeric argument"
      (interactive "p")
      (save-excursion
        (let ((nb (or n 1))
    	  (current-line (thing-at-point 'line)))
          ;; when on last line, insert a newline first
          (when (or (= 1 (forward-line 1)) (eq (point) (point-max)))
    	(insert "\n"))
    
          ;; now insert as many time as requested
          (while (> n 0)
    	(insert current-line)
    	(decf n)))))
    
    (global-set-key (kbd "C-S-d") 'duplicate-current-line)

smart copy region

To copy the rest of the line without marking it, I use

    (defun my-kill-ring-save ()
        (interactive)
        (if (equal mark-active nil) (kill-ring-save (point) (line-end-position)) (kill-ring-save (point) (mark))))
    (global-set-key "\M-w" 'my-kill-ring-save)

If you mark a region this behaves as expected and saves the region to the kill ring, otherwise, saves the region between (point) and the end of line to the kill ring.

Copy line or region

The below works with lines or regions. It preserves cursor position. It does not alter kill ring.

    (defun duplicate-line-or-region (&optional n)
      "Duplicate current line, or region if active.
    With argument N, make N copies.
    With negative N, comment out original line and use the absolute value."
      (interactive "*p")
      (let ((use-region (use-region-p)))
        (save-excursion
          (let ((text (if use-region        ;Get region if active, otherwise line
                          (buffer-substring (region-beginning) (region-end))
                        (prog1 (thing-at-point 'line)
                          (end-of-line)
                          (if (< 0 (forward-line 1)) ;Go to beginning of next line, or make a new one
                              (newline))))))
            (dotimes (i (abs (or n 1)))     ;Insert N times, or once if not specified
              (insert text))))
        (if use-region nil                  ;Only if we're working with a line (not a region)
          (let ((pos (- (point) (line-beginning-position)))) ;Save column
            (if (> 0 n)                             ;Comment out original with negative arg
                (comment-region (line-beginning-position) (line-end-position)))
            (forward-line 1)
            (forward-char pos)))))

As posted in [1]

Modifying the default commands

SlickEdit, TextMate and VisualStudio have clever line-wise behavior: if no text is selected, the copy and cut commands act on the current line instead. To do this in Emacs (with M-w and C-w), see WholeLineOrRegion.

A more versatile solution is provided by Leo: if the region is active, M-w saves the region, otherwise it tries in order of URL, e-mail and the current line. M-w followed by the key f, l, s or w copies file name, list, S-expression and word, respectively. The selection can be expanded or shrunk line-wise or list-wise. See easy-kill for more details.


CategoryRegion CategoryMouse