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中抄袭的。这会导致 emacsuntabify在保存 C++ 文件之前在缓冲区上运行。

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

我不是 elisp 大师,但我认为该(make-local-hook 'write-contents-hooks)行试图使添加write-contents-hooks仅适用于本地缓冲区。但是,它不起作用,并且c++-mode-untabify适用于write-contents-hooks所有缓冲区。

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

4

3 回答 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)
于 2008-11-27T01:17:36.963 回答
5

我的 Emacs 中的文档说 make-local-hook 从 21.1 开始已经过时了,因为 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)))))
于 2008-11-25T20:21:14.457 回答
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 时才会这样做。

然而,这是一个奇怪的解决方案。如果您删除所有选项卡,您将如何将选项卡放回原处?如果你停止任何事情,你就不需要这个黑客。

于 2008-11-25T20:23:13.343 回答