避免字体锁定干扰注释内部

Avoid font-locking interfering inside of comments

在我的 font-lock-defaults 我有:

("\(^\| \|\t\)\(![^\n]+\)\n" 2 'factor-font-lock-comment)

评论字符是!,这使得评论得到正确的表情。这主要有效,除非评论中存在竞争的字体锁定实体,例如字符串(由双引号分隔):

! this line is font-locked fine
! this one is "not" because "strings"

您如何获得字体锁定以了解注释已经很好地字体锁定并且不需要尝试对其中的任何字符串进行字体锁定?显而易见的方法是在 table:

语法中将 ! 添加到评论起始符 class
(modify-syntax-entry ?! "< 2b" table)

这个解决方案是不可能的,因为包含 ! 的函数名称和其他符号是合法的,例如 map! filter!foo!bar。添加 ! 会导致包含此类名称的代码被错误地突出显示。

通常,使用 font-lock 关键字来突出显示评论是个坏主意。最好使用句法阶段。

尽管语法 table 不足以描述您的语言的语法,但仍然可以在语法字体锁定阶段使用突出显示注释。解决方案是提供一个自定义函数,将句法属性分配给应该开始注释的 ! 个字符。这是使用变量 syntax-propertize-function.

完成的

请参阅 elisp manual for details. Also, this tutorial 对此进行了非常详细的介绍。

更新: 下面是一个简单的例子,将!定义为注释开始字符,但不在标识符中。一个真实世界的例子可能需要一种更精确的方法来检查某物是否是标识符。

(defun exmark-syntax-propertize (start end)
  (funcall (syntax-propertize-rules
            ("[[:alnum:]_]\(!\)"
             (1 "_")))
           start
           end))

(defvar exmark-mode-syntax-table
  (let ((table (make-syntax-table)))
    (modify-syntax-entry ?\n ">   " table)
    (modify-syntax-entry ?!  "<   " table)
    table))

(define-derived-mode exmark-mode prog-mode "!-Mark"
  "Major mode for !-mark."
  (set (make-local-variable 'syntax-propertize-function)
       'exmark-syntax-propertize))