编写自己的格式化程序¶
除了创建 自己的词法分析器,为 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() 方法传递了两个参数:tokensource 和 outfile。第一个是 (token_type, value)
元组的可迭代对象,第二个是具有 write() 方法的文件类对象。
由于格式化程序非常基本,因此它不会覆盖 get_style_defs() 方法。
样式¶
样式不会被实例化,但它们的元类提供了一些类函数,以便您可以轻松访问样式定义。
样式是可迭代的,并以 (ttype, d)
形式产生元组,其中 ttype 是一个令牌,而 d 是一个具有以下键的字典
'color'
十六进制颜色值(例如:
'ff0000'
表示红色)或 None(如果未定义)。'bold'
True 如果值应为粗体
'italic'
True 如果值应为斜体
'underline'
True 如果值应为下划线
'bgcolor'
背景的十六进制颜色值(例如:
'eeeeeee'
表示浅灰色)或 None(如果未定义)。'border'
边框的十六进制颜色值(例如:
'0000aa'
表示深蓝色)或 None 表示无边框。
将来可能会出现其他键,格式化程序应忽略它们不支持的所有键。
HTML 3.2 格式化程序¶
对于更复杂的示例,让我们实现一个 HTML 3.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
。