toc.py :  » Web-Frameworks » Spyce » spyce-2.1 » contrib » modules » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Spyce 
Spyce » spyce 2.1 » contrib » modules » toc.py
##################################################
# SPYCE - Python-based HTML Scripting
# Copyright (c) 2002 Rimon Barr.
#
# Refer to spyce.py
# CVS: $Id: toc.py 944 2006-07-22 17:25:58Z ellisj $
##################################################

from spyceModule import spyceModule
import tree

__doc__ = '''
The TOC module provides support for constructing a table contents for a
lengthy document, such as this user documentation. The primary task of the TOC
module is to maintain a document tree, and initiate callbacks at the
appropriate points in the document. Note that this module may automatically
force a secondary processing of the Spyce file to resolve forward references.
<p>

The module provides the following methods to segment the document:

<ul>

  <li><b>begin</b>( data, [tag] ): <br> Increase the nesting level and add a
  new section. The <b>data</b> is stored in the document tree, and used for
  callbacks (see later). An optional <b>tag</b> may be associated with the
  node, otherwise one will automatically be generated. The function <b>b</b>()
  is equivalent. </li><p>
  
  <li><b>next</b>( data, [tag] ): <br> Add a new section at the same nesting
  level. The <b>data</b> is stored in the document tree, and used for
  callbacks (see later). An optional <b>tag</b> may be associated with the
  node, or one will be automatically generated. The function <b>n</b>() is
  equivalent.</li><p>

  <li><b>end</b>(): <br> Decrease the nesting level. The function <b>e</b>()
  is equivalent.</li><p>

  <li><b>anchor</b>( data, [tag] ): <br> Set <b>data</b> and optionally the
  <b>tag</b> associated with the root of the document tree. If the tag is
  omitted, it defaults to the string <i>'root'</i>. </li><p>

  <li><b>level</b>( depth, data, [tag] ): <br> Start a new section at given
  <b>depth</b> with given <b>data</b> and optional <b>tag</b>. The necessary
  begin(), next() and end() calls are automatically made, based on the current
  document depth, so both types of calls can be inter-mixed. </li> <p>

  <li><b>l1</b>( data, [tag] ): <br> Start a level&nbsp;1 section. This
  function merely calls <b>level</b>(1,&nbsp;<b>data</b>,&nbsp;<b>tag</b>).
  The functions, <b>l2</b>()...<b>l9</b>() are similarly defined. </li> <p>

</ul> <p>

The following methods provide access to document information:

<ul>

  <li><b>getTag</b>(): <br> Return the tag of the current document section.
  </li><p>

  <li><b>getNumbering</b>( [tag] ) <br> Return the numbering of some section
  of the document identified by the given <b>tag</b>. If the tag is omitted,
  the current document section is assumed. The numbering is an array of
  numbers. This function may return 'None' on the first pass through a
  document. </li><p>

  <li><b>getData</b>( [tag] ) <br> Return the data associated with some
  section of the document identified by the given <b>tag</b>. If the tag is
  omitted, the current document section is assumed. This function may return
  'None' on the first pass through a document. </li><p>

  <li><b>getDepth</b>( [tag] ) <br> Return the depth of some section of the
  document identified by the given <b>tag</b>. If the tag is omitted, the
  current document section is assumed. This function may return 'None' on the 
  first pass through a document. </li><p>

  <li><b>getNextTag</b>( [tag] ) <br> Return the tag of the section following
  some section of the document identified by the given <b>tag</b>. If the tag
  is omitted, the current document section is assumed. If this is the last
  section of the document, then this function will return 'None'. This
  function may return 'None' on the first pass through a document. </li><p>

  <li><b>getPrevTag</b>( [tag] ) <br> Return the tag of the section before
  some section of the document identified by the given <b>tag</b>. If the tag
  is omitted, the current document section is assumed. If this is the first
  section of the document, then this function will return 'None'. This
  function may return 'None' on the first pass through a document. </li><p>

  <li><b>getParentTag</b>( [tag] ) <br> Return the tag of the section above
  (or containing) some section of the document identified by the given
  <b>tag</b>. If the tag is omitted, the current document section is assumed.
  If this is the top-most section of the document, then this function will
  return 'None'. This function may return 'None' on the first pass through a
  document. </li><p>

  <li><b>getChildrenTags</b>( [tag] ) <br> Return a list (possibly empty) of
  tags of the sections directly contained within some section of the document
  identified by the given <b>tag</b>. If the tag is omitted, the current
  document section is assumed. This function may return a shorter list than
  anticipated or 'None', on the first pass through a document.
  
</ul> <p>

The TOC modules can make callbacks to handlers that format the document
correctly. The handlers should be defined and registered before the first
section break in the document. The following functions register handlers:

<ul>

  <li><b>setDOC_PUSH</b>( f ): <br> Register a function <b>f</b> to be called
  when the nesting depth of the document increases. </li><p>

  <li><b>setDOC_POP</b>( f ): <br> Register a function <b>f</b> to be called
  when the nesting depth of the document decreases. </li><p>

  <li><b>setDOC_START</b>( f ): <br> Register a funtion <b>f</b> to be called
  at the beginning of a section. </li><p>

  <li><b>setDOC_END</b>( f ): <br> Register a function <b>f</b> to be called
  at the end of a section. </li><p>

  <li><b>setTOC_PUSH</b>( f ): <br> Register a function <b>f</b> to be called
  when the nesting depth of the table of contents increases. </li><p>

  <li><b>setTOC_POP</b>( f ): <br> Register a function <b>f</b> to be called
  when the nesting depth of the table of contents decreases. </li><p>

  <li><b>setTOC_ENTRY</b>( f ): <br> Register a function <b>f</b> to be called
  for each table of contents entry. </li><p>

</ul><p>

Each callback function should be of the form: <center> <b>f</b>(depth,
tag, numbering, data), </center> where: <b>depth</b> is the nesting depth,
<b>tag</b> is the associated tag, <b>numbering</b> is the position array, and
<b>data</b> is the associated data of the section for which the callback was
made.<p>

The <i>DOC</i> callbacks are made as the sections are encountered. The
<i>TOC</i> callbacks are made while printing the table of contents. If the
modules detects that forward references exist in the document, the document
will be processed twice, and only the second output will be sent. Note that
buffering MUST be turned on for this to function correctly. <p>

To display a table of contents, define the appropriate TOC callback functions
and call:

<ul>

  <li><b>showTOC</b>(): Display the table of contents.
  
</ul>
'''

