嵌套正则表达式的Emacs语法高亮显示

Mik*_*e B 5 lisp regex emacs bioinformatics font-lock

我正在尝试编写一个Emacs主要模式来处理生物序列数据(即DNA和多肽),我想实现语法高亮,其中不同的字母颜色不同.由于该模式需要能够区分DNA序列和氨基酸序列并对它们进行不同的着色,我将文件中的每个序列放在一行中,并带有单字符前缀(+或#),表示后续行如何应该突出显示.

因此,例如,如果文件包含一行读取:

+AAGATCCCAGATT
Run Code Online (Sandbox Code Playgroud)

"A"应该都是一种颜色,与行的其他部分不同.

我尝试了以下测试:

(setq dna-keyword
 '(("^\+\\([GCT\-]*\\(A\\)\\)*" (2 font-lock-function-name-face))
  )
)

(define-derived-mode bioseq-mode fundamental-mode
  (setq font-lock-defaults '(dna-keyword))
  (setq mode-name "bioseq mode")
)
Run Code Online (Sandbox Code Playgroud)

但这只匹配最后一个A而不是所有它们.

我的第一个想法是尝试将整行与一个正则表达式匹配,然后使用另一个正则表达式来匹配该行中的A,但我不知道这是否可能在font-lock-mode的上下文中或者它将如何实现.关于如何做这样的事情,或者如何以不同的方式实现这一目标的任何想法?

Jon*_* O. 7

实际上,Emacs通过字体锁定模式的"锚定匹配"功能提供了所需的功能.语法有点毛茸茸,但它允许您指定其他"匹配器"(基本上是正则表达式,子表达式标识符和面名称),默认情况下将在主"匹配器"正则表达式完成的位置之后应用.队伍的尽头.有更复杂的方法可以自定义它们适用的文本范围,但这是一般的想法.

这是一个简单的例子,它还展示了如何为此目的定义自己的面孔:

(defface bioseq-mode-a
  '((((min-colors 8)) :foreground "red"))
  "Face for As in bioseq-mode")

(defface bioseq-mode-g
  '((((min-colors 8)) :foreground "blue"))
  "Face for Gs in bioseq-mode")

(setq dna-keyword
      '(("^\\+" ("A" nil nil (0 'bioseq-mode-a)))
        ("^\\+" ("G" nil nil (0 'bioseq-mode-g)))))
Run Code Online (Sandbox Code Playgroud)

您还可以为一个主匹配器指定两个或多个锚定匹配器(这里的主匹配器是正则表达式"^\\+").为了使这项工作,每个锚定的匹配器在第一次需要在开始搜索之前明确地返回到行的开头; 否则它只会在上次锚定匹配器的最后一次出现后开始突出显示.这是通过将(行首)放入PRE-MATCH-FORM插槽(列表的元素2;见下文)来实现的.

(setq dna-keyword
      '(("^\\+"
         ("A" nil nil (0 'bioseq-mode-a))
         ("G" (beginning-of-line) nil (0 'bioseq-mode-g)))))
Run Code Online (Sandbox Code Playgroud)

我认为这主要是你喜欢的味道问题; 第二种方式可能是稍微清晰的代码,如果你有一个单行的许多不同的锚定匹配器,但我怀疑有显着的性能差异.

以下是文档的相关内容font-lock-defaults:

突出显示应该是MATCH-HIGHLIGHT或MATCH-ANCHORED.

[....]

MATCH-ANCHORED应具有以下形式:

(MATCHER PRE-MATCH-FORM后匹配形式匹配 - 亮点...)

其中MATCHER是要搜索的正则表达式或要调用的函数名称以进行搜索,如上面的MATCH-HIGHLIGHT,但有一个例外; 见下文.PRE-MATCH-FORM和POST-MAT​​CH-FORM在第一个之前进行评估,在最后一个之后,使用实例MATCH-ANCHORED的MATCHER.因此,它们可用于在使用MATCHER之前进行初始化和清理.通常,在使用MATCH-ANCHORED的MATCHER开始之前,PRE-MATCH-FORM用于移动到相对于原始MATCHER的某个位置.在使用MATCH-ANCHORED的父级MATCHER恢复之前,可以使用POST-MAT​​CH-FORM移回.

上述例外情况如下.在评估PRE-MATCH-FORM之后,MATCHER搜索的限制默认为行的结尾.但是,如果PRE-MATCH-FORM返回的位置大于评估PRE-MATCH-FORM后的位置,则该位置将用作搜索的限制.返回大于行尾的位置通常是个坏主意,即导致MATCHER搜索跨越行.

我总是发现在开始对我有意义之前我必须阅读三次字体锁文档;-)