Emacs:如何在不使用kill ring的情况下删除文本?

92

我想删除一些文本,以便可以复制其他文本而不是它。我该怎么做?使用C-w剪切所选文本到kill ring并且我最终没有想要复制的文本。

另外,有没有可能直接复制文本而不是按下按钮将其删除?


参见:https://dev59.com/qm025IYBdhLWcg3wvIq2 - phils
2
请参考下面的答案,您可以使用键盘上的退格按钮回答第一个问题,对于第二个问题,请标记文本。 - Kevin Zhu
你定义完代码块后,是不是只需要使用 C-x r k 就可以了呢? - yalu2015
15个回答

58

我经常使用 M-x delete-region 命令,但你也可以将其绑定到一个按键上。

在较新版本的Emacs中,使用Delete Selection Mode,你无需输入命令,只需开始输入:

默认情况下,即使标记处于活动状态,文本插入也会正常进行——例如,打字“a”会插入字符“a”,然后取消激活标记。删除选区模式是一种次要模式,可以修改此行为:如果启用该模式,那么在标记处于活动状态时插入文本会首先删除区域中的文本。此外,通常仅删除一个字符的命令(例如C-dDEL)将删除整个区域。要切换打开或关闭删除选区模式,请键入 M-x delete-selection-mode.


41
最新版本的Emacs已经将 delete-region 绑定到一个快捷键不再必要,因为现在可以使用 Backspace 键来完成该操作。换句话说,Backspace 键删除所选区域中的内容,而不是将其移动到 kill ring 中保存。这是因为 delete-active-region 的值默认为 t,除非你自定义了它的值为其他值。 - Jisang Yoo

39

21

我也遇到了同样的问题。目前我找到的最接近解决方案就是编写一个小函数,大致如下:

(defun ruthlessly-kill-line ()
  "Deletes a line, but does not put it in the kill-ring. (kinda)"
  (interactive)
  (move-beginning-of-line 1)
  (kill-line 1)
  (setq kill-ring (cdr kill-ring)))

2
为什么不直接使用(delete-region (line-beginning-position) (line-end-position))呢? - CodyChan
列出的函数听起来不错,但总体上对我没有用。特别是,我发现它会导致yank指针指向kill-ring的另一端,而通常(实际上几乎总是?)不是列表中的下一个元素!(仍在尝试通过委托给`kill-line'编写可靠工作的函数...也许我只会像其他人一样采用delete-region...) - pnkfelix

16

来源于EmacsWiki

The equivalent of ‘kill-line’ (‘C-k’) but without kill-ring side effects:

(delete-region (point) (line-end-position))

1
在我看来,这是最佳答案。我将Ctrl-Shift-W绑定到删除区域:(global-set-key (kbd "C-S-w") 'delete-region)。 - Tongfa

5

M-x eval-expression (setq kill-ring (cdr kill-ring)) - 从kill-ring中删除最后一个项目


它只在当前会话中进行这样的操作,这很奇怪。在emacs外部,它不会从kill ring中删除! - PascalVKooten

4

大多数删除函数使用kill-region来实际删除文本。我使用一个Lisp宏从杀死功能创建删除函数。

(defmacro jpk/delete-instead-of-kill (&rest body)
  "Replaces `kill-region' with `delete-region' in BODY."
  `(cl-letf (((symbol-function 'kill-region)
              (lambda (beg end &optional yank-handler)
                (delete-region beg end))))
     ,@body))

(defun jpk/delete-word (arg)
  "Like `kill-word', but does not save to the `kill-ring'."
  (interactive "*p")
  (jpk/delete-instead-of-kill (kill-word arg)))

它是如何工作的?你有更多关于这个的信息吗?这太棒了。 - sinekonata
1
cl-letf 可以创建一个具有动态作用域的函数的本地绑定。这意味着它仅对 cl-letf 内部的代码有效,但它适用于整个调用树(例如,kill-region 不直接出现在 body 中,但 kill-word 调用 kill-region 并被替换为 delete-region)。 - jpkotta
如果您首先在 cl-letf 中将其绑定到不同的名称,则甚至可以从其替换中调用原始函数。 在这个意义上,cl-letf 的工作方式类似于 let* - jpkotta
我大致明白,但对我来说仍然太技术化了。我在Python方面只有初级经验。这种“覆盖”/重写/分叉函数的通用名称是什么?它是像Lisp这样的语言的特定功能吗? - sinekonata
1
我不确定这种技术的通用名称是什么。我认为我会将其描述为函数的动态作用域,并且大多数语言都不常见,因为很容易被滥用。Emacs正在逐渐转向词法作用域,这是大多数语言使用的方式。我不确定一般情况下是否可以在Python中做到这一点,您需要设计您的代码以允许在特定范围内覆盖函数。 - jpkotta

4

对于您的第二个问题,除了使用DeleteSelectionMode,您还可以启用CUA Mode,它还提供了一个很好的矩形选择模式,通过按C-Return键启用。自22.1版本以来,CUA模式已成为Emacs的一部分。


3
我找到了这个问题的答案。 我首先在这里发布了这里
;; Ctrl-K with no kill
(defun delete-line-no-kill ()
  (interactive)
  (delete-region
   (point)
   (save-excursion (move-end-of-line 1) (point)))
 (delete-char 1)
)
(global-set-key (kbd "C-k") 'delete-line-no-kill)

问题在于这个命令总是删除换行符,而kill-line只有在变量kill-whole-line的值非nil时才会删除换行符。最好将“(delete-char 1)”更改为“(if kill-whole-line (delete-char 1))”。 - Alan

2

从技术上讲,其他答案在第一部分是错误的。

这是我的实现和动机:

(defun delete-word (arg)
  "Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."
  (interactive "p")
  (delete-region (point) (progn (backward-word arg) (point))))

我从 simple.el 中的“kill-word”代码进行了修改。我使用 delete-region 替换了 kill-region,并将 forward-word 替换为 backward-word。这样它就真正不会影响 kill-ring,而在其他情况下,我注意到在 Emacs 之外,kill-ring 受到了影响。


2
我更喜欢这个答案,因为它不会破坏从操作系统剪贴板粘贴的内容(从 kill ring 中删除最后一个内容并没有帮助,因为操作系统剪贴板中的内容已经丢失)。 - Brel
请查看我的答案,了解一种在不复制kill函数定义的情况下完成此操作的方法。 - jpkotta

1
(defun copy-to-register-z (p1 p2)
  "Copy text selection to register named “z”."
  (interactive "r")
  (copy-to-register ?z p1 p2))
(defun replace-register-content-z (p1 p2)
  "Replace register named “z”'s content."
  (interactive "r")
  (delete-region p1 p2)
  (insert-register ?z))
(global-set-key (kbd "C-c c") 'copy-to-register-z)
(global-set-key (kbd "C-c v") 'replace-register-content-z)

我喜欢这个,但是因为我不使用瞬时标记模式,所以我更喜欢一个"插入寄存器内容-z",除了删除区域那行。 - Joshua Goldberg

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