]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/samples/stxview/StructuredText/DocumentClass.py
1 ##############################################################################
3 # Zope Public License (ZPL) Version 1.0
4 # -------------------------------------
6 # Copyright (c) Digital Creations. All rights reserved.
8 # This license has been certified as Open Source(tm).
10 # Redistribution and use in source and binary forms, with or without
11 # modification, are permitted provided that the following conditions are
14 # 1. Redistributions in source code must retain the above copyright
15 # notice, this list of conditions, and the following disclaimer.
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
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.
30 # 4. All advertising materials and documentation mentioning
31 # features derived from or use of this software must display
32 # the following acknowledgement:
34 # "This product includes software developed by Digital Creations
35 # for use in the Z Object Publishing Environment
36 # (http://www.zope.org/)."
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.
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.
46 # 6. Modified redistributions of any form whatsoever must retain
47 # the following acknowledgment:
49 # "This product includes software developed by Digital Creations
50 # for use in the Z Object Publishing Environment
51 # (http://www.zope.org/)."
53 # Intact (re-)distributions of any official Zope release do not
54 # require an external acknowledgement.
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.
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
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.
84 ##############################################################################
87 from string
import split
, join
, replace
, expandtabs
, strip
, find
, rstrip
92 class StructuredTextExample(ST
.StructuredTextParagraph
):
93 """Represents a section of document with literal text, as for examples"""
95 def __init__(self
, subs
, **kw
):
97 for s
in subs
: a(s
.getNodeValue())
98 apply(ST
.StructuredTextParagraph
.__init
__,
99 (self
, join(t
,'\n\n'), ()),
102 def getColorizableTexts(self
): return ()
103 def setColorizableTexts(self
, src
): pass # never color examples
105 class StructuredTextBullet(ST
.StructuredTextParagraph
):
106 """Represents a section of a document with a title and a body"""
108 class StructuredTextNumbered(ST
.StructuredTextParagraph
):
109 """Represents a section of a document with a title and a body"""
111 class StructuredTextDescriptionTitle(ST
.StructuredTextParagraph
):
112 """Represents a section of a document with a title and a body"""
114 class StructuredTextDescriptionBody(ST
.StructuredTextParagraph
):
115 """Represents a section of a document with a title and a body"""
117 class StructuredTextDescription(ST
.StructuredTextParagraph
):
118 """Represents a section of a document with a title and a body"""
120 def __init__(self
, title
, src
, subs
, **kw
):
121 apply(ST
.StructuredTextParagraph
.__init
__, (self
, src
, subs
), kw
)
124 def getColorizableTexts(self
): return self
._title
, self
._src
125 def setColorizableTexts(self
, src
): self
._title
, self
._src
= src
127 def getChildren(self
):
128 return (StructuredTextDescriptionTitle(self
._title
),
129 StructuredTextDescriptionBody(self
._src
, self
._subs
))
131 class StructuredTextSectionTitle(ST
.StructuredTextParagraph
):
132 """Represents a section of a document with a title and a body"""
134 class StructuredTextSection(ST
.StructuredTextParagraph
):
135 """Represents a section of a document with a title and a body"""
136 def __init__(self
, src
, subs
=None, **kw
):
137 apply(ST
.StructuredTextParagraph
.__init
__,
138 (self
, StructuredTextSectionTitle(src
), subs
),
141 # a StructuredTextTable holds StructuredTextRows
142 class StructuredTextTable(ST
.StructuredTextDocument
):
144 rows is a list of lists containing tuples, which
145 represent the columns/cells in each rows.
147 rows = [[('row 1:column1',1)],[('row2:column1',1)]]
150 def __init__(self
, rows
, src
, subs
, **kw
):
151 apply(ST
.StructuredTextDocument
.__init
__,(self
,subs
),kw
)
155 self
._rows
.append(StructuredTextRow(row
,kw
))
161 return self
.getRows()
163 def getColumns(self
):
165 for row
in self
._rows
:
166 result
.append(row
.getColumns())
169 def _getColumns(self
):
170 return self
.getColumns()
172 def setColumns(self
,columns
):
173 for index
in range(len(self
._rows
)):
174 self
._rows
[index
].setColumns(columns
[index
])
176 def _setColumns(self
,columns
):
177 return self
.setColumns(columns
)
179 def getColorizableTexts(self
):
181 return a tuple where each item is a column/cell's
182 contents. The tuple, result, will be of this format.
183 ("r1 col1", "r1=col2", "r2 col1", "r2 col2")
187 for row
in self
._rows
:
188 for column
in row
.getColumns()[0]:
189 result
.append(column
.getColorizableTexts()[0])
192 def setColorizableTexts(self
,texts
):
194 texts is going to a tuple where each item is the
195 result of being mapped to the colortext function.
196 Need to insert the results appropriately into the
197 individual columns/cells
199 for row_index
in range(len(self
._rows
)):
200 for column_index
in range(len(self
._rows
[row_index
]._columns
)):
201 self
._rows
[row_index
]._columns
[column_index
].setColorizableTexts((texts
[0],))
204 def _getColorizableTexts(self
):
205 return self
.getColorizableTexts()
207 def _setColorizableTexts(self
):
208 return self
.setColorizableTexts()
210 # StructuredTextRow holds StructuredTextColumns
211 class StructuredTextRow(ST
.StructuredTextDocument
):
213 def __init__(self
,row
,kw
):
215 row is a list of tuples, where each tuple is
216 the raw text for a cell/column and the span
217 of that cell/column".
219 [('this is column one',1), ('this is column two',1)]
222 apply(ST
.StructuredTextDocument
.__init
__,(self
,[]),kw
)
225 self
._columns
.append(StructuredTextColumn(column
[0],column
[1],kw
))
227 def getColumns(self
):
228 return [self
._columns
]
230 def _getColumns(self
):
231 return [self
._columns
]
233 def setColumns(self
,columns
):
234 self
._columns
= columns
236 def _setColumns(self
,columns
):
237 return self
.setColumns(columns
)
239 # this holds the text of a table cell
240 class StructuredTextColumn(ST
.StructuredTextParagraph
):
242 StructuredTextColumn is a cell/column in a table.
243 A cell can hold multiple paragraphs. The cell
244 is either classified as a StructuredTextTableHeader
245 or StructuredTextTableData.
248 def __init__(self
,text
,span
,kw
):
249 # print "StructuredTextColumn", text, span
250 apply(ST
.StructuredTextParagraph
.__init
__,(self
,text
,[]),kw
)
259 class StructuredTextTableHeader(ST
.StructuredTextDocument
): pass
261 class StructuredTextTableData(ST
.StructuredTextDocument
): pass
263 class StructuredTextMarkup(STDOM
.Element
):
265 def __init__(self
, v
, **kw
):
267 self
._attributes
=kw
.keys()
268 for k
, v
in kw
.items(): setattr(self
, k
, v
)
270 def getChildren(self
, type=type, lt
=type([])):
272 if type(v
) is not lt
: v
=[v
]
275 def getColorizableTexts(self
): return self
._value
,
276 def setColorizableTexts(self
, v
): self
._value
=v
[0]
279 return '%s(%s)' % (self
.__class
__.__name
__, `self
._value`
)
281 class StructuredTextLiteral(StructuredTextMarkup
):
282 def getColorizableTexts(self
): return ()
283 def setColorizableTexts(self
, v
): pass
285 class StructuredTextEmphasis(StructuredTextMarkup
): pass
287 class StructuredTextStrong(StructuredTextMarkup
): pass
289 class StructuredTextInnerLink(StructuredTextMarkup
): pass
291 class StructuredTextNamedLink(StructuredTextMarkup
): pass
293 class StructuredTextUnderline(StructuredTextMarkup
): pass
295 class StructuredTextSGML(StructuredTextMarkup
): pass
297 class StructuredTextLink(StructuredTextMarkup
): pass
301 Class instance calls [ex.=> x()] require a structured text
302 structure. Doc will then parse each paragraph in the structure
303 and will find the special structures within each paragraph.
304 Each special structure will be stored as an instance. Special
305 structures within another special structure are stored within
307 EX : '-underline this-' => would be turned into an underline
308 instance. '-underline **this**' would be stored as an underline
309 instance with a strong instance stored in its string
332 def __call__(self
, doc
):
333 if type(doc
) is type(''):
334 doc
=ST
.StructuredText(doc
)
335 doc
.setSubparagraphs(self
.color_paragraphs(
336 doc
.getSubparagraphs()))
338 doc
=ST
.StructuredTextDocument(self
.color_paragraphs(
339 doc
.getSubparagraphs()))
342 def parse(self
, raw_string
, text_type
,
343 type=type, st
=type(''), lt
=type([])):
346 Parse accepts a raw_string, an expr to test the raw_string,
347 and the raw_string's subparagraphs.
349 Parse will continue to search through raw_string until
350 all instances of expr in raw_string are found.
352 If no instances of expr are found, raw_string is returned.
353 Otherwise a list of substrings and instances is returned
356 tmp
= [] # the list to be returned if raw_string is split
359 if type(text_type
) is st
: text_type
=getattr(self
, text_type
)
362 t
= text_type(raw_string
)
364 #an instance of expr was found
367 if start
: append(raw_string
[0:start
])
371 # if we get a string back, add it to text to be parsed
372 raw_string
= t
+raw_string
[end
:len(raw_string
)]
375 # is we get a list, append it's elements
378 # normal case, an object
380 raw_string
= raw_string
[end
:len(raw_string
)]
382 if not tmp
: return raw_string
# nothing found
384 if raw_string
: append(raw_string
)
385 elif len(tmp
)==1: return tmp
[0]
390 def color_text(self
, str, types
=None):
391 """Search the paragraph for each special structure
393 if types
is None: types
=self
.text_types
395 for text_type
in types
:
397 if type(str) is StringType
:
398 str = self
.parse(str, text_type
)
399 elif type(str) is ListType
:
402 if type(s
) is StringType
:
403 s
=self
.parse(s
, text_type
)
404 if type(s
) is ListType
: r
[len(r
):]=s
407 s
.setColorizableTexts(
409 s
.getColorizableTexts()
414 r
=[]; a
=r
.append
; color
=self
.color_text
415 for s
in str.getColorizableTexts():
416 color(s
, (text_type
,))
419 str.setColorizableTexts(r
)
423 def color_paragraphs(self
, raw_paragraphs
,
424 type=type, sequence_types
=(type([]), type(())),
427 for paragraph
in raw_paragraphs
:
428 #print type(paragraph)
429 if paragraph
.getNodeName() != 'StructuredTextParagraph':
430 result
.append(paragraph
)
433 for pt
in self
.paragraph_types
:
435 # grab the corresponding function
437 # evaluate the paragraph
440 if type(r
) not in sequence_types
:
443 for paragraph
in new_paragraphs
:
444 paragraph
.setSubparagraphs(self
.color_paragraphs(paragraph
.getSubparagraphs()))
447 new_paragraphs
=ST
.StructuredTextParagraph(paragraph
.getColorizableTexts()[0],
448 self
.color_paragraphs(paragraph
.getSubparagraphs()),
449 indent
=paragraph
.indent
),
451 # color the inline StructuredText types
452 # for each StructuredTextParagraph
453 for paragraph
in new_paragraphs
:
455 if paragraph
.getNodeName() is "StructuredTextTable":
456 #print "we have a table"
457 cells
= paragraph
.getColumns()
458 text
= paragraph
.getColorizableTexts()
459 text
= map(ST
.StructuredText
,text
)
460 text
= map(self
.__call
__,text
)
461 #for index in range(len(text)):
462 # text[index].setColorizableTexts(map(self.color_text,text[index].getColorizableTexts()))
463 paragraph
.setColorizableTexts(text
)
465 paragraph
.setColorizableTexts(
467 paragraph
.getColorizableTexts()
469 result
.append(paragraph
)
473 def doc_table(self
, paragraph
, expr
= re
.compile('\s*\|[-]+\|').match
):
474 text
= paragraph
.getColorizableTexts()[0]
477 subs
= paragraph
.getSubparagraphs()
483 rows
= split(text
,'\n')
489 TDdivider
= re
.compile("[\-]+").match
490 THdivider
= re
.compile("[\=]+").match
492 # find where the column markers are located
493 col
= re
.compile('\|').search
495 rows
= split(text
,'\n')
496 for row
in range(len(rows
)):
497 rows
[row
] = strip(rows
[row
])
501 tmp
= row
[1:len(tmp
)-1] # remove leading and trailing |
505 start
,end
= col(tmp
).span()
506 if not start
+offset
in spans
:
507 spans
.append(start
+ offset
)
508 COLS
.append((tmp
[0:start
],start
+offset
))
509 tmp
= " " + tmp
[end
:]
510 offset
= offset
+ (start
)
511 if not offset
+len(tmp
) in spans
:
512 spans
.append(offset
+len(tmp
))
513 COLS
.append((tmp
,offset
+len(tmp
)))
519 ROWS
= ROWS
[1:len(ROWS
)]
521 # find each column span
531 cur
= 1 # the current column span
533 C
= [] # holds the span of each cell
544 # make rows contain the cell's text and the span
546 for index
in range(len(C
)):
547 for i
in range(len(C
[index
])):
548 ROWS
[index
][i
] = (ROWS
[index
][i
][0],C
[index
][i
])
551 # now munge the table cells together
555 for index
in range(len(row
)):
557 COLS
= range(len(row
))
558 for i
in range(len(COLS
)):
560 if TDdivider(row
[index
][0]) or THdivider(row
[index
][0]):
564 COLS
[index
][0] = COLS
[index
][0] + rstrip(row
[index
][0]) + "\n"
565 COLS
[index
][1] = row
[index
][1]
566 return StructuredTextTable(ROWS
,text
,subs
,indent
=paragraph
.indent
)
568 def doc_bullet(self
, paragraph
, expr
= re
.compile('\s*[-*o]\s+').match
):
569 top
=paragraph
.getColorizableTexts()[0]
575 subs
=paragraph
.getSubparagraphs()
577 subs
=[StructuredTextExample(subs
)]
579 return StructuredTextBullet(top
[m
.span()[1]:], subs
,
580 indent
=paragraph
.indent
,
581 bullet
=top
[:m
.span()[1]]
586 expr
= re
.compile('(\s*[a-zA-Z]+\.)|(\s*[0-9]+\.)|(\s*[0-9]+\s+)').match
):
588 # This is the old expression. It had a nasty habit
589 # of grabbing paragraphs that began with a single
590 # letter word even if there was no following period.
592 #expr = re.compile('\s*'
593 # '(([a-zA-Z]|[0-9]+|[ivxlcdmIVXLCDM]+)\.)*'
594 # '([a-zA-Z]|[0-9]+|[ivxlcdmIVXLCDM]+)\.?'
597 top
=paragraph
.getColorizableTexts()[0]
599 if not m
: return None
600 subs
=paragraph
.getSubparagraphs()
602 subs
=[StructuredTextExample(subs
)]
604 return StructuredTextNumbered(top
[m
.span()[1]:], subs
,
605 indent
=paragraph
.indent
,
606 number
=top
[:m
.span()[1]])
610 delim
= re
.compile('\s+--\s+').search
,
611 nb
=re
.compile(r
'[^\0- ]').search
,
614 top
=paragraph
.getColorizableTexts()[0]
616 if not d
: return None
617 start
, end
= d
.span()
619 if find(title
, '\n') >= 0: return None
620 if not nb(title
): return None
624 subs
=paragraph
.getSubparagraphs()
626 subs
=[StructuredTextExample(subs
)]
629 return StructuredTextDescription(
631 indent
=paragraph
.indent
,
634 def doc_header(self
, paragraph
,
635 expr
= re
.compile('[ a-zA-Z0-9.:/,-_*<>\?\'\"]+').match
637 subs
=paragraph
.getSubparagraphs()
638 if not subs
: return None
639 top
=paragraph
.getColorizableTexts()[0]
640 if not strip(top
): return None
642 subs
=StructuredTextExample(subs
)
643 if strip(top
)=='::': return subs
644 return ST
.StructuredTextParagraph(
645 top
[:-1], [subs
], indent
=paragraph
.indent
)
647 if find(top
,'\n') >= 0: return None
648 return StructuredTextSection(top
, subs
, indent
=paragraph
.indent
)
654 "([^ \t\n\r\f\v']|[^ \t\n\r\f\v'][^\n']*[^ \t\n\r\f\v'])" # contents
655 "'(?:\s|[,.;:!?]|$)" # close
660 start
, end
= r
.span(1)
661 return (StructuredTextLiteral(s
[start
:end
]), start
-1, end
+1)
667 expr
= re
.compile('\s*\*([ \na-zA-Z0-9.:/;,\'\"\?]+)\*(?!\*|-)').search
672 start
, end
= r
.span(1)
673 return (StructuredTextEmphasis(s
[start
:end
]), start
-1, end
+1)
677 def doc_inner_link(self
,
679 expr1
= re
.compile("\.\.\s*").search
,
680 expr2
= re
.compile("\[[a-zA-Z0-9]+\]").search
):
682 # make sure we dont grab a named link
683 if expr2(s
) and expr1(s
):
684 start1
,end1
= expr1(s
).span()
685 start2
,end2
= expr2(s
).span()
687 # uh-oh, looks like a named link
690 # the .. is somewhere else, ignore it
691 return (StructuredTextInnerLink(s
[start2
+1,end2
-1],start2
,end2
))
693 elif expr2(s
) and not expr1(s
):
694 start
,end
= expr2(s
).span()
695 return (StructuredTextInnerLink(s
[start
+1:end
-1]),start
,end
)
698 def doc_named_link(self
,
700 expr
=re
.compile("(\.\.\s)(\[[a-zA-Z0-9]+\])").search
):
704 start
,end
= result
.span(2)
706 str = strip(s
[a
:b
]) + s
[start
:end
]
707 st
,en
= result
.span()
708 return (StructuredTextNamedLink(str),st
,en
)
709 #return (StructuredTextNamedLink(s[st:en]),st,en)
712 def doc_underline(self
,
714 expr
=re
.compile("\_([a-zA-Z0-9\s\.,\?]+)\_").search
):
718 start
,end
= result
.span(1)
720 return (StructuredTextUnderline(s
[start
:end
]),st
,e
)
726 expr
= re
.compile('\s*\*\*([ \na-zA-Z0-9.:/;\-,!\?\'\"]+)\*\*').search
731 start
, end
= r
.span(1)
732 return (StructuredTextStrong(s
[start
:end
]), start
-2, end
+2)
739 expr1
= re
.compile("(\"[ a-zA-Z0-9\n\-\.\,\;\(\)\/\:\/]+\")(:)([a-zA-Z0-9\:\/\.\~\-]+)([,]*\s*)").search
,
740 expr2
= re
.compile('(\"[ a-zA-Z0-9\n\-\.\:\;\(\)\/]+\")([,]+\s+)([a-zA-Z0-9\@\.\,\?\!\/\:\;\-\#]+)(\s*)').search
):
742 punctuation
= re
.compile("[\,\.\?\!\;]+").match
743 r
=expr1(s
) or expr2(s
)
746 # need to grab the href part and the
751 name
= replace(name
,'"','',2)
754 if punctuation(s
[end
-1:end
]):
759 # name is the href title, link is the target
761 return (StructuredTextLink(name
, href
=link
),
764 #return (StructuredTextLink(s[start:end], href=s[start:end]),
769 def doc_sgml(self
,s
,expr
=re
.compile("\<[a-zA-Z0-9\.\=\'\"\:\/\-\#\+\s]+\>").search
):
771 SGML text is ignored and outputed as-is
777 return (StructuredTextSGML(text
),start
,end
)