moved the DocutilsInterface class to pygments_code_block_directive.py
[pylit.git] / rstdocs / features / pygments_code_block_directive.py
blobe0d526771106a91d6192d07066cbe48f1810d3ae
1 #!/usr/bin/python
3 # :Author: a Pygments author|contributor; Felix Wiemann; Guenter Milde
4 # :Date: $Date: $
5 # :Copyright: This module has been placed in the public domain.
6 #
7 # This is a merge of `Using Pygments in ReST documents`_ from the pygments_
8 # documentation, and a `proof of concept`_ by Felix Wiemann.
9 #
10 # ========== ===========================================================
11 # 2007-06-01 Removed redundancy from class values.
12 # 2007-06-04 Merge of successive tokens of same type
13 # (code taken from pygments.formatters.others).
14 # 2007-06-05 Separate docutils formatter script
15 # Use pygments' CSS class names (like the html formatter)
16 # allowing the use of pygments-produced style sheets.
17 # 2007-06-07 Re-include the formatting of the parsed tokens
18 # (class DocutilsInterface)
19 # ========== ===========================================================
21 # ::
23 """Define and register a code-block directive using pygments
24 """
26 # Requirements
27 # ------------
28 # ::
30 from docutils import nodes
31 from docutils.parsers.rst import directives
32 import pygments
33 from pygments.lexers import get_lexer_by_name
34 from pygments.formatters.html import _get_ttype_class
36 # Customisation
37 # -------------
39 # Do not insert inline nodes for the following tokens.
40 # (You could add e.g. Token.Punctuation like ``['', 'p']``.) ::
42 unstyled_tokens = ['']
44 # DocutilsInterface
45 # -----------------
47 # This interface class combines code from
48 # pygments.formatters.html and pygments.formatters.others::
50 class DocutilsInterface(object):
51 """Yield tokens for addition to the docutils document tree.
53 Merge subsequent tokens of the same token-type.
55 Yields the tokens as ``(ttype_class, value)`` tuples,
56 where ttype_class is taken from pygments.token.STANDARD_TYPES and
57 corresponds to the class argument used in pygments html output.
59 """
60 name = 'docutils'
61 # aliases = ['docutils tokens']
63 def __init__(self, tokensource):
64 self.tokensource = tokensource
66 def __iter__(self):
67 lasttype = None
68 lastval = u''
69 for ttype, value in self.tokensource:
70 if ttype is lasttype:
71 lastval += value
72 else:
73 if lasttype:
74 yield(_get_ttype_class(lasttype), lastval)
75 lastval = value
76 lasttype = ttype
77 yield(_get_ttype_class(lasttype), lastval)
81 # code_block_directive
82 # --------------------
83 # ::
85 def code_block_directive(name, arguments, options, content, lineno,
86 content_offset, block_text, state, state_machine):
87 language = arguments[0]
88 # create a literal block element and set class argument
89 code_block = nodes.literal_block(raw_content=content,
90 classes=["code-block", language])
91 # Get lexer for language (use text as fallback)
92 try:
93 lexer = get_lexer_by_name(language)
94 except ValueError:
95 lexer = get_lexer_by_name('text')
97 # parse content with pygments
98 tokens = list(pygments.lex(u'\n'.join(content), lexer))
100 for cls, value in DocutilsInterface(tokens):
101 if cls in unstyled_tokens:
102 # insert as Text to decrease the verbosity of the output.
103 code_block += nodes.Text(value, value)
104 else:
105 code_block += nodes.inline(value, value, classes=[cls])
107 return [code_block]
110 # Register Directive
111 # ------------------
112 # ::
114 code_block_directive.arguments = (1, 0, 1)
115 code_block_directive.content = 1
116 directives.register_directive('code-block', code_block_directive)
118 # .. _doctutils: http://docutils.sf.net/
119 # .. _pygments: http://pygments.org/
120 # .. _Using Pygments in ReST documents: http://pygments.org/docs/rstdirective/
121 # .. _proof of concept:
122 # http://article.gmane.org/gmane.text.docutils.user/3689
124 # Test output
125 # -----------
127 # If called from the command line, call the docutils publisher to render the
128 # input::
130 if __name__ == '__main__':
131 from docutils.core import publish_cmdline, default_description
132 description = "code-block directive test output" + default_description
133 try:
134 import locale
135 locale.setlocale(locale.LC_ALL, '')
136 except:
137 pass
138 # Uncomment the desired output format:
139 publish_cmdline(writer_name='pseudoxml', description=description)
140 # publish_cmdline(writer_name='xml', description=description)
141 # publish_cmdline(writer_name='html', description=description)
142 # publish_cmdline(writer_name='latex', description=description)
143 # publish_cmdline(writer_name='newlatex2e', description=description)