在Emacs的C / C ++模式下,将#if 0 ...#endif块中的代码面改为注释面

时间:2010-12-28 19:54:59

标签: regex emacs aquamacs emacs-faces

我正在尝试将其他代码编辑器中的功能添加到我的Emacs配置中,其中#if 0 ... #endif块中的C / C ++代码会自动设置为注释面/字体。根据我的测试, cpp-highlight-mode 做了我想要的事情,但需要用户采取行动。似乎绑定字体锁功能是使行为自动化的正确选项。

我已经成功地遵循了GNU文档中的示例来更改单行正则表达式的表面。例如:

(add-hook 'c-mode-common-hook
  (lambda ()
    (font-lock-add-keywords nil
      '(("\\<\\(FIXME\\|TODO\\|HACK\\|fixme\\|todo\\|hack\\)" 1 
        font-lock-warning-face t)))))

可以很好地突出显示文件中任何位置的调试相关关键字。但是,我在将#if 0 ...#endif作为多行正则表达式进行匹配时遇到问题。我在这篇文章中发现了一些有用的信息(How to compose region like "<?php foo; bar; ?>"),这表明必须特别告知Emacs允许多行匹配。但是这段代码:

(add-hook 'c-mode-common-hook
  (lambda ()
    '(progn
      (setq font-lock-multiline t)
      (font-lock-add-keywords nil
        '(("#if 0\\(.\\|\n\\)*?#endif" 1
          font-lock-comment-face t))))))

仍然不适合我。也许我的正则表达式是错误的(虽然它似乎使用 M-x re-builder ),但我搞砸了我的语法,或者我完全遵循了错误的方法。我在OS X 10.6.5上使用Aquamacs 2.1(基于GNU Emacs 23.2.50.1),如果这有所不同。

任何帮助都将不胜感激!

1 个答案:

答案 0 :(得分:15)

即使你让多行regexp工作,你仍然会遇到嵌套#ifdef/#endif的问题,因为它会在第一个#endif停止字体锁定。这段代码有效,但我不确定大文件是否会明显减慢:

(defun my-c-mode-font-lock-if0 (limit)
  (save-restriction
    (widen)
    (save-excursion
      (goto-char (point-min))
      (let ((depth 0) str start start-depth)
        (while (re-search-forward "^\\s-*#\\s-*\\(if\\|else\\|endif\\)" limit 'move)
          (setq str (match-string 1))
          (if (string= str "if")
              (progn
                (setq depth (1+ depth))
                (when (and (null start) (looking-at "\\s-+0"))
                  (setq start (match-end 0)
                        start-depth depth)))
            (when (and start (= depth start-depth))
              (c-put-font-lock-face start (match-beginning 0) 'font-lock-comment-face)
              (setq start nil))
            (when (string= str "endif")
              (setq depth (1- depth)))))
        (when (and start (> depth 0))
          (c-put-font-lock-face start (point) 'font-lock-comment-face)))))
  nil)

(defun my-c-mode-common-hook ()
  (font-lock-add-keywords
   nil
   '((my-c-mode-font-lock-if0 (0 font-lock-comment-face prepend))) 'add-to-end))

(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

修改 考虑#else

编辑#2: 用于处理if / else / endif的任意嵌套的Niftier代码