【问题标题】:How does a progn form in font-lock-keywords work?font-lock-keywords 中的 progn 形式如何工作?
【发布时间】:2013-09-02 09:50:12
【问题描述】:

以下代码将通过将 progn 表单传递给字体锁定关键字来直观地将“hello world”替换为“HW”。

(font-lock-add-keywords
 nil '(("\\(hello world\\)"
        (0 (progn (put-text-property (match-beginning 1) (match-end 1)
                                     'display "HW")
                  nil)))))

我查看了C-h v font-lock-keywords,看看这是否是字体锁定的文档化功能。 hello world 元素似乎是这种形式:

(MATCHER HIGHLIGHT ...)

这意味着 (0 ...) 是 HIGHLIGHT 并且文档说

HIGHLIGHT should be either MATCH-HIGHLIGHT or MATCH-ANCHORED.

MATCH-HIGHLIGHT should be of the form:

 (SUBEXP FACENAME [OVERRIDE [LAXMATCH]])

所以我猜 0 是 SUBEXP,(progn ...) 是 FACENAME。但是如果(progn ..) 是一个有效的FACENAME,下面的代码会起作用,但它不起作用。

;;  (MATCHER . FACENAME)
(font-lock-add-keywords
 nil '(("goodbye lenin"
        . (progn (put-text-property (match-beginning 1) (match-end 1)
                                    'display "GL")
                 nil))))

这让我想到了第一个代码如何工作以及它是否依赖于未记录的功能的问题。


更新

旁注:更简单的视觉替换方法,没有字体锁定错误

(font-lock-add-keywords
 nil '(("my llama"
        (0 (progn (put-text-property (match-beginning 0) (match-end 0)
                                     'display "ML")
                  nil)))))

【问题讨论】:

    标签: emacs elisp syntax-highlighting font-lock


    【解决方案1】:

    它确实有效 - 但您的 MATCHER 不正确 - 匹配的结果未被存储。例如,这不起作用:

    (font-lock-add-keywords
     nil '(("goodbye lenin"
            (0 (progn (put-text-property (match-beginning 1) (match-end 1)
                                        'display "GL")
                      nil)))))
    

    虽然这样做:

    (font-lock-add-keywords
     nil '(("\\(goodbye lenin\\)"
            . (progn (put-text-property (match-beginning 1) (match-end 1)
                                        'display "GL")
                     nil))))
    

    文档说:“FACENAME 是一个表达式,其值是要使用的人脸名称。 FACENAME 可以评估为属性列表,而不是一张脸 形式为(face FACE PROP1 VAL1 PROP2 VAL2 ...) 在这种情况下,将设置所有列出的文本属性,而不是 只是FACE。”

    这里,FACENAME 表达式 (progn) 的计算结果为 nil,因此没有设置任何属性或面 - 这是由 put-text-property 引起的唯一效果。

    【讨论】:

    • ("\\(goodbye lenin\\)" . (progn..)) 示例有效,但不知何故它会在消息中生成Error during redisplay: (jit-lock-function 1) signaled (invalid-function progn),当我输入(defun goodbye lenin) 时,只要我输入,单词 defun 就会停止用 font-lock-keyword-face 突出显示完成结束括号。
    • 确实如此。在我看来,在后一种语法的情况下,表单在 font-lock.el 第 1542 行(emacs 24.2)进行评估。有一个funcall,而progn 不是函数,因此会出现错误。将 funcall 更改为 eval 可以消除错误,但我不是 emacs 字体锁定方面的专家,所以我不能保证这不会破坏某些东西。另外,当您在“lenin”之后键入下一个字符时,我找不到整行失去高亮显示的原因。
    • 无论如何,我认为这里的要点是,是的,定义是相等的,因此它们的行为应该相同 - 但是这两种情况是由两段不同的代码实现的,它们不会产生 100% 相同的结果.
    • 整行失去高亮的原因可能是字体锁定错误。当 font-lock-keywords 中的某个元素导致错误时,font-lock 有时会放弃处理该元素之后的其他元素,并且将用于突出显示单词 defun 的元素放置在最近添加的再见 lenin 元素之后的某个位置。
    • 即使通过将 funcall 更改为 eval 来修复错误后,高亮也会丢失,因此这不是(唯一)原因。
    【解决方案2】:

    一个 ("goodbye lenin" . (progn (put-text-property (match-beginning 1) (match-end 1) 'display "GL") nil)) 的问题在于它是 只是另一种写法:("goodbye lenin" progn (put-text-property (match-beginning 1) (match-end 1) 'display "GL") nil),还有这些 等价会导致歧义,这就是为什么在这种情况下你会得到 错误。

    所以(MATCHER . HIGHLIGHT)(match . FACENAME)等形式 仅应在 HIGHLIGHTFACENAME 不是它们自己时使用 列表。

    【讨论】:

    • 这是否意味着("bob" . 'warning) 也是模棱两可的,因为它与("bob" quote warning) 相同,应该写成("bob" (0 'warning))("bob" 0 'warning)
    • 是的。它可能会按原样工作,但较长的形式不会更长,让您不必担心它是否模棱两可。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-15
    • 2014-10-01
    • 2012-04-29
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 2020-03-20
    相关资源
    最近更新 更多