2010-12-28 10 views
12

Diğer bazı kod düzenleyicilerinde bulunan işlevselliği, Emacs yapılandırmamamıza eklemeye çalışıyorum, böylece C/C++ #if 0 ... # endif blokları içindeki kod otomatik olarak yorum yüzüne/yazı tipine ayarlanır. Testlerime dayanarak, cpp vurgulama modu istediğim gibi bir şey yapar, ancak kullanıcı eylemi gerektirir. Yazı tipi kilitleme işlevine bağlanmanın, davranışı otomatik hale getirmek için doğru seçenek olduğu anlaşılıyor.Emacs'de C/C++ modunda, yüz yüze yorum yapmak için #if 0 ... # endif bloğundaki kodun yüzünü değiştirin

Tek satırlı normal ifadelerin yüzünü değiştirmek için GNU belgelerinde örnekleri başarıyla takip ettim. Örneğin, bir dosyanın herhangi bir yerinde hata ayıklama ile ilgili anahtar sözcükleri vurgulamak için iyi çalışıyor gibi

. Ancak, çok satırlı düzenli bir ifade olarak #if 0 ... # endif ile eşleşen problemler yaşıyorum. Bu yazıda ( How to compose region like "<?php foo; bar; ?>") yararlı bilgiler buldum, bu da Emacs'ın çok satırlı eşleşmelere izin vermek için özel olarak anlatılması gerektiğini önerdi. Ama bu kodu:

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

hala beni çalışmıyor. Belki de benim düzenli ifadem yanlış (M-x yeniden oluşturucu kullanarak çalışmak gibi görünüyor olsa da), sözdizimi berbat ettik veya tamamen yanlış yaklaşımı takip ediyorum. OS X 10.6.5'te Aquamac 2.1'i (GNU Emacs 23.2.50.1'e göre) kullanıyorum, eğer bu bir fark yaratıyorsa.

Her türlü yardım mutluluk duyacaktır!

cevap

15

Çok satırlı regexp'in çalışmaya başlamasına rağmen, ilk #endif numaralı telefondan font kilitlemeyi durduracağından, iç içe geçmiş #ifdef/#endif'larda sorun yaşarsınız.

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

DÜZENLEME: dikkate alın #else

DÜZENLEME # 2: Niftier ben farkedilir büyük dosyalar için yavaşlatmak olacaktır emin değilim rağmen bu kod çalışır if/else/endif'in

+0

rasgele yerleştirme işleminin gerçekleştirilmesi için gereken kod. Teşekkürler!! – pogopop77

+0

Yorum yüzünü durdurmak için 'else' kelimesini başka bir anahtar kelime olarak ekledim. Yani bir satır şöyle olur: (while (ve (> derinlik 0) (yeniden-arama "^ \\ s - * # \\ s - * \\ (eğer \\ | endif \\ | else \\\) "limit 'move") Ayrıca, küçük dosyalar için (<100-200k) yavaşlama en düşüktür.Daha büyük bir dosyada (4.3MB) farkedilir - ancak genellikle bu dosyaları büyük boyutta düzenlemem. – pogopop77

+0

@ pogopop77 : '# Else' işlemek, yaptığınızdan biraz daha zorlayıcıdır, bu yüzden kodu güncelledim. '#if 0' içinde #if 0 'üzerinde çalışmıyor. Muhtemelen daha sonra güncelleştirir.Ayrıca: 200k küçük bir dosyadır?;) – scottfrazer

İlgili konular