it-swarm.cn

如何在Emacs中复制整行?

我看到 这个问题对于VIM 这是我自己想知道如何为Emacs做的事情。在ReSharper中,我使用CTRL-D进行此操作。在Emacs中执行此操作的最少命令数是多少?

143
Ray Vega

我用

C-a C-SPACE C-n M-w C-y

分解为

  • C-a:将光标移动到行首
  • C-SPACE:开始选择(“设置标记”)
  • C-n:将光标移动到下一行
  • M-w:复制区域
  • C-y:粘贴(“yank”)

之前所提

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

相同的东西(TMTOWTDI)

  • C-a:将光标移动到行首
  • C-k:剪切(“杀死”)该行
  • C-k:剪切换行符
  • C-y:粘贴(“yank”)(我们回到正方形)
  • C-y:再次粘贴(现在我们有两行副本)

与编辑器中的C-d相比,这些都是令人尴尬的冗长,但在Emacs中总是有自定义。 C-d默认绑定到delete-char,那么C-c C-d怎么样?只需将以下内容添加到.emacs

(global-set-key "\C-c\C-d" "\C-a\C- \C-n\M-w\C-y")

(@ Nathan的elisp版本可能更可取,因为如果任何键绑定被更改,它将不会中断。)

注意:一些Emacs模式可能会回收C-c C-d来做其他事情。

140
Chris Conway

除了之前的答案,您还可以定义自己的函数来复制一行。例如,将以下内容放在.emacs文件中将使C-d复制当前行。

