撰寫您自己的格式器¶
除了建立您自己的詞法分析器之外,為 Pygments 撰寫新的格式器也是簡單且直接的。
格式器是一個類別,它使用一些關鍵字參數(格式器選項)初始化,並且必須提供一個 format() 方法。此外,格式器應該提供一個 get_style_defs() 方法,該方法以格式器輸出格式可用的形式,從樣式中返回樣式定義。
快速入門¶
Pygments 附帶的最基本格式器是 NullFormatter。它只是將 Token 的值發送到輸出流。
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 是一個 Token,而 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
。