ROOT_NAME = 'root'

class toc(spyceModule):

  def start(self):
    if not self._api.getModule('pool').has_key('toc'):
      self._api.getModule('pool')['toc'] = {}
    try:
      self.oldtree, self.oldtags = self._api.getModule('pool')['toc'][self._api.getFilename()]
    except (KeyError, TypeError):
      self.oldtree = tree.tree( (ROOT_NAME, [], None) )
      self.oldtags = {ROOT_NAME: self.oldtree}
    # tree data: (tag, numbering, data)
    self.tree = tree.tree((ROOT_NAME, [], None))
    self.tags = {ROOT_NAME: self.tree}
    self.node = self.tree
    self.numbering = []
    self.autotag = 0
    self.tocShown = 0
    self.fDOC_PUSH = None
    self.fDOC_POP = None
    self.fDOC_START = None
    self.fDOC_END = None
    self.fTOC_PUSH = None
    self.fTOC_POP = None
    self.fTOC_ENTRY = None

  def finish(self, theError):
    if self.oldtree is not None:
      self.oldtree.delete()
      self.oldtree = None
      self.oldtags = None

  def generate(self):
    self.tree.computePreChain()
    regenerate = not (self.oldtree == self.tree)
    file = self._api.getFilename()
    self._api.getModule('pool')['toc'][file] = self.tree, self.tags
    if self.tocShown and regenerate:
      self._api.getModule('redirect').internal(filename=file)
    
  # set callbacks
  def setDOC_PUSH(self, f):
    self.fDOC_PUSH = f
  def setDOC_POP(self, f):
    self.fDOC_POP = f
  def setDOC_START(self, f):
    self.fDOC_START = f
  def setDOC_END(self, f):
    self.fDOC_END = f
  def setTOC_PUSH(self, f):
    self.fTOC_PUSH = f
  def setTOC_POP(self, f):
    self.fTOC_POP = f
  def setTOC_ENTRY(self, f):
    self.fTOC_ENTRY = f

  # sectioning
  def begin(self, data, tag=None, number=1):
    self._emit(self.node, self.fDOC_PUSH)
    self.numbering = _in(self.numbering)
    if number: 
      self.numbering = _inc(self.numbering)
      self.node = self.node.append( (tag, self.numbering, data) )
    else:
      self.node = self.node.append( (tag, None, data) )
    if not tag: tag = self._genTag()
    self.tags[tag] = self.node
    self._emit(self.node, self.fDOC_START)
  def end(self):
    self._emit(self.node, self.fDOC_END)
    self.numbering = _out(self.numbering)
    self.node = self.node.parent
    self._emit(self.node, self.fDOC_POP)
  def next(self, data, tag=None, number=1):
    self._emit(self.node, self.fDOC_END)
    self.node = self.node.parent
    if number:
      self.numbering = _inc(self.numbering)
      self.node = self.node.append( (tag, self.numbering, data) )
    else:
      self.node = self.node.append( (tag, None, data) )
    if not tag: tag = self._genTag()
    self.tags[tag] = self.node
    self._emit(self.node, self.fDOC_START)
  def anchor(self, data, tag=ROOT_NAME):
    self.tree.data = tag, [], data
    self.tags[tag] = self.tree

  # shortcuts
  b=begin
  e=end
  n=next

  # sectioning by depth
  def level(self, depth, data, tag=None):
    curdepth = self.getDepth()
    if curdepth > depth:  # indent
      while curdepth > depth:
        self.end()
        curdepth = self.getDepth()
      self.next(data, tag)
    elif curdepth < depth:  # outdent
      while curdepth < depth - 1:
        self.begin(None)
        curdepth = self.getDepth()
      self.begin(data, tag)
    else: # next
      self.next(data, tag)
  def l1(self, data, tag=None):
    self.level(1, data, tag)
  def l2(self, data, tag=None):
    self.level(2, data, tag)
  def l3(self, data, tag=None):
    self.level(3, data, tag)
  def l4(self, data, tag=None):
    self.level(4, data, tag)
  def l5(self, data, tag=None):
    self.level(5, data, tag)
  def l6(self, data, tag=None):
    self.level(6, data, tag)
  def l7(self, data, tag=None):
    self.level(7, data, tag)
  def l8(self, data, tag=None):
    self.level(8, data, tag)
  def l9(self, data, tag=None):
    self.level(9, data, tag)

  # show toc
  def showTOC(self):
    self.tocShown = 1
    self._tocHelper(self.oldtree)
  def _tocHelper(self, node):
    self._emit(node, self.fTOC_ENTRY)
    if node.children:
      self._emit(node, self.fTOC_PUSH)
      for c in node.children:
        self._tocHelper(c)
      self._emit(node, self.fTOC_POP)

  # current state
  def getTag(self, node=None):
    self.tocShown = 1
    if not node: node = self.node
    tag, numbering, data = node.data
    return tag
  def getNumbering(self, tag=None):
    self.tocShown = 1
    try:
      node = self.node
      if tag: node = self.oldtags[tag]
      tag, numbering, data = node.data
      return numbering
    except KeyError:
      return None
  def getData(self, tag=None):
    self.tocShown = 1
    try:
      node = self.node
      if tag: node = self.oldtags[tag]
      tag, numbering, data = node.data
      return data
    except KeyError:
      return None
  def getDepth(self, tag=None):
    self.tocShown = 1
    try:
      node = self.node
      if tag: node = self.tags[tag]
      return node.depth
    except KeyError:
      return None
  def getNextTag(self, tag=None):
    self.tocShown = 1
    try:
      if not tag: tag = self.getTag()
      tag = self.oldtags[tag].next
      if tag==None: return None
      return self.getTag(tag)
    except KeyError:
      return None
  def getPrevTag(self, tag=None):
    self.tocShown = 1
    try:
      if not tag: tag = self.getTag()
      node = self.oldtags[tag].prev
      if node==None: return None
      return self.getTag(node)
    except KeyError:
      return None
  def getParentTag(self, tag=None):
    self.tocShown = 1
    try:
      if not tag: tag = self.getTag()
      node = self.oldtags[tag].parent
      if node==None: return None
      return self.getTag(node)
    except KeyError:
      return None
  def getChildrenTags(self, tag=None):
    self.tocShown = 1
    try:
      if not tag: tag = self.getTag()
      nodes = self.oldtags[tag].children
      return map(self.getTag, nodes)
    except KeyError:
      return None

  # internal helpers
  def _genTag(self):
    tag = 'auto_'+str(self.autotag)
    self.autotag = self.autotag + 1
    return tag
  def _emit(self, node, f):
    tag, numbering, data = node.data
    if f: s = f(node.depth, tag, numbering, data)

# hierarchical counting
def _inc(numbering, inc=1):
  return numbering[:-1]+[numbering[-1]+inc]
def _in(numbering, start=0):
  return numbering+[start]
def _out(numbering):
  return numbering[:-1]

def defaultOutput(tag, numbering, data):
  return reduce(lambda s, i: '%s%d.' % (s, i), numbering, '') + ' ' + str(data)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.