2012-02-26 6 views
12

कुछ पृष्ठभूमि, मैं Emacs Lisp के साथ सहज हूं, और इसके कई लाइनें लिखी हैं। हालांकि मैंने कभी भी एक प्रमुख मोड नहीं लिखा है, इसलिए मैं बिल्कुल नया हूं कि फ़ॉन्ट-लॉकिंग तंत्र कैसे काम करता है।emacs: क्या मल्टी-लाइन फ़ॉन्ट-लॉकिंग का स्पष्ट उदाहरण है?

मेरी वर्तमान प्रोजेक्ट के लिए, मैं html-mode पर हाइलाइटिंग इनलाइन जावास्क्रिप्ट और सीएसएस जोड़ना चाहता हूं। वर्तमान में, मैं इसे एमएमएम-मोड के साथ करता हूं, लेकिन यह भारी है और मैं इसकी अन्य सुविधाओं का उपयोग नहीं करता, इसलिए मैं सिर्फ एक नाबालिग मोड बनाना चाहता हूं या यहां तक ​​कि सिर्फ एक हैक जिसे मैं sgml-mode-hook में जोड़ सकता हूं हाइलाइटिंग करें।

मुझे मैनुअल के section मिल गया है, जिसमें एक उदाहरण की कमी नहीं है, और टूटा कोड के इस emacswiki page

क्या कोई मुझे यह स्पष्ट उदाहरण दिखा सकता है कि यह कैसे किया जा सकता है?

संपादित करें: मुझे यह स्पष्ट करना चाहिए कि मैं जावास्क्रिप्ट/सीएसएस भाग के भीतर मोड-विशिष्ट फ़ॉन्ट-लॉकिंग देखना नहीं चाहता हूं। एकमात्र आवश्यकता यह है कि मैं उनके लिए एक अलग चेहरा लगाकर भाग देखने में सक्षम हूं।

उत्तर

6

नीचे दिए गए उदाहरण में, मैं फ़ॉन्ट-लॉक कीवर्ड के "एंकर" फ़ॉर्म का उपयोग करता हूं, यह आपको वर्तमान लाइन से अधिक खोज करने की अनुमति देता है। "चाल" यह है कि "प्री" हुक दो चीजें करता है: 1) यह आपको खोज की शुरुआत में बिंदु को स्थिति देने की अनुमति देता है और 2) यह आपको अंत-स्थिति को वापस कर खोज को सीमित करने की अनुमति देता है। नीचे दिए गए उदाहरण में, मैंने दूसरी संपत्ति का उपयोग किया है।

ध्यान दें कि यह केवल एक सबूत-अवधारणा है। आपको यह सुनिश्चित करने की आवश्यकता होगी कि font-lock-multiline परिवर्तनीय और फ़ॉन्ट-लॉक कीवर्ड सही बफर पर लागू होते हैं।

(defun my-end-of-paragraph-position (&rest foo) 
    "Return position of next empty line." 
    (save-excursion 
    (while (not (or (eobp)    ; Stop at end of buffer. 
        (and (bolp)  ; Or at an empty line. 
         (eolp)))) 
     (forward-line)) 
    (point))) 

(setq font-lock-multiline t) 

(font-lock-add-keywords nil 
         '(("^FOO" 
          (0 font-lock-keyword-face) ;; Face for FOO 
          ("BAR" 
          (my-end-of-paragraph-position) 
          nil 
          (0 font-lock-variable-name-face))))) 
नीचे

, बार के पहले दो लाइनों पर प्रकाश डाला जाएगा, लेकिन नहीं पिछले:

FOO BAR BAR BAR BAR 
BAR BAR BAR BAR 

BAR BAR BAR BAR 
+1

