# -*- coding: utf-8 -*- """ MoinMoin - "text/latex" Formatter Copyright 2005 Johannes Berg Copyright (c) 2003 by João Neves Copyright (c) 2000, 2001, 2002 by Jürgen Hermann All rights reserved, see COPYING for details. """ # Imports import sys, re from MoinMoin.formatter import FormatterBase from MoinMoin.Page import Page ############################################################################# ### LaTeX Formatter ############################################################################# class Formatter(FormatterBase): """ Send text data. """ hardspace = ' ' def __init__(self, request, **kw): apply(FormatterBase.__init__, (self, request), kw) self.verbatim = False self.itemized = False def text2latex(self, text): "Escape special characters if not in verbatim mode" if self.verbatim: return text text = text.replace('\\', '$\\backslash$ '); text = text.replace('$', r'\$'); text = text.replace(r'\$\backslash\$', r'$\backslash$') text = text.replace('#', r'\#'); text = text.replace('%', r'\%'); text = text.replace('^', r'\^{}'); text = text.replace('&', r'\&'); text = text.replace('_', r'\_'); text = text.replace('{', r'\{'); text = text.replace('}', r'\}'); text = text.replace('~', r'\~{}'); text = text.replace('"', r'\"{}'); text = text.replace(u'ä', r'"a'); text = text.replace(u'ü', r'"u'); text = text.replace(u'ö', r'"o'); text = text.replace(u'Ä', r'"A'); text = text.replace(u'Ü', r'"U'); text = text.replace(u'Ö', r'"O'); text = text.replace(u'ß', r'\ss{}'); return text def write_text(self, text): if self.item is None: return text else: self.item = (self.item[0], self.item[1]+text) return '' def startDocument(self, pagename): extra_preamble = '' preamble_page = self.request.pragma.get('latex_preamble', None) if preamble_page is not None: extra_preamble = Page(self.request, preamble_page).get_raw_body() extra_preamble = re.sub(re.compile('^#'), '%', extra_preamble) return """ \\documentclass[a4paper,12pt]{article} \\usepackage[utf8]{inputenc} \\usepackage{helvet} \\usepackage{graphicx} \\usepackage{multicol} \\usepackage{fullpage} \\usepackage{fancyhdr} \\usepackage{multirow} \\makeatletter \\DeclareRobustCommand*\\textsubscript[1]{%% \\@textsubscript{\\selectfont#1}} \\def\\@textsubscript#1{%% {\\m@th\\ensuremath{_{\\mbox{\\fontsize\\sf@size\\z@#1}}}}} \\makeatother %% begin extra preamble inclusion %% %s %% end extra preamble inclusion %% \\title{%s} \\author{ } \\date{ } \\renewcommand{\\theenumi}{\\arabic{enumi}} \\renewcommand{\\theenumii}{\\arabic{enumi}.\\arabic{enumii}} \\renewcommand{\\theenumiii}{\\arabic{enumi}.\\arabic{enumii}.\\arabic{enumiii}} \\renewcommand{\\theenumiv}{\\arabic{enumi}.\\arabic{enumii}.\\arabic{enumiii}.\\arabic{enumiv}} \\begin{document} """ % (extra_preamble, pagename) def endDocument(self): return '\\end{document}\n' def sysmsg(self, text, **kw): return self.write_text('') def pagelink(self, on, pagename, text=None, **kw): return self.write_text('') def url(self, on, url=None, css=None, **kw): if not on: return self.write_text('}') if url[-4:] == '.pdf': nid = self.next_img_data self.next_img_data = '' return '\\includegraphics%s{' % nid url = url.replace('&', '\\&') return self.write_text('\\href{%s}{' % self.text2latex(url)) def text(self, text): return self.write_text(self.text2latex(text)) def rule(self, size=0): size = min(size, 10) ch = "---~=*+#####"[size] return self.write_text('\n\n\\hrulefill{}\n\n') def strong(self, on): return self.write_text(['{\\bf ', '}'][not on]) def emphasis(self, on): return self.write_text(['{\\em ', '}'][not on]) def highlight(self, on): return self.write_text(['{\\tt ', '}'][not on]) def number_list(self, on, type=None, start=None): self.itemized = on if on: text = "\\begin{enumerate}" else: text = '\\end{enumerate}\n' return self.write_text(text) def bullet_list(self, on): self.itemized = on return self.write_text(['\\begin{itemize}\n', '\n\\end{itemize}\n'][not on]) def listitem(self, on, **kw): if not self.itemized: return '' self._in_li = on != 0 if on: return self.write_text('\\item ') else: return '' def sup(self, on): return self.write_text(['\\textsuperscript{', '}'][not on]) def sub(self, on): return self.write_text(['\\textsubscript{', '}'][not on]) def code(self, on, **kw): return self.write_text(['{\\tt ', '}'][not on]) def code_area(self, on, code_id, code_type='code', show=0, start=-1, step=-1): res = self.preformatted(on) self.verbatim = False return self.write_text(res) def code_token(self, on, tok_type): return self.write_text('') def code_line(self, on): return self.write_text('\n') def preformatted(self, on): FormatterBase.preformatted(self, on) self.verbatim = on return self.write_text(['\\begin{verbatim}\n', '\\end{verbatim}\n'][not on]) def smiley(self, text): return self.write_text(self.text2latex(text)) def paragraph(self, on, **kw): FormatterBase.paragraph(self, on) return self.write_text(['', '\n\n'][not on]) def linebreak(self, preformatted=1): if preformatted==1: return self.write_text('\n') else: return self.write_text('\\newline') def heading(self, on, depth, **kw): if depth == 1: rv = (r'\section{','}\n') elif depth == 2: rv = ('\\subsection{','}\n') elif depth == 3: rv = ('\\subsubsection{','}\n') else: rv = (r'\paragraph{','}\n',) return self.write_text(rv[not on]) rows = [] row = [] item = None def table(self, on, attrs={}): def count_cols(row): cols = 0 for cell in row: if cell[0].has_key('colspan'): cols += int(cell[0]['colspan'][1:-1]) else: cols += 1 return cols if on: self.rows = [] self.item = None self.row = [] return '' # not on: if self.rows == []: return '' cols = count_cols(self.rows[0]) rows = len(self.rows) _table = [[0 for i in xrange(0,cols)] for j in xrange(0,rows)] _rownum = -1 for _row in self.rows: _rownum += 1 _cellnum = -1 for _cell in _row: _cellnum += 1 while _table[_rownum][_cellnum] is None or type(_table[_rownum][_cellnum]) == type(()): _cellnum += 1 if _cell[0].get('rowspan') == '"1"': del _cell[0]['rowspan'] if _cell[0].get('colspan') == '"1"': del _cell[0]['colspan'] _rowspan = int(_cell[0].get('rowspan', '"1"')[1:-1]) _colspan = int(_cell[0].get('colspan', '"1"')[1:-1]) for j in xrange(0,_rowspan): for i in xrange(0,_colspan): _table[_rownum+j][_cellnum+i] = None _table[_rownum+j][_cellnum] = ({'colspan':'"%d"'%_colspan},None) _table[_rownum][_cellnum] = _cell table = '\\begin{tabular}{|%s}\n' % (cols * 'l|') for _row in _table: row = '' cellnum = 0 _lines = [] _do_line = True for _cell in _row: cellnum+=1 if _cell == 0: return 'INVALID TABLE' if _cell is None: if _do_line: _lines += [cellnum] continue _rowspan = int(_cell[0].get('rowspan', '"1"')[1:-1]) _colspan = int(_cell[0].get('colspan', '"1"')[1:-1]) format = '%s' if not (_cell[1] is None): _do_line = True _lines += [cellnum] else: _do_line = False _cell = (_cell[0], u'') if _rowspan > 1: format = r'\multirow{%d}*{%%s}' % _rowspan if _colspan > 1: format = r'\multicolumn{%d}{|l|}{ %s }' % (_colspan, format) row += (format+' & ') % _cell[1].replace('\n',' ') for l in _lines: table += r'\cline{%d-%d}' % (l,l) table += row[0:-3] + '\\\\ \n' table += '\\hline\\end{tabular}\n\n' return table def table_row(self, on, attrs={}): if not on: self.rows += [self.row] self.row = [] return '' def table_cell(self, on, attrs={}): if not on: self.row += [self.item] self.item = None else: self.item = (attrs,'') return '' def underline(self, on): return self.write_text(['\\underline{', '}'][not on]) def definition_list(self, on): return self.write_text(['\\begin{description}\n', '\\end{description}\n'][not on]) def definition_term(self, on, compact=0): return self.write_text(['\\item[', '] '][not on]) def definition_desc(self, on): return self.write_text('') def attachment_image(self, fname, **kw): return self.image(src=fname) def image(self, **kw): # I am using alt for caption, but how to integrate the image? text = '' imgname = kw['src'].split('=')[-1] nid = self.next_img_data self.next_img_data = '' return '\\includegraphics%s{%s}' % (nid, imgname) #if kw.has_key('alt'): # text += '\\begin{picture}\n' # text += '\\caption{%s}\n' % kw[alt] # text += '\\end{picture}\n' #return self.write_text(text) def crans_portal(self, entries): code = '' for pic, tit, bod in entries: code += "\\begin{minipage}{0.5\\linewidth}\n%s\\\\\n%s\n\\end{minipage}\n" % (tit, bod) return code def crans_box(self, tit, bod, color=None): return '%s\n%s' % (tit, bod) def johill_sidecall_emit_latex(self, code): # nothing else for now return code next_img_data = '' def johill_sidecall_next_image_data(self, data): self.next_img_data = '['+data+']' def open(self, on, **kw): return "" def close(self, on, **kw): return "" # suckers who call this. we can't do raw HTML, so we ignore it def rawHTML(self, markup): return ''