编写自己的格式化程序

以及创造 your own lexer 为Pygments编写新的格式化程序既简单又简单。

格式化程序是用一些关键字参数(格式化程序选项)初始化的类,它必须提供“format()”方法。此外,格式化程序还应提供一个“get_style_defs()”方法,该方法以可用于格式化程序输出格式的形式从样式返回样式定义。

快速启动

与Pygments一起提供的最基本的格式化程序是 NullFormatter . 它只是将令牌的值发送到输出流:

from pygments.formatter import Formatter

class NullFormatter(Formatter):
    def format(self, tokensource, outfile):
        for ttype, value in tokensource:
            outfile.write(value)

如你所见, format() 方法传递两个参数: tokensourceoutfile . 第一个是 (token_type, value) 元组,后者是具有 write() 方法。

因为格式化程序是基本的,所以它不会覆盖“get_style_defs()”方法。

风格

样式没有被实例化,但是它们的元类提供了一些类函数,这样您就可以轻松地访问样式定义。

样式是不可重复的,并在形式中生成元组 (ttype, d) 在哪里? ttype 是令牌和 d 是带有以下键的dict:

'color'

十六进制颜色值(例如: 'ff0000' 为红色)或 None 如果没有定义。

'bold'

True 如果该值应为粗体

'italic'

True 如果该值应为斜体

'underline'

True 如果该值应加下划线

'bgcolor'

背景的十六进制颜色值(例如: 'eeeeeee' 浅灰色)或 None 如果没有定义。

'border'

边框的十六进制颜色值(例如: '0000aa' 对于深蓝色)或 None 没有边界。

以后可能会出现其他键,格式化程序应该忽略它们不支持的所有键。

HTML 3.2格式化程序

对于更复杂的示例,让我们实现一个HTML3.2格式化程序。我们不使用CSS而是使用内联标记 (<u><font> 等)。因为这不是很好的样式,此格式化程序不在标准库中;-)

from pygments.formatter import Formatter

class OldHtmlFormatter(Formatter):

    def __init__(self, **options):
        Formatter.__init__(self, **options)

        # create a dict of (start, end) tuples that wrap the
        # value of a token so that we can use it in the format
        # method later
        self.styles = {}

        # we iterate over the `_styles` attribute of a style item
        # that contains the parsed style values.
        for token, style in self.style:
            start = end = ''
            # a style item is a tuple in the following form:
            # colors are readily specified in hex: 'RRGGBB'
            if style['color']:
                start += '<font color="#%s">' % style['color']
                end = '</font>' + end
            if style['bold']:
                start += '<b>'
                end = '</b>' + end
            if style['italic']:
                start += '<i>'
                end = '</i>' + end
            if style['underline']:
                start += '<u>'
                end = '</u>' + end
            self.styles[token] = (start, end)

    def format(self, tokensource, outfile):
        # lastval is a string we use for caching
        # because it's possible that an lexer yields a number
        # of consecutive tokens with the same token type.
        # to minimize the size of the generated html markup we
        # try to join the values of same-type tokens here
        lastval = ''
        lasttype = None

        # wrap the whole output with <pre>
        outfile.write('<pre>')

        for ttype, value in tokensource:
            # if the token type doesn't exist in the stylemap
            # we try it with the parent of the token type
            # eg: parent of Token.Literal.String.Double is
            # Token.Literal.String
            while ttype not in self.styles:
                ttype = ttype.parent
            if ttype == lasttype:
                # the current token type is the same of the last
                # iteration. cache it
                lastval += value
            else:
                # not the same token as last iteration, but we
                # have some data in the buffer. wrap it with the
                # defined style and write it to the output file
                if lastval:
                    stylebegin, styleend = self.styles[lasttype]
                    outfile.write(stylebegin + lastval + styleend)
                # set lastval/lasttype to current values
                lastval = value
                lasttype = ttype

        # if something is left in the buffer, write it to the
        # output file, then close the opened <pre> tag
        if lastval:
            stylebegin, styleend = self.styles[lasttype]
            outfile.write(stylebegin + lastval + styleend)
        outfile.write('</pre>\n')

评论应该能解释这一点。同样,此格式化程序不会重写'get_style_defs()'方法。如果我们使用CSS类而不是内联HTML标记,那么我们需要首先生成CSS。为此,存在“get_style_defs()”方法:

生成样式定义

一些格式化程序 LatexFormatter 以及 HtmlFormatter 不输出内联标记,但引用宏或css类。因为这些定义不是输出的一部分,所以 get_style_defs() 方法存在。它被传递一个参数(如果它被使用,它的使用方式取决于格式化程序),并且必须返回一个字符串或 None .