# HG changeset patch # User cmlenz # Date 1181124389 0 # Node ID cabd80e75dad58ce2e776a7137dfe563286cbeea # Parent c006015dc52d5af5944de6c7763d08f28c5f5db4 Enable syntax highlighting (with Pygments) on doc page. diff --git a/doc/streams.txt b/doc/streams.txt --- a/doc/streams.txt +++ b/doc/streams.txt @@ -22,7 +22,9 @@ * programmatically generated. For example, the functions ``XML()`` and ``HTML()`` can be used to convert -literal XML or HTML text to a markup stream:: +literal XML or HTML text to a markup stream: + +.. code-block:: python >>> from genshi import XML >>> stream = XML('

Some text and ' @@ -41,7 +43,7 @@ * ``pos`` is a ``(filename, lineno, column)`` tuple that describes where the event “comes from”. -:: +.. code-block:: python >>> for kind, data, pos in stream: ... print kind, `data`, pos @@ -64,7 +66,9 @@ stream, either filters that come with Genshi, or your own custom filters. A filter is simply a callable that accepts the stream as parameter, and returns -the filtered stream:: +the filtered stream: + +.. code-block:: python def noop(stream): """A filter that doesn't actually do anything with the stream.""" @@ -72,17 +76,23 @@ yield kind, data, pos Filters can be applied in a number of ways. The simplest is to just call the -filter directly:: +filter directly: + +.. code-block:: python stream = noop(stream) The ``Stream`` class also provides a ``filter()`` method, which takes an -arbitrary number of filter callables and applies them all:: +arbitrary number of filter callables and applies them all: + +.. code-block:: python stream = stream.filter(noop) Finally, filters can also be applied using the *bitwise or* operator (``|``), -which allows a syntax similar to pipes on Unix shells:: +which allows a syntax similar to pipes on Unix shells: + +.. code-block:: python stream = stream | noop @@ -90,17 +100,23 @@ ``genshi.filters``. It processes a stream of HTML markup, and strips out any potentially dangerous constructs, such as Javascript event handlers. ``HTMLSanitizer`` is not a function, but rather a class that implements -``__call__``, which means instances of the class are callable:: +``__call__``, which means instances of the class are callable: + +.. code-block:: python stream = stream | HTMLSanitizer() Both the ``filter()`` method and the pipe operator allow easy chaining of -filters:: +filters: + +.. code-block:: python from genshi.filters import HTMLSanitizer stream = stream.filter(noop, HTMLSanitizer()) -That is equivalent to:: +That is equivalent to: + +.. code-block:: python stream = stream | noop | HTMLSanitizer() @@ -121,7 +137,9 @@ (which are basically unicode strings that are considered safe for output on the web). The latter returns a single string, by default UTF-8 encoded. -Here's the output from ``serialize()``:: +Here's the output from ``serialize()``: + +.. code-block:: python >>> for output in stream.serialize(): ... print `output` @@ -135,14 +153,18 @@ '> '> -And here's the output from ``render()``:: +And here's the output from ``render()``: + +.. code-block:: python >>> print stream.render()

Some text and a link.

Both methods can be passed a ``method`` parameter that determines how exactly the events are serialzed to text. This parameter can be either “xml” (the -default), “xhtml”, “html”, “text”, or a custom serializer class:: +default), “xhtml”, “html”, “text”, or a custom serializer class: + +.. code-block:: python >>> print stream.render('html')

Some text and a link.

@@ -154,14 +176,18 @@ defaults to “UTF-8”. If set to ``None``, the result will be a unicode string. The different serializer classes in ``genshi.output`` can also be used -directly:: +directly: + +.. code-block:: python >>> from genshi.filters import HTMLSanitizer >>> from genshi.output import TextSerializer >>> print ''.join(TextSerializer()(HTMLSanitizer()(stream))) Some text and a link. -The pipe operator allows a nicer syntax:: +The pipe operator allows a nicer syntax: + +.. code-block:: python >>> print stream | HTMLSanitizer() | TextSerializer() Some text and a link. @@ -200,7 +226,9 @@ =========== XPath can be used to extract a specific subset of the stream via the -``select()`` method:: +``select()`` method: + +.. code-block:: python >>> substream = stream.select('a') >>> substream @@ -211,7 +239,9 @@ Often, streams cannot be reused: in the above example, the sub-stream is based on a generator. Once it has been serialized, it will have been fully consumed, and cannot be rendered again. To work around this, you can wrap such a stream -in a ``list``:: +in a ``list``: + +.. code-block:: python >>> from genshi import Stream >>> substream = Stream(list(stream.select('a'))) @@ -251,7 +281,9 @@ ``(tagname, attrs)``, where ``tagname`` is a ``QName`` instance describing the qualified name of the tag, and ``attrs`` is an ``Attrs`` instance containing the attribute names and values associated with the tag (excluding namespace -declarations):: +declarations): + +.. code-block:: python START, (QName(u'p'), Attrs([(u'class', u'intro')])), pos @@ -260,7 +292,9 @@ The closing tag of an element. The ``data`` item of end events consists of just a ``QName`` instance -describing the qualified name of the tag:: +describing the qualified name of the tag: + +.. code-block:: python END, QName(u'p'), pos @@ -268,7 +302,9 @@ ---- Character data outside of elements and comments. -For text events, the ``data`` item should be a unicode object:: +For text events, the ``data`` item should be a unicode object: + +.. code-block:: python TEXT, u'Hello, world!', pos @@ -279,7 +315,9 @@ The ``data`` item of this kind of event is a tuple of the form ``(prefix, uri)``, where ``prefix`` is the namespace prefix and ``uri`` is the full URI to which the prefix is bound. Both should be unicode objects. If the -namespace is not bound to any prefix, the ``prefix`` item is an empty string:: +namespace is not bound to any prefix, the ``prefix`` item is an empty string: + +.. code-block:: python START_NS, (u'svg', u'http://www.w3.org/2000/svg'), pos @@ -288,7 +326,9 @@ The end of a namespace mapping. The ``data`` item of such events consists of only the namespace prefix (a -unicode object):: +unicode object): + +.. code-block:: python END_NS, u'svg', pos @@ -299,7 +339,9 @@ For this type of event, the ``data`` item is a tuple of the form ``(name, pubid, sysid)``, where ``name`` is the name of the root element, ``pubid`` is the public identifier of the DTD (or ``None``), and ``sysid`` is -the system identifier of the DTD (or ``None``):: +the system identifier of the DTD (or ``None``): + +.. code-block:: python DOCTYPE, (u'html', u'-//W3C//DTD XHTML 1.0 Transitional//EN', \ u'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'), pos @@ -309,7 +351,9 @@ A comment. For such events, the ``data`` item is a unicode object containing all character -data between the comment delimiters:: +data between the comment delimiters: + +.. code-block:: python COMMENT, u'Commented out', pos @@ -320,7 +364,9 @@ The ``data`` item is a tuple of the form ``(target, data)`` for processing instructions, where ``target`` is the target of the PI (used to identify the application by which the instruction should be processed), and ``data`` is text -following the target (excluding the terminating question mark):: +following the target (excluding the terminating question mark): + +.. code-block:: python PI, (u'php', u'echo "Yo" '), pos @@ -328,7 +374,9 @@ ----------- Marks the beginning of a ``CDATA`` section. -The ``data`` item for such events is always ``None``:: +The ``data`` item for such events is always ``None``: + +.. code-block:: python START_CDATA, None, pos @@ -336,6 +384,8 @@ --------- Marks the end of a ``CDATA`` section. -The ``data`` item for such events is always ``None``:: +The ``data`` item for such events is always ``None``: + +.. code-block:: python END_CDATA, None, pos diff --git a/doc/style/edgewall.css b/doc/style/edgewall.css --- a/doc/style/edgewall.css +++ b/doc/style/edgewall.css @@ -1,4 +1,5 @@ -@import(docutils.css); +@import url(docutils.css); +@import url(pygments.css); html, body { height: 100%; margin: 0; padding: 0; } html, body { background: #4b4d4d url(bkgnd_pattern.png); color: #000; } @@ -45,8 +46,9 @@ h1.title { background: url(vertbars.png) repeat-x; } div.document#genshi h1.title { text-indent: -4000px; } div.document#genshi h1 { text-align: center; } -pre.literal-block { background: #d7d7d7; border: 1px solid #e6e6e6; color: #000; - margin: 1em 1em; padding: .25em; overflow: auto; +pre.literal-block, div.highlight pre { background: #f4f4f4; + border: 1px solid #e6e6e6; color: #000; margin: 1em 1em; padding: .25em; + overflow: auto; } div.contents { font-size: 90%; position: absolute; position: fixed; @@ -61,7 +63,9 @@ color: #fff; } -p.admonition-title { font-weight: bold; margin-bottom: 0; } -div.note, div.warning { font-style: italic; margin-left: 2em; - margin-right: 2em; +div.admonition, div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning { + border: none; color: #333; font-style: italic; margin: 1em 2em; } +p.admonition-title { margin-bottom: 0; } +div.note, div.warning { font-style: italic; } diff --git a/doc/style/pygments.css b/doc/style/pygments.css new file mode 100644 --- /dev/null +++ b/doc/style/pygments.css @@ -0,0 +1,57 @@ +div.highlight { background: #ffffff; } +div.highlight .c { color: #999988; font-style: italic } +div.highlight .err { color: #a61717; background-color: #e3d2d2 } +div.highlight .k { font-weight: bold } +div.highlight .o { font-weight: bold } +div.highlight .cm { color: #999988; font-style: italic } +div.highlight .cp { color: #999999; font-weight: bold } +div.highlight .c1 { color: #999988; font-style: italic } +div.highlight .cs { color: #999999; font-weight: bold; font-style: italic } +div.highlight .gd { color: #000000; background-color: #ffdddd } +div.highlight .ge { font-style: italic } +div.highlight .gr { color: #aa0000 } +div.highlight .gh { color: #999999 } +div.highlight .gi { color: #000000; background-color: #ddffdd } +div.highlight .go { color: #888888 } +div.highlight .gp { color: #555555 } +div.highlight .gs { font-weight: bold } +div.highlight .gu { color: #aaaaaa } +div.highlight .gt { color: #aa0000 } +div.highlight .kc { font-weight: bold } +div.highlight .kd { font-weight: bold } +div.highlight .kp { font-weight: bold } +div.highlight .kr { font-weight: bold } +div.highlight .kt { color: #445588; font-weight: bold } +div.highlight .m { color: #009999 } +div.highlight .s { color: #bb8844 } +div.highlight .na { color: #008080 } +div.highlight .nb { color: #999999 } +div.highlight .nc { color: #445588; font-weight: bold } +div.highlight .no { color: #008080 } +div.highlight .ni { color: #800080 } +div.highlight .ne { color: #990000; font-weight: bold } +div.highlight .nf { color: #990000; font-weight: bold } +div.highlight .nn { color: #555555 } +div.highlight .nt { color: #000080 } +div.highlight .nv { color: #008080 } +div.highlight .ow { font-weight: bold } +div.highlight .mf { color: #009999 } +div.highlight .mh { color: #009999 } +div.highlight .mi { color: #009999 } +div.highlight .mo { color: #009999 } +div.highlight .sb { color: #bb8844 } +div.highlight .sc { color: #bb8844 } +div.highlight .sd { color: #bb8844 } +div.highlight .s2 { color: #bb8844 } +div.highlight .se { color: #bb8844 } +div.highlight .sh { color: #bb8844 } +div.highlight .si { color: #bb8844 } +div.highlight .sx { color: #bb8844 } +div.highlight .sr { color: #808000 } +div.highlight .s1 { color: #bb8844 } +div.highlight .ss { color: #bb8844 } +div.highlight .bp { color: #999999 } +div.highlight .vc { color: #008080 } +div.highlight .vg { color: #008080 } +div.highlight .vi { color: #008080 } +div.highlight .il { color: #009999 } diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -35,9 +35,29 @@ def run(self): from docutils.core import publish_cmdline + from docutils.nodes import raw + from docutils.parsers import rst + docutils_conf = os.path.join('doc', 'docutils.conf') epydoc_conf = os.path.join('doc', 'epydoc.conf') + try: + from pygments import highlight + from pygments.lexers import get_lexer_by_name + from pygments.formatters import HtmlFormatter + + def code_block(name, arguments, options, content, lineno, + content_offset, block_text, state, state_machine): + lexer = get_lexer_by_name(arguments[0]) + html = highlight('\n'.join(content), lexer, HtmlFormatter()) + return [raw('', html, format='html')] + code_block.arguments = (1, 0, 0) + code_block.options = {'language' : rst.directives.unchanged} + code_block.content = 1 + rst.directives.register_directive('code-block', code_block) + except ImportError: + print 'Pygments not installed, syntax highlighting disabled' + for source in glob('doc/*.txt'): dest = os.path.splitext(source)[0] + '.html' if not os.path.exists(dest) or \ @@ -58,7 +78,6 @@ ] cli.cli() sys.argv[1:] = old_argv - except ImportError: print 'epydoc not installed, skipping API documentation.'