4

For some reason, copying lines in Emacs is very unintuitive and difficult. If I'm doing something wrong here, please let me know. It is surprising that Emacs does not have this by default somewhere.

I am trying to write a function that copies a line. I always used to have:

(global-set-key (kbd "C-x c") "\C-a\C- \C-n\M-w")

This is a little annoying since it copies any new line after the line. I decided to change it to:

(global-set-key (kbd "C-x c") "\M-m\C- \C-e\M-w")

Now, I saw: http://www.emacswiki.org/emacs/CopyingWholeLines and it appears that their copy-line function prints a message with the number of lines it copied. I am trying to insert that message into my global-set-key above but it is not working. Basically, I am unable to run a raw sequence as above in a function. So I conveyed each keystroke into a function and did this:

(defun copy-line ()
   (interactive)
   (kill-ring-save
    (back-to-indentation)
    (move-end-of-line 1))
    (message "1 line copied"))
;; optional key binding                 
(global-set-key "\C-c\C-k" 'copy-line)

This however, throws a wrong number of arguments error.

My first question: How can I put (message "1 line copied") into my global-set-key above?

My second question: using the standard copy-line found in the link above:

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

From the message, it appears that you can have multiple lines copied. However, when selecting multiple lines and copying, only one is copied. Why is the message structured in this way? How can it select multiple lines?

darksky
  • 20,411
  • 61
  • 165
  • 254
  • 1
    The two arguments of `kill-ring-save` are positions in the buffer (think coordinates). Instead you used called functions that move the point but do not return coordinates (they return nil). – Nicolas Dudebout Mar 18 '14 at 13:41
  • Cross-referencing with http://stackoverflow.com/questions/88399/how-do-i-duplicate-a-whole-line-in-emacs – phils Mar 19 '14 at 03:02

2 Answers2

3

Here's your function, fixed:

(defun copy-line ()
  (interactive)
  (save-excursion
    (back-to-indentation)
    (kill-ring-save
     (point)
     (line-end-position)))
     (message "1 line copied"))

The problem was that back-to-indentation doesn't return point.

As for the other function, it will copy multiple lines when called with a prefix argument, e.g. C-u or M-5.

abo-abo
  • 20,038
  • 3
  • 50
  • 71
2

Here's a shorter version of the simple function:

(defun copy-line ()
  (interactive)
  (kill-ring-save (point-at-bol) (point-at-eol))
  (message "1 line copied"))

For the multiline copy version that you cited, use the prefix to indicate how many lines you want copied (as the other answer suggests). So, with your keybinding of C-c C-k, do the following to copy, say, 3 lines: C-u 3 C-c C-k.

Dan
  • 5,209
  • 1
  • 25
  • 37
  • This does not work as the OP wants. It does not go back to the indentation but to the beginning of the line. – Nicolas Dudebout Mar 18 '14 at 13:40
  • If you want to change it to the first non-whitespace, change it to: (kill-ring-save (save-excursion (back-to-indentation) (point)) (point-at-eol)). Of course, that basically gives the original function; the point of the simple one is that there are fewer moving parts and thus easier to understand. – Dan Mar 18 '14 at 14:01