इस [थ्रेड] (http://lists.gnu.org/archive/html/help-gnu-emacs/2004-09/msg00534.html) में, स्टीफन मोनियर कहते हैं कि फ़ॉन्ट-लॉक-मल्टी-लाइन है आमतौर पर सिंगल लाइन वाली चीजों के लिए उपयुक्त, लेकिन कभी-कभी बहु-पंक्ति। टिप्पणियाँ? –

+0

खैर, स्टीफन मोनियर एक निश्चित संदर्भ है जब यह किसी भी फ़ॉन्ट-लॉक से संबंधित होता है, इसलिए उसके द्वारा कोई सलाह अच्छी तरह से योग्य है। सिंटैक्टिक सिस्टम का उपयोग करते हुए, जैसा कि वह सुझाव देता है, ऐसा करने का एक तरीका है। एक अन्य regexp के बजाय "मैच फ़ंक्शन" का उपयोग करना है, जो पूरे ब्लॉक से मेल खा सकता है। आपको मेरे उत्तरों को प्रश्न के सीधा जवाब के रूप में देखना चाहिए (बहु-पंक्ति फ़ॉन्ट-लॉक सुविधा का एक उदाहरण प्रदान करें) और शायद मूल पोस्टर के बारे में पूछे जाने वाले किसी भी काम को पूरा करने के लिए सबसे अच्छा तरीका नहीं है। – Lindydancer

3

यह शायद सबसे अच्छा संभव उदाहरण नहीं है, लेकिन आप कैसे haml-mode देख सकते हैं सुलझ गया है समस्या submode क्षेत्रों में हाइलाइटिंग वाक्यविन्यास का। उच्च स्तरीय विवरण के साथ blog post यहां है।

ध्यान दें कि वर्तमान haml-mode में Emacs 24 संगतता के साथ कुछ समस्याएं हैं, लेकिन कुछ फोर्क इसके लिए ठीक हो गए हैं।

मल्टीलाइन फ़ॉन्ट-लॉकिंग के संबंध में, मुझे लगता है कि आप गलत सवाल पूछ रहे हैं। लेकिन मूल रूप से, यह समस्या को हल करता है कि क्या उपयोगकर्ता ने मध्य में या मल्टीलाइन सिंटैक्टिक निर्माण के अंत में संपादन किया है। प्रारंभ में, फ़ॉन्ट-लॉक बिंदु की स्थिति से बफर को दोबारा शुरू करना शुरू कर देता है। दो डिफ़ॉल्ट font-lock-extend-region-functions, font-lock-extend-region-wholelines और font-lock-extend-region-multiline, font-lock-multiline संपत्ति के आधार पर, फिर से कहीं भी आगे की जगह पर पुनर्वितरण क्षेत्र की शुरुआत को स्थानांतरित करें। यदि आपको आगे बढ़ने की आवश्यकता है, तो आप या तो font-lock-region-functions पर एक और फ़ंक्शन जोड़ते हैं, या font-lock-region-function या syntax-propertize-function के अंदर कुछ संरचनाओं को पार्स करते समय प्रोग्रामेटिक रूप से बैकट्रैक करना सुनिश्चित करें।

बाद के दृष्टिकोण का एक उदाहरण रूबी के हेरेडोक और ruby-syntax-propertize-heredoc Emacs ट्रंक में होगा। इसे ruby-syntax-propertize-function में दो स्थानों से बुलाया जाता है। मामले को संभालने के लिए पहली बार जब हम पहले से ही हेडियोक शाब्दिक के अंदर हैं, और उसके बाद किसी भी बाद के हेडवर्क्स के लिए।

4

मैं <style> (सीएसएस) और <script> (जावास्क्रिप्ट, आदि) ब्लॉक को हाइलाइट करने के लिए एक साधारण प्रमुख मोड की रूपरेखा तैयार करूंगा। बहु फ़ॉन्ट ताला काफी अच्छा काम कर पाने के लिए, आपको पहले font-lock-extend-region-functions जो प्रासंगिक खोज क्षेत्र का विस्तार होगा पाठ के बड़े ब्लॉकों को रोकने के लिए में जोड़ने के लिए font-lock-multilinet को निर्धारित करके सक्षम करना होगा और एक समारोह लिखने के लिए की आवश्यकता होगी। फिर, आपको मल्टीलाइन मैचर्स लिखना होगा-या तो नियमित अभिव्यक्ति या फ़ंक्शन-और उन्हें font-lock-defaults पर जोड़ें।

यहाँ, एक बुनियादी प्रमुख मोड परिभाषा यह है कि नाम फॉन्ट ताला कीवर्ड सूची (यहाँ, test-font-lock-keywords) है बहु फ़ॉन्ट ताला सक्षम बनाता है, और इस क्षेत्र विस्तार समारोह test-font-lock-extend-region कहते हैं।

(define-derived-mode test-mode html-mode "Test" 
    "Major mode for highlighting JavaScript and CSS blocks." 
    ;; Basic font lock 
    (set (make-local-variable 'font-lock-defaults) 
     '(test-font-lock-keywords)) 
    ;; Multiline font lock 
    (set (make-local-variable 'font-lock-multiline) t) 
    (add-hook 'font-lock-extend-region-functions 
      'test-font-lock-extend-region)) 

क्षेत्र विस्तार समारोह कुछ इस तरह दिखना चाहिए:

(defun test-font-lock-extend-region() 
    "Extend the search region to include an entire block of text." 
    ;; Avoid compiler warnings about these global variables from font-lock.el. 
    ;; See the documentation for variable `font-lock-extend-region-functions'. 
    (eval-when-compile (defvar font-lock-beg) (defvar font-lock-end)) 
    (save-excursion 
    (goto-char font-lock-beg) 
    (let ((found (or (re-search-backward "\n\n" nil t) (point-min)))) 
     (goto-char font-lock-end) 
     (when (re-search-forward "\n\n" nil t) 
     (beginning-of-line) 
     (setq font-lock-end (point))) 
     (setq font-lock-beg found)))) 

इस समारोह वैश्विक चर font-lock-beg और font-lock-end है, जो शुरू करने और के समाप्त होने के पदों खोज क्षेत्र शामिल पर लग रहा है, और इस क्षेत्र को टेक्स्ट के पूरे ब्लॉक (रिक्त रेखाओं से अलग, या "\n\n") शामिल करने के लिए विस्तारित करता है।

अब Emacs बड़े क्षेत्रों में मैचों की खोज करेगा, हम को test-font-lock-keywords सूची सेट अप करने की आवश्यकता है। मल्टीलाइन संरचनाओं के मिलान के बारे में जाने के लिए दो उचित तरीके हैं: एक नियमित अभिव्यक्ति जो लाइनों से मेल खाती है और फ़ंक्शन से मेल खाती है। मैं दोनों के उदाहरण दूंगा।

(defvar test-font-lock-keywords 
    (list 
    (cons test-style-block-regexp 'font-lock-string-face) 
    (cons 'test-match-script-blocks '((0 font-lock-keyword-face))) 
    ) 
    "Font lock keywords for inline JavaScript and CSS blocks.") 

सूची में पहला आइटम सीधा है:: इस कीवर्ड सूची <script> ब्लॉक मिलान के लिए <style> ब्लॉक और एक समारोह मिलान के लिए एक रेगुलर एक्सप्रेशन शामिल एक रेगुलर एक्सप्रेशन और है कि नियमित रूप से मेल खाता है पर प्रकाश डाला के लिए एक चेहरा अभिव्यक्ति। दूसरा थोड़ा अधिक जटिल दिखता है, लेकिन को फ़ंक्शन द्वारा निर्दिष्ट मिलान डेटा में परिभाषित विभिन्न समूहों के लिए अलग-अलग चेहरे निर्दिष्ट करने के लिए सामान्यीकृत किया जा सकता है। यहां, हम font-lock-keyword-face का उपयोग करके समूह शून्य (संपूर्ण मिलान) को हाइलाइट करते हैं। ( इन matchers के लिए प्रासंगिक दस्तावेज Emacs मैनुअल की Search-based fontification खंड में है।)

<style> ब्लॉक मिलान के लिए एक बुनियादी नियमित अभिव्यक्ति होगा:

(defconst test-style-block-regexp 
    "<style>\\(.\\|\n\\)*</style>" 
    "Regular expression for matching inline CSS blocks.") 

नोट है कि हम \n डाल करने के लिए आंतरिक समूह में . मिलान न्यूलाइन नहीं है।

मिलान समारोह, दूसरे हाथ पर,, एकल दिया तर्क को बिंदु से इस क्षेत्र में पहले <script> ब्लॉक के लिए देखो की जरूरत है last:

(defun test-match-script-blocks (last) 
    "Match JavaScript blocks from the point to LAST." 
    (cond ((search-forward "<script" last t) 
     (let ((beg (match-beginning 0))) 
      (cond ((search-forward-regexp "</script>" last t) 
        (set-match-data (list beg (point))) 
        t) 
       (t nil)))) 
     (t nil))) 

इस समारोह मैच डेटा सेट , जो begin-0 end-0 begin-1 end-1 ... की एक सूची है शून्य समूह, पहला समूह, और इसी तरह की शुरुआत और अंत दे रही है। यहां, हम केवल पर मिलान किए गए पूरे ब्लॉक पर सीमाएं देते हैं, लेकिन आप कुछ और परिष्कृत कर सकते हैं, जैसे कि टैग के लिए अलग-अलग चेहरे और सामग्री सेट करना।

आप एक एकल फाइल में इस कोड के सभी गठबंधन और M-x test-mode चलाते हैं, तो यह इन दो प्रकार के ब्लॉक के पर प्रकाश डाला के लिए काम करना चाहिए। जबकि मेरा मानना ​​है कि यह नौकरी करता है, यदि इसके बारे में जाने का कुशल या उचित तरीका है, तो मैं भी को जानकर उत्सुक हूं।

संबंधित मुद्दे