以最少的击键杀死或复制当前行


32

我确实C-a C-k C-k要杀死整个线路点。

如果我想复制该行而不是杀死它,则可以C-/ C-/ 在键入上面的序列后立即点击。

或者,我可以做C-a C-SPC C-n M-w

有没有更快的方法来终止或复制整个线点?


1
哇!这些答案表明,人们将竭尽全力避免使用内置功能kill-whole-line。:)
奥马尔

如下所示,请使用evil-mode。学习Vim命令,您不会后悔!
A.暴雪

Answers:


44

您可以使用kill-whole-line杀死整个线路上的点。点的位置无关紧要。C-S-DEL默认情况下绑定此命令。

您还可以通过将变量设置为非值来指示kill-line(绑定到C-k)杀死整行: kill-whole-linenil

(setq kill-whole-line t)

请注意,此点必须在行的开头才能生效。


然后有两个宝石(通过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)))))

通过这些操作,您可以通过一次击键杀死或复制线点:

  • C-w 杀死当前行
  • M-w 复制当前行

注意,如果有一个活动区,kill-regionkill-ring-save会继续做他们通常做的:杀死或复制。


移植slick-cutslick-copy新的建议系统

Emacs 24.4引入了新的建议系统。尽管defadvice 仍然可以使用,但有可能在Emacs的未来版本中不赞成使用该新系统。要为做准备,你可能想使用的更新版本slick-cutslick-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)

2
请注意,kill-regionkill-ring-save仍然工作,即使该地区不是“积极的”。这将覆盖该行为。我会不时使用这种行为,但是如果您不习惯以这种方式使用它们,那么您可能不会注意到其中的区别。
nispio 2014年

@nispio请扩展时/如何上kill-region时等是可用的/有用mark-activenil
菲尔·哈德森

1
@PhilHudson可以(通常是)设置该标记而不激活它。尝试做C-SPC两次以激活然后取消激活该标记。将光标移动到文件中的其他位置并运行kill-region,即使标记未处于活动状态,它也会杀死点和标记之间的区域。设置(但不激活)标记的命令的一些示例是yankisearch。执行完这些排序命令后,即使该标记未处于活动状态,我也知道该标记在哪里,并且许多命令(包括kill-region)将允许我使用该标记而无需显式激活它。
nispio

谢谢@nispio。当然。在可见区域突出显示成为默认的几个主要版本之前,这就是以前的唯一方式,对吗?我将“活动”与“设置”混淆了。
Phil Hudson

1
这是任何SX上发布的最大答案。说真的
本杰明·林德奎斯特

15

我为自己找到的解决方案是使用前缀参数。

对我来说,杀死半条线是一个有用的功能,但是我也希望有一种更简单的方法来杀死整条线。因此,我做到了这一点,以至于kill-line在给定前缀参数时, 它会杀死所有可见的东西。

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

有了这个小宏,它C-k仍然是致命的,但是 C-3 C-k吞下了整整三行。作为奖励,我们 kill-whole-line通过做得到行为C-1 C-k


真是个好主意,谢谢分享!:)您将如何调整此解决方案以使其能够复制一个或多个行?kill-ring-save不接受前缀参数...
itsjeyd 2014年

@itsjeyd我确定可以做类似的事情来合并两个答案。但这需要更多的工作。
马拉巴巴2014年

最后一行是指paredit-kill。有意吗
Boccaperta-IT 2014年

1
哦,好的,谢谢。我没有得到预期的行为。如果我将指针放在一行的中间并按C-3 Ck,则第一行不会被完全杀死。这是应该起作用的方式还是我做错了什么?
Boccaperta-IT 2014年

1
@Malabarba您说对了,kill-visual-line必定会与C-k。我会解决的。再次感谢。
Boccaperta-IT 2014年

15

有一个名为的软件包whole-line-or-region,它建议各种内置命令,以便在没有活动区域的情况下它们可作用于当前行,因此M-w将复制当前行C-w并将其杀死。我已经使用了多年了,发现它是必不可少的。

此外,此软件包可以使数字前缀指示要作用的行数,因此M-2 M-w可以复制两行。这里的其他答案不提供该方便的功能。

当作者停止维护它并变得无响应时,我用我的github帐户接管了该程序包的维护。

