]>
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
)