(defun duplicate-line()
  (interactive)
  (move-beginning-of-line 1)
  (kill-line)
  (yank)
  (open-line 1)
  (next-line 1)
  (yank)
)
(global-set-key (kbd "C-d") 'duplicate-line)
93
Nate

将光标放在线上,如果不是在开头做一个 CTRL - A, 然后:

CTRL - K

CTRL - K

CTRL - Y

CTRL - Y

60
epatel

我的函数版本复制一行,使用撤消工作,并且不会弄乱光标位置。这是1997年11月在gnu.emacs.sources中进行 讨论的结果

(defun duplicate-line (arg)
  "Duplicate current line, leaving point in lower line."
  (interactive "*p")

  ;; save the point for undo
  (setq buffer-undo-list (cons (point) buffer-undo-list))

  ;; local variables for start and end of line
  (let ((bol (save-excursion (beginning-of-line) (point)))
        eol)
    (save-excursion

      ;; don't use forward-line for this, because you would have
      ;; to check whether you are at the end of the buffer
      (end-of-line)
      (setq eol (point))

      ;; store the line and disable the recording of undo information
      (let ((line (buffer-substring bol eol))
            (buffer-undo-list t)
            (count arg))
        ;; insert the line arg times
        (while (> count 0)
          (newline)         ;; because there is no newline in 'line'
          (insert line)
          (setq count (1- count)))
        )

      ;; create the undo information
      (setq buffer-undo-list (cons (cons eol (point)) buffer-undo-list)))
    ) ; end-of-let

  ;; put the point in the lowest line and return
  (next-line arg))

然后你可以定义CTRL-D来调用这个函数:

(global-set-key (kbd "C-d") 'duplicate-line)
51
pesche

而不是像kill-lineC-kC-aC-kC-k中的C-yC-y)使用 kill-whole-line 命令:

C-S-Backspace
C-y
C-y

优于C-k的优点包括无论线上的哪个点都不重要(与C-k不同,它需要在线的起点)并且它也会杀死换行符(同样C-k没有做到这一点)。

43
Ray Vega

这是另一个执行此操作的功能。我的版本没有碰到杀戮戒指,光标最终出现在原来的新线上。如果区域处于活动状态(瞬态标记模式),它将复制该区域,否则默认为复制该区域。如果给出前缀arg,它也会生成多个副本,如果给出一个负前缀arg,则注释掉原始行(这对于测试不同版本的命令/语句同时保留旧的命令/语句非常有用)。

(defun duplicate-line-or-region (&optional n)
  "Duplicate current line, or region if active.
With argument N, make N copies.
With negative N, comment out original line and use the absolute value."
  (interactive "*p")
  (let ((use-region (use-region-p)))
    (save-excursion
      (let ((text (if use-region        ;Get region if active, otherwise line
                      (buffer-substring (region-beginning) (region-end))
                    (prog1 (thing-at-point 'line)
                      (end-of-line)
                      (if (< 0 (forward-line 1)) ;Go to beginning of next line, or make a new one
                          (newline))))))
        (dotimes (i (abs (or n 1)))     ;Insert N times, or once if not specified
          (insert text))))
    (if use-region nil                  ;Only if we're working with a line (not a region)
      (let ((pos (- (point) (line-beginning-position)))) ;Save column
        (if (> 0 n)                             ;Comment out original with negative arg
            (comment-region (line-beginning-position) (line-end-position)))
        (forward-line 1)
        (forward-char pos)))))

我把它绑定到C-c d

(global-set-key [?\C-c ?d] 'duplicate-line-or-region)

永远不应该通过模式或任何东西重新分配,因为C-c后跟一个(未修改的)字母保留给用户绑定。

25
qmega

Nathan添加到您的.emacs文件是可行的方法,但可以通过替换来略微简化

  (open-line 1)
  (next-line 1)

  (newline)

生产

(defun duplicate-line()
  (interactive)
  (move-beginning-of-line 1)
  (kill-line)
  (yank)
  (newline)
  (yank)
)
(global-set-key (kbd "C-d") 'duplicate-line)
16
pw.

从melpa安装重复的东西:

M-x package-install RET duplicate-thing

并将此键绑定添加到 init文件

(global-set-key(kbd“M-c”)'重复的东西)

5
user2626414

我不太清楚线复制是如何在其他任何地方工作的,但作为一名前SciTE用户,我喜欢SciTE-way的一件事:它没有触及光标位置!所以上面的所有收件人对我来说都不够好,这是我的嬉皮版:

(defun duplicate-line ()
    "Clone line at cursor, leaving the latter intact."
    (interactive)
    (save-excursion
        (let ((kill-read-only-ok t) deactivate-mark)
            (toggle-read-only 1)
            (kill-whole-line)
            (toggle-read-only 0)
            (yank))))

请注意,在进程中实际上没有任何内容被杀死,标记和当前选择保持不变.

顺便说一句,为什么你们这么喜欢摇晃光标,当有这个Nice'n'clean kill-whole-line thingy(C-S-backspace)?

5
mk-fg

我将copy-from-above-command绑定到一个密钥并使用它。它提供了XEmacs,但我不知道GNU Emacs。

`copy-from-above-command'是一个交互式编译的LISP函数
- 从“/usr/share/xemacs/21.4.15/LISP/misc.elc”加载(copy-from-above-command&optional ARG)

文档: 从上一个非空行 ,从上面开始复制字符。复制ARG字符,但不能超过该行的结尾。如果没有给出参数,则复制整行的其余部分。复制的字符将在点之前插入缓冲区。

4
Darron

因为我不知道,我会用慢球来开始这一轮高尔夫:

ctrl-k,y,y

4
Kevin Conner

'我写了自己的duplicate-line版本,因为我不想搞砸杀戮戒指。

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

使用最近的emacs,您可以在行中的任何位置使用M-w来复制它。所以它变成:

M-w C-a RET C-y
3
Louis Kottmann
C-a C-k C-k C-y C-y
3
sverrejoh

您可能希望在.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的优点是你可以在其他地方复制该行,而不是仅仅在当前行之下。

3
polyglot

我喜欢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
phils

默认值对此非常可怕。但是,您可以将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
Marius Andersen

无论如何,我看到非常复杂的解决方案......

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

有一个名为 Avy的包 它有命令avy-copy-line。当您使用该命令时,窗口中的每一行都会得到字母组合。然后你只需要输入组合就可以得到那条线。这也适用于地区。然后你只需要输入两个组合。

在这里你可以看到界面:

http://i68.tinypic.com/24fk5eu.png

3
teksturi

@ [凯文康纳]:据我所知,非常接近。唯一需要考虑的是打开kill-whole-line以在C-k中包含换行符。

2
Allen

当交互式调用没有活动区域时,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 up the current line."
  (interactive)
  (transpose-lines 1)
  (forward-line -2)
  (indent-according-to-mode))

(defun move-line-down ()
  "Move down the current line."
  (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)
2
yPhil

我根据自己的喜好写了一个。

(defun duplicate-line ()
  "Duplicate current line."
  (interactive)
  (let ((text (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
        (cur-col (current-column)))
    (end-of-line) (insert "\n" text)
    (beginning-of-line) (right-char cur-col)))
(global-set-key (kbd "C-c d l") 'duplicate-line)

但我发现当当前行包含多字节字符(例如CJK字符)时会出现问题。如果您遇到此问题,请尝试以下方法:

(defun duplicate-line ()
  "Duplicate current line."
  (interactive)
  (let* ((text (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
         (cur-col (length (buffer-substring-no-properties (point-at-bol) (point)))))
    (end-of-line) (insert "\n" text)
    (beginning-of-line) (right-char cur-col)))
(global-set-key (kbd "C-c d l") 'duplicate-line)
1
kuanyui

ctrl - k, ctrl - k,(位置到新的位置) ctrl - y

添加一个 ctrl - a 如果你没有在行的开头开始。第二个 ctrl - k 是抓住换行符。如果您只想要文本,可以将其删除。

1
CJP

此功能应与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: 
   http://stackoverflow.com/questions/88399/how-do-i-duplicate-a-whole-line-in-emacs#answer-551053"
  (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)
1
AesopHimself

M-cShift+Insertx2(或任何粘贴快捷方式)都可以。

0
Andrew Naguib
;; http://www.emacswiki.org/emacs/WholeLineOrRegion#toc2
;; cut, copy, yank
(defadvice kill-ring-save (around slick-copy activate)
  "When called interactively with no active region, copy a single line instead."
  (if (or (use-region-p) (not (called-interactively-p)))
      ad-do-it
    (kill-new (buffer-substring (line-beginning-position)
                                (line-beginning-position 2))
              nil '(yank-line))
    (message "Copied line")))
(defadvice kill-region (around slick-copy activate)
  "When called interactively with no active region, kill a single line instead."
  (if (or (use-region-p) (not (called-interactively-p)))
      ad-do-it
    (kill-new (filter-buffer-substring (line-beginning-position)
                                       (line-beginning-position 2) t)
              nil '(yank-line))))
(defun yank-line (string)
  "Insert STRING above the current line."
  (beginning-of-line)
  (unless (= (elt string (1- (length string))) ?\n)
    (save-excursion (insert "\n")))
  (insert string))

(global-set-key (kbd "<f2>") 'kill-region)    ; cut.
(global-set-key (kbd "<f3>") 'kill-ring-save) ; copy.
(global-set-key (kbd "<f4>") 'yank)           ; paste.

将上面的elisp添加到init.el,然后立即剪切/复制整行功能,然后你可以F3 F4复制一行。

0
WisdomFusion

就克里斯康威选定的答案而言,这感觉更自然。

(global-set-key“\ C-c\C-d”“\ C-a\C-\C-n\M-w\C-y\C-p\C-e”)

这允许您通过简单地重复\ C-c\C-d键击来多次复制一行。

0
Shim Kporku

这是复制当前行的功能。使用前缀参数,它将多次复制该行。例如,C-3 C-S-o将复制当前行三次。不会改变杀戮戒指。

(defun duplicate-lines (arg)
  (interactive "P")
  (let* ((arg (if arg arg 1))
         (beg (save-excursion (beginning-of-line) (point)))
         (end (save-excursion (end-of-line) (point)))
         (line (buffer-substring-no-properties beg end)))
    (save-excursion
      (end-of-line)
      (open-line arg)
      (setq num 0)
      (while (< num arg)
        (setq num (1+ num))
        (forward-line 1)
        (insert-string line))
      )))

(global-set-key (kbd "C-S-o") 'duplicate-lines)
0
Dodgie

正如其他答案中所提到的,将关键笔划绑定到LISP代码比将它们绑定到另一个关键笔划更好。使用@ mw的答案,代码重复该行并将标记移动到新行的末尾。此修改将标记位置保留在新行的同一列:

fun duplicate-line ()
  (interactive)
  (let ((col (current-column)))
    (move-beginning-of-line 1)
    (kill-line)
    (yank)
    (newline)
    (yank)
    (move-to-column col)))
0
krsoni

我无法相信所有这些复杂的解决方案。这是两次击键:

<C-S-backspace>运行命令kill-whole-line

C-/运行命令undo

所以<C-S-backspace> C-/“复制”整行(杀死和撤消)。

当然,您可以将其与数字和负数args相结合,以向前或向后杀死多条线。

0
Andy

最简单的方法是Chris Conway的方法。

C-a C-SPACE C-n M-w C-y

这是EMACS规定的默认方式。在我看来,最好使用标准。我总是小心翼翼地在EMACS中定制一个自己的密钥绑定。 EMACS已经足够强大,我认为我们应该尽力适应自己的密钥绑定。

虽然它有点冗长,但是当你习惯它时,你可以做得很快,并会发现这很有趣!

0
linbianxiaocao

使用前缀参数,以及(我希望)直观行为是什么:

(defun duplicate-line (&optional arg)
  "Duplicate it. With prefix ARG, duplicate ARG times."
  (interactive "p")
  (next-line 
   (save-excursion 
     (let ((beg (line-beginning-position))
           (end (line-end-position)))
       (copy-region-as-kill beg end)
       (dotimes (num arg arg)
         (end-of-line) (newline)
         (yank))))))

光标将保留在最后一行。或者,您可能希望指定一个前缀以一次复制下几行:

(defun duplicate-line (&optional arg)
  "Duplicate it. With prefix ARG, duplicate ARG times."
  (interactive "p")
  (save-excursion 
    (let ((beg (line-beginning-position))
          (end 
           (progn (forward-line (1- arg)) (line-end-position))))
      (copy-region-as-kill beg end)
      (end-of-line) (newline)
      (yank)))
  (next-line arg))

我发现自己经常使用两者,使用包装函数来切换前缀参数的行为。

还有一个键绑定:(global-set-key (kbd "C-S-d") 'duplicate-line)

0
Karthik