一些背景知识,我对Emacs Lisp很熟悉,并且已经写了很多行。然而,我从来没有写过一个主要的模式,所以我对字体锁定机制是如何工作的还是个新手。
对于我当前的项目,我想在html-mode中添加内联javascript和css高亮显示。目前,我使用MMM模式来做这件事,但是它很笨重,而且我不使用它的其他功能,所以我只想做一个小模式,或者甚至是一个hack,我可以将它添加到sgml-mode-hook中来做高亮显示。
我找到了这本手册的section,它严重缺乏一个例子,以及这段破碎代码的emacswiki page。
有没有人可以给我一个清晰的例子,说明如何做到这一点?
编辑:我应该澄清一下,我不希望在javascript/css块中看到特定于模式的字体锁定。唯一的要求是,我能够通过将不同的面孔应用于块来查看块。
发布于 2012-02-27 04:15:54
在下面的示例中,我使用了"anchored“形式的font-lock关键字,它允许您搜索比当前行更多的内容。“诀窍”是"pre“钩子做两件事: 1)它允许你将点定位到搜索的开始位置;2)它允许你通过返回结束位置来限制搜索。在下面的示例中,我使用了第二个属性。
请注意,这只是一个概念验证。您需要确保将font-lock-multiline变量和font-lock关键字应用于正确的缓冲区。
(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发布于 2013-03-06 13:32:27
我将概述一个简单的主要模式,用于突出显示<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.")列表中的第一项很简单:一个正则表达式和一个用于突出显示该正则表达式的匹配项的face。第二个看起来有点复杂,但可以推广到为函数指定的匹配数据中定义的不同组指定不同的面孔。在这里,我们只使用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放在内部组中,因为.不匹配换行符。
另一方面,匹配函数需要在从该点到单个给定参数last的区域中查找第一个<script>块
(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,那么它应该可以突出显示这两种类型的块。虽然我相信这可以完成这项工作,但如果有更有效或更合适的方式来做这件事,我也很好奇。
发布于 2012-02-27 04:40:35
这可能不是最好的例子,但您可以看看haml-mode是如何解决子模式区域中语法突出显示的问题的。下面是带有高级描述的blog post。
请注意,当前的haml-mode在与Emacs24的兼容性方面存在一些问题,但是有几个分支已经修复了这个问题。
关于多行字体锁定,我认为你可能问错了问题。最初,font-lock从点的位置开始重新格式化缓冲区。
后一种方法的一个例子是Ruby的heredoc和Emacs主干中的ruby-syntax-propertize-heredoc。它是从ruby-syntax-propertize-function的两个地方调用的。当我们已经在heredoc文本中时,第一次处理这种情况,然后处理任何后续的heredocs。
https://stackoverflow.com/questions/9452615
复制相似问题