How do I duplicate a whole line in Emacs?

Solution 1:

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.

Solution 2:

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)

Solution 3:

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

CTRL-K

CTRL-K

CTRL-Y

CTRL-Y

Solution 4:

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)