#! /usr/bin/env python import os, sys, re from reportlab.lib import colors from reportlab.lib.enums import TA_JUSTIFY from reportlab.lib.units import cm from reportlab.lib.pagesizes import A4 from reportlab.lib.styles import getSampleStyleSheet from reportlab.pdfgen import canvas from reportlab.platypus.flowables \ import Spacer, Preformatted, Image, KeepTogether from reportlab.platypus.paragraph import Paragraph from reportlab.platypus.xpreformatted \ import PythonPreformatted from reportlab.platypus.frames import Frame from reportlab.platypus.doctemplate \ import PageTemplate, BaseDocTemplate def eachPage(canvas, doc): "Adornments for each page." canvas.saveState() canvas.setFont('Helvetica', 8) canvas.setFillColor(colors.black) # add page number num = "%d" % doc.page canvas.drawCentredString(10.5*cm, 1*cm, num) canvas.restoreState() class LinuxMagDocTemplate(BaseDocTemplate): "The document template used for all pages." def __init__(self, filename, **kw): fw, fh = 8.5*cm, 26.5*cm f1 = Frame(2*cm, 1.5*cm, fw, fh, id='c1') f2 = Frame(10.5*cm, 1.5*cm, fw, fh, id='c2') self.allowSplitting = 0 BDT, PT = BaseDocTemplate, PageTemplate apply(BDT.__init__, (self, filename), kw) pt = PT('TwoCol', [f1, f2], eachPage) self.addPageTemplates(pt) def handlePara(para): "Convert intra-paragraph markup." # quotes while '"' in para: for j in chr(227), chr(210): i = para.find('"') para = para[:i] + j + para[i+1:] # guillemets and URLs data = [ ('', chr(200), chr(199)), # ('', '', '')] ('', '', '')] for (tag, before, after) in data: pat = '%s.*?%s' % (tag, tag) while para.find(tag) >= 0: m = re.search(pat, para) if not m: continue start, end = m.start()+3, m.end()-3 word = para[start:end] if tag == '': before = before % word word = before + word + after para = re.sub(pat, word, para, 1) return para def handleCode(lines, i): "Handle external code listing." listing = lines # strip off heading and trailing empty lines if listing: while not listing[0].strip(): del listing[0] while not listing[-1].strip(): del listing[-1] # number lines if we have more than 10 lines listLen = len(listing) if listLen > 10: format = "%%%dd %%s" format = format % len(str(listLen)) for k in xrange(len(listing)): listing[k] = format % (k+1, listing[k]) # assemble and add to story listing = ''.join(listing) return listing, i def handleInlineListing(lines, i): "Handle inline listing." # extract lines belonging to the listing listing = [] j = 0 while 1: j = j + 1 try: line = lines[i + j] except IndexError: break if line and line[0] == '@': break else: listing.append(line) i = i + j - 1 return handleCode(listing, i) def main(path): "The main meat." lines = open(path).readlines() print len(lines) # Platypus variables. story = [] styleSheet = getSampleStyleSheet() h1 = styleSheet['Heading1'] h2 = styleSheet['Heading2'] h3 = styleSheet['Heading3'] code = styleSheet['Code'] bt = styleSheet['BodyText'] for h in (h1, h2, h3): h.fontName = 'Helvetica-Bold' ## h.spaceAfter = -5 bt.spaceBefore = 0 bt.spaceAfter = 0 bt.fontSize = 9 bt.alignment = TA_JUSTIFY bt.bulletFontName = 'ZapfDingbats' bt.bulletFontSize = 7 code.leftIndent = 0 code.firstLineIndent = 0 code.fontSize = 7 code.spaceBefore = 3 code.spaceAfter = 9 P = Paragraph bold = '%s' author = '' allowedKeys = 'T V ZT IT L IL KT LI B Bi CO' allowedKeys = allowedKeys.split() i = -1 while i < len(lines)-1: i = i + 1 line = lines[i].strip() key = '' m = re.match('^@([A-Za-z]+):', line) if m: key = m.groups()[0] keyLen = len(key) + 2 elif line[:2] == '* ': key, keyLen = '* ', 2 else: continue rline = line[keyLen:].strip() if key == 'A': author = line[keyLen:] elif key == 'Bi': p = Image(rline, width=8.5*cm, height=200, kind='proportional') print "img: %s " % rline elif key == 'LI': listing, i = handleInlineListing(lines, i) p = PythonPreformatted(listing, code) # Added to LinuxMag format elif key == 'CO': clines = open(rline).readlines() print "%s (%d)" % (rline, len(clines)) listing, i = handleCode(clines, i) p = PythonPreformatted(listing, code) else: para = handlePara(rline) bpara = bold % para vformat = "%s (%s)" dict = { 'L': P(para, bt), 'IL': P(bpara, bt), 'T': P(para, h1), 'ZT': P(para, h2), 'IT': P(bpara, h3), 'B': P(bpara, h3), 'KT': P(bpara, h3), '* ': P(para, bt, bulletText=chr(110)), 'V': KeepTogether([ P(vformat % (para, author), bt), Spacer(0, 12)]) } p = dict.get(key, None) if key in allowedKeys + ['* ']: story.append(p) # Build the PDF document. path = os.path.splitext(path)[0] + '.pdf' doc = LinuxMagDocTemplate(path) doc.build(story) if __name__ == '__main__': main(sys.argv[1])