В режиме 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 в виде многострочного регулярного выражения. В этом посте я нашел некоторую полезную информацию ( Как составить регион, например, " 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))))))
все еще не работает для меня. Возможно, мое регулярное выражение неверно (хотя, похоже, оно работает с использованием реструктуризации 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