在emacs中删除(而不是杀死)一行。外部剪贴板不会添加到kill ring中。

7
很多时候,我需要将路径从任何地方复制到emacs的minibuffer中。为了快速清除minibuffer,我会导航到开头并执行C-k(删除行)。这有效地用刚刚在minibuffer中删除的临时路径覆盖了系统剪贴板中的任何路径。使用M-y导航kill ring无法带回我在系统剪贴板中的路径。
有没有一种方法可以删除当前行而不杀死它(即将其删除并添加到kill ring中)?
到目前为止,我正在标记该行并按下delete,同时激活delete-selection-mote。我想要一个类似于C-k的一键解决方案。

不,他正在询问特定的文本删除子集,即行,类似于C-k(删除行的其余部分)。另一个问题更通用。 - Chris E
1
对于这个特定的例子,如果路径是绝对的(例如以/~开头,或者像NTEmacs中的C:/),那么您可能不需要删除已经存在的内容,因为Emacs可以识别新路径的开始并忽略前面的文本。这对于find-file肯定是适用的,我认为对于任何调用read-file-name的东西也是如此。 - phils
路径可以是绝对的或者相对的。重点是彻底删除 minibuffer 中的任何内容。此外,我想要一种通用的方法来删除一行,而不将其附加到 kill ring 中。 - octi
2
你考虑过直接移动到想要插入文本的位置,将其粘贴进去,然后删除剩余的文本吗? - Marcin
6个回答

9

从Emacs 23.2版本开始,您可以将save-interprogram-paste-before-kill设置为非nil值(感谢Tyler),以便将剪贴板中的选择复制到“kill ring”中,以便通过C-y M-y使用:

(setq save-interprogram-paste-before-kill t)

如果你使用的是较旧版本的Emacs,下面的建议具有相同的功能:
(defadvice kill-new (before kill-new-push-xselection-on-kill-ring activate)
  "Before putting new kill onto the kill-ring, add the clipboard/external selection to the kill ring"
  (let ((have-paste (and interprogram-paste-function
                         (funcall interprogram-paste-function))))
    (when have-paste (push have-paste kill-ring))))

而且,您可以像这样做(可自定义的糟糕绑定键)来删除从光标位置到行尾的内容:

(define-key minibuffer-local-map (kbd "C-S-d") 'delete-line)
(defun delete-line (&optional arg)
  (interactive "P")
  ;; taken from kill-line
  (delete-region (point)
                 ;; It is better to move point to the other end of the kill
                 ;; before killing.  That way, in a read-only buffer, point
                 ;; moves across the text that is copied to the kill ring.
                 ;; The choice has no effect on undo now that undo records
                 ;; the value of point from before the command was run.
                 (progn
                   (if arg
                       (forward-visible-line (prefix-numeric-value arg))
                     (if (eobp)
                         (signal 'end-of-buffer nil))
                     (let ((end
                            (save-excursion
                              (end-of-visible-line) (point))))
                       (if (or (save-excursion
                                 ;; If trailing whitespace is visible,
                                 ;; don't treat it as nothing.
                                 (unless show-trailing-whitespace
                                   (skip-chars-forward " \t" end))
                                 (= (point) end))
                               (and kill-whole-line (bolp)))
                           (forward-visible-line 1)
                         (goto-char end))))
                   (point))))

1
我认为这个功能重复了 save-interprogram-paste-before-kill 的作用? - Tyler
@Tyler,太好了。我会相应地更新我的答案(以及我的.emacs文件)。谢谢。 - Trey Jackson
这非常有用。向你和泰勒致敬。 - octi

4
从Emacs 23.2版本开始,可以使用save-interprogram-paste-before-kill解决这个问题。如果将此变量设置为t,则剪贴板中的内容将被添加到kill-ring中,并且不会在下一次kill时丢失。
文档如下:
保存剪贴板字符串到kill ring中,然后再替换它们。当你选择另一个程序中的内容想要粘贴到Emacs中时,但在实际粘贴之前先在Emacs中kill了一些东西,如果这个变量是非空的,则其他程序的选择会在Emacs kill之前保存在`kill-ring'中,你仍然可以使用C-y M-y来粘贴它。

1

Xahlee的页面上可以看到一些令人烦恼的命令。

(defun my-delete-word (arg)
  "Delete characters forward until encountering the end of a word.
With argument, do this that many times.
This command does not push erased text to kill-ring."
  (interactive "p")
  (delete-region (point) (progn (forward-word arg) (point))))

(defun my-backward-delete-word (arg)
  "Delete characters backward until encountering the beginning of a word.
With argument, do this that many times.
This command does not push erased text to kill-ring."
  (interactive "p")
  (my-delete-word (- arg)))

(defun my-delete-line ()
  "Delete text from current position to end of line char."
  (interactive)
  (delete-region
   (point)
   (save-excursion (move-end-of-line 1) (point)))
  (delete-char 1)
)

(defun my-delete-line-backward ()
  "Delete text between the beginning of the line to the cursor position."
  (interactive)
  (let (x1 x2)
    (setq x1 (point))
    (move-beginning-of-line 1)
    (setq x2 (point))
    (delete-region x1 x2)))

; Here's the code to bind them with emacs's default shortcut keys:

(global-set-key (kbd "M-d") 'my-delete-word)
(global-set-key (kbd "<M-backspace>") 'my-backward-delete-word)
(global-set-key (kbd "C-k") 'my-delete-line)
(global-set-key (kbd "C-S-k") 'my-delete-line-backward)

0

没有。

来自GNU Emacs手册

我们已经描述了基本的删除命令C-d(delete-char)和C-Backspace(delete-backward-char)。请参见Erasing。

其他删除命令是仅删除空格字符:空格、制表符和换行符。M-\(delete-horizontal-space)删除点前后的所有空格和制表符。使用前缀参数,它只删除点之前的空格和制表符。M-(just-one-space)同样如此,但无论先前存在多少个空格,都会在点后留下一个单独的空格(即使以前没有)。使用数字参数n,它在点后留下n个空格。


有没有宏可以移动到行尾,激活标记,移动到行首然后清除选择?:P - octi

0

这个怎么样:

(defun del-line (p1)
  (interactive "d")
  (move-end-of-line 1)
  (when (eq p1 (point)) ; special case when p1 is already at the end of the line
     (forward-line))
  (delete-region p1 (point)))

行为应该类似于C-k,但不影响系统剪贴板或kill-ring。

预计完成时间:我仔细阅读了Trey的解决方案,看起来这只是他解决方案的一个简单情况。在我的(非常有限的)测试中它有效,但可能会在一些更复杂的kill-line代码正确工作的特殊情况下失败。


0

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