如何在emacs中用yank缓冲区内容替换一个区域?

44

当我使用VIM或大多数无模式编辑器(如Eclipse、NetBeans等)时,经常会做如下操作。如果我有相似的文本块,并且需要将它们全部更改,我会更改其中一个,复制它(或使用非删除yank),选择下一个需要更改的块,并将更改后的版本粘贴到其上。如果我在emacs中执行相同的操作(选择区域并使用C-y粘贴),它不会替换区域,而只是在光标位置粘贴。在emacs中如何做到这一点?


在你的代码中有类似的文本块通常意味着你需要进行一些重构,例如用一个包含“相似文本”的函数/方法调用来替换这些相似的文本块。我猜这也是我从未真正错过Emacs中“替换区域”功能的原因之一... - slu
@slu 你如何重命名你提取出来的好函数/方法? - Bryan Ash
1
@slu,这显然是想用剪贴板替换所选区域的示例。你的第二个猜测答案没有任何建设性,只表现出了想要通过编码实践来发出美德信号而不是回答合理的问题的愿望。 - RichieHH
8个回答

79

将以下代码添加到您的.emacs文件中:

(delete-selection-mode 1)

只要在区域处于激活状态时写入缓冲区的任何内容都会覆盖它,包括粘贴,但也包括简单的输入或击退操作。


4
为什么这不是默认设置? - Lenar Hoyt
5
可能的原因与最近区域默认不可见的情况相同;标准的Emacs实践是(或曾经是)将标记保持在一个位置,而您在移动光标的同时不会更改该标记,它们之间存在区域这一事实是无关紧要的,除非您使用特定于该区域的命令。您不希望每次输入时都破坏该区域,并且有像exchange-point-and-mark这样的命令可以跳转到您放置标记的位置。现在我怀疑大多数人不会以这种方式使用标记,因此始终显示该区域并将其视为“活动”可能是可以接受的。 - Michael Mrozek
3
这在手动键入标记区域时有效,但粘贴文本时无效。 :( Emacs 24 / Ubuntu 14.04。 - mcandre
@mcandre 哦,没事了:在评论之后,我想如果这对我不起作用,可能我应该看看这是否可以在没有我的配置的情况下工作。经过快速搜索,我找到了问题所在:我的复制命令是 x-clipboard-yank,因为它更舒适(带有一些其他设置 - 我完全分离了 kill ring 和 clipboard)。所以,问题似乎是 x-clipboard-yank 没有按照需要工作... - Hi-Angel
我在这里留下一个固定的函数,以防其他人遇到了问题,即使启用了“delete-selection-mode”,x-cliboard-yank也无法替换选择。 (defun x-clipboard-yank-fixed () (interactive) (when mark-active (kill-region (region-beginning) (region-end))) (x-clipboard-yank)) - Hi-Angel
显示剩余3条评论

16

如Michael所建议的那样,设置delete-selection-mode似乎是最自然的方法。

但是,这不是我的做法 :) 相反,我将好的内容放入一个“寄存器”中——例如,寄存器“a”——使用C-x r x a。 然后我杀掉另一个副本,并使用C-x r g a将寄存器复制到同一位置。

这很方便,因为杀死不会影响寄存器,因此C-x r g a始终插入好的内容。


9
默认的做法不是很优雅,具体步骤如下:
  1. 将想要替换的文本复制到kill ring中(例如,M-w)。
  2. 选择要替换的区域。
  3. 删除它(C-w)。
  4. 用之前复制的区域替换它(C-y,M-y)。这将使用刚刚删除的内容粘贴相同的文本(C-y),然后再次使用缓冲区环中保存的最近的缓冲区替换它(M-y)。
如果您想要使用相同的文本进行10次替换,那么这将变得非常麻烦,因为每次删除区域时,所需的替换都会被推到kill ring的更远位置,因此每次想要粘贴它时,都必须调用M-w越来越多次。

我刚刚发现了M-x delete-region,感谢Emacs:如何在不使用kill ring的情况下删除文本?。正如问题所暗示的那样,这将删除有问题的文本而不将其放入kill ring中,避免了将替换文本推到堆栈底部的问题。而且,正如相关回答所提到的,您可以将其绑定到您选择的快捷键上。


4
我这样做的方法是:
  • 进入您想要添加新内容的位置
  • 粘贴好的内容
  • 现在您的光标位于新内容和您想要删除的内容之间
  • 向前选择,直到选中您想要删除的所有内容
  • 删除它
这是一种稍微不同的思考方式。先粘贴您想要的内容,然后再删除您不想要的内容,而不是用您想要的内容替换您不想要的内容。

3
如果您启用CUA模式,这个在选定区域上粘贴的行为将变为正常行为。

3

如果有人不想像我一样更改全局设置,可以使用以下函数和按键绑定:

(defun replace-yank(beg end)
  (interactive "r")
  (kill-region beg end)
  (yank 3))

(global-set-key (kbd "C-S-y") 'replace-yank)

我会将所选文本添加到kill ring中,以便以后使用,并且会取出先前在ring中的内容。


(说明:kill ring是Emacs编辑器中的一个功能,用于存储最近删除的文本。yank则是将文本从kill ring中插入到当前光标位置的操作。)

这个好像不是预期的行为,为什么它不是yank 2? - JJ on SE

2

以便复制的文本替换此区域。 - RichieHH

0
如果您不介意保留剪贴板中的高亮文本,您可以使用类似于ekneiling上面的答案的内容。
(defun replace-yank(beg end)
  (interactive "r")
  (delete-region beg end)
  (yank 1))

(global-set-key (kbd "C-S-y") 'replace-yank)

一个优点是可以重复进行上述操作。


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