Someone on the Emacs Help mailing list asked for an easy way to duplicate a line
and, optionally, comment-out the first one.
Let's first look at simple duplication of a line. This is a common operation,
vi-users might use something like
Yp for that. In emacs, one way to do
this is by typing
C-a C-k C-k C-y C-y, which is actually not as bizarre as
it looks if you try it. When using slick copy, as explained in another post,
it's as easy as
M-w C-n C-y; and of course it's easy to define a shorter key
repeat after me repeat after me
However, neither of these methods works correctly when you're on the last line
of the buffer (by default at least). Also, it puts the point (cursor) below
the duplicated line, while I'd like to put it at the start of it. It seems we
need something a little smarter.
While we're at it, let's also consider the second question: commenting-out the
first line of the duplicates. This is a quite common thing to do when writing
programs or configuration files; you want to try the effect of a small
variation of a line, but want to keep the original so it can be restored when
the variation turns out not to be as good as expected.
/* for (;;) fork (); */ for (;;) fork ();
I hacked up something quickly to solve both questions, and it has evolved a
little bit since – to answer both of the questions. The bit of weirdness in
the end is because of the special case of the last line in a buffer. It
defines key bindings
C-c y for duplicating a line, and
C-c c for
duplicating + commenting – but of course you can change those.
(defun djcb-duplicate-line (&optional commentfirst) "comment line at point; if COMMENTFIRST is non-nil, comment the original" (interactive) (beginning-of-line) (push-mark) (end-of-line) (let ((str (buffer-substring (region-beginning) (region-end)))) (when commentfirst (comment-region (region-beginning) (region-end))) (insert-string (concat (if (= 0 (forward-line 1)) "" "\n") str "\n")) (forward-line -1))) ;; or choose some better bindings.... ;; duplicate a line (global-set-key (kbd "C-c y") 'djcb-duplicate-line) ;; duplicate a line and comment the first (global-set-key (kbd "C-c c") (lambda()(interactive)(djcb-duplicate-line t)))