当保存特定文件类型(仅限这些文件类型)时,让Emacs执行去制表符操作。

12

我在我的 .emacs 文件中有以下内容:

 (defun c++-mode-untabify ()
   (save-excursion
     (goto-char (point-min))
     (while (re-search-forward "[ \t]+$" nil t)
       (delete-region (match-beginning 0) (match-end 0)))
     (goto-char (point-min))
     (if (search-forward "\t" nil t)
         (untabify (1- (point)) (point-max))))
   nil)

 (add-hook 'c++-mode-hook
           '(lambda ()
              (make-local-hook 'write-contents-hooks)
              (add-hook 'write-contents-hooks 'c++-mode-untabify)))

大部分内容来自于http://www.jwz.org/doc/tabs-vs-spaces.html。这会导致在保存C++文件之前,emacs会对缓冲区运行untabify

问题是,在我加载了一个C++文件之后,untabify钩子将被应用于所有后续的文件写入,即使是其他文件类型的缓冲区。这意味着如果我打开一个C++文件,然后编辑一个制表符分隔的文本文件,当保存该文件时,制表符会被覆盖。

我不是elisp大师,但我认为(make-local-hook 'write-contents-hooks)行试图使对write-contents-hooks的添加仅适用于本地缓冲区。然而,它并没有起作用,并且在所有缓冲区的write-contents-hooks中。

我正在Windows XP机器上使用EmacsW32 22.0。有人知道如何使write-contents-hooks更改为特定缓冲区的本地或如何在切换到其他非C++缓冲区时将其重置为nil吗?

3个回答

22

write-contents-hooks也已经过时了。这是你需要的内容:

(add-hook 'c++-mode-hook
      '(lambda ()
         (add-hook 'before-save-hook
                   (lambda ()
                     (untabify (point-min) (point-max))))))

这是从我使用的内容中提炼出来的,它还可以执行其他一些操作并被抽象化以适用于编程特定模式:

(defun untabify-buffer ()
  "Untabify current buffer"
  (interactive)
  (untabify (point-min) (point-max)))

(defun progmodes-hooks ()
  "Hooks for programming modes"
  (yas/minor-mode-on)
  (add-hook 'before-save-hook 'progmodes-write-hooks))

(defun progmodes-write-hooks ()
  "Hooks which run on file write for programming modes"
  (prog1 nil
    (set-buffer-file-coding-system 'utf-8-unix)
    (untabify-buffer)
    (copyright-update)
    (maybe-delete-trailing-whitespace)))

(defun delete-trailing-whitespacep ()
  "Should we delete trailing whitespace when saving this file?"
  (save-excursion
    (goto-char (point-min))
    (ignore-errors (next-line 25))
    (let ((pos (point)))
      (goto-char (point-min))
      (and (re-search-forward (concat "@author +" user-full-name) pos t) t))))

(defun maybe-delete-trailing-whitespace ()
  "Delete trailing whitespace if I am the author of this file."
  (interactive)
  (and (delete-trailing-whitespacep) (delete-trailing-whitespace)))

(add-hook 'php-mode-hook 'progmodes-hooks)
(add-hook 'python-mode-hook 'progmodes-hooks)
(add-hook 'js2-mode-hook 'progmodes-hooks)

5

我的Emacs文档说,从21.1版本开始make-local-hook已经过时了,因为add-hook现在有一个可选参数可以使钩子成为缓冲区本地的。所以你可以尝试这样做:

(add-hook 'c++-mode-hook
           '(lambda ()
              (add-hook 'write-contents-hooks 'c++-mode-untabify nil t)))

另一个选择是让c++-mode-untabify函数检查当前模式。我可能会这样写:

(defun c++-mode-untabify ()
  (if (string= (substring mode-name 0 3) "C++")
      (save-excursion
       (delete-trailing-whitespace)
       (untabify (point-min) (point-max)))))

2

尝试按照以下方式添加您的钩子:

 (add-hook 'c++-mode-hook
           '(lambda ()
              (add-hook 'write-contents-hooks 'c++-mode-untabify nil t)))

请注意add-hook中的两个额外参数。如果我理解正确,根据文档,尾随的t应该执行make-local-hook所做的事情(或者反之亦然),但我也看到有关make-local-hook被弃用的参考资料。至少在我的电脑上(linux,gnu emacs 21.3.1),我看到了你想要的效果--钩子仅附加到c++缓冲区而不是所有其他缓冲区。
作为最后的手段,您始终可以在c++-mode-untabify函数中放置一个检查,只有当当前主模式为c++-mode时才执行其操作。
这是一个好奇的解决方案。如果您删除了所有制表符,那么您将如何重新插入制表符?如果停止任何操作,您将不需要此hack。

谢谢!我加入了这个功能,可以自动删除旧代码中的制表符,这些代码不是我编写的,但偶尔需要维护。 - DanielMcP

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