duplicating lines and commenting them

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,

and 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

binding.



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

No comments:

Post a Comment

Followers

Popular Posts