Pygments 和 ImageFormatter:将输出设置为 80 列

问题描述

ImageFormatter 总是创建一个 PNG 输出,其宽度取决于行长。

例如,此 PNG 的宽度为 192 像素:

short

这是 384:

long

Pygments 中是否有模拟 80 列输出的设置,以便所有图像都具有相同的宽度?

这是我用来生成示例的代码

#!/usr/bin/python3

from pygments import highlight
from pygments import lexers
from pygments.formatters.img import ImageFormatter
from pygments.styles import get_style_by_name,get_all_styles

lexer = lexers.get_lexer_by_name('C')

source_short = 'printf("%d\\n",i);'
source_long = 'printf("variable i is equal to %d.\\n",i);'

formatter = ImageFormatter(full = True,style = get_style_by_name('vim'))
open('short.png','wb').write(highlight(source_short,lexer,formatter))
formatter = ImageFormatter(full = True,style = get_style_by_name('vim'))
open('long.png','wb').write(highlight(source_long,formatter))

解决方法

不确定这是否是最好的方法,但对我有用。

这是 MyFormatter,来自 ImageFormatter,其中行中的字符数始终为 80。方法 format 的改动很小。

from pygments.formatter import Formatter
from pygments.util import get_bool_opt,get_int_opt,get_list_opt,\
    get_choice_opt,xrange
from PIL import Image,ImageDraw,ImageFont
import subprocess

class MyFormatter(ImageFormatter):
    def __init__(self,**options):
        super().__init__(**options)

    def format(self,tokensource,outfile):
        self._create_drawables(tokensource)
        self._draw_line_numbers()
        im = Image.new(
            'RGB',self._get_image_size(80,self.maxlineno),# always 80
            self.background_color
        )
        self._paint_line_number_bg(im)
        draw = ImageDraw.Draw(im)
        # Highlight
        if self.hl_lines:
            x = self.image_pad + self.line_number_width - self.line_number_pad + 1
            recth = self._get_line_height()
            rectw = im.size[0] - x
            for linenumber in self.hl_lines:
            y = self._get_line_y(linenumber - 1)
            draw.rectangle([(x,y),(x + rectw,y + recth)],fill=self.hl_color)
        for pos,value,font,kw in self.drawables:
            draw.text(pos,font=font,**kw)
        im.save(outfile,self.image_format.upper())