X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e42c7b856732d0f7c3a209a42c269c613d40578a..ddfc587a2ea899f654d940c21f102316a39985bd:/wxPython/samples/stxview/StructuredText/ClassicStructuredText.py diff --git a/wxPython/samples/stxview/StructuredText/ClassicStructuredText.py b/wxPython/samples/stxview/StructuredText/ClassicStructuredText.py new file mode 100644 index 0000000000..b591558f73 --- /dev/null +++ b/wxPython/samples/stxview/StructuredText/ClassicStructuredText.py @@ -0,0 +1,625 @@ +#! /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