3 # :Author: a Pygments author|contributor; Felix Wiemann; Guenter Milde
5 # :Copyright: This module has been placed in the public domain.
7 # This is a merge of `Using Pygments in ReST documents`_ from the pygments_
8 # documentation, and a `proof of concept`_ by Felix Wiemann.
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 # ========== ===========================================================
23 """Define and register a code-block directive using pygments
30 from docutils
import nodes
31 from docutils
.parsers
.rst
import directives
33 from pygments
.lexers
import get_lexer_by_name
34 from pygments
.formatters
.html
import _get_ttype_class
39 # Do not insert inline nodes for the following tokens.
40 # (You could add e.g. Token.Punctuation like ``['', 'p']``.) ::
42 unstyled_tokens
= ['']
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.
61 # aliases = ['docutils tokens']
63 def __init__(self
, tokensource
):
64 self
.tokensource
= tokensource
69 for ttype
, value
in self
.tokensource
:
74 yield(_get_ttype_class(lasttype
), lastval
)
77 yield(_get_ttype_class(lasttype
), lastval
)
81 # code_block_directive
82 # --------------------
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)
93 lexer
= get_lexer_by_name(language
)
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
)
105 code_block
+= nodes
.inline(value
, value
, classes
=[cls
])
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
127 # If called from the command line, call the docutils publisher to render the
130 if __name__
== '__main__':
131 from docutils
.core
import publish_cmdline
, default_description
132 description
= "code-block directive test output" + default_description
135 locale
.setlocale(locale
.LC_ALL
, '')
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)