diff --git a/wxPython/MANIFEST.in b/wxPython/MANIFEST.in index 11ad108fbd..0dbd7d830c 100644 --- a/wxPython/MANIFEST.in +++ b/wxPython/MANIFEST.in @@ -44,11 +44,6 @@ include samples/doodle/*.txt include samples/doodle/*.py include samples/doodle/*.iss include samples/doodle/sample.ddl -include samples/stxview/*.txt -include samples/stxview/*.py -include samples/stxview/*.stx -include samples/stxview/StructuredText/*.py -include samples/stxview/StructuredText/*.txt include samples/wxProject/*.txt include samples/wxProject/*.py include samples/StyleEditor/*.py diff --git a/wxPython/distrib/make_installer.py b/wxPython/distrib/make_installer.py index f478064eb0..e75b23d43f 100644 --- a/wxPython/distrib/make_installer.py +++ b/wxPython/distrib/make_installer.py @@ -168,12 +168,6 @@ Source: "samples\doodle\superdoodle.iss"; DestDir: "{app}\wxPython\samples\doo Source: "samples\wxProject\*.txt"; DestDir: "{app}\wxPython\samples\wxProject"; Components: samples Source: "samples\wxProject\*.py"; DestDir: "{app}\wxPython\samples\wxProject"; Components: samples -Source: "samples\stxview\*.py"; DestDir: "{app}\wxPython\samples\stxview"; Components: samples -Source: "samples\stxview\*.stx"; DestDir: "{app}\wxPython\samples\stxview"; Components: samples -Source: "samples\stxview\*.txt"; DestDir: "{app}\wxPython\samples\stxview"; Components: samples -Source: "samples\stxview\StructuredText\*.py"; DestDir: "{app}\wxPython\samples\stxview\StructuredText"; Components: samples -Source: "samples\stxview\StructuredText\*.txt"; DestDir: "{app}\wxPython\samples\stxview\StructuredText"; Components: samples - Source: "samples\StyleEditor\*.txt"; DestDir: "{app}\wxPython\samples\StyleEditor"; Components: samples Source: "samples\StyleEditor\*.py"; DestDir: "{app}\wxPython\samples\StyleEditor"; Components: samples Source: "samples\StyleEditor\*.cfg"; DestDir: "{app}\wxPython\samples\StyleEditor"; Components: samples @@ -245,10 +239,6 @@ Type: files; Name: "{app}\wxPython\samples\wxProject\*.pyc"; Type: files; Name: "{app}\wxPython\samples\wxProject\*.pyo"; Type: files; Name: "{app}\wxPython\samples\StyleEditor\*.pyc"; Type: files; Name: "{app}\wxPython\samples\StyleEditor\*.pyo"; -Type: files; Name: "{app}\wxPython\samples\stxview\*.pyc"; -Type: files; Name: "{app}\wxPython\samples\stxview\*.pyo"; -Type: files; Name: "{app}\wxPython\samples\stxview\StructuredText\*.pyc"; -Type: files; Name: "{app}\wxPython\samples\stxview\StructuredText\*.pyo"; Type: files; Name: "{app}\wxPython\samples\frogedit\*.pyc"; Type: files; Name: "{app}\wxPython\samples\frogedit\*.pyo"; Type: files; Name: "{app}\wxPython\demo\data\*.pyc"; diff --git a/wxPython/samples/stxview/README.txt b/wxPython/samples/stxview/README.txt deleted file mode 100644 index e25e6c52c8..0000000000 --- a/wxPython/samples/stxview/README.txt +++ /dev/null @@ -1,3 +0,0 @@ - -This sample is a simple StructuredText viewer/editor. - diff --git a/wxPython/samples/stxview/StructuredText/ClassicDocumentClass.py b/wxPython/samples/stxview/StructuredText/ClassicDocumentClass.py deleted file mode 100644 index 69fc9c81bb..0000000000 --- a/wxPython/samples/stxview/StructuredText/ClassicDocumentClass.py +++ /dev/null @@ -1,684 +0,0 @@ -############################################################################## -# -# Zope Public License (ZPL) Version 1.0 -# ------------------------------------- -# -# Copyright (c) Digital Creations. All rights reserved. -# -# This license has been certified as Open Source(tm). -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions in source code must retain the above copyright -# notice, this list of conditions, and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions, and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# 3. Digital Creations requests that attribution be given to Zope -# in any manner possible. Zope includes a "Powered by Zope" -# button that is installed by default. While it is not a license -# violation to remove this button, it is requested that the -# attribution remain. A significant investment has been put -# into Zope, and this effort will continue if the Zope community -# continues to grow. This is one way to assure that growth. -# -# 4. All advertising materials and documentation mentioning -# features derived from or use of this software must display -# the following acknowledgement: -# -# "This product includes software developed by Digital Creations -# for use in the Z Object Publishing Environment -# (http://www.zope.org/)." -# -# In the event that the product being advertised includes an -# intact Zope distribution (with copyright and license included) -# then this clause is waived. -# -# 5. Names associated with Zope or Digital Creations must not be used to -# endorse or promote products derived from this software without -# prior written permission from Digital Creations. -# -# 6. Modified redistributions of any form whatsoever must retain -# the following acknowledgment: -# -# "This product includes software developed by Digital Creations -# for use in the Z Object Publishing Environment -# (http://www.zope.org/)." -# -# Intact (re-)distributions of any official Zope release do not -# require an external acknowledgement. -# -# 7. Modifications are encouraged but must be packaged separately as -# patches to official Zope releases. Distributions that do not -# clearly separate the patches from the original work must be clearly -# labeled as unofficial distributions. Modifications which do not -# carry the name Zope may be packaged in any form, as long as they -# conform to all of the clauses above. -# -# -# Disclaimer -# -# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY -# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# -# This software consists of contributions made by Digital Creations and -# many individuals on behalf of Digital Creations. Specific -# attributions are listed in the accompanying credits file. -# -############################################################################## - -import re, ST, STDOM -from string import split, join, replace, expandtabs, strip, find -from STletters import letters,lettpunc,punctuations - -StringType=type('') -ListType=type([]) - -class StructuredTextExample(ST.StructuredTextParagraph): - """Represents a section of document with literal text, as for examples""" - - def __init__(self, subs, **kw): - t=[]; a=t.append - for s in subs: a(s.getNodeValue()) - apply(ST.StructuredTextParagraph.__init__, - (self, join(t,'\n\n'), ()), - kw) - - def getColorizableTexts(self): return () - def setColorizableTexts(self, src): pass # never color examples - -class StructuredTextBullet(ST.StructuredTextParagraph): - """Represents a section of a document with a title and a body""" - -class StructuredTextNumbered(ST.StructuredTextParagraph): - """Represents a section of a document with a title and a body""" - -class StructuredTextDescriptionTitle(ST.StructuredTextParagraph): - """Represents a section of a document with a title and a body""" - -class StructuredTextDescriptionBody(ST.StructuredTextParagraph): - """Represents a section of a document with a title and a body""" - -class StructuredTextDescription(ST.StructuredTextParagraph): - """Represents a section of a document with a title and a body""" - - def __init__(self, title, src, subs, **kw): - apply(ST.StructuredTextParagraph.__init__, (self, src, subs), kw) - self._title=title - - def getColorizableTexts(self): return self._title, self._src - def setColorizableTexts(self, src): self._title, self._src = src - - def getChildren(self): - return (StructuredTextDescriptionTitle(self._title), - StructuredTextDescriptionBody(self._src, self._subs)) - -class StructuredTextSectionTitle(ST.StructuredTextParagraph): - """Represents a section of a document with a title and a body""" - -class StructuredTextSection(ST.StructuredTextParagraph): - """Represents a section of a document with a title and a body""" - def __init__(self, src, subs=None, **kw): - apply(ST.StructuredTextParagraph.__init__, - (self, StructuredTextSectionTitle(src), subs), - kw) - - def getColorizableTexts(self): - return self._src.getColorizableTexts() - - def setColorizableTexts(self,src): - self._src.setColorizableTexts(src) - -# a StructuredTextTable holds StructuredTextRows -class StructuredTextTable(ST.StructuredTextDocument): - """ - rows is a list of lists containing tuples, which - represent the columns/cells in each rows. - EX - rows = [[('row 1:column1',1)],[('row2:column1',1)]] - """ - - def __init__(self, rows, src, subs, **kw): - apply(ST.StructuredTextDocument.__init__,(self,subs),kw) - self._rows = [] - for row in rows: - if row: - self._rows.append(StructuredTextRow(row,kw)) - - def getRows(self): - return [self._rows] - - def _getRows(self): - return self.getRows() - - def getColorizableTexts(self): - """ - return a tuple where each item is a column/cell's - contents. The tuple, result, will be of this format. - ("r1 col1", "r1=col2", "r2 col1", "r2 col2") - """ - - #result = () - result = [] - for row in self._rows: - for column in row.getColumns()[0]: - #result = result[:] + (column.getColorizableTexts(),) - result.append(column.getColorizableTexts()[0]) - return result - - def setColorizableTexts(self,texts): - """ - texts is going to a tuple where each item is the - result of being mapped to the colortext function. - Need to insert the results appropriately into the - individual columns/cells - """ - for row_index in range(len(self._rows)): - for column_index in range(len(self._rows[row_index]._columns)): - self._rows[row_index]._columns[column_index].setColorizableTexts((texts[0],)) - texts = texts[1:] - - def _getColorizableTexts(self): - return self.getColorizableTexts() - - def _setColorizableTexts(self): - return self.setColorizableTexts() - -# StructuredTextRow holds StructuredTextColumns -class StructuredTextRow(ST.StructuredTextDocument): - - def __init__(self,row,kw): - """ - row is a list of tuples, where each tuple is - the raw text for a cell/column and the span - of that cell/column". - EX - [('this is column one',1), ('this is column two',1)] - """ - - apply(ST.StructuredTextDocument.__init__,(self,[]),kw) - self._columns = [] - for column in row: - self._columns.append(StructuredTextColumn(column[0],column[1],kw)) - def getColumns(self): - return [self._columns] - - def _getColumns(self): - return [self._columns] - -# this holds the raw text of a table cell -class StructuredTextColumn(ST.StructuredTextParagraph): - """ - StructuredTextColumn is a cell/column in a table. - This contains the actual text of a column and is - thus a StructuredTextParagraph. A StructuredTextColumn - also holds the span of its column - """ - - def __init__(self,text,span,kw): - apply(ST.StructuredTextParagraph.__init__,(self,text,[]),kw) - self._span = span - - def getSpan(self): - return self._span - - def _getSpan(self): - return self._span - -class StructuredTextMarkup(STDOM.Element): - - def __init__(self, v, **kw): - self._value=v - self._attributes=kw.keys() - for k, v in kw.items(): setattr(self, k, v) - - def getChildren(self, type=type, lt=type([])): - v=self._value - if type(v) is not lt: v=[v] - return v - - def getColorizableTexts(self): return self._value, - def setColorizableTexts(self, v): self._value=v[0] - - def __repr__(self): - return '%s(%s)' % (self.__class__.__name__, `self._value`) - -class StructuredTextLiteral(StructuredTextMarkup): - def getColorizableTexts(self): return () - def setColorizableTexts(self, v): pass - -class StructuredTextEmphasis(StructuredTextMarkup): pass - -class StructuredTextStrong(StructuredTextMarkup): pass - -class StructuredTextInnerLink(StructuredTextMarkup): pass - -class StructuredTextNamedLink(StructuredTextMarkup): pass - -class StructuredTextUnderline(StructuredTextMarkup): pass - -class StructuredTextLink(StructuredTextMarkup): - "A simple hyperlink" - -class DocumentClass: - """ - Class instance calls [ex.=> x()] require a structured text - structure. Doc will then parse each paragraph in the structure - and will find the special structures within each paragraph. - Each special structure will be stored as an instance. Special - structures within another special structure are stored within - the 'top' structure - EX : '-underline this-' => would be turned into an underline - instance. '-underline **this**' would be stored as an underline - instance with a strong instance stored in its string - """ - - paragraph_types = [ - 'doc_bullet', - 'doc_numbered', - 'doc_description', - 'doc_header', - 'doc_table', - ] - - text_types = [ - 'doc_href', - 'doc_strong', - 'doc_emphasize', - 'doc_literal', - 'doc_inner_link', - 'doc_named_link', - 'doc_underline', - ] - - def __call__(self, doc): - if type(doc) is type(''): - doc=ST.StructuredText(doc) - doc.setSubparagraphs(self.color_paragraphs( - doc.getSubparagraphs())) - else: - doc=ST.StructuredTextDocument(self.color_paragraphs( - doc.getSubparagraphs())) - return doc - - def parse(self, raw_string, text_type, - type=type, st=type(''), lt=type([])): - - """ - Parse accepts a raw_string, an expr to test the raw_string, - and the raw_string's subparagraphs. - - Parse will continue to search through raw_string until - all instances of expr in raw_string are found. - - If no instances of expr are found, raw_string is returned. - Otherwise a list of substrings and instances is returned - """ - - tmp = [] # the list to be returned if raw_string is split - append=tmp.append - - if type(text_type) is st: text_type=getattr(self, text_type) - - while 1: - t = text_type(raw_string) - if not t: break - #an instance of expr was found - t, start, end = t - - if start: append(raw_string[0:start]) - - tt=type(t) - if tt is st: - # if we get a string back, add it to text to be parsed - raw_string = t+raw_string[end:len(raw_string)] - else: - if tt is lt: - # is we get a list, append it's elements - tmp[len(tmp):]=t - else: - # normal case, an object - append(t) - raw_string = raw_string[end:len(raw_string)] - - if not tmp: return raw_string # nothing found - - if raw_string: append(raw_string) - elif len(tmp)==1: return tmp[0] - - return tmp - - - def color_text(self, str, types=None): - """Search the paragraph for each special structure - """ - if types is None: types=self.text_types - - for text_type in types: - - if type(str) is StringType: - str = self.parse(str, text_type) - elif type(str) is ListType: - r=[]; a=r.append - for s in str: - if type(s) is StringType: - s=self.parse(s, text_type) - if type(s) is ListType: r[len(r):]=s - else: a(s) - else: - s.setColorizableTexts( - map(self.color_text, - s.getColorizableTexts() - )) - a(s) - str=r - else: - r=[]; a=r.append; color=self.color_text - for s in str.getColorizableTexts(): - color(s, (text_type,)) - a(s) - - str.setColorizableTexts(r) - - return str - - def color_paragraphs(self, raw_paragraphs, - type=type, sequence_types=(type([]), type(())), - st=type('')): - result=[] - for paragraph in raw_paragraphs: - - if paragraph.getNodeName() != 'StructuredTextParagraph': - result.append(paragraph) - continue - - for pt in self.paragraph_types: - if type(pt) is st: - # grab the corresponding function - pt=getattr(self, pt) - # evaluate the paragraph - r=pt(paragraph) - if r: - if type(r) not in sequence_types: - r=r, - new_paragraphs=r - for paragraph in new_paragraphs: - paragraph.setSubparagraphs(self.color_paragraphs(paragraph.getSubparagraphs())) - break - else: - new_paragraphs=ST.StructuredTextParagraph(paragraph.getColorizableTexts()[0], - self.color_paragraphs(paragraph.getSubparagraphs()), - indent=paragraph.indent), - # color the inline StructuredText types - # for each StructuredTextParagraph - for paragraph in new_paragraphs: - paragraph.setColorizableTexts( - map(self.color_text, - paragraph.getColorizableTexts() - )) - result.append(paragraph) - - return result - - def doc_table(self,paragraph, expr = re.compile('(\s*)([||]+)').match): - #print "paragraph=>", type(paragraph), paragraph, paragraph._src - text = paragraph.getColorizableTexts()[0] - m = expr(text) - - if not (m): - return None - rows = [] - - # initial split - for row in split(text,"\n"): - rows.append(row) - - # clean up the rows - for index in range(len(rows)): - tmp = [] - rows[index] = strip(rows[index]) - l = len(rows[index])-2 - result = split(rows[index][:l],"||") - for text in result: - if text: - tmp.append(text) - tmp.append('') - else: - tmp.append(text) - rows[index] = tmp - # remove trailing '''s - for index in range(len(rows)): - l = len(rows[index])-1 - rows[index] = rows[index][:l] - - result = [] - for row in rows: - cspan = 0 - tmp = [] - for item in row: - if item: - tmp.append((item,cspan)) - cspan = 0 - else: - cspan = cspan + 1 - result.append(tmp) - - subs = paragraph.getSubparagraphs() - indent=paragraph.indent - return StructuredTextTable(result,text,subs,indent=paragraph.indent) - - def doc_bullet(self, paragraph, expr = re.compile('\s*[-*o]\s+').match): - top=paragraph.getColorizableTexts()[0] - m=expr(top) - - if not m: - return None - - subs=paragraph.getSubparagraphs() - if top[-2:]=='::': - subs=[StructuredTextExample(subs)] - top=top[:-1] - return StructuredTextBullet(top[m.span()[1]:], subs, - indent=paragraph.indent, - bullet=top[:m.span()[1]] - ) - - def doc_numbered( - self, paragraph, - expr = re.compile('(\s*[%s]+\.)|(\s*[0-9]+\.)|(\s*[0-9]+\s+)' % letters).match): - - # This is the old expression. It had a nasty habit - # of grabbing paragraphs that began with a single - # letter word even if there was no following period. - - #expr = re.compile('\s*' - # '(([a-zA-Z]|[0-9]+|[ivxlcdmIVXLCDM]+)\.)*' - # '([a-zA-Z]|[0-9]+|[ivxlcdmIVXLCDM]+)\.?' - # '\s+').match): - - top=paragraph.getColorizableTexts()[0] - m=expr(top) - if not m: return None - subs=paragraph.getSubparagraphs() - if top[-2:]=='::': - subs=[StructuredTextExample(subs)] - top=top[:-1] - return StructuredTextNumbered(top[m.span()[1]:], subs, - indent=paragraph.indent, - number=top[:m.span()[1]]) - - def doc_description( - self, paragraph, - delim = re.compile('\s+--\s+').search, - nb=re.compile(r'[^\000- ]').search, - ): - - top=paragraph.getColorizableTexts()[0] - d=delim(top) - if not d: return None - start, end = d.span() - title=top[:start] - if find(title, '\n') >= 0: return None - if not nb(title): return None - d=top[start:end] - top=top[end:] - - subs=paragraph.getSubparagraphs() - if top[-2:]=='::': - subs=[StructuredTextExample(subs)] - top=top[:-1] - - return StructuredTextDescription( - title, top, subs, - indent=paragraph.indent, - delim=d) - - def doc_header(self, paragraph, - expr = re.compile('[ %s0-9.:/,-_*<>\?\'\"]+' % letters).match - ): - subs=paragraph.getSubparagraphs() - if not subs: return None - top=paragraph.getColorizableTexts()[0] - if not strip(top): return None - if top[-2:]=='::': - subs=StructuredTextExample(subs) - if strip(top)=='::': return subs - return ST.StructuredTextParagraph(top[:-1], - [subs], - indent=paragraph.indent, - level=paragraph.level) - - if find(top,'\n') >= 0: return None - return StructuredTextSection(top, subs, indent=paragraph.indent, level=paragraph.level) - - def doc_literal( - self, s, - expr=re.compile( - "(?:\s|^)'" # open - "([^ \t\n\r\f\v']|[^ \t\n\r\f\v'][^\n']*[^ \t\n\r\f\v'])" # contents - "'(?:\s|[,.;:!?]|$)" # close - ).search): - - r=expr(s) - if r: - start, end = r.span(1) - return (StructuredTextLiteral(s[start:end]), start-1, end+1) - else: - return None - - def doc_emphasize( - self, s, - expr = re.compile('\s*\*([ \n%s0-9]+)\*(?!\*|-)' % lettpunc).search - ): - - r=expr(s) - if r: - start, end = r.span(1) - return (StructuredTextEmphasis(s[start:end]), start-1, end+1) - else: - return None - - def doc_inner_link(self, - s, - expr1 = re.compile("\.\.\s*").search, - expr2 = re.compile("\[[%s0-9]+\]" % letters).search): - - # make sure we dont grab a named link - if expr2(s) and expr1(s): - start1,end1 = expr1(s).span() - start2,end2 = expr2(s).span() - if end1 == start2: - # uh-oh, looks like a named link - return None - else: - # the .. is somewhere else, ignore it - return (StructuredTextInnerLink(s[start2+1:end2-1]),start2,end2) - return None - elif expr2(s) and not expr1(s): - start,end = expr2(s).span() - return (StructuredTextInnerLink(s[start+1:end-1]),start,end) - return None - - def doc_named_link(self, - s, - expr=re.compile("(\.\.\s)(\[[%s0-9]+\])" % letters).search): - - result = expr(s) - if result: - start,end = result.span(2) - a,b = result.span(1) - str = strip(s[a:b]) + s[start:end] - str = s[start+1:end-1] - st,en = result.span() - return (StructuredTextNamedLink(str),st,en) - #return (StructuredTextNamedLink(s[st:en]),st,en) - return None - - def doc_underline(self, - s, - expr=re.compile("\s+\_([0-9%s ]+)\_" % lettpunc).search): - - result = expr(s) - if result: - start,end = result.span(1) - st,e = result.span() - return (StructuredTextUnderline(s[start:end]),st,e) - else: - return None - - def doc_strong(self, - s, - expr = re.compile('\s*\*\*([ \n%s0-9]+)\*\*' % lettpunc).search - ): - - r=expr(s) - if r: - start, end = r.span(1) - return (StructuredTextStrong(s[start:end]), start-2, end+2) - else: - return None - - def doc_href( - - self, s, - expr1 = re.compile("(\"[ %s0-9\n\-\.\,\;\(\)\/\:\/\*\']+\")(:)([a-zA-Z0-9\@\.\,\?\!\/\:\;\-\#\~]+)([,]*\s*)" % letters).search, - expr2 = re.compile('(\"[ %s0-9\n\-\.\:\;\(\)\/\*\']+\")([,]+\s+)([a-zA-Z0-9\@\.\,\?\!\/\:\;\-\#\~]+)(\s*)' % letters).search): - - r=expr1(s) or expr2(s) - - if r: - # need to grab the href part and the - # beginning part - - start,e = r.span(1) - name = s[start:e] - name = replace(name,'"','',2) - st,end = r.span(3) - - if s[end-1:end] in punctuations: end-=1 - link = s[st:end] - - # name is the href title, link is the target - # of the href - return (StructuredTextLink(name, href=link), - start, end) - - - else: - return None diff --git a/wxPython/samples/stxview/StructuredText/ClassicStructuredText.py b/wxPython/samples/stxview/StructuredText/ClassicStructuredText.py deleted file mode 100644 index b591558f73..0000000000 --- a/wxPython/samples/stxview/StructuredText/ClassicStructuredText.py +++ /dev/null @@ -1,625 +0,0 @@ -#! /usr/bin/env python -- # -*- python -*- -############################################################################## -# -# Zope Public License (ZPL) Version 1.0 -# ------------------------------------- -# -# Copyright (c) Digital Creations. All rights reserved. -# -# This license has been certified as Open Source(tm). -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions in source code must retain the above copyright -# notice, this list of conditions, and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions, and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# 3. Digital Creations requests that attribution be given to Zope -# in any manner possible. Zope includes a "Powered by Zope" -# button that is installed by default. While it is not a license -# violation to remove this button, it is requested that the -# attribution remain. A significant investment has been put -# into Zope, and this effort will continue if the Zope community -# continues to grow. This is one way to assure that growth. -# -# 4. All advertising materials and documentation mentioning -# features derived from or use of this software must display -# the following acknowledgement: -# -# "This product includes software developed by Digital Creations -# for use in the Z Object Publishing Environment -# (http://www.zope.org/)." -# -# In the event that the product being advertised includes an -# intact Zope distribution (with copyright and license included) -# then this clause is waived. -# -# 5. Names associated with Zope or Digital Creations must not be used to -# endorse or promote products derived from this software without -# prior written permission from Digital Creations. -# -# 6. Modified redistributions of any form whatsoever must retain -# the following acknowledgment: -# -# "This product includes software developed by Digital Creations -# for use in the Z Object Publishing Environment -# (http://www.zope.org/)." -# -# Intact (re-)distributions of any official Zope release do not -# require an external acknowledgement. -# -# 7. Modifications are encouraged but must be packaged separately as -# patches to official Zope releases. Distributions that do not -# clearly separate the patches from the original work must be clearly -# labeled as unofficial distributions. Modifications which do not -# carry the name Zope may be packaged in any form, as long as they -# conform to all of the clauses above. -# -# -# Disclaimer -# -# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY -# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# -# This software consists of contributions made by Digital Creations and -# many individuals on behalf of Digital Creations. Specific -# attributions are listed in the accompanying credits file. -# -############################################################################## -'''Structured Text Manipulation - -Parse a structured text string into a form that can be used with -structured formats, like html. - -Structured text is text that uses indentation and simple -symbology to indicate the structure of a document. - -A structured string consists of a sequence of paragraphs separated by -one or more blank lines. Each paragraph has a level which is defined -as the minimum indentation of the paragraph. A paragraph is a -sub-paragraph of another paragraph if the other paragraph is the last -preceding paragraph that has a lower level. - -Special symbology is used to indicate special constructs: - -- A single-line paragraph whose immediately succeeding paragraphs are lower - level is treated as a header. - -- A paragraph that begins with a '-', '*', or 'o' is treated as an - unordered list (bullet) element. - -- A paragraph that begins with a sequence of digits followed by a - white-space character is treated as an ordered list element. - -- A paragraph that begins with a sequence of sequences, where each - sequence is a sequence of digits or a sequence of letters followed - by a period, is treated as an ordered list element. - -- A paragraph with a first line that contains some text, followed by - some white-space and '--' is treated as - a descriptive list element. The leading text is treated as the - element title. - -- Sub-paragraphs of a paragraph that ends in the word 'example' or the - word 'examples', or '::' is treated as example code and is output as is. - -- Text enclosed single quotes (with white-space to the left of the - first quote and whitespace or punctuation to the right of the second quote) - is treated as example code. - -- Text surrounded by '*' characters (with white-space to the left of the - first '*' and whitespace or punctuation to the right of the second '*') - is emphasized. - -- Text surrounded by '**' characters (with white-space to the left of the - first '**' and whitespace or punctuation to the right of the second '**') - is made strong. - -- Text surrounded by '_' underscore characters (with whitespace to the left - and whitespace or punctuation to the right) is made underlined. - -- Text encloded by double quotes followed by a colon, a URL, and concluded - by punctuation plus white space, *or* just white space, is treated as a - hyper link. For example: - - "Zope":http://www.zope.org/ is ... - - Is interpreted as 'Zope is ....' - Note: This works for relative as well as absolute URLs. - -- Text enclosed by double quotes followed by a comma, one or more spaces, - an absolute URL and concluded by punctuation plus white space, or just - white space, is treated as a hyper link. For example: - - "mail me", mailto:amos@digicool.com. - - Is interpreted as 'mail me.' - -- Text enclosed in brackets which consists only of letters, digits, - underscores and dashes is treated as hyper links within the document. - For example: - - As demonstrated by Smith [12] this technique is quite effective. - - Is interpreted as '... by Smith [12] this ...'. Together - with the next rule this allows easy coding of references or end notes. - -- Text enclosed in brackets which is preceded by the start of a line, two - periods and a space is treated as a named link. For example: - - .. [12] "Effective Techniques" Smith, Joe ... - - Is interpreted as '[12] "Effective Techniques" ...'. - Together with the previous rule this allows easy coding of references or - end notes. - - -- A paragraph that has blocks of text enclosed in '||' is treated as a - table. The text blocks correspond to table cells and table rows are - denoted by newlines. By default the cells are center aligned. A cell - can span more than one column by preceding a block of text with an - equivalent number of cell separators '||'. Newlines and '|' cannot - be a part of the cell text. For example: - - |||| **Ingredients** || - || *Name* || *Amount* || - ||Spam||10|| - ||Eggs||3|| - - is interpreted as:: - - - - - - - - - - - - - - - - - -
Ingredients
Name Amount
Spam10
Eggs3
- -''' - -import ts_regex -import regex -from ts_regex import gsub -from string import split, join, strip, find -import string,re - - -def untabify(aString, - indent_tab=ts_regex.compile('\(\n\|^\)\( *\)\t').search_group, - ): - '''\ - Convert indentation tabs to spaces. - ''' - result='' - rest=aString - while 1: - ts_results = indent_tab(rest, (1,2)) - if ts_results: - start, grps = ts_results - lnl=len(grps[0]) - indent=len(grps[1]) - result=result+rest[:start] - rest="\n%s%s" % (' ' * ((indent/8+1)*8), - rest[start+indent+1+lnl:]) - else: - return result+rest - -def indent(aString, indent=2): - """Indent a string the given number of spaces""" - r=split(untabify(aString),'\n') - if not r: return '' - if not r[-1]: del r[-1] - tab=' '*level - return "%s%s\n" % (tab,join(r,'\n'+tab)) - -def reindent(aString, indent=2, already_untabified=0): - "reindent a block of text, so that the minimum indent is as given" - - if not already_untabified: aString=untabify(aString) - - l=indent_level(aString)[0] - if indent==l: return aString - - r=[] - - append=r.append - - if indent > l: - tab=' ' * (indent-l) - for s in split(aString,'\n'): append(tab+s) - else: - l=l-indent - for s in split(aString,'\n'): append(s[l:]) - - return join(r,'\n') - -def indent_level(aString, - indent_space=ts_regex.compile('\n\( *\)').search_group, - ): - '''\ - Find the minimum indentation for a string, not counting blank lines. - ''' - start=0 - text='\n'+aString - indent=l=len(text) - while 1: - - ts_results = indent_space(text, (1,2), start) - if ts_results: - start, grps = ts_results - i=len(grps[0]) - start=start+i+1 - if start < l and text[start] != '\n': # Skip blank lines - if not i: return (0,aString) - if i < indent: indent = i - else: - return (indent,aString) - -def paragraphs(list,start): - l=len(list) - level=list[start][0] - i=start+1 - while i < l and list[i][0] > level: i=i+1 - return i-1-start - -def structure(list): - if not list: return [] - i=0 - l=len(list) - r=[] - while i < l: - sublen=paragraphs(list,i) - i=i+1 - r.append((list[i-1][1],structure(list[i:i+sublen]))) - i=i+sublen - return r - - -class Table: - CELL=' %s\n' - ROW=' \n%s \n' - TABLE='\n\n%s
' - - def create(self,aPar, - td_reg=re.compile(r'[ \t\n]*\|\|([^\0x00|]*)') - ): - '''parses a table and returns nested list representing the - table''' - self.table=[] - text=filter(None,split(aPar,'\n')) - for line in text: - row=[] - while 1: - mo = td_reg.match(line) - if not mo: return 0 - pos = mo.end(1) - row.append(mo.group(1)) - if pos==len(line):break - line=line[pos:] - self.table.append(row) - return 1 - - def html(self): - '''Creates an HTML representation of table''' - htmltable=[] - for row in self.table: - htmlrow=[] - colspan=1 - for cell in row: - if cell=='': - colspan=colspan+1 - continue - else: - htmlrow.append(self.CELL%(colspan,cell)) - colspan=1 - htmltable.append(self.ROW%join(htmlrow,'')) - return self.TABLE%join(htmltable,'') - -table=Table() - -class StructuredText: - - """Model text as structured collection of paragraphs. - - Structure is implied by the indentation level. - - This class is intended as a base classes that do actual text - output formatting. - """ - - def __init__(self, aStructuredString, level=0, - paragraph_divider=regex.compile('\(\r?\n *\)+\r?\n'), - ): - '''Convert a structured text string into a structured text object. - - Aguments: - - aStructuredString -- The string to be parsed. - level -- The level of top level headings to be created. - ''' - - - pat = ' \"([%s0-9-_,./?=@~&]*)\":' % string.letters+ \ - '([-:%s0-9_,./?=@#~&]*?)' % string.letters + \ - '([.:?;] )' - - p_reg = re.compile(pat,re.M) - - aStructuredString = p_reg.sub(r'\1\3 ' , aStructuredString) - - pat = ' \"([%s0-9-_,./?=@~&]*)\", ' % string.letters+ \ - '([-:%s0-9_,./?=@#~&]*?)' % string.letters + \ - '([.:?;] )' - - p_reg = re.compile(pat,re.M) - - aStructuredString = p_reg.sub(r'\1\3 ' , aStructuredString) - - - protoless = find(aStructuredString, '\2\3',s) - s=under.sub( r'\1\2\3',s) - s=code.sub( r'\1\2\3',s) - s=em.sub( r'\1\2\3',s) - return s - -class HTML(StructuredText): - - '''\ - An HTML structured text formatter. - '''\ - - def __str__(self, - extra_dl=re.compile("\n
"), - extra_ul=re.compile("\n