How do I duplicate a whole line in Emacs?

Viewed 81106

I saw this same question for VIM and it has been something that I myself wanted to know how to do for Emacs. In ReSharper I use CTRL-D for this action. What is the least number of commands to perform this in Emacs?

34 Answers

I use

C-a C-SPACE C-n M-w C-y

which breaks down to

  • C-a: move cursor to start of line
  • C-SPACE: begin a selection ("set mark")
  • C-n: move cursor to next line
  • M-w: copy region
  • C-y: paste ("yank")

The aforementioned

C-a C-k C-k C-y C-y

amounts to the same thing (TMTOWTDI)

  • C-a: move cursor to start of line
  • C-k: cut ("kill") the line
  • C-k: cut the newline
  • C-y: paste ("yank") (we're back at square one)
  • C-y: paste again (now we've got two copies of the line)

These are both embarrassingly verbose compared to C-d in your editor, but in Emacs there's always a customization. C-d is bound to delete-char by default, so how about C-c C-d? Just add the following to your .emacs:

(global-set-key "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y")

(@Nathan's elisp version is probably preferable, because it won't break if any of the key bindings are changed.)

Beware: some Emacs modes may reclaim C-c C-d to do something else.

In addition to the previous answers you can also define your own function to duplicate a line. For example, putting the following in your .emacs file will make C-d duplicate the current line.

(defun duplicate-line()
  (interactive)
  (move-beginning-of-line 1)
  (kill-line)
  (yank)
  (open-line 1)
  (next-line 1)
  (yank)
)
(global-set-key (kbd "C-d") 'duplicate-line)

Place cursor on line, if not at beginning do a CTRL-A, then:

CTRL-K

CTRL-K

CTRL-Y

CTRL-Y

My version of a function to duplicate a line that works nice with undo and doesn't mess with the cursor position. It was the result of a discussion in gnu.emacs.sources from November 1997.

(defun duplicate-line (arg)
  "Duplicate current line, leaving point in lower line."
  (interactive "*p")

  ;; save the point for undo
  (setq buffer-undo-list (cons (point) buffer-undo-list))

  ;; local variables for start and end of line
  (let ((bol (save-excursion (beginning-of-line) (point)))
        eol)
    (save-excursion

      ;; don't use forward-line for this, because you would have
      ;; to check whether you are at the end of the buffer
      (end-of-line)
      (setq eol (point))

      ;; store the line and disable the recording of undo information
      (let ((line (buffer-substring bol eol))
            (buffer-undo-list t)
            (count arg))
        ;; insert the line arg times
        (while (> count 0)
          (newline)         ;; because there is no newline in 'line'
          (insert line)
          (setq count (1- count)))
        )

      ;; create the undo information
      (setq buffer-undo-list (cons (cons eol (point)) buffer-undo-list)))
    ) ; end-of-let

  ;; put the point in the lowest line and return
  (next-line arg))

Then you can define CTRL-D to call this function:

(global-set-key (kbd "C-d") 'duplicate-line)

Here's yet another function for doing this. My version doesn't touch the kill ring, and the cursor ends up on the new line where it was on the original. It will duplicate the region if it's active (transient mark mode), or default to duplicating the line otherwise. It will also make multiple copies if given a prefix arg, and comment out the original line if given a negative prefix arg (this is useful for testing a different version of a command/statement while keeping the old one).

(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)))))

I have it bound to C-c d:

