2010-12-28 9 views
12

Estoy intentando agregar la funcionalidad encontrada en otros editores de código a mi configuración de Emacs, por lo que C/C++ el código dentro de los bloques #if 0 ... # endif se establece automáticamente en el comentario face/font. Según mis pruebas, cpp-highlight-mode hace algo como lo que yo quiero, pero requiere acción del usuario. Parece que vincularse a la funcionalidad de bloqueo de fuentes es la opción correcta para que el comportamiento sea automático.En el modo C/C++ en Emacs, cambie la cara del código en el bloque #if 0 ... # endif para comentar la cara

He seguido con éxito los ejemplos en la documentación de GNU para cambiar la apariencia de las expresiones regulares de una sola línea. Por ejemplo:

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

funciona bien para poner de relieve las palabras clave relacionadas depuración en cualquier parte de un archivo. Sin embargo, tengo problemas para hacer coincidir #if 0 ... # endif como una expresión regular de varias líneas. Encontré información útil en esta publicación (How to compose region like "<?php foo; bar; ?>"), que sugería que se debía indicar específicamente a Emacs que permitiera las coincidencias de líneas múltiples. Pero este código:

(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)))))) 

todavía no funciona para mí. Tal vez mi expresión regular es incorrecta (aunque parece funcionar usando M-x re-builder), he estropeado mi sintaxis, o estoy siguiendo el enfoque equivocado por completo. Estoy usando Aquamacs 2.1 (que está basado en GNU Emacs 23.2.50.1) en OS X 10.6.5, si eso hace la diferencia.

¡Cualquier ayuda sería apreciada!

Respuesta

15

Incluso si tiene la expresión regular multilínea para trabajar, todavía tendría problemas con #ifdef/#endif anidados ya que detendría el bloqueo de fuente en el primer #endif. Este código funciona, aunque no estoy seguro de si habrá una notable reducir la velocidad de archivos de gran tamaño:

(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) 

EDIT: tener en cuenta #else

editar # 2: niftier código para manejar la anidación arbitraria de if/else/endif

+0

Esto parece funcionar bien. ¡¡Gracias!! – pogopop77

+0

Agregué 'else' como otra palabra clave para detener el comentario en. Entonces, la línea se convierte en: (while (y (> profundidad 0) (búsqueda de reenvío "^ \\ s - * # \\ s - * \\ (si \\ | endif \\ | else \\\) "límite" movimiento)). Además, para archivos pequeños (<100-200k) la desaceleración es mínima. En un archivo más grande (4.3MB) es notable, pero no a menudo edito archivos tan grandes. – pogopop77

+0

@ pogopop77 : Manejar '# else' es un poco más complicado que lo que hiciste, así que actualicé el código. No funciona en un' #if 0' dentro del '# else' de un' #if 0', pero yo ' Probablemente lo actualice más tarde. Además: ¿200k es un archivo pequeño?;) – scottfrazer

Cuestiones relacionadas