]> git.saurik.com Git - wxWidgets.git/blame - wxPython/samples/stxview/StructuredText/ClassicDocumentClass.py
implement wxColourDialog::Move() (patch 548048)
[wxWidgets.git] / wxPython / samples / stxview / StructuredText / ClassicDocumentClass.py
CommitLineData
c12bc4de 1##############################################################################
ddfc587a 2#
c12bc4de
RD
3# Zope Public License (ZPL) Version 1.0
4# -------------------------------------
ddfc587a 5#
c12bc4de 6# Copyright (c) Digital Creations. All rights reserved.
ddfc587a 7#
c12bc4de 8# This license has been certified as Open Source(tm).
ddfc587a 9#
c12bc4de
RD
10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions are
12# met:
ddfc587a 13#
c12bc4de
RD
14# 1. Redistributions in source code must retain the above copyright
15# notice, this list of conditions, and the following disclaimer.
ddfc587a 16#
c12bc4de
RD
17# 2. Redistributions in binary form must reproduce the above copyright
18# notice, this list of conditions, and the following disclaimer in
19# the documentation and/or other materials provided with the
20# distribution.
ddfc587a 21#
c12bc4de
RD
22# 3. Digital Creations requests that attribution be given to Zope
23# in any manner possible. Zope includes a "Powered by Zope"
24# button that is installed by default. While it is not a license
25# violation to remove this button, it is requested that the
26# attribution remain. A significant investment has been put
27# into Zope, and this effort will continue if the Zope community
28# continues to grow. This is one way to assure that growth.
ddfc587a 29#
c12bc4de
RD
30# 4. All advertising materials and documentation mentioning
31# features derived from or use of this software must display
32# the following acknowledgement:
ddfc587a 33#
c12bc4de
RD
34# "This product includes software developed by Digital Creations
35# for use in the Z Object Publishing Environment
36# (http://www.zope.org/)."
ddfc587a 37#
c12bc4de
RD
38# In the event that the product being advertised includes an
39# intact Zope distribution (with copyright and license included)
40# then this clause is waived.
ddfc587a 41#
c12bc4de
RD
42# 5. Names associated with Zope or Digital Creations must not be used to
43# endorse or promote products derived from this software without
44# prior written permission from Digital Creations.
ddfc587a 45#
c12bc4de
RD
46# 6. Modified redistributions of any form whatsoever must retain
47# the following acknowledgment:
ddfc587a 48#
c12bc4de
RD
49# "This product includes software developed by Digital Creations
50# for use in the Z Object Publishing Environment
51# (http://www.zope.org/)."
ddfc587a 52#
c12bc4de
RD
53# Intact (re-)distributions of any official Zope release do not
54# require an external acknowledgement.
ddfc587a 55#
c12bc4de
RD
56# 7. Modifications are encouraged but must be packaged separately as
57# patches to official Zope releases. Distributions that do not
58# clearly separate the patches from the original work must be clearly
59# labeled as unofficial distributions. Modifications which do not
60# carry the name Zope may be packaged in any form, as long as they
61# conform to all of the clauses above.
ddfc587a
RD
62#
63#
c12bc4de 64# Disclaimer
ddfc587a 65#
c12bc4de
RD
66# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
67# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
69# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
70# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
71# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
72# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
73# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
74# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
75# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
76# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
77# SUCH DAMAGE.
ddfc587a
RD
78#
79#
c12bc4de
RD
80# This software consists of contributions made by Digital Creations and
81# many individuals on behalf of Digital Creations. Specific
82# attributions are listed in the accompanying credits file.
ddfc587a 83#
c12bc4de
RD
84##############################################################################
85
86import re, ST, STDOM
87from string import split, join, replace, expandtabs, strip, find
ddfc587a 88from STletters import letters,lettpunc,punctuations
c12bc4de
RD
89
90StringType=type('')
91ListType=type([])
92
93class StructuredTextExample(ST.StructuredTextParagraph):
94 """Represents a section of document with literal text, as for examples"""
95
96 def __init__(self, subs, **kw):
97 t=[]; a=t.append
98 for s in subs: a(s.getNodeValue())
99 apply(ST.StructuredTextParagraph.__init__,
100 (self, join(t,'\n\n'), ()),
101 kw)
102
103 def getColorizableTexts(self): return ()
104 def setColorizableTexts(self, src): pass # never color examples
105
106class StructuredTextBullet(ST.StructuredTextParagraph):
107 """Represents a section of a document with a title and a body"""
108
109class StructuredTextNumbered(ST.StructuredTextParagraph):
110 """Represents a section of a document with a title and a body"""
111
112class StructuredTextDescriptionTitle(ST.StructuredTextParagraph):
113 """Represents a section of a document with a title and a body"""
114
115class StructuredTextDescriptionBody(ST.StructuredTextParagraph):
116 """Represents a section of a document with a title and a body"""
117
118class StructuredTextDescription(ST.StructuredTextParagraph):
119 """Represents a section of a document with a title and a body"""
ddfc587a 120
c12bc4de
RD
121 def __init__(self, title, src, subs, **kw):
122 apply(ST.StructuredTextParagraph.__init__, (self, src, subs), kw)
123 self._title=title
124
125 def getColorizableTexts(self): return self._title, self._src
126 def setColorizableTexts(self, src): self._title, self._src = src
127
128 def getChildren(self):
129 return (StructuredTextDescriptionTitle(self._title),
130 StructuredTextDescriptionBody(self._src, self._subs))
131
132class StructuredTextSectionTitle(ST.StructuredTextParagraph):
133 """Represents a section of a document with a title and a body"""
134
135class StructuredTextSection(ST.StructuredTextParagraph):
136 """Represents a section of a document with a title and a body"""
137 def __init__(self, src, subs=None, **kw):
138 apply(ST.StructuredTextParagraph.__init__,
139 (self, StructuredTextSectionTitle(src), subs),
140 kw)
141
ddfc587a
RD
142 def getColorizableTexts(self):
143 return self._src.getColorizableTexts()
144
145 def setColorizableTexts(self,src):
146 self._src.setColorizableTexts(src)
147
c12bc4de
RD
148# a StructuredTextTable holds StructuredTextRows
149class StructuredTextTable(ST.StructuredTextDocument):
150 """
151 rows is a list of lists containing tuples, which
152 represent the columns/cells in each rows.
153 EX
154 rows = [[('row 1:column1',1)],[('row2:column1',1)]]
155 """
ddfc587a 156
c12bc4de
RD
157 def __init__(self, rows, src, subs, **kw):
158 apply(ST.StructuredTextDocument.__init__,(self,subs),kw)
159 self._rows = []
160 for row in rows:
161 if row:
162 self._rows.append(StructuredTextRow(row,kw))
ddfc587a 163
c12bc4de
RD
164 def getRows(self):
165 return [self._rows]
ddfc587a 166
c12bc4de
RD
167 def _getRows(self):
168 return self.getRows()
ddfc587a 169
c12bc4de
RD
170 def getColorizableTexts(self):
171 """
172 return a tuple where each item is a column/cell's
173 contents. The tuple, result, will be of this format.
174 ("r1 col1", "r1=col2", "r2 col1", "r2 col2")
175 """
ddfc587a 176
c12bc4de
RD
177 #result = ()
178 result = []
179 for row in self._rows:
180 for column in row.getColumns()[0]:
181 #result = result[:] + (column.getColorizableTexts(),)
182 result.append(column.getColorizableTexts()[0])
183 return result
ddfc587a 184
c12bc4de
RD
185 def setColorizableTexts(self,texts):
186 """
187 texts is going to a tuple where each item is the
188 result of being mapped to the colortext function.
189 Need to insert the results appropriately into the
190 individual columns/cells
191 """
192 for row_index in range(len(self._rows)):
193 for column_index in range(len(self._rows[row_index]._columns)):
194 self._rows[row_index]._columns[column_index].setColorizableTexts((texts[0],))
195 texts = texts[1:]
ddfc587a 196
c12bc4de
RD
197 def _getColorizableTexts(self):
198 return self.getColorizableTexts()
ddfc587a 199
c12bc4de
RD
200 def _setColorizableTexts(self):
201 return self.setColorizableTexts()
ddfc587a 202
c12bc4de
RD
203# StructuredTextRow holds StructuredTextColumns
204class StructuredTextRow(ST.StructuredTextDocument):
ddfc587a 205
c12bc4de
RD
206 def __init__(self,row,kw):
207 """
208 row is a list of tuples, where each tuple is
209 the raw text for a cell/column and the span
ddfc587a
RD
210 of that cell/column".
211 EX
c12bc4de
RD
212 [('this is column one',1), ('this is column two',1)]
213 """
ddfc587a 214
c12bc4de
RD
215 apply(ST.StructuredTextDocument.__init__,(self,[]),kw)
216 self._columns = []
ddfc587a 217 for column in row:
c12bc4de
RD
218 self._columns.append(StructuredTextColumn(column[0],column[1],kw))
219 def getColumns(self):
220 return [self._columns]
221
222 def _getColumns(self):
223 return [self._columns]
ddfc587a 224
c12bc4de
RD
225# this holds the raw text of a table cell
226class StructuredTextColumn(ST.StructuredTextParagraph):
227 """
228 StructuredTextColumn is a cell/column in a table.
229 This contains the actual text of a column and is
230 thus a StructuredTextParagraph. A StructuredTextColumn
231 also holds the span of its column
232 """
ddfc587a 233
c12bc4de
RD
234 def __init__(self,text,span,kw):
235 apply(ST.StructuredTextParagraph.__init__,(self,text,[]),kw)
236 self._span = span
ddfc587a 237
c12bc4de
RD
238 def getSpan(self):
239 return self._span
ddfc587a 240
c12bc4de
RD
241 def _getSpan(self):
242 return self._span
ddfc587a 243
c12bc4de 244class StructuredTextMarkup(STDOM.Element):
ddfc587a 245
c12bc4de
RD
246 def __init__(self, v, **kw):
247 self._value=v
248 self._attributes=kw.keys()
249 for k, v in kw.items(): setattr(self, k, v)
250
251 def getChildren(self, type=type, lt=type([])):
252 v=self._value
253 if type(v) is not lt: v=[v]
254 return v
255
256 def getColorizableTexts(self): return self._value,
257 def setColorizableTexts(self, v): self._value=v[0]
258
259 def __repr__(self):
260 return '%s(%s)' % (self.__class__.__name__, `self._value`)
261
262class StructuredTextLiteral(StructuredTextMarkup):
263 def getColorizableTexts(self): return ()
264 def setColorizableTexts(self, v): pass
265
266class StructuredTextEmphasis(StructuredTextMarkup): pass
267
268class StructuredTextStrong(StructuredTextMarkup): pass
269
270class StructuredTextInnerLink(StructuredTextMarkup): pass
271
272class StructuredTextNamedLink(StructuredTextMarkup): pass
273
274class StructuredTextUnderline(StructuredTextMarkup): pass
275
276class StructuredTextLink(StructuredTextMarkup):
277 "A simple hyperlink"
278
ddfc587a 279class DocumentClass:
c12bc4de
RD
280 """
281 Class instance calls [ex.=> x()] require a structured text
282 structure. Doc will then parse each paragraph in the structure
283 and will find the special structures within each paragraph.
284 Each special structure will be stored as an instance. Special
285 structures within another special structure are stored within
286 the 'top' structure
287 EX : '-underline this-' => would be turned into an underline
288 instance. '-underline **this**' would be stored as an underline
289 instance with a strong instance stored in its string
290 """
291
292 paragraph_types = [
293 'doc_bullet',
294 'doc_numbered',
295 'doc_description',
296 'doc_header',
297 'doc_table',
298 ]
299
300 text_types = [
301 'doc_href',
302 'doc_strong',
303 'doc_emphasize',
304 'doc_literal',
305 'doc_inner_link',
306 'doc_named_link',
307 'doc_underline',
308 ]
309
310 def __call__(self, doc):
311 if type(doc) is type(''):
312 doc=ST.StructuredText(doc)
313 doc.setSubparagraphs(self.color_paragraphs(
314 doc.getSubparagraphs()))
315 else:
316 doc=ST.StructuredTextDocument(self.color_paragraphs(
317 doc.getSubparagraphs()))
318 return doc
319
320 def parse(self, raw_string, text_type,
321 type=type, st=type(''), lt=type([])):
322
323 """
324 Parse accepts a raw_string, an expr to test the raw_string,
325 and the raw_string's subparagraphs.
ddfc587a
RD
326
327 Parse will continue to search through raw_string until
328 all instances of expr in raw_string are found.
329
c12bc4de
RD
330 If no instances of expr are found, raw_string is returned.
331 Otherwise a list of substrings and instances is returned
332 """
333
334 tmp = [] # the list to be returned if raw_string is split
335 append=tmp.append
336
337 if type(text_type) is st: text_type=getattr(self, text_type)
338
339 while 1:
340 t = text_type(raw_string)
341 if not t: break
342 #an instance of expr was found
343 t, start, end = t
344
345 if start: append(raw_string[0:start])
346
347 tt=type(t)
348 if tt is st:
349 # if we get a string back, add it to text to be parsed
350 raw_string = t+raw_string[end:len(raw_string)]
351 else:
352 if tt is lt:
353 # is we get a list, append it's elements
354 tmp[len(tmp):]=t
355 else:
356 # normal case, an object
357 append(t)
358 raw_string = raw_string[end:len(raw_string)]
359
360 if not tmp: return raw_string # nothing found
ddfc587a 361
c12bc4de
RD
362 if raw_string: append(raw_string)
363 elif len(tmp)==1: return tmp[0]
ddfc587a 364
c12bc4de
RD
365 return tmp
366
367
368 def color_text(self, str, types=None):
369 """Search the paragraph for each special structure
370 """
371 if types is None: types=self.text_types
372
373 for text_type in types:
374
375 if type(str) is StringType:
376 str = self.parse(str, text_type)
377 elif type(str) is ListType:
378 r=[]; a=r.append
379 for s in str:
380 if type(s) is StringType:
381 s=self.parse(s, text_type)
382 if type(s) is ListType: r[len(r):]=s
383 else: a(s)
384 else:
385 s.setColorizableTexts(
386 map(self.color_text,
387 s.getColorizableTexts()
388 ))
389 a(s)
390 str=r
391 else:
392 r=[]; a=r.append; color=self.color_text
393 for s in str.getColorizableTexts():
394 color(s, (text_type,))
395 a(s)
ddfc587a 396
c12bc4de
RD
397 str.setColorizableTexts(r)
398
399 return str
400
401 def color_paragraphs(self, raw_paragraphs,
402 type=type, sequence_types=(type([]), type(())),
403 st=type('')):
404 result=[]
405 for paragraph in raw_paragraphs:
ddfc587a 406
c12bc4de
RD
407 if paragraph.getNodeName() != 'StructuredTextParagraph':
408 result.append(paragraph)
409 continue
ddfc587a 410
c12bc4de
RD
411 for pt in self.paragraph_types:
412 if type(pt) is st:
413 # grab the corresponding function
414 pt=getattr(self, pt)
415 # evaluate the paragraph
416 r=pt(paragraph)
417 if r:
418 if type(r) not in sequence_types:
419 r=r,
420 new_paragraphs=r
421 for paragraph in new_paragraphs:
422 paragraph.setSubparagraphs(self.color_paragraphs(paragraph.getSubparagraphs()))
423 break
424 else:
425 new_paragraphs=ST.StructuredTextParagraph(paragraph.getColorizableTexts()[0],
426 self.color_paragraphs(paragraph.getSubparagraphs()),
427 indent=paragraph.indent),
428 # color the inline StructuredText types
429 # for each StructuredTextParagraph
430 for paragraph in new_paragraphs:
431 paragraph.setColorizableTexts(
432 map(self.color_text,
433 paragraph.getColorizableTexts()
434 ))
435 result.append(paragraph)
436
437 return result
ddfc587a 438
c12bc4de 439 def doc_table(self,paragraph, expr = re.compile('(\s*)([||]+)').match):
ddfc587a 440 #print "paragraph=>", type(paragraph), paragraph, paragraph._src
c12bc4de
RD
441 text = paragraph.getColorizableTexts()[0]
442 m = expr(text)
ddfc587a 443
c12bc4de
RD
444 if not (m):
445 return None
446 rows = []
ddfc587a 447
c12bc4de
RD
448 # initial split
449 for row in split(text,"\n"):
ddfc587a
RD
450 rows.append(row)
451
c12bc4de
RD
452 # clean up the rows
453 for index in range(len(rows)):
454 tmp = []
455 rows[index] = strip(rows[index])
456 l = len(rows[index])-2
457 result = split(rows[index][:l],"||")
458 for text in result:
459 if text:
460 tmp.append(text)
461 tmp.append('')
462 else:
463 tmp.append(text)
464 rows[index] = tmp
465 # remove trailing '''s
466 for index in range(len(rows)):
467 l = len(rows[index])-1
468 rows[index] = rows[index][:l]
ddfc587a 469
c12bc4de
RD
470 result = []
471 for row in rows:
472 cspan = 0
473 tmp = []
474 for item in row:
475 if item:
ddfc587a 476 tmp.append((item,cspan))
c12bc4de
RD
477 cspan = 0
478 else:
479 cspan = cspan + 1
480 result.append(tmp)
ddfc587a 481
c12bc4de
RD
482 subs = paragraph.getSubparagraphs()
483 indent=paragraph.indent
484 return StructuredTextTable(result,text,subs,indent=paragraph.indent)
ddfc587a 485
c12bc4de
RD
486 def doc_bullet(self, paragraph, expr = re.compile('\s*[-*o]\s+').match):
487 top=paragraph.getColorizableTexts()[0]
488 m=expr(top)
489
490 if not m:
491 return None
ddfc587a 492
c12bc4de
RD
493 subs=paragraph.getSubparagraphs()
494 if top[-2:]=='::':
495 subs=[StructuredTextExample(subs)]
496 top=top[:-1]
497 return StructuredTextBullet(top[m.span()[1]:], subs,
498 indent=paragraph.indent,
499 bullet=top[:m.span()[1]]
500 )
501
502 def doc_numbered(
503 self, paragraph,
ddfc587a
RD
504 expr = re.compile('(\s*[%s]+\.)|(\s*[0-9]+\.)|(\s*[0-9]+\s+)' % letters).match):
505
c12bc4de
RD
506 # This is the old expression. It had a nasty habit
507 # of grabbing paragraphs that began with a single
508 # letter word even if there was no following period.
ddfc587a 509
c12bc4de
RD
510 #expr = re.compile('\s*'
511 # '(([a-zA-Z]|[0-9]+|[ivxlcdmIVXLCDM]+)\.)*'
512 # '([a-zA-Z]|[0-9]+|[ivxlcdmIVXLCDM]+)\.?'
513 # '\s+').match):
ddfc587a 514
c12bc4de
RD
515 top=paragraph.getColorizableTexts()[0]
516 m=expr(top)
517 if not m: return None
518 subs=paragraph.getSubparagraphs()
519 if top[-2:]=='::':
520 subs=[StructuredTextExample(subs)]
521 top=top[:-1]
522 return StructuredTextNumbered(top[m.span()[1]:], subs,
523 indent=paragraph.indent,
524 number=top[:m.span()[1]])
525
526 def doc_description(
527 self, paragraph,
528 delim = re.compile('\s+--\s+').search,
ddfc587a 529 nb=re.compile(r'[^\000- ]').search,
c12bc4de
RD
530 ):
531
532 top=paragraph.getColorizableTexts()[0]
533 d=delim(top)
534 if not d: return None
535 start, end = d.span()
536 title=top[:start]
537 if find(title, '\n') >= 0: return None
538 if not nb(title): return None
539 d=top[start:end]
540 top=top[end:]
541
542 subs=paragraph.getSubparagraphs()
543 if top[-2:]=='::':
544 subs=[StructuredTextExample(subs)]
545 top=top[:-1]
546
547 return StructuredTextDescription(
548 title, top, subs,
549 indent=paragraph.indent,
550 delim=d)
551
552 def doc_header(self, paragraph,
ddfc587a 553 expr = re.compile('[ %s0-9.:/,-_*<>\?\'\"]+' % letters).match
c12bc4de
RD
554 ):
555 subs=paragraph.getSubparagraphs()
556 if not subs: return None
557 top=paragraph.getColorizableTexts()[0]
558 if not strip(top): return None
559 if top[-2:]=='::':
560 subs=StructuredTextExample(subs)
561 if strip(top)=='::': return subs
562 return ST.StructuredTextParagraph(top[:-1],
563 [subs],
564 indent=paragraph.indent,
565 level=paragraph.level)
566
567 if find(top,'\n') >= 0: return None
568 return StructuredTextSection(top, subs, indent=paragraph.indent, level=paragraph.level)
569
570 def doc_literal(
571 self, s,
572 expr=re.compile(
ddfc587a 573 "(?:\s|^)'" # open
c12bc4de 574 "([^ \t\n\r\f\v']|[^ \t\n\r\f\v'][^\n']*[^ \t\n\r\f\v'])" # contents
ddfc587a 575 "'(?:\s|[,.;:!?]|$)" # close
c12bc4de 576 ).search):
ddfc587a 577
c12bc4de
RD
578 r=expr(s)
579 if r:
580 start, end = r.span(1)
581 return (StructuredTextLiteral(s[start:end]), start-1, end+1)
582 else:
583 return None
584
585 def doc_emphasize(
586 self, s,
ddfc587a 587 expr = re.compile('\s*\*([ \n%s0-9]+)\*(?!\*|-)' % lettpunc).search
c12bc4de
RD
588 ):
589
590 r=expr(s)
591 if r:
592 start, end = r.span(1)
593 return (StructuredTextEmphasis(s[start:end]), start-1, end+1)
594 else:
595 return None
ddfc587a 596
c12bc4de
RD
597 def doc_inner_link(self,
598 s,
599 expr1 = re.compile("\.\.\s*").search,
ddfc587a
RD
600 expr2 = re.compile("\[[%s0-9]+\]" % letters).search):
601
c12bc4de
RD
602 # make sure we dont grab a named link
603 if expr2(s) and expr1(s):
604 start1,end1 = expr1(s).span()
605 start2,end2 = expr2(s).span()
606 if end1 == start2:
607 # uh-oh, looks like a named link
608 return None
609 else:
610 # the .. is somewhere else, ignore it
ddfc587a 611 return (StructuredTextInnerLink(s[start2+1:end2-1]),start2,end2)
c12bc4de
RD
612 return None
613 elif expr2(s) and not expr1(s):
614 start,end = expr2(s).span()
615 return (StructuredTextInnerLink(s[start+1:end-1]),start,end)
616 return None
ddfc587a 617
c12bc4de
RD
618 def doc_named_link(self,
619 s,
ddfc587a
RD
620 expr=re.compile("(\.\.\s)(\[[%s0-9]+\])" % letters).search):
621
c12bc4de
RD
622 result = expr(s)
623 if result:
624 start,end = result.span(2)
625 a,b = result.span(1)
626 str = strip(s[a:b]) + s[start:end]
627 str = s[start+1:end-1]
628 st,en = result.span()
629 return (StructuredTextNamedLink(str),st,en)
630 #return (StructuredTextNamedLink(s[st:en]),st,en)
631 return None
ddfc587a 632
c12bc4de
RD
633 def doc_underline(self,
634 s,
ddfc587a
RD
635 expr=re.compile("\s+\_([0-9%s ]+)\_" % lettpunc).search):
636
c12bc4de
RD
637 result = expr(s)
638 if result:
639 start,end = result.span(1)
640 st,e = result.span()
641 return (StructuredTextUnderline(s[start:end]),st,e)
642 else:
643 return None
ddfc587a
RD
644
645 def doc_strong(self,
c12bc4de 646 s,
ddfc587a 647 expr = re.compile('\s*\*\*([ \n%s0-9]+)\*\*' % lettpunc).search
c12bc4de
RD
648 ):
649
650 r=expr(s)
651 if r:
652 start, end = r.span(1)
653 return (StructuredTextStrong(s[start:end]), start-2, end+2)
654 else:
655 return None
ddfc587a 656
c12bc4de 657 def doc_href(
ddfc587a 658
c12bc4de 659 self, s,
ddfc587a
RD
660 expr1 = re.compile("(\"[ %s0-9\n\-\.\,\;\(\)\/\:\/\*\']+\")(:)([a-zA-Z0-9\@\.\,\?\!\/\:\;\-\#\~]+)([,]*\s*)" % letters).search,
661 expr2 = re.compile('(\"[ %s0-9\n\-\.\:\;\(\)\/\*\']+\")([,]+\s+)([a-zA-Z0-9\@\.\,\?\!\/\:\;\-\#\~]+)(\s*)' % letters).search):
662
c12bc4de
RD
663 r=expr1(s) or expr2(s)
664
665 if r:
666 # need to grab the href part and the
667 # beginning part
ddfc587a 668
c12bc4de
RD
669 start,e = r.span(1)
670 name = s[start:e]
671 name = replace(name,'"','',2)
c12bc4de 672 st,end = r.span(3)
ddfc587a
RD
673
674 if s[end-1:end] in punctuations: end-=1
c12bc4de 675 link = s[st:end]
ddfc587a 676
c12bc4de
RD
677 # name is the href title, link is the target
678 # of the href
679 return (StructuredTextLink(name, href=link),
680 start, end)
ddfc587a
RD
681
682
c12bc4de
RD
683 else:
684 return None