whole-line-or-region 还提供了将这种行为添加到其他命令的功能,如果需要的话。


请为此提交MELPA问题,因为我不确定您的意思:我一直都在MELPA上安装此软件包,没有任何问题。
sanityinc

9

这不是正统emacs的答案。但是,如果您愿意亵渎evil的模式编辑,则可以:

  • dd 杀线
  • cc 用于复制行

两者都可以加上要杀死/复制的行数作为前缀(例如,4cc将复制接下来的4行)。


5

除了@itsjeyd答案,我可以建议这两个功能吗?

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

然后,输入关键定义(您可能需要调整它们):

(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

ErgoEmacs提供


感谢您的回答!您可能需要考虑扩展这些命令,方法是描述这些命令与此处发布的其他解决方案的不同之处。是的,该信息可以在文档字符串中找到,但是让以后的读者更容易看到它也不会受到损害:)
itsjeyd 2014年

1
是否可以执行此操作,但可以像下面的@Jonathan post一样对其进行修改,以便它首先采用sexp或word,然后如果再次调用则采用该行?
J Spen '18

@JSpen我正在做的是分配一个快捷键来起作用。乔纳森(Jonathan)的工作是为功能定义建议。因此,您可以建议该功能,然后定义该建议功能的快捷键;这样您就可以得到结果。抱歉造成延迟;)
Nsukami _

4

作为上述@itsjeyd答案的扩展,我有以下内容。(逻辑可能会稍作清理,当我移植到新的建议系统时,我会把它扩展到sexp/,paragraph如果再次重复的话)。

初始C-w/ M-w将抓住只在点的字,而称其为第二次将抓住整行。

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

您是否对此进行了更新,如果是的话,副本在哪里?同样,这会在标记环上增加大量标记。它可以仅在复制位置的开头添加一个标记。因此,单词的开头或行的开头。现在,每次都会添加四个标记,这很烦人。我实际上已将其更改为使用(向后扩展),但有时找不到它,并给出了错误。如果找不到,可以复制行吗?我不确定如何执行此操作,或者只是忽略错误而不发出声音。抱歉,我不是最好的Lisp。
J Spen '18

1

由于您希望用最少的按键来完成此操作,因此可以使用David Andersson出色的按键和弦包。“和弦”是同时按下两个键,或者一次按下两次。

您可以将任何和弦绑定到这些功能。

(require 'key-chord)
(key-chord-mode 1)
(key-chord-define-global "dd"  'kill-whole-line)
(key-chord-define-global "cc"  'yank-whole-line)

感谢您的回答:)过去我尝试过几次和弦,但实际上并没有习惯。但这绝对是对此处收集的有用的补充,如果这里收集了答案!
itsjeyd 2015年

1

一种不太特别的方法是定义mark-whole-line,Emacs确实应该为其提供默认命令。

(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

然后C-2 C-w将完成工作。

它还使事情变得更容易,例如注释当前的整行。


0

这是其最高答案的修改,它是目前投票率最高的答案,也是我多年来使用的答案。但是,它存在一些问题:建议的版本kill-ring-save有时会因为未设置标记而失败(通常在新缓冲区中),即使该标记确实起作用,使用该函数复制一行后光标也会发生奇怪的舞动。经过一番挖掘后,我想到发生这种情况是因为在完成工作后kill-ring-save调用indicate-copied-region,但由于点和标记与复制的区域不匹配,因此indicate-copied-region标记了错误的区域。

说够了。这是解决此问题的解决方案:

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

耶德的建议并没有错kill-region。无论如何,这是它的一种变体,在样式上与上面的描述更加一致:

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

请注意,如果transient-mark-mode未打开,则这些建议不会执行任何操作。


如果您需要更全面的解决方案,请考虑使用该软件包whole-line-or-region。请参阅@sanityinc的答案。
哈拉德·汉彻·奥尔森

0

我使用了一个名为composable.el的软件包。关于该软件包的整洁之处在于它修改了Mw和Cw(复制并杀死命令),使其更像Vim,不同之处在于它接受了传统的emacs命令。因此C-w l杀死了整条线。但是您也可以执行一些操作,例如C-w M->终止文件结尾。标记区域时,这两个命令都像正常一样。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.