Pygments中的特殊非语法突出显示

时间:2018-10-01 10:18:17

标签: python-3.x latex markdown pygments

我正在使用Pygments作为MarkDown,Python和LaTeX的一部分(通过c.wait())。由于这些原因,我不能轻易地换用其他工具,而是想在Pygments中找到解决方案。

我想要实现的是在普通语法突出显示之外还具有“特殊突出显示”。例如,这包括使特定的终端输出保持其原始颜色。或添加额外的样式以更轻松地突出显示供用户填写的参数。肯定可以使这个例子更容易理解。

在Apple编写的Swift手册中,您要填写的参数在气球中突出显示。这使得它们更容易识别,并且气球可以覆盖一系列令牌:

that

我想实现与Pygments类似的功能。仅仅改变样式是行不通的。您希望这些东西不在气球中时通常按其标记类型设置样式,并且当它们在气球中时不希望任何类型的特定突出显示。我不认为这些气球在当前的香草酱中是可行的。我认为我需要一种新型的令牌来实现我想要的。我想将其用于多种语言,因此理想情况下,我想找到以最少的修改就能做到这一点的方法。可悲的是,我不认为我可以用Pygments过滤器实现我想要的。我的直觉是我需要为所有要使用的语言重写词法分析器,但我认为可以通过将它们子类化来实现。

总而言之,我要输入的代码是

c.wait()

,例如HTML输出,例如

minted

出来。在这种新的环境或类似的情况下,我并不想限制使用符号§label name§: while §condition§ { 的使用,它只是预期行为的一个示例。

由于为我使用的每种语言修改了词法分析器是相当努力的,并且由于Pygments的文档非常简单,因此我想问一下如何解决这个问题以及我是否忽略了某些内容。我是否假设我需要一个新令牌并需要重写每个词法分析器对吗?还是有更聪明的方法?

1 个答案:

答案 0 :(得分:0)

感谢Waylan的评论,我已经走上正确的道路,找到了行之有效的解决方案:

from pygments import token
from pygments.lexer import inherit
from pygments.lexers import Python3Lexer, SwiftLexer


# create a new token and associate with it a new short style name
token.STANDARD_TYPES[token.Token.Balloon] = "balloon"
Balloon = token.Token.Balloon


# create a callback which ignores the special § characters
def process_balloon(_, match):
    yield match.start(), Balloon, match.group(1)


# subclass the Python 3 lexer to identify ballooned text
# when subclassing, the tokens dictionaries will be merged
class Python3BalloonLexer(Python3Lexer):
    tokens = {
        "root": [(r'§(.*?)§', process_balloon),  # balloons are processed first
                 inherit]  # and then merge the superclass tokens here
    }

# do the same for the Swift language with a one-liner
class SwiftBalloonLexer(SwiftLexer):
    tokens = { "root": [(r'§(.*?)§', process_balloon), inherit] }


# example output below
from pygments import highlight
from pygments.formatters import HtmlFormatter
my_lexer_python = Python3BalloonLexer()
my_lexer_swift = SwiftBalloonLexer()
print(highlight('print(§"Hello World"§)', my_lexer_python, HtmlFormatter()))
print(highlight('§label name§: while §condition§ {\n  §statements§\n}', 
      my_lexer_swift, HtmlFormatter()))
简而言之,该解决方案创建了一个新令牌,以确保与现有令牌没有冲突。然后,对于希望使用气球的每种语言,将该语言分类,以添加对新令牌的支持。该令牌由回调函数处理,该回调函数仅接受§符号之间的内容。找到所有气球后,普通词法分析器将接管并处理语言的其余部分。

此解决方案似乎打勾了大多数框,除了需要将每种语言逐一细分。这有点麻烦,但不是太大的问题。该方法仍然有些脆弱,因为它假定§仅用于突出显示这些提示框。

只需采用子类添加/堆叠更多词法扩展程序,就可以采用类似的方法来强制必须始终使用相同颜色的例如文本使用特定样式。当然,这增加了潜在冲突的风险,因为这意味着添加更多的特殊符号(例如§),这些符号可能已在代码的其他位置使用。

相关问题