1 """
2 MoinMoin - "text/latex" Formatter
3
4 Copyright 2005-2007 Johannes Berg <johannes@sipsolutions.net>
5 Copyright (c) 2003 by João Neves <moin@silvaneves.org>
6 Copyright (c) 2000, 2001, 2002 by Jürgen Hermann <jh@web.de>
7
8 If you want to have the latex formatter easily accessible from
9 the actions menu, add add this code to a file called LatexOutput.py
10 in your actions plugin directory:
11 ---->%---->%----
12 # -*- coding: iso-8859-1 -*-
13
14 from MoinMoin.Page import Page
15 from MoinMoin.request import MoinMoinFinish
16 from MoinMoin import wikiutil
17
18 def execute(pagename, request):
19 url = Page(request, pagename).url(request,
20 {'action': 'format',
21 'mimetype': 'text_latex'},
22 relative=False)
23 request.http_redirect(url)
24 ----%<----%<----
25
26 @copyright: GPL v2
27 """
28
29
30
31 import sys, re
32
33
34 from MoinMoin.formatter.base import FormatterBase
35
36
37
38 from MoinMoin.Page import Page
39
40
41
42
43
44 class Formatter(FormatterBase):
45 """
46 Send text data.
47 """
48
49 hardspace = ' '
50
51 def __init__(self, request, **kw):
52 apply(FormatterBase.__init__, (self, request), kw)
53 self.verbatim = False
54 self.itemized = False
55
56 def text2latex(self, text):
57 "Escape special characters if not in verbatim mode"
58 if self.verbatim: return text
59 text = text.replace('\\', '$\\backslash$ ');
60 text = text.replace('$', r'\$');
61 text = text.replace(r'\$\backslash\$', r'$\backslash$')
62 text = text.replace('#', '\#');
63 text = text.replace('%', '\%');
64 text = text.replace('^', '\^{}');
65 text = text.replace('&', '\&');
66 text = text.replace('_', '\_');
67 text = text.replace('{', '\{');
68 text = text.replace('}', '\}');
69 text = text.replace('~', '\~{}');
70 text = text.replace('"', '\"');
71 return text
72
73 def write_text(self, text):
74 if self.item is None:
75 return text
76 else:
77 self.item = (self.item[0], self.item[1]+text)
78 return ''
79
80 def startDocument(self, pagename):
81 extra_preamble = ''
82 preamble_page = self.request.pragma.get('latex_preamble', None)
83 if preamble_page is not None:
84 extra_preamble = Page(self.request, preamble_page).get_raw_body()
85 extra_preamble = re.sub(re.compile('^#'), '%', extra_preamble)
86 return """
87 \\documentclass[a4paper,12pt]{article}
88
89 \\usepackage[utf8]{inputenc}
90 \\usepackage{helvet}
91 \\usepackage{graphicx}
92 \\usepackage{multicol}
93 \\usepackage{fullpage}
94 \\usepackage{fancyhdr}
95 \\usepackage{hyperref}
96 \\usepackage{multirow}
97 \\makeatletter
98 \\DeclareRobustCommand*\\textsubscript[1]{%%
99 \\@textsubscript{\\selectfont#1}}
100 \\def\\@textsubscript#1{%%
101 {\\m@th\\ensuremath{_{\\mbox{\\fontsize\\sf@size\\z@#1}}}}}
102 \\makeatother
103
104 %% begin extra preamble inclusion %%
105 %s
106
107 %% end extra preamble inclusion %%
108
109 \\title{%s}
110
111 \\author{ }
112
113 \\date{ }
114
115 \\renewcommand{\\theenumi}{\\arabic{enumi}}
116 \\renewcommand{\\theenumii}{\\arabic{enumi}.\\arabic{enumii}}
117 \\renewcommand{\\theenumiii}{\\arabic{enumi}.\\arabic{enumii}.\\arabic{enumiii}}
118 \\renewcommand{\\theenumiv}{\\arabic{enumi}.\\arabic{enumii}.\\arabic{enumiii}.\\arabic{enumiv}}
119
120 \\begin{document}
121 """ % (extra_preamble, pagename)
122
123 def endDocument(self):
124 return '\\end{document}\n'
125
126 def sysmsg(self, text, **kw):
127 return self.write_text('')
128
129 def pagelink(self, on, pagename, text=None, **kw):
130 return self.write_text('')
131
132 def url(self, on, url=None, css=None, **kw):
133 if not on:
134 return self.write_text('}')
135 url = url.replace('&', '\\&')
136 return self.write_text('\\href{%s}{' % url)
137
138 def text(self, text):
139 return self.write_text(self.text2latex(text))
140
141 def rule(self, size=0):
142 size = min(size, 10)
143 ch = "---~=*+#####"[size]
144 return self.write_text('\\vrule \n')
145
146 def strong(self, on):
147 return self.write_text(['{\\bf ', '}'][not on])
148
149 def emphasis(self, on):
150 return self.write_text(['{\\em ', '}'][not on])
151
152 def highlight(self, on):
153 return self.write_text(['{\\tt ', '}'][not on])
154
155 def number_list(self, on, type=None, start=None):
156 self.itemized = on
157 if on:
158 text = "\\begin{enumerate}"
159 else:
160 text = '\\end{enumerate}\n'
161 return self.write_text(text)
162
163 def bullet_list(self, on):
164 self.itemized = on
165 return self.write_text(['\\begin{itemize}\n', '\n\\end{itemize}\n'][not on])
166
167 def listitem(self, on, **kw):
168 if not self.itemized: return ''
169 self._in_li = on != 0
170 if on:
171 return self.write_text('\\item ')
172 else:
173 return ''
174
175 def sup(self, on):
176 return self.write_text(['\\textsuperscript{', '}'][not on])
177
178 def sub(self, on):
179 return self.write_text(['\\textsubscript{', '}'][not on])
180
181 def code(self, on, **kw):
182 return self.write_text(['{\\tt ', '}'][not on])
183
184 def code_area(self, on, code_id, code_type='code', show=0, start=-1, step=-1):
185 res = self.preformatted(on)
186 self.verbatim = False
187 return self.write_text(res)
188
189 def code_token(self, on, tok_type):
190 return self.write_text('')
191
192 def code_line(self, on):
193 return self.write_text('\n')
194
195 def preformatted(self, on):
196 FormatterBase.preformatted(self, on)
197 self.verbatim = on
198 return self.write_text(['\\begin{verbatim}\n', '\\end{verbatim}\n'][not on])
199
200 def smiley(self, text):
201 return self.write_text(self.text2latex(text))
202
203 def paragraph(self, on, **kw):
204 FormatterBase.paragraph(self, on)
205 return self.write_text(['', '\n\n'][not on])
206
207 def linebreak(self, preformatted=1):
208 if preformatted==1:
209 return self.write_text('\n')
210 else:
211 return self.write_text('\\newline')
212
213 def heading(self, on, depth, **kw):
214 if depth == 1:
215 rv = (r'\section{','}')
216 elif depth == 2:
217 rv = ('\\subsection{','}')
218 elif depth == 3:
219 rv = ('\\subsubsection{','}')
220 else:
221 rv = (r'\paragraph{','}',)
222 return self.write_text(rv[not on])
223
224 rows = []
225 row = []
226 item = None
227
228 def table(self, on, attrs={}):
229 def count_cols(row):
230 cols = 0
231 for cell in row:
232 if cell[0].has_key('colspan'):
233 cols += int(cell[0]['colspan'][1:-1])
234 else:
235 cols += 1
236 return cols
237
238 if on:
239 self.rows = []
240 self.item = None
241 self.row = []
242 return ''
243
244 if self.rows == []: return ''
245 cols = count_cols(self.rows[0])
246 rows = len(self.rows)
247 _table = [[0 for i in xrange(0,cols)] for j in xrange(0,rows)]
248 _rownum = -1
249 for _row in self.rows:
250 _rownum += 1
251 _cellnum = -1
252 for _cell in _row:
253 _cellnum += 1
254
255 while _table[_rownum][_cellnum] is None or type(_table[_rownum][_cellnum]) == type(()):
256 _cellnum += 1
257
258 if _cell[0].get('rowspan') == '"1"':
259 del _cell[0]['rowspan']
260 if _cell[0].get('colspan') == '"1"':
261 del _cell[0]['colspan']
262
263 _rowspan = int(_cell[0].get('rowspan', '"1"')[1:-1])
264 _colspan = int(_cell[0].get('colspan', '"1"')[1:-1])
265
266 for j in xrange(0,_rowspan):
267 for i in xrange(0,_colspan):
268 _table[_rownum+j][_cellnum+i] = None
269 _table[_rownum+j][_cellnum] = ({'colspan':'"%d"'%_colspan},None)
270 _table[_rownum][_cellnum] = _cell
271
272
273 table = '\\begin{tabular}{|%s}\n' % (cols * 'l|')
274 for _row in _table:
275 row = ''
276 cellnum = 0
277 _lines = []
278 _do_line = True
279 for _cell in _row:
280 cellnum+=1
281 if _cell == 0:
282 return 'INVALID TABLE'
283 if _cell is None:
284 if _do_line:
285 _lines += [cellnum]
286 continue
287 _rowspan = int(_cell[0].get('rowspan', '"1"')[1:-1])
288 _colspan = int(_cell[0].get('colspan', '"1"')[1:-1])
289 format = '%s'
290 if not (_cell[1] is None):
291 _do_line = True
292 _lines += [cellnum]
293 else:
294 _do_line = False
295 _cell = (_cell[0], u'')
296 if _rowspan > 1:
297 format = r'\multirow{%d}*{%%s}' % _rowspan
298 if _colspan > 1:
299 format = r'\multicolumn{%d}{|l|}{ %s }' % (_colspan, format)
300 row += (format+' & ') % _cell[1].replace('\n',' ')
301 for l in _lines:
302 table += r'\cline{%d-%d}' % (l,l)
303 table += row[0:-3] + '\\\\ \n'
304 table += '\\hline\\end{tabular}\n\n'
305 return table
306
307
308 def table_row(self, on, attrs={}):
309 if not on:
310 self.rows += [self.row]
311 self.row = []
312 return ''
313
314 def table_cell(self, on, attrs={}):
315 if not on:
316 self.row += [self.item]
317 self.item = None
318 else:
319 self.item = (attrs,'')
320 return ''
321
322 def underline(self, on):
323 return self.write_text(['\\underline{', '}'][not on])
324
325 def definition_list(self, on):
326 return self.write_text(['\\begin{description}\n', '\\end{description}\n'][not on])
327
328 def definition_term(self, on, compact=0):
329 return self.write_text(['\\item[', '] '][not on])
330
331 def definition_desc(self, on):
332 return self.write_text('')
333
334 def attachment_image(self, fname):
335 return self.image(src=fname)
336 def image(self, **kw):
337
338 text = ''
339
340
341
342
343 return self.write_text(text)
344
345 def johill_sidecall_emit_latex(self, code):
346
347 return code
348
349 def open(self, on, **kw):
350 return ""
351 def close(self, on, **kw):
352 return ""
353
354
355 def rawHTML(self, markup):
356 return ''