我看到了关于VIM的相同问题,这也是我自己在Emacs中想要知道如何实现的。在ReSharper中,我使用CTRL-D来执行此操作。在Emacs中执行此操作的最少命令数是多少?
'我写了自己的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)
(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)
你可能希望在你的.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的优点是你可以在其他地方复制该行,而不仅仅是在当前行下面。
C-a C-k C-k C-y C-y
有一个叫做Avy的包,它有一个名为avy-copy-line的命令。当你使用该命令时,窗口中的每一行都会得到字母组合。然后你只需输入组合即可获取该行。这也适用于区域。然后你只需输入两个组合。
在这里你可以看到界面:
当没有活动区域时,交互式调用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)))))
(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)
move-line-up/down
的添加 - 因为那将是我的下一个问题! - Steve Eynon我看到了非常复杂的解决方案,不管怎样...
(defun duplicate-line ()
"Duplicate current line"
(interactive)
(kill-whole-line)
(yank)
(yank))
(global-set-key (kbd "C-x M-d") 'duplicate-line)
我喜欢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)))))
(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 ...
。
最近的 Emacs 中,你可以在行中任何位置使用 M-w 复制它。因此它变成:
M-w C-a RET C-y
M-w
绑定了easy-kill
。当你执行C-h c M-w
时,请检查是否得到了这个结果。 - Louis Kottmann