在编程模式下,仅在保存时删除 Emacs 的行末空格

9
以下代码会在保存时删除所有训练中的空格。
(add-hook 'write-file-hooks 'delete-trailing-whitespace)

但我希望仅在编程模式下使用此功能,因此我进行了以下操作:

(defun nuke_traling ()
  (add-hook 'write-file-hooks 'delete-trailing-whitespace) 
)

(add-hook 'prog-mode-hook 'nuke_traling)

这并不是阻止非编程模式下的内容。

6个回答

22

已经提到了使钩子变量成为缓冲区本地的方法。不要这样做。或者更确切地说,不要使用make-local-variable实现它。

通常的挂钩机制内置了缓冲区本地支持——这就是add-hookLOCAL参数的目的。当运行钩子时,它会运行全局和缓冲区本地值两者

因此,针对问题中的示例代码,您可以将其更改为:

(add-hook 'write-file-hooks 'delete-trailing-whitespace nil t)

然后 delete-trailing-whitespace 将在运行 write-file-hooks 时被调用,但仅在已运行 prog-mode-hook 的缓冲区中生效。
然而,还有更好的方法来实现这一点。
我同意 Drew 的观点,最好测试您的模式是否派生自 prog-mode,并且 Juanleon 建议使用 before-save-hook。因此,您可以尝试以下内容:
(add-hook 'before-save-hook 'my-prog-nuke-trailing-whitespace)

(defun my-prog-nuke-trailing-whitespace ()
  (when (derived-mode-p 'prog-mode)
    (delete-trailing-whitespace)))

但是我实际上推荐使用ws-trimws-butler来更加智能地处理这个问题。

盲目地从文件中删除所有尾随空格是一种很好的方法,可以让你在版本控制存储库中提交大量不相关的行。提到的这两个库都会确保你自己提交的内容没有尾随空格,并且不会在文件的其他位置引入不必要的修改。


8

write-file-hooks已经自Emacs-22起过时,被write-file-functions所取代。但是这个钩子有点棘手(因为它也可以用于执行写入操作),所以我建议您使用before-save-hook。为了使其仅适用于当前缓冲区,请在add-hook中传递一个非nil值的local参数,如下所示:

(defun nuke_traling ()
  (add-hook 'before-save-hook #'delete-trailing-whitespace nil t))
(add-hook 'prog-mode-hook #'nuke_traling)

1

不好的写法:

(add-to-list 'write-file-functions 'delete-trailing-whitespace)

更好的方法是使用ws-butler
(straight-use-package 'ws-butler)
(add-hook 'prog-mode-hook #'ws-butler-mode)

ws-butler-mode 只在更改的行上删除空格。


1
是的,因为一旦进入prog-mode模式,您就会将该函数添加到write-file-hooks中,并保留在那里。而该挂钩适用于写入任何文件,无论其缓冲区的模式如何。

您可以添加一个测试模式的函数,仅在您想要执行空格删除的模式下进行操作,而不是将该简单函数放在钩子上。

否则,您需要使write-file-hooks成为缓冲区本地变量(我认为您不希望这样做---该钩子通常用于更广泛的用途)。


自 Emacs-21 起,“使钩子缓冲区本地化”是一个过时的概念。所有钩子都有全局和缓冲区本地部分。您只需要告诉 add-hook 您想要修改哪个部分即可。 - Stefan

0
你需要将变量 buffer 做成本地变量:
(defun nuke_traling ()
    (make-variable-buffer-local 'write-file-hooks)
    (add-hook 'write-file-hooks 'delete-trailing-whitespace))

但我建议使用before-save-hook

(defun nuke_traling ()
    (add-to-list 'before-save-hook 'delete-trailing-whitespace))

write-file-hooks 如果被用作文件本地变量可能存在风险,而文档推荐使用 before-save-hook 来代替执行您想要完成的操作。


1
make-variable-buffer-local 几乎永远不应该从函数中调用。你可能想要使用 make-local-variable。但是,它不应该用于钩子。相反,你应该使用 add-hooklocal 参数。 - Stefan

-1
在 Emacs 21 或更高版本中,您可以像这样将此钩子添加到特定模式中:
(add-hook 'prog-mode-hook
                (lambda () (add-to-list 'write-file-functions 'delete-trailing-whitespace)))

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