33

I do C-a C-k C-k to kill the entire line point is on.

If I want to copy the line instead of killing it, I can hit C-/ C-/ right after typing the sequence above.

Alternatively, I can do C-a C-SPC C-n M-w.

Is there a faster way to kill or copy the entire line point is on?

2
  • 1
    Wow! These answer show the great lengths people will go to in order to avoid using the built-in kill-whole-line. :)
    – Omar
    Feb 24, 2019 at 0:02
  • As suggested below, use evil-mode. Learn Vim commands, you will not regret!
    – Arktik
    Feb 26, 2019 at 15:45

10 Answers 10

44

You can use kill-whole-line to kill the entire line point is on. Position of point does not matter. This command is bound to C-S-DEL by default.

You can also instruct kill-line (bound to C-k) to kill the entire line by setting the variable kill-whole-line to a non-nil value:

(setq kill-whole-line t)

Note that point has to be at the beginning of the line for this to work.


Then there are these two gems (via emacs-fu):

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

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

With these in place you can kill or copy the line point is on with a single keystroke:

  • C-w kills the current line
  • M-w copies the current line

Note that if there is an active region, kill-region and kill-ring-save will continue to do what they normally do: Kill or copy it.


Porting slick-cut and slick-copy to new advice system

Emacs 24.4 introduces a new advice system. While defadvice still works, there is a chance that it might be deprecated in favor of the new system in future versions of Emacs. To prepare for that, you might want to use updated versions of slick-cut and slick-copy:

(defun slick-cut (beg end)
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (list (line-beginning-position) (line-beginning-position 2)))))

(advice-add 'kill-region :before #'slick-cut)

(defun slick-copy (beg end)
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (message "Copied line")
     (list (line-beginning-position) (line-beginning-position 2)))))

(advice-add 'kill-ring-save :before #'slick-copy)
6
  • 2
    Note that kill-region and kill-ring-save still work even when the region is not "active." This will override that behavior. I use that behavior from time to time, but if you aren't used to using them this way, then you probably won't notice the difference.
    – nispio
    Oct 21, 2014 at 21:47
  • @nispio Please expand on when/how kill-region etc is usable/useful when mark-active is nil. Oct 22, 2016 at 8:30
  • 1
    @PhilHudson The mark can be (and usually is) set without being active. Try doing C-SPC twice to activate and then deactivate the mark. Move the cursor elsewhere in the file and run kill-region and it will kill the region between point and mark, even though the mark is not active. A few examples of commands that set (but do not activate) the mark are yank and isearch. After performing these sorts commands, I know where the mark is, even if it is not active, and many commands (including kill-region) will let me use the mark without explicitly activating it.
    – nispio
    Oct 31, 2016 at 19:37
  • Thanks @nispio. Of course. That's how it used to be, exclusively, before visible region highlighting became the default a couple of major releases back, right? I was confusing "active" with "set". Nov 1, 2016 at 18:38
  • 1
    This is the greatest answer ever posted on any SX. Seriously. Oct 10, 2017 at 19:37
17

There's a package called whole-line-or-region which advises various built-in commands so that they act on the current line if no region is active, so M-w will copy the current line, and C-w will kill it, for example. I've been using the package for years, and find it indispensable.

Additionally, this package makes it so that a numeric prefix will indicate the number of lines to act upon, so M-2 M-w will copy two lines. The other answers here do not provide that handy functionality.

I took over maintenance of the package at my github account when the author stopped maintaining it and became unresponsive.

whole-line-or-region also provides facilities for adding this behaviour to further commands, should you need that.

1
  • Please file a MELPA issue for that, because I'm not sure what you mean: I install this package from MELPA all the time without issues.
    – sanityinc
    Dec 25, 2018 at 21:09
15

The solution I've found for myself is to use prefix arguments.

For me, killing half a line is a useful feature, but I want an easier way of killing entire lines too. So I made it so that kill-line just murders everything in sight when given a prefix argument.

