5

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

因此,例如,如果文件包含一行内容:

+AAGATCCCAGATT

“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")
)

但这仅匹配最后一个 A 而不是全部。

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

4

1 回答 1

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)))))

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

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

我认为这主要是您喜欢的口味问题。如果单行有许多不同的锚定匹配器,第二种方法可能会稍微清晰一些,但我怀疑是否存在显着的性能差异。

这是文档的相关位font-lock-defaults

HIGHLIGHT 应该是 MATCH-HIGHLIGHT 或 MATCH-ANCHORED。

[……]

MATCH-ANCHORED 应采用以下形式:

(MATCHER 赛前形式 赛后形式 MATCH-HIGHLIGHT ...)

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

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

我总是发现我必须阅读 font-lock 文档大约三遍才能开始对我有意义;-)

于 2012-04-29T00:04:25.007 回答