(global-set-key [?\C-c ?d] 'duplicate-line-or-region)

This should never be re-assigned by a mode or anything because C-c followed by a single (unmodified) letter is reserved for user bindings.

Nathan's addition to your .emacs file is the way to go but it could be simplified slightly by replacing

  (open-line 1)
  (next-line 1)

with

  (newline)

yielding

(defun duplicate-line()
  (interactive)
  (move-beginning-of-line 1)
  (kill-line)
  (yank)
  (newline)
  (yank)
)
(global-set-key (kbd "C-d") 'duplicate-line)

I have copy-from-above-command bound to a key and use that. It's provided with XEmacs, but I don't know about GNU Emacs.

`copy-from-above-command' is an interactive compiled Lisp function
-- loaded from "/usr/share/xemacs/21.4.15/lisp/misc.elc" (copy-from-above-command &optional ARG)

Documentation: Copy characters from previous nonblank line, starting just above point. Copy ARG characters, but not past the end of that line. If no argument given, copy the entire rest of the line. The characters copied are inserted in the buffer before point.

I don't quite remember how line duplication works anywhere else, but as a former SciTE user I liked one thing about SciTE-way: it doesn't touch the cursor position! So all the recipies above weren't good enough for me, here's my hippie-version:

(defun duplicate-line ()
    "Clone line at cursor, leaving the latter intact."
    (interactive)
    (save-excursion
        (let ((kill-read-only-ok t) deactivate-mark)
            (toggle-read-only 1)
            (kill-whole-line)
            (toggle-read-only 0)
            (yank))))

Note that nothing gets actually killed in process, leaving marks and current selection intact.

BTW, why you guys so fond of jerking cursor around when there's this nice'n'clean kill-whole-line thingy (C-S-backspace)?

because i don't know, i'll start this round of golf with a slowball:

ctrl-k, y, y

something you might want to have in your .emacs is

(setq kill-whole-line t)

Which basically kills the entire line plus the newline whenever you invoke kill-line (i.e. via C-k). Then without extra code, you can just do C-a C-k C-y C-y to duplicate the line. It breaks down to

C-a go to beginning of line
C-k kill-line (i.e. cut the line into clipboard)
C-y yank (i.e. paste); the first time you get the killed line back; 
    second time gives the duplicated line.

But if you use this often then maybe a dedicated key binding might be a better idea, but the advantage of just using C-a C-k C-y C-y is you can duplicate the line elsewhere, instead of just below the current line.

' I wrote my own version of duplicate-line, cause I don't want to screw up the killing ring.

  (defun jr-duplicate-line ()
    "EASY"
    (interactive)
    (save-excursion
      (let ((line-text (buffer-substring-no-properties
                        (line-beginning-position)
                        (line-end-position))))
        (move-end-of-line 1)
        (newline)
        (insert line-text))))
  (global-set-key "\C-cd" 'jr-duplicate-line)

The defaults are horrible for this. However, you can extend Emacs to work like SlickEdit and TextMate, that is, copy/cut the current line when no text is selected:

(transient-mark-mode t)
(defadvice kill-ring-save (before slick-copy activate compile)
  "When called interactively with no active region, copy a single line instead."
  (interactive
   (if mark-active (list (region-beginning) (region-end))
     (message "Copied line")
     (list (line-beginning-position)
           (line-beginning-position 2)))))
(defadvice kill-region (before slick-cut activate compile)
  "When called interactively with no active region, kill a single line instead."
  (interactive
   (if mark-active (list (region-beginning) (region-end))
     (list (line-beginning-position)
           (line-beginning-position 2)))))

Place the above in .emacs. Then, to copy a line, M-w. To delete a line, C-w. To duplicate a line, C-a M-w C-y C-y C-y ....

With recent emacs, you can use M-w anywhere in the line to copy it. So it becomes:

M-w C-a RET C-y

ctrl-k, ctrl-k, (position to new location) ctrl-y

Add a ctrl-a if you're not starting at the beginning of the line. And the 2nd ctrl-k is to grab the newline character. It can be removed if you just want the text.

@[Kevin Conner]: Pretty close, so far as I know. The only other thing to consider is turning on kill-whole-line to include the newline in the C-k.

Here's a function for duplicating current line. With prefix arguments, it will duplicate the line multiple times. E.g., C-3 C-S-o will duplicate the current line three times. Doesn't change kill ring.

(defun duplicate-lines (arg)
  (interactive "P")
  (let* ((arg (if arg arg 1))
         (beg (save-excursion (beginning-of-line) (point)))
         (end (save-excursion (end-of-line) (point)))
         (line (buffer-substring-no-properties beg end)))
    (save-excursion
      (end-of-line)
      (open-line arg)
      (setq num 0)
      (while (< num arg)
        (setq num (1+ num))
        (forward-line 1)
        (insert line))
      )))

(global-set-key (kbd "C-S-o") 'duplicate-lines)

If you're using Spacemacs, you can simply use duplicate-line-or-region, bound to:

SPC x l d 

There's a package called 'move-dup' on Melpa that can help you with that.

Disclaimer: I'm the author of that package.

I cannot believe all these complicated solutions. This is two keystrokes:

<C-S-backspace> runs the command kill-whole-line

C-/ runs the command undo

So <C-S-backspace> C-/ to "copy" a whole line (kill and undo).

You can, of course, combine this with numeric and negative args to kill multiple lines either forward or backward.

As mentioned in other answers, binding key strokes to lisp code is a better idea than binding them to another key strokes. With @mw's answer, code duplicates the line and moves the mark to end of new line. This modification keeps the mark position at same column on the new line:

fun duplicate-line ()
  (interactive)
  (let ((col (current-column)))
    (move-beginning-of-line 1)
    (kill-line)
    (yank)
    (newline)
    (yank)
    (move-to-column col)))

The simplest way is Chris Conway's method.

C-a C-SPACE C-n M-w C-y

That's the default way mandated by EMACS. In my opinion, it's better to use the standard. I am always careful towards customization one's own key-binding in EMACS. EMACS is already powerful enough, I think we should try our best to adapt to its own key-bindings.

Though it's a bit lengthy, but when you are used to it, you can do fast and will find this is fun!

This feels more natural, with respect to the selected answer by Chris Conway.

(global-set-key "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y\C-p\C-e")

This allows you to duplicate a line multiple times by simply repeating the \C-c\C-d key strokes.

well ive usually used:

Ctl-Space (set the mark)
move to end of line
Ctl-K kill line
Ctl-Y * 2 (yank the line back)

there may be a much better way though :P

Related