如何在Emacs中复制整行?

175

我看到了关于VIM的相同问题,这也是我自己在Emacs中想要知道如何实现的。在ReSharper中,我使用CTRL-D来执行此操作。在Emacs中执行此操作的最少命令数是多少?


2
当然,这是emacs,所以TMTOWTDI - 有22种!(还在不断增加中)http://c2.com/cgi/wiki?ThereIsMoreThanOneWayToDoIt - Tom
34个回答

4

'我写了自己的duplicate-line版本,因为我不想搞砸了kill环。'

  (defun jr-duplicate-line ()
    "EASY"
    (interactive)
    (save-excursion
      (let ((line-text (buffer-substring-no-properties
                        (line-beginning-position)
                        (line-end-position))))
        (move-end-of-line 1)
        (newline)
        (insert line-text))))
  (global-set-key "\C-cd" 'jr-duplicate-line)

4
这个功能应该与JetBrains的实现相匹配,可以按行或区域进行复制,然后像预期的那样保留点和/或活动区域:
只是一个交互式表单的包装器:
(defun wrx/duplicate-line-or-region (beg end)
  "Implements functionality of JetBrains' `Command-d' shortcut for `duplicate-line'.
   BEG & END correspond point & mark, smaller first
   `use-region-p' explained: 
   http://emacs.stackexchange.com/questions/12334/elisp-for-applying-command-to-only-the-selected-region#answer-12335"
  (interactive "r")
  (if (use-region-p)
      (wrx/duplicate-region-in-buffer beg end)
    (wrx/duplicate-line-in-buffer)))

这会调用它:

(defun wrx/duplicate-region-in-buffer (beg end)
  "copy and duplicate context of current active region
   |------------------------+----------------------------|
   |        before          |           after            |
   |------------------------+----------------------------|
   | first <MARK>line here  | first line here            |
   | second item<POINT> now | second item<MARK>line here |
   |                        | second item<POINT> now     |
   |------------------------+----------------------------|
   TODO: Acts funky when point < mark"
  (set-mark-command nil)
  (insert (buffer-substring beg end))
  (setq deactivate-mark nil))

或者这个

(defun wrx/duplicate-line-in-buffer ()
  "Duplicate current line, maintaining column position.
   |--------------------------+--------------------------|
   |          before          |          after           |
   |--------------------------+--------------------------|
   | lorem ipsum<POINT> dolor | lorem ipsum dolor        |
   |                          | lorem ipsum<POINT> dolor |
   |--------------------------+--------------------------|
   TODO: Save history for `Cmd-Z'
   Context: 
   https://dev59.com/qnVD5IYBdhLWcg3wGXlI"
  (setq columns-over (current-column))
  (save-excursion
    (kill-whole-line)
    (yank)
    (yank))
  (let (v)
    (dotimes (n columns-over v)
      (right-char)
      (setq v (cons n v))))
  (next-line))

然后我把这个绑定到meta+shift+d

(global-set-key (kbd "M-D") 'wrx/duplicate-line-or-region)

4

你可能希望在你的.emacs文件中添加以下内容:

(setq kill-whole-line t)

基本上,每当您调用kill-line(即通过C-k)时,它就会删除整行以及换行符。然后,不需要额外的代码,您只需执行C-a C-k C-y C-y即可复制该行。它可以简化为

C-a go to beginning of line
C-k kill-line (i.e. cut the line into clipboard)
C-y yank (i.e. paste); the first time you get the killed line back; 
    second time gives the duplicated line.

但如果你经常使用这个功能,也许一个专门的快捷键绑定可能更好,但只使用C-a C-k C-y C-y的优点是你可以在其他地方复制该行,而不仅仅是在当前行下面。


4
C-a C-k C-k C-y C-y

4

有一个叫做Avy的包,它有一个名为avy-copy-line的命令。当你使用该命令时,窗口中的每一行都会得到字母组合。然后你只需输入组合即可获取该行。这也适用于区域。然后你只需输入两个组合。

在这里你可以看到界面:

enter image description here


3

当没有活动区域时,交互式调用COPY(M-w)会复制单行:

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

当在无活动区域的情况下交互调用时,KILL(C-w)只会删除一行。
(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))
     (message "Killed line")
     (list (line-beginning-position)
           (line-beginning-position 2)))))

此外,还有一个相关的问题:
(defun move-line-up ()
  "Move the current line up."
  (interactive)
  (transpose-lines 1)
  (forward-line -2)
  (indent-according-to-mode))

(defun move-line-down ()
  "Move the current line down."
  (interactive)
  (forward-line 1)
  (transpose-lines 1)
  (forward-line -1)
  (indent-according-to-mode))

(global-set-key [(meta shift up)]  'move-line-up)
(global-set-key [(meta shift down)]  'move-line-down)

1
我喜欢move-line-up/down的添加 - 因为那将是我的下一个问题! - Steve Eynon

3

我看到了非常复杂的解决方案,不管怎样...

(defun duplicate-line ()
  "Duplicate current line"
  (interactive)
  (kill-whole-line)
  (yank)
  (yank))
(global-set-key (kbd "C-x M-d") 'duplicate-line)

请注意,这将影响 kill ring。 - Dodgie
当文件不以新行符结束且该行为最后一行时,此操作将该行追加到自身末尾。 - Mark

3

我喜欢FraGGod的版本,但有两个问题:(1) 它没有使用(interactive "*")检查缓冲区是否已经只读,(2) 如果最后一行为空(因为在这种情况下无法删除该行),它会在缓冲区的最后一行失败,使您的缓冲区变成只读。

我做了以下更改以解决这个问题:

(defun duplicate-line ()
  "Clone line at cursor, leaving the latter intact."
  (interactive "*")
  (save-excursion
    ;; The last line of the buffer cannot be killed
    ;; if it is empty. Instead, simply add a new line.
    (if (and (eobp) (bolp))
        (newline)
      ;; Otherwise kill the whole line, and yank it back.
      (let ((kill-read-only-ok t)
            deactivate-mark)
        (toggle-read-only 1)
        (kill-whole-line)
        (toggle-read-only 0)
        (yank)))))

3
默认设置很糟糕。但是,您可以扩展Emacs的功能,使其像SlickEdit和TextMate一样工作,即在未选择文本时复制/剪切当前行:
(transient-mark-mode t)
(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)))))
(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)))))

将上述内容放入.emacs中。然后,要复制一行,请按M-w。要删除一行,请按C-w。要复制一行,请按C-a M-w C-y C-y C-y ...


3

最近的 Emacs 中,你可以在行中任何位置使用 M-w 复制它。因此它变成:

M-w C-a RET C-y

真的吗?那是哪个“最近”的Emacs呢?24.4不是这种情况:你会得到“现在未设置标记,因此没有区域。” - Davor Cubranic
当前的Emacs版本是24.5,M-w绑定了easy-kill。当你执行C-h c M-w时,请检查是否得到了这个结果。 - Louis Kottmann
1
在Emacs 24.5.1中无法工作。只复制了从行首到插入前面空行后同一行开头的位置。 - Derek Mahar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接