Sphinx Pygments词法过滤器扩展?

6

我有一种类似Lisp的语言,想要在Sphinx代码段文档中使用Pygments进行高亮显示。我的方法是通过使用NameHighlightFilter扩展现有的CommonLispLexer来添加内置名称。 然而,它没有起作用,所以我肯定忽略了一些显而易见的东西。我已经在我的conf.py文件中添加了以下内容:

def setup(app): 
    from sphinx.highlighting import lexers
    from pygments.lexers import CommonLispLexer
    from pygments.token import Name
    from pygments.filters import NameHighlightFilter
    tl_lexer = CommonLispLexer()
    tl_lexer.add_filter(NameHighlightFilter(
            names=['define-function', 'define-macro', 
                   'define-variable', 'define-constant'],
            tokentype=Name.Builtin,
            ))
    app.add_lexer('tl', tl_lexer)

highlight_language = 'tl'

但是NameHighlightFilter没有效果。代码块被突出显示,就好像它们是Lisp一样,但我的新内置名称没有特殊的突出显示。

在交互式Python会话中运行此代码可以确认过滤器的工作方式与我的意图不符。即使以上已经调用了add_filterdefine-function 仍然被标记为 Name.Variable 而不是 Name.Builtin - Jennifer Smith
1个回答

7
原因是NameHighlighFilter仅转换由词法分析器归类为Token.Name的标记,但CommonLispLexer将几乎所有内容归类为Name.Variable。以下是Pygments源代码中的NameHighlightFilter过滤函数:
def filter(self, lexer, stream):
    for ttype, value in stream:
        if ttype is Name and value in self.names:
            yield self.tokentype, value
        else:
            yield ttype, value

我的唯一解决办法是编写自己的过滤器。这个函数给我想要的外观。

def filter(self, lexer, stream):
    define = False
    for ttype, value in stream:
        if value in self.tl_toplevel_forms:
            ttype = Name.Builtin
            define = True
        elif define and ttype == Name.Variable:
            define = False
            ttype = Name.Function
        elif value in self.tl_special_forms:
            ttype = Name.Variable
        # the Common Lisp lexer highlights everything else as
        # variables, which isn't the look I want.  Instead
        # highlight all non-special things as text.
        elif ttype == Name.Variable:
            ttype = Name.Text
        yield ttype, value

作为对Pygments开发者的一则说明,也许NameHighlightFilter可以接受一个可选参数来表示要转换的记号类型(目前它只能接受输出记号类型)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接