В режиме C/C++ в Emacs измените лицо кода в #if 0...#endif блоке, чтобы комментировать лицо

Я пытаюсь добавить функциональность, найденную в некоторых других редакторах кода, в мою конфигурацию Emacs, в результате чего код C/C++ в блоках #if 0...#endif автоматически устанавливается на лицо / шрифт комментария. Основываясь на моем тестировании, 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 в виде многострочного регулярного выражения. В этом посте я нашел некоторую полезную информацию ( Как составить регион, например, ""), В котором говорилось, что 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))))))

все еще не работает для меня. Возможно, мое регулярное выражение неверно (хотя, похоже, оно работает с использованием реструктуризации Mx), я испортил синтаксис или полностью придерживаюсь неправильного подхода. Я использую Aquamacs 2.1 (который основан на GNU Emacs 23.2.50.1) на OS X 10.6.5, если это имеет значение.

Любая помощь будет оценена!

1 ответ

Решение

Даже если вы используете многострочное регулярное выражение, у вас все равно будут проблемы с вложенными #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: Niftier код для обработки произвольного вложения if/else/endif

Другие вопросы по тегам