我将概述一个简单的主要模式,用于突出显示 <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 将零组(整个匹配)分组。
(相关文件为
这些匹配器位于Search-based fontification 部分
Emacs 手册。)
匹配<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,它应该可以突出这两种类型
块。虽然我相信这可以完成工作,但如果有更多
有效或适当的方法,我也很好奇
也知道。