summaryrefslogtreecommitdiff
path: root/sandbox/code-block-directive/pygments_code_block_directive.py
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/code-block-directive/pygments_code_block_directive.py')
-rwxr-xr-xsandbox/code-block-directive/pygments_code_block_directive.py248
1 files changed, 0 insertions, 248 deletions
diff --git a/sandbox/code-block-directive/pygments_code_block_directive.py b/sandbox/code-block-directive/pygments_code_block_directive.py
deleted file mode 100755
index 23b8f6a3d..000000000
--- a/sandbox/code-block-directive/pygments_code_block_directive.py
+++ /dev/null
@@ -1,248 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8
-
-# :Author: Georg Brandl; Felix Wiemann; Günter Milde
-# :Date: $Date$
-# :Copyright: This module has been placed in the public domain.
-#
-# This is a merge of `Using Pygments in ReST documents`_ from the pygments_
-# documentation, and a `proof of concept`_ by Felix Wiemann.
-#
-# .. class:: borderless
-#
-# ========== =============================================================
-# 2007-06-01 Removed redundancy from class values.
-# 2007-06-04 Merge of successive tokens of same type
-# (code taken from pygments.formatters.others).
-# 2007-06-05 Separate docutils formatter script
-# Use pygments' CSS class names (like the html formatter)
-# allowing the use of pygments-produced style sheets.
-# 2007-06-07 Merge in the formatting of the parsed tokens
-# (misnamed as docutils_formatter) as class DocutilsInterface
-# 2007-06-08 Failsave implementation (fallback to a standard literal block
-# if pygments not found)
-# 2010-11-27 Rename directive from "code-block" to "code".
-# Fix fallback if pygments not found.
-# Use class-based interface.
-# Add "number-lines" option.
-# ========== =============================================================
-#
-# ::
-
-"""Define and register a code directive using pygments"""
-
-# Requirements
-# ------------
-# ::
-
-from docutils import nodes
-from docutils.parsers.rst import directives, Directive
-from docutils.parsers.rst.roles import set_classes
-try:
- import pygments
- from pygments.lexers import get_lexer_by_name
- from pygments.formatters.html import _get_ttype_class
- with_pygments = True
-except ImportError:
- with_pygments = False
-
-# Customisation
-# -------------
-#
-# Do not insert inline nodes for the following tokens.
-# (You could add e.g. Token.Punctuation like ``['', 'p']``.) ::
-
-unstyled_tokens = [''] # Token.Text
-
-# Lexer
-# ---------
-#
-# This interface class combines code from
-# pygments.formatters.html and pygments.formatters.others.
-
-class Lexer(object):
- """Parse `code` lines and yield "classified" tokens.
-
- Arguments
-
- code -- list of source code lines to parse
- language -- formal language the code is written in.
-
- Merge subsequent tokens of the same token-type.
-
- Iterating over an instance 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):
- """
- Set up a lexical analyzer for `code` in `language`.
- """
- self.code = code
- self.language = language
- self.lexer = None
- # get lexical analyzer for `language`:
- if language in ('', 'text'):
- return
- if not with_pygments:
- raise ApplicationError('Cannot highlight code. '
- 'Pygments package not found.')
- try:
- self.lexer = get_lexer_by_name(self.language)
- except pygments.util.ClassNotFound:
- raise ApplicationError('Cannot highlight code. '
- 'No Pygments lexer found for "%s".' % language)
-
- # Since version 1.2. (released Jan 01, 2010) Pygments has a
- # TokenMergeFilter. ``self.merge(tokens)`` in __iter__ can be
- # replaced by ``self.lexer.add_filter('tokenmerge')`` in __init__.
-
- def merge(self, tokens):
- """Merge subsequent tokens of same token-type.
-
- Also strip the final '\n' (added by pygments).
- """
- 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)
- if lastval != '\n':
- yield(lasttype, lastval)
-
- def __iter__(self):
- """Parse self.code and yield "classified" tokens
- """
- codestring = u'\n'.join(self.code)
- if self.lexer is None:
- yield [('', codestring)]
- return
- tokens = pygments.lex(codestring, self.lexer)
- for ttype, value in self.merge(tokens):
- # yield (ttype, value) # token type objects
- yield (_get_ttype_class(ttype), value) # short name strings
-
-
-class NumberLines(object):
- """Insert linenumber-tokens in front of every newline.
-
- Arguments
-
- tokens -- iterable of ``(ttype_class, value)`` tuples
- startline -- first line number
- endline -- last line number
-
- Iterating over an instance yields the tokens preceded by
- a ``('ln', '<line number>')`` token for every line.
- Multi-line tokens from pygments are splitted. """
-
- def __init__(self, tokens, startline, endline):
- self.tokens = tokens
- self.startline = startline
- # pad linenumbers, e.g. endline == 100 -> fmt_str = '%3d '
- self.fmt_str = '%%%dd ' % len(str(endline))
-
- def __iter__(self):
- lineno = self.startline
- yield ('ln', self.fmt_str % lineno)
- for ttype, value in self.tokens:
- lines = value.split('\n')
- for line in lines[:-1]:
- yield (ttype, line + '\n')
- lineno += 1
- yield ('ln', self.fmt_str % lineno)
- yield (ttype, lines[-1])
-
-
-# CodeBlock directive
-# --------------------
-# ::
-
-class CodeBlock(Directive):
- """Parse and mark up content of a code block.
- """
- optional_arguments = 1
- option_spec = {'class': directives.class_option,
- 'name': directives.unchanged,
- 'number-lines': directives.unchanged # integer or None
- }
- has_content = True
-
- def run(self):
- self.assert_has_content()
- if self.arguments:
- language = self.arguments[0]
- else:
- language = ''
- set_classes(self.options)
- classes = ['code', language]
- if 'classes' in self.options:
- classes.extend(self.options['classes'])
-
- # TODO: config setting to skip lexical analysis:
- ## if document.settings.no_highlight:
- ## language = ''
-
- # set up lexical analyzer
- tokens = Lexer(self.content, language)
-
- if 'number-lines' in self.options:
- # optional argument `startline`, defaults to 1
- try:
- startline = int(self.options['number-lines'] or 1)
- except ValueError:
- raise self.error(':number-lines: with non-integer start value')
- endline = startline + len(self.content)
- # add linenumber filter:
- tokens = NumberLines(tokens, startline, endline)
-
- node = nodes.literal_block('\n'.join(self.content), classes=classes)
- self.add_name(node)
-
- # analyze content and add nodes for every token
- for cls, value in tokens:
- # print (cls, value)
- if cls in unstyled_tokens:
- # insert as Text to decrease the verbosity of the output.
- node += nodes.Text(value, value)
- else:
- node += nodes.inline(value, value, classes=[cls])
-
- return [node]
-
-
-# Register Directive
-# ------------------
-# ::
-
-directives.register_directive('code', CodeBlock)
-
-# .. _doctutils: http://docutils.sf.net/
-# .. _pygments: http://pygments.org/
-# .. _Using Pygments in ReST documents: http://pygments.org/docs/rstdirective/
-# .. _proof of concept:
-# http://article.gmane.org/gmane.text.docutils.user/3689
-#
-# Test output
-# -----------
-#
-# If called from the command line, call the docutils publisher to render the
-# input::
-
-if __name__ == '__main__':
- from docutils.core import publish_cmdline, default_description
- description = 'code-block directive test output' + default_description
- try:
- import locale
- locale.setlocale(locale.LC_ALL, '')
- except:
- pass
- # Uncomment the desired output format:
- # publish_cmdline(writer_name='pseudoxml', description=description)
- # publish_cmdline(writer_name='xml', description=description)
- # publish_cmdline(writer_name='html', description=description)
- publish_cmdline(writer_name='latex', description=description)