(defmacro bol-with-prefix (function)
  "Define a new function which calls FUNCTION.
Except it moves to beginning of line before calling FUNCTION when
called with a prefix argument. The FUNCTION still receives the
prefix argument."
  (let ((name (intern (format "endless/%s-BOL" function))))
    `(progn
       (defun ,name (p)
         ,(format 
           "Call `%s', but move to BOL when called with a prefix argument."
           function)
         (interactive "P")
         (when p
           (forward-line 0))
         (call-interactively ',function))
       ',name)))

(global-set-key [remap paredit-kill] (bol-with-prefix paredit-kill))
(global-set-key [remap org-kill-line] (bol-with-prefix org-kill-line))
(global-set-key [remap kill-line] (bol-with-prefix kill-line))
(global-set-key "\C-k" (bol-with-prefix kill-line))

With this little macro, C-k still kills from point, but C-3 C-k swallows three whole lines. As a bonus, we get the kill-whole-line behavior by doing C-1 C-k.

7
  • That's a great idea, thanks for sharing it! :) How would you adapt this solution to work for copying one or more lines? kill-ring-save does not accept prefix arguments...
    – itsjeyd
    Oct 20, 2014 at 7:22
  • @itsjeyd I'm sure something similar could be done to merge the two answers. But it'd take just a bit more work.
    – Malabarba
    Oct 20, 2014 at 13:36
  • Last line refers to paredit-kill. Is it intended? Oct 20, 2014 at 13:40
  • 1
    Oh, ok, thanks. I'm not getting the expected behaviour, though. If I place pointer at the middle of a line and hit C-3 C-k, first line is not entirely killed. Is this how it is supposed to be working or am I doing something wrong? Oct 20, 2014 at 13:54
  • 1
    @Malabarba you're right, kill-visual-line is bound to C-k. I'll fix it. Thanks again. Oct 20, 2014 at 14:02
10

This is not an answer for orthodox emacs. If, however, you're willing to blaspheme with evil's modal editing, you can:

  • dd for kill line
  • yy for copy/yank line

Both can be prefixed by the number of lines to kill/copy (eg, 4yy will copy the next 4 lines).

2
  • Don't you mean Y or yy for "yank line"? cc "changes" the current line, killing the content and placing the cursor at the beginning of the line in Insert mode. Excuse me if the "API" has changed since you posted. Dec 18, 2020 at 20:10
  • @LoremIpsum: not sure what I was thinking about cc; you're right, yy is yank line. I've fixed the answer text.
    – Dan
    Dec 18, 2020 at 20:17
5

Besides @itsjeyd answer, may I suggest those two functions?

(defun xah-copy-line-or-region ()
  "Copy current line, or text selection.
When `universal-argument' is called first, copy whole buffer (but respect `narrow-to-region')."
  (interactive)
  (let (p1 p2)
    (if (null current-prefix-arg)
        (progn (if (use-region-p)
                   (progn (setq p1 (region-beginning))
                          (setq p2 (region-end)))
                 (progn (setq p1 (line-beginning-position))
                        (setq p2 (line-end-position)))))
      (progn (setq p1 (point-min))
             (setq p2 (point-max))))
    (kill-ring-save p1 p2)))

(defun xah-cut-line-or-region ()
  "Cut current line, or text selection.
When `universal-argument' is called first, cut whole buffer (but respect `narrow-to-region')."
  (interactive)
  (let (p1 p2)
    (if (null current-prefix-arg)
        (progn (if (use-region-p)
                   (progn (setq p1 (region-beginning))
                          (setq p2 (region-end)))
                 (progn (setq p1 (line-beginning-position))
                        (setq p2 (line-beginning-position 2)))))
      (progn (setq p1 (point-min))
             (setq p2 (point-max))))
    (kill-region p1 p2)))

Then, key definitions (you'll probably want to adapt them):

(global-set-key (kbd "<f2>") 'xah-cut-line-or-region) ; cut

(global-set-key (kbd "<f3>") 'xah-copy-line-or-region) ; copy

(global-set-key (kbd "<f4>") 'yank) ; paste

Courtesy of ErgoEmacs

3
  • Thanks for your answer! You might want to consider extending it a bit by describing how these commands differ from other solutions posted here. Yes, this information is available in the docstrings, but it doesn't hurt to make it more visible for future readers :)
    – itsjeyd
    Oct 20, 2014 at 8:44
  • 1
    Is it possible to do this but modify it like @Jonathan post below so it first takes the sexp or word and then takes the line if called again?
    – J Spen
    Dec 24, 2018 at 3:41
  • @JSpen What I'm doing is assigning a shortcut key to function. What Jonathan is doing is defining an advice to a function. So, you can just advice the function, then define a shortcut key to the adviced function; and you'll have your result. Sorry for the delay ;)
    – Nsukami _
    Jan 15, 2019 at 11:46
4

As an extension to @itsjeyd's answer above I have the following. (The logic could probably be cleaned up slightly and I will when I port to the new advice system, I'll likely also extend it to extend to sexp/paragraph if repeated again).

An initial C-w/M-w will grab only the word at point, while calling it a second time will grab the entire line.

;; *** Copy word/line without selecting
(defadvice kill-ring-save (before slick-copy-line activate compile)
  "When called interactively with no region, copy the word or line

Calling it once without a region will copy the current word.
Calling it a second time will copy the current line."
    (interactive
     (if mark-active (list (region-beginning) (region-end))
       (if (eq last-command 'kill-ring-save)
           (progn
             ;; Uncomment to only keep the line in the kill ring
             ;; (kill-new "" t)
             (message "Copied line")
             (list (line-beginning-position)
                   (line-beginning-position 2)))
         (save-excursion
           (forward-char)
           (backward-word)
           (mark-word)
           (message "Copied word")
           (list (mark) (point)))))))

;; *** Kill word/line without selecting
(defadvice kill-region (before slick-cut-line first activate compile)
  "When called interactively kill the current word or line.

Calling it once without a region will kill the current word.
Calling it a second time will kill the current line."
  (interactive
   (if mark-active (list (region-beginning) (region-end))
    (if (eq last-command 'kill-region)
        (progn
          ;; Return the previous kill to rebuild the line
          (yank)
          ;; Add a blank kill, otherwise the word gets appended.
          ;; Change to (kill-new "" t) to remove the word and only
          ;; keep the whole line.
          (kill-new "")
          (message "Killed Line")
          (list (line-beginning-position)
                (line-beginning-position 2)))
      (save-excursion
        (forward-char)
        (backward-word)
        (mark-word)
        (message "Killed Word")
        (list (mark) (point)))))))
1
  • Did you update this and if so where is a copy? Also, this adds a ton of marks to the mark ring. Can it just add one mark at the beginning of where it copied. So the beginning of the word or the beginning of the line. Now it adds like four marks everytime which is annoying. I've actually changed it to use (backward-sexp) but sometimes it can't find one and it gives an error. Can it just copy the line if it doesn't find one? I wasn't sure how to do this or just ignore the error and not make a noise. Sorry, I'm not the best at lisp.
    – J Spen
    Dec 24, 2018 at 3:14
2

A less ad-hoc way is to define mark-whole-line, which Emacs really should have a default command for.

(defun mark-whole-line ()               
    "Combinition of C-a, mark, C-e"
    (interactive)
    (move-beginning-of-line nil)
    (set-mark-command nil)
    (move-end-of-line nil)
)
(global-set-key (kbd "C-2") 'mark-whole-line) ; 2 is near w

Then C-2 C-w will do the job.

It also make things easier like commenting the current whole line.

1

Since you want to do it with minimal key strokes, you can use David Andersson's excellent key-chord package. A "key chord" is two keys pressed simultaneously, or a single key pressed twice.

You can bind any key chords to those functions.

(require 'key-chord)
(key-chord-mode 1)
(key-chord-define-global "dd"  'kill-whole-line)
(key-chord-define-global "cc"  'yank-whole-line)
1
  • Thanks for your answer :) I tried key chords a couple of times in the past and couldn't really get used to them. But this is definitely a useful addition to the set if answers collected here!
    – itsjeyd
    Sep 19, 2015 at 6:00
0

This is a modification of the answer by itsjeyd – currently the highest voted answer, and one I have used for years. However, it has issues: The adviced version of kill-ring-save would sometime fail because the mark is not set (typically in a new buffer), and even when it did work, the cursor did a strange dance after use of the function to copy a single line. After some digging, it dawned on me that this happens because kill-ring-save calls indicate-copied-region after it has done its work, but as point and mark do not match the copied region, indicate-copied-region marked the wrong region.

Enough said. Here is a solution that remedies this:

(define-advice kill-ring-save
    (:before-while (beg end &optional region) slick)
  (or mark-active
      (not (called-interactively-p 'interactive))
      (prog1 nil
    (copy-region-as-kill
     (line-beginning-position) (line-beginning-position 2))
    (message "Copied current line"))))

There is nothing wrong with itsjeyd's advice on kill-region. Here is a variant of it anyhow, stylistically more consistent with the above:

(define-advice kill-region
    (:around (kill-region beg end &optional region) slick)
  (if (or mark-active (not region))
      (funcall kill-region beg end region)
    (funcall kill-region
             (line-beginning-position) (line-beginning-position 2))
    (message "Killed current line")))

Note that if transient-mark-mode is not turned on, these advices do nothing.

1
  • If you want a more comprehensive solution, consider using the package whole-line-or-region instead; see the answer by @sanityinc. Feb 23, 2019 at 20:49
0

I use a package called composable.el. The neat thing about the package is it modifies M-w and C-w (copy and kill commands) to be more Vim-like with the twist being it accepts traditional emacs commands instead. So C-w l kills a whole line. But you can also do things like C-w M-> to kill end of file. Both commands act like normal when marking a region.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.