我將概述一個簡單的主要模式,用於突出顯示<style>
(CSS)和 <script>
(JavaScript等)塊。爲了得到多字體鎖 工作還算不錯,你需要通過設置 font-lock-multiline
到t
先啓用它,寫一個函數添加到 font-lock-extend-region-functions
這將延長相關 搜索區域包含較大的文本塊。然後,你需要 寫多行匹配器 - 正則表達式或函數 - 和 將它們添加到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
列表。有兩個 合理的好方法去匹配多行結構: 一個正則表達式,將跨線匹配和一個匹配的功能 函數。我會舉兩個例子。這個關鍵字列表包含 一個正則表達式匹配<style>
塊和函數 匹配<script>
塊:
(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.")
在列表中的第一項是直接的:正則表達式 和麪部用於突出,經常的比賽表達。 第二個看起來有點複雜,但可以概括爲 ,爲函數指定的 匹配數據中定義的不同組指定不同的面。在這裏,我們只使用font-lock-keyword-face
突出顯示 組0(整個比賽)。 (用於 這些匹配的相關文件是在 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 ...
的形式的列表,其給出了第0組,第一組等的開始和結束 。在這裏,我們只對 給出了匹配的整個塊的界限,但您可以做些更復雜的操作,比如爲標籤和 內容設置不同的面。
如果結合所有這些代碼到一個單一的文件並運行 ,它應該工作的突出這兩種類型的塊 。雖然我相信這可以做到這一點,但如果有更多有效或正確的解決方法,我也會好奇 。
在這個[thread](http://lists.gnu.org/archive/html/help-gnu-emacs/2004-09/msg00534.html)中,Stefan Monnier說font-lock-multi-line是適合那些通常是單線的事物,但偶爾會多線。註釋? – 2012-03-04 17:25:10
那麼,Stefan Monnier是關於任何與字體鎖相關的權威參考,所以他的任何建議都值得關注。正如他所說,使用句法系統是實現它的一種方法。另一個是使用「匹配函數」而不是正則表達式,它可以匹配整個塊。您應該將我的答案看作是對問題的直接回答(提供多行字體鎖定功能的示例),並且可能不是以最佳方式完成原始海報問及的任何答案。 – Lindydancer 2012-03-04 17:43:57