[Checkins] SVN: gzo.plonepolicy/trunk/gzo/plonepolicy/ Add support
for code-block and sidebar ReST directives.
Kevin Teague
kevin at bud.ca
Sat Dec 29 23:10:03 EST 2007
Log message for revision 82566:
Add support for code-block and sidebar ReST directives.
Changed:
U gzo.plonepolicy/trunk/gzo/plonepolicy/__init__.py
A gzo.plonepolicy/trunk/gzo/plonepolicy/rest_hacks.py
U gzo.plonepolicy/trunk/gzo/plonepolicy/setuphandlers.py
-=-
Modified: gzo.plonepolicy/trunk/gzo/plonepolicy/__init__.py
===================================================================
--- gzo.plonepolicy/trunk/gzo/plonepolicy/__init__.py 2007-12-30 04:08:26 UTC (rev 82565)
+++ gzo.plonepolicy/trunk/gzo/plonepolicy/__init__.py 2007-12-30 04:10:03 UTC (rev 82566)
@@ -1,2 +1,7 @@
+#
+# ReST features that are not included in Plone 3.0.x that we are using
+#
+import rest_hacks
+
def initialize(context):
"""Intializer called when used as a Zope 2 product."""
Added: gzo.plonepolicy/trunk/gzo/plonepolicy/rest_hacks.py
===================================================================
--- gzo.plonepolicy/trunk/gzo/plonepolicy/rest_hacks.py (rev 0)
+++ gzo.plonepolicy/trunk/gzo/plonepolicy/rest_hacks.py 2007-12-30 04:10:03 UTC (rev 82566)
@@ -0,0 +1,125 @@
+"""
+Define and register a code-block directive using pygments.
+
+Define and register a sidebar directive.
+"""
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+from docutils.parsers.rst.directives.body import topic
+
+import pygments
+from pygments.lexers import get_lexer_by_name
+from pygments.formatters.html import _get_ttype_class
+
+#
+# code-block directive
+#
+
+unstyled_tokens = ['']
+
+class DocutilsInterface(object):
+ """Parse `code` string and yield "classified" tokens.
+
+ Arguments
+
+ code -- string of source code to parse
+ language -- formal language the code is written in.
+
+ Merge subsequent tokens of the same token-type.
+
+ Yields the tokens as ``(ttype_class, value)`` tuples,
+ where ttype_class is taken from pygments.token.STANDARD_TYPES and
+ corresponds to the class argument used in pygments html output.
+
+ """
+
+ def __init__(self, code, language):
+ self.code = code
+ self.language = language
+
+ def lex(self):
+ # Get lexer for language (use text as fallback)
+ try:
+ lexer = get_lexer_by_name(self.language)
+ except ValueError:
+ # info: "no pygments lexer for %s, using 'text'"%self.language
+ lexer = get_lexer_by_name('text')
+ return pygments.lex(self.code, lexer)
+
+
+ def join(self, tokens):
+ """join subsequent tokens of same token-type
+ """
+ tokens = iter(tokens)
+ (lasttype, lastval) = tokens.next()
+ for ttype, value in tokens:
+ if ttype is lasttype:
+ lastval += value
+ else:
+ yield(lasttype, lastval)
+ (lasttype, lastval) = (ttype, value)
+ yield(lasttype, lastval)
+
+ def __iter__(self):
+ """parse code string and yield "clasified" tokens
+ """
+ try:
+ tokens = self.lex()
+ except IOError:
+ print "INFO: Pygments lexer not found, using fallback"
+ # TODO: write message to INFO
+ yield ('', self.code)
+ return
+
+ for ttype, value in self.join(tokens):
+ yield (_get_ttype_class(ttype), value)
+
+
+
+def code_block_directive(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ """parse and classify content of a code_block
+ """
+ language = arguments[0]
+
+ # create a literal block element and set class argument
+ code_block = nodes.literal_block(classes=["code-block", language])
+
+ # parse content with pygments and add to code_block element
+ for cls, value in DocutilsInterface(u'\n'.join(content), language):
+ if cls in unstyled_tokens:
+ # insert as Text to decrease the verbosity of the output.
+ code_block += nodes.Text(value, value)
+ else:
+ code_block += nodes.inline(value, value, classes=[cls])
+
+ return [code_block]
+
+
+code_block_directive.arguments = (1, 0, 1)
+code_block_directive.content = 1
+directives.register_directive('code-block', code_block_directive)
+
+
+#
+# Sidebar directive
+#
+
+def sidebar(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ if isinstance(state_machine.node, nodes.sidebar):
+ error = state_machine.reporter.error(
+ 'The "%s" directive may not be used within a sidebar element.'
+ % name, nodes.literal_block(block_text, block_text), line=lineno)
+ return [error]
+ return topic(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine,
+ node_class=nodes.sidebar)
+
+sidebar.arguments = (1, 0, 1)
+sidebar.options = {'subtitle': directives.unchanged_required,
+ 'class': directives.class_option}
+sidebar.content = 1
+
+directives.register_directive('sidebar', sidebar)
Modified: gzo.plonepolicy/trunk/gzo/plonepolicy/setuphandlers.py
===================================================================
--- gzo.plonepolicy/trunk/gzo/plonepolicy/setuphandlers.py 2007-12-30 04:08:26 UTC (rev 82565)
+++ gzo.plonepolicy/trunk/gzo/plonepolicy/setuphandlers.py 2007-12-30 04:10:03 UTC (rev 82566)
@@ -82,7 +82,8 @@
def setupSampleContent(context):
"Sample content for providing something to add CSS too"
- # TODO: enable an easy way to skip this step
+ if context.readDataFile('gzo.sample_content.txt') is None:
+ return
# p is for plone site
p = context.getSite()
More information about the Checkins
mailing list