22
20
self._in_code_area = 0
23
21
self._in_code_line = 0
24
22
self._code_area_state = [0, -1, -1, 0]
27
self._text = None # XXX does not work with links in headings!!!!!
29
self._skip_text = False
30
self._wrap_skip_text = False
33
self._listitem_on = []
34
self._empty_line_count = 2
35
self._paragraph_ended = False
36
self._paragraph_skip_begin = True
26
self._text = None # XXX does not work with links in headings!!!!!
38
28
def startDocument(self, pagename):
39
line = u'\n'.rjust(len(pagename) + 2, u'*')
40
return self.wrap(u"%s %s \n%s" % (line, pagename, line))
29
line = u"*" * (len(pagename) + 2) + u'\n'
30
return u"%s %s \n%s" % (line, pagename, line)
43
return self.flush(True)
32
def endDocument(self):
45
35
def sysmsg(self, on, **kw):
46
return self.wrap((u'\n\n*** ', u' ***\n\n')[not on])
36
return (u'\n\n*** ', u' ***\n\n')[not on]
48
38
def pagelink(self, on, pagename='', page=None, **kw):
49
39
FormatterBase.pagelink(self, on, pagename, page, **kw)
51
if not self._textbuf or self._textbuf[-1] in ('\n', ' '):
52
result = self.wrap(u'<')
54
result = self.wrap(u' <')
56
self.add_missing_space()
61
orig_pagename = pagename
62
if pagename.find('/'):
63
pagename = pagename.replace('/', '.')
65
if linktext == orig_pagename:
66
return self.wrap(u'%s>' % pagename)
68
return self.wrap(u'%s> [%s]' % (linktext, pagename))
40
return (u">>", u"<<") [not on]
70
42
def interwikilink(self, on, interwiki='', pagename='', **kw):
72
self.add_missing_space()
73
44
self._url = u"%s:%s" % (interwiki, pagename)
48
if "".join(self._text) == self._url:
82
result = self.wrap(u' [%s]' % (self._url))
55
return u' [%s]' % (self._url)
86
57
def url(self, on, url='', css=None, **kw):
88
self.add_missing_space()
95
if text == self._url or 'mailto:' + text == self._url:
63
if "".join(self._text) == self._url:
98
result = self.wrap(u' [%s]' % (self._url))
70
return u' [%s]' % (self._url)
102
72
def attachment_link(self, on, url=None, **kw):
104
if 'title' in kw and kw['title']:
105
if kw['title'] != url:
106
return self.wrap(u'[attachment:%s ' % url)
107
return self.wrap(u'[attachment:')
108
return self.wrap(']')
110
78
def attachment_image(self, url, **kw):
112
80
for a in (u'title', u'html__title', u'alt', u'html_alt'):
114
82
title = ':' + kw[a]
115
return self.wrap("[image:%s%s]" % (url, title))
83
return "[image:%s%s]" % (url, title)
117
85
def attachment_drawing(self, url, text, **kw):
118
return self.wrap("[drawing:%s]" % text)
86
return "[drawing:%s]" % text
120
88
def text(self, text, **kw):
121
90
if self._text is not None:
123
if self._wrap_skip_text:
125
return self.wrap(text)
91
self._text.append(text)
127
94
def rule(self, size=0, **kw):
128
95
size = min(size, 10)
129
96
ch = u"---~=*+#####"[size]
130
self.paragraph_begin()
131
result = self.wrap((ch * (79 - self._indent)))
97
return (ch * 79) + u'\n'
135
99
def strong(self, on, **kw):
137
self.add_missing_space()
138
return self.wrap(u'*')
140
102
def emphasis(self, on, **kw):
142
self.add_missing_space()
143
return self.wrap(u'/')
145
105
def highlight(self, on, **kw):
148
108
def number_list(self, on, type=None, start=None, **kw):
151
# No empty lines between sublists
152
self._paragraph_ended = False
153
self.paragraph_begin()
154
self._lists.append(0)
155
self._listitem_on.append(False)
158
num = self._lists.pop()
159
listitem_on = self._listitem_on.pop()
161
prefix = ' %d. ' % (num)
162
self._indent -= len(prefix)
111
return [u'\n', u'\n\n'][not self._did_para]
114
if not self._did_para:
165
119
def bullet_list(self, on, **kw):
168
# No empty lines between sublists
169
self._paragraph_ended = False
170
self.paragraph_begin()
171
self._lists.append(-1)
172
self._listitem_on.append(False)
122
return [u'\n', u'\n\n'][not self._did_para]
176
listitem_on = self._listitem_on.pop()
125
if not self._did_para:
181
130
def listitem(self, on, **kw):
182
self._paragraph_ended = False
184
# we can't rely on this
189
num = self._lists.pop()
190
listitem_on = self._listitem_on.pop()
191
if listitem_on and on:
192
# we didn't receive on=False for previous listitem
195
prefix = ' %d. ' % (num)
196
self._indent -= len(prefix)
132
if self._in_list > 0:
135
return ' %d. ' % (self._in_list-1, )
136
elif self._in_list < 0:
202
prefix = ' %d. ' % (num)
204
# FIXME: also before tables, at leat in LDA.Sieve.txt
206
self._lists.append(num)
207
self._listitem_on.append(on)
209
result += self.wrap(prefix)
210
self._indent += len(prefix)
211
self._paragraph_skip_begin = True
214
145
def sup(self, on, **kw):
216
return self.wrap(u'^')
220
148
def sub(self, on, **kw):
221
return self.wrap(u'_')
223
151
def strike(self, on, **kw):
225
self.add_missing_space()
226
return self.wrap(u'__')
228
154
def code(self, on, **kw):
230
self.add_missing_space()
231
return self.wrap(u"'")
155
#return [unichr(0x60), unichr(0xb4)][not on]
156
return u"'" # avoid high-ascii
233
158
def preformatted(self, on, **kw):
234
159
FormatterBase.preformatted(self, on)
235
snip = u'%s\n' % u'---%<'.ljust(78 - self._indent, u'-')
161
snip = snip + (u'-' * (78 - len(snip)))
237
self.paragraph_begin()
238
return self.wrap(snip)
163
return u'\n' + snip + u'\n'
240
if self._textbuf and not self._textbuf.endswith('\n'):
241
self._textbuf += '\n'
242
result = self.wrap(snip)
246
167
def small(self, on, **kw):
248
self.add_missing_space()
251
170
def big(self, on, **kw):
253
self.add_missing_space()
256
def code_area(self, on, code_id, code_type='code', show=0, start=-1,
258
snip = u'%s\n' % u'---CodeArea'.ljust(78 - self._indent, u'-')
173
def code_area(self, on, code_id, code_type='code', show=0, start=-1, step=-1):
174
snip = u'---CodeArea'
175
snip = snip + (u'-' * (78 - len(snip)))
260
self.paragraph_begin()
261
177
self._in_code_area = 1
262
178
self._in_code_line = 0
263
179
self._code_area_state = [show, start, step, start]
264
return self.wrap(snip)
180
return u'\n' + snip + u'\n'
266
182
if self._in_code_line:
267
return self.wrap(self.code_line(0) + snip)
268
result = self.wrap(snip)
183
return self.code_line(0) + snip + u'\n'
272
186
def code_line(self, on):
278
192
res += u' %4d ' % self._code_area_state[3]
279
193
self._code_area_state[3] += self._code_area_state[2]
280
194
self._in_code_line = on != 0
281
return self.wrap(res)
283
197
def code_token(self, on, tok_type):
286
def add_missing_space(self):
287
if self._textbuf and self._textbuf[-1].isalnum():
290
200
def paragraph(self, on, **kw):
291
201
FormatterBase.paragraph(self, on)
293
self.paragraph_begin()
204
return [u'\n', u''][not on]
298
206
def linebreak(self, preformatted=1):
299
return self.wrap(u'\n')
301
209
def smiley(self, text):
302
return self.wrap(text)
304
212
def heading(self, on, depth, **kw):
306
self.paragraph_begin()
315
result = u'\n%s\n' % (ch * len(self._text))
317
result = self.wrap(result)
321
def get_table_sep(self, col_widths):
323
for width in col_widths:
324
result += '+' + ('-' * width)
325
return result + '+\n'
327
def fix_col_widths(self):
328
min_widths = self._table_column_min_len
329
max_widths = self._table_column_max_len
330
max_len = sum(max_widths)
331
# take the needed space equally from all columns
332
count = len(max_widths)
334
available_len = 79 - count - 1
335
while max_len > available_len:
336
if max_widths[idx] > min_widths[idx]:
343
# there are only too wide columns
217
result = u'\n%s\n\n' % (u'=' * len("".join(self._text)))
351
221
def table(self, on, attrs={}, **kw):
354
self._table_column_min_len = []
355
self._table_column_max_len = []
356
result = self.flush(True)
359
col_widths = self.fix_col_widths()
360
for row in self._table:
361
result += self.get_table_sep(col_widths)
369
lf_idx = col.find('\n')
373
next_idx = lf_idx + 1
377
# possibly break earlier if we need to wrap
378
if col_len > col_widths[num]:
379
idx = col.rfind(' ', 0, col_widths[num])
381
idx = col.find(' ', col_widths[num])
386
result += ' ' + col[:col_len]
387
result += (' ' * (col_widths[num] - col_len - 1)) + '|'
388
row[num] = col[next_idx:]
391
result += self.get_table_sep(col_widths)
393
self._table_column_min_len = None
394
self._table_column_max_len = None
395
self._empty_line_count = 0
399
224
def table_row(self, on, attrs={}, **kw):
401
self._table.append([])
404
227
def table_cell(self, on, attrs={}, **kw):
407
self._wrap_skip_text = True
409
# keep track of the longest word and the longest line in the cell
410
self._text = self._text.strip()
413
for line in self._text.split('\n'):
414
if len(line) > max_line_len:
415
max_line_len = len(line)
416
for word in self._text.split(' '):
417
if len(word) > max_word_len:
418
max_word_len = len(word)
419
# one preceding and trailing cell whitespace
423
rownum = len(self._table) - 1
424
colnum = len(self._table[rownum])
425
if len(self._table_column_max_len) <= colnum:
426
self._table_column_min_len.append(max_word_len)
427
self._table_column_max_len.append(max_line_len)
429
if max_word_len > self._table_column_min_len[colnum]:
430
self._table_column_min_len[colnum] = max_word_len
431
if self._table_column_max_len[colnum] < max_line_len:
432
self._table_column_max_len[colnum] = max_line_len
433
self._table[rownum].append(self._text)
437
230
def underline(self, on, **kw):
438
return self.wrap(u'_')
440
233
def definition_list(self, on, **kw):
442
self.paragraph_begin()
447
236
def definition_term(self, on, compact=0, **kw):
450
# result = result + u'\n'
239
result = result + u'\n'
452
result = result + u':'
453
return self.wrap(result)
241
result = result + u':\n'
455
244
def definition_desc(self, on, **kw):
458
self.paragraph_begin()
461
self._textbuf += '\n'
245
return [u' ', u'\n'][not on]
465
247
def image(self, src=None, **kw):
466
248
for a in (u'title', u'html__title', u'alt', u'html_alt'):
468
return self.wrap(kw[a] + ' [' + src + ']')
469
return self.wrap('[' + src + ']')
253
def transclusion(self, on, **kw):
256
def transclusion_param(self, **kw):
471
259
def lang(self, on, lang_name):
474
def paragraph_begin(self):
475
if self._paragraph_ended:
476
self._textbuf += '\n'
477
elif not self._paragraph_skip_begin:
478
if self._textbuf and not self._textbuf.endswith('\n'):
479
self._textbuf += '\n'
480
self._paragraph_ended = False
481
self._paragraph_skip_begin = False
483
def paragraph_end(self):
484
if self._textbuf and not self._textbuf.endswith('\n'):
485
self._textbuf += '\n'
486
self._paragraph_ended = True
488
def wrap(self, text):
491
if self._wrap_skip_text:
493
#self._text += 'w{' + text + '}'
497
self._paragraph_ended = False
498
self._paragraph_skip_begin = False
500
# add indents after all LFs. kind of dirty to split twice though..
501
lines = text.split('\n')
504
text += '\n%s%s' % (' ' * self._indent, lines.pop(0))
506
if not self._textbuf or self._textbuf.endswith('\n'):
507
self._textbuf += ' ' * self._indent
508
self._textbuf += text
510
lines = self._textbuf.split('\n')
514
self._textbuf += lines.pop(0)
517
text += self.flush(True)
518
if len(self._textbuf) > 80 and \
519
self._textbuf.find(' ', self._indent) != -1:
521
text += self.flush(False)
524
def flush(self, addlf):
527
while len(self._textbuf) >= 80:
529
last_space = self._textbuf.rfind(' ', self._indent, 80)
531
# a long line. split at the next possible space
532
last_space = self._textbuf.find(' ', self._indent)
535
result += self._textbuf[:last_space] + '\n'
536
self._empty_line_count = 0
537
self._textbuf = ' ' * self._indent + self._textbuf[last_space + 1:]
538
self._textbuf = self._textbuf.rstrip()
540
if not self._textbuf:
543
self._empty_line_count += 1
544
if self._empty_line_count >= 2:
547
self._empty_line_count = 0
550
result += self._textbuf + '\n'
554
def text_on(self, skip_text=False):
555
if self._text is None:
556
self._text_stack.append(None)
558
self._text_stack.append(self._text)
559
#self._text_stack.append('[' + self._text + ']')
560
self._text_stack.append(self._skip_text)
561
self._text_stack.append(self._wrap_skip_text)
563
self._skip_text = skip_text
565
self._wrap_skip_text = True
568
prev_skip_text = self._skip_text
569
self._wrap_skip_text = self._text_stack.pop()
570
self._skip_text = self._text_stack.pop()
571
old_text = self._text_stack.pop()
575
if not prev_skip_text:
576
#self._text = 'o#' + old_text + '#|#' + self._text + '#'
577
self._text = old_text + self._text
579
self._text = old_text