[Doc-SIG] code-block directive
Gael Varoquaux
gael.varoquaux at normalesup.org
Mon Nov 13 02:23:15 CET 2006
Hello,
I have added python-code syntax-highlighting. This feature has been hand
coded in extensions like the trac extension, or in rest2web. This leads
to variants of rest that are not compatible with docutils. I have thus
added a crude version of syntax-highlighting. The new directive follows
the trac directive:
.. code-block:: python
I have not coded support for other language than python, and the
directive default to a literal block if the language isn't python.
For the latex2e writer, where I was able to use the listings package, and
thus get free support for other languages. For the newlatex2e it is
impossible to use the listings package, as the code cannot be passed as
macro arguments (see section 5.1 of the listings manual).
This is a first draft and is probably of a lower quality then other
directive. I would like to push for inclusion of this new directive even
if it doesn't support all the features it could to regain language
compatibility with trac.
Comments on the patch are welcome.
Regards,
Gaël
-------------- next part --------------
Index: docutils/docutils/parsers/rst/directives/body.py
===================================================================
--- docutils/docutils/parsers/rst/directives/body.py (revision 4799)
+++ docutils/docutils/parsers/rst/directives/body.py (working copy)
@@ -108,7 +108,21 @@
node.line = self.content_offset + 1
return [node] + messages
+class CodeBlock(Directive):
+ required_arguments = 1
+ optional_arguments = 0
+ has_content = True
+
+ def run(self):
+ self.assert_has_content()
+ text = '\n'.join(self.content)
+ self.options['language'] = self.arguments[0]
+ node = nodes.code_block(text, text, **self.options)
+ node.line = self.content_offset + 1
+ return [node]
+
+
class Rubric(Directive):
required_arguments = 1
Index: docutils/docutils/parsers/rst/directives/__init__.py
===================================================================
--- docutils/docutils/parsers/rst/directives/__init__.py (revision 4799)
+++ docutils/docutils/parsers/rst/directives/__init__.py (working copy)
@@ -29,6 +29,7 @@
'topic': ('body', 'Topic'),
'line-block': ('body', 'LineBlock'),
'parsed-literal': ('body', 'ParsedLiteral'),
+ 'code-block': ('body', 'CodeBlock'),
'rubric': ('body', 'Rubric'),
'epigraph': ('body', 'Epigraph'),
'highlights': ('body', 'Highlights'),
Index: docutils/docutils/writers/html4css1/__init__.py
===================================================================
--- docutils/docutils/writers/html4css1/__init__.py (revision 4799)
+++ docutils/docutils/writers/html4css1/__init__.py (working copy)
@@ -21,6 +21,8 @@
import time
import re
from types import ListType
+import token, tokenize
+import cStringIO
try:
import Image # check for the Python Imaging Library
except ImportError:
@@ -28,8 +30,8 @@
import docutils
from docutils import frontend, nodes, utils, writers, languages
from docutils.transforms import writer_aux
+from docutils.colorizer import python2html
-
class Writer(writers.Writer):
supported = ('html', 'html4css1', 'xhtml')
@@ -1075,6 +1077,18 @@
# Content already processed:
raise nodes.SkipNode
+ def visit_code_block(self, node):
+ if node['language'] == 'python':
+ self.body.append(python2html(node.astext().encode('ascii')))
+ else:
+ self.body.append('<div class="pysrc">')
+ self.body.append(node.astext().encode('ascii'))
+ self.body.append('</div>\n')
+ raise nodes.SkipNode
+
+ def depart_code_block(self, node):
+ pass
+
def visit_literal_block(self, node):
self.body.append(self.starttag(node, 'pre', CLASS='literal-block'))
Index: docutils/docutils/writers/html4css1/html4css1.css
===================================================================
--- docutils/docutils/writers/html4css1/html4css1.css (revision 4799)
+++ docutils/docutils/writers/html4css1/html4css1.css (working copy)
@@ -273,3 +273,29 @@
ul.auto-toc {
list-style-type: none }
+
+/* Python syntax highlighting */
+.pysrc {
+ font-weight: normal;
+ background-color: #eef2f7;
+ background-position: right;
+ background-repeat: repeat-y;
+ border: 1px solid;
+ border-color: #999999;
+ margin: 20px;
+ padding:10px 10px 10px 20px;
+ font-size: smaller;
+ white-space: pre ;
+}
+
+.pykeyword {
+ font-weight: bold;
+ color: #262668 ;
+}
+.pycomment { color: #007600; }
+.pystring { color: #0000bb; }
+.pynumber { color:purple; }
+.pyoperator { color:purple; font-weight: bold; }
+.pytext { color:black; }
+.pyerror { font-weight: bold; color: red; }
+
Index: docutils/docutils/writers/latex2e/__init__.py
===================================================================
--- docutils/docutils/writers/latex2e/__init__.py (revision 4799)
+++ docutils/docutils/writers/latex2e/__init__.py (working copy)
@@ -639,6 +639,13 @@
'\\usepackage{amsmath}\n', # what fore amsmath.
self.graphicx_package,
'\\usepackage{color}\n',
+ '\\definecolor{darkgreen}{cmyk}{0.7, 0, 1, 0.5}\n',
+ '\\definecolor{darkblue}{cmyk}{1, 0.8, 0, 0}\n',
+ '\\definecolor{lightblue}{cmyk}{0.05,0,0,0.05}\n',
+ '\\definecolor{grey}{cmyk}{0.1,0.1,0.1,1}\n',
+ '\\definecolor{lightgrey}{cmyk}{0,0,0,0.5}\n',
+ '\\definecolor{purple}{cmyk}{0.8,1,0,0}\n',
+ '\\usepackage{listings}\n\\def\\codeblocksize{\\small}\n',
'\\usepackage{multirow}\n',
'\\usepackage{ifthen}\n', # before hyperref!
self.linking % (self.colorlinks, self.hyperlink_color, self.hyperlink_color),
@@ -1052,6 +1059,40 @@
def depart_classifier(self, node):
self.body.append( '})\n' )
+ def visit_code_block(self, node):
+ self.literal = 1
+ self.body.append(r"""
+{\codeblocksize
+\lstset{language=%s,
+ extendedchars=true,
+ basicstyle=\ttfamily,
+ keywordstyle=\sffamily\bfseries,
+ identifierstyle=\sffamily,
+ commentstyle=\slshape\color{darkgreen},
+ stringstyle=\rmfamily\color{blue},
+ showstringspaces=false,
+ tabsize=4,
+ breaklines=true,
+ classoffset=1,
+ otherkeywords={[,],=,:},
+ keywordstyle=\color{purple}\bfseries,
+ classoffset=0
+ escapebegin={\color{darkgreen}},
+ backgroundcolor=\color{lightblue},
+ fillcolor=\color{lightblue},
+ xleftmargin=0pt,
+ fillcolor=\color{white},
+ frame=single,
+ fillcolor=\color{lightblue},
+ rulecolor=\color{lightgrey},
+ basicstyle=\ttfamily\codeblocksize}
+\begin{lstlisting}{language=%s}
+""" %( node['language'], node['language']) )
+
+ def depart_code_block(self, node):
+ self.body.append('\n\\end{lstlisting}}\n')
+ self.literal = 0
+
def visit_colspec(self, node):
self.active_table.visit_colspec(node)
Index: docutils/docutils/writers/newlatex2e/__init__.py
===================================================================
--- docutils/docutils/writers/newlatex2e/__init__.py (revision 4799)
+++ docutils/docutils/writers/newlatex2e/__init__.py (working copy)
@@ -22,6 +22,7 @@
from docutils.writers.newlatex2e import unicode_map
from docutils.transforms import writer_aux
+from docutils.colorizer import python2latex
class Writer(writers.Writer):
@@ -402,6 +403,18 @@
visit_doctest_block = visit_literal_block
depart_doctest_block = depart_literal_block
+ def visit_code_block(self, node):
+ if node['language'] == 'python':
+ self.body.append(python2latex(node.astext().encode('ascii')))
+ else:
+ self.body.append('\n\\begin{verbatim}\n')
+ self.body.append(node.astext().encode('ascii'))
+ self.body.append('\n\\end{verbatim}\n')
+ raise nodes.SkipChildren
+
+ def depart_code_block(self, node):
+ pass
+
inline_literal = 0
def visit_literal(self, node):
Index: docutils/docutils/writers/newlatex2e/base.tex
===================================================================
--- docutils/docutils/writers/newlatex2e/base.tex (revision 4799)
+++ docutils/docutils/writers/newlatex2e/base.tex (working copy)
@@ -79,6 +79,12 @@
\usepackage[colorlinks=false,pdfborder={0 0 0}]{hyperref}
% Get color, e.g. for links and system messages.
\usepackage{color}
+ \definecolor{darkgreen}{cmyk}{0.7, 0, 1, 0.5}
+ \definecolor{darkblue}{cmyk}{1, 0.8, 0, 0}
+ \definecolor{lightblue}{cmyk}{0.05,0,0,0.05}
+ \definecolor{grey}{cmyk}{0.1,0.1,0.1,1}
+ \definecolor{lightgrey}{cmyk}{0,0,0,0.5}
+ \definecolor{purple}{cmyk}{0.8,1,0,0}
% Get \textnhtt macro (non-hyphenating type writer).
\usepackage{hyphenat}
% For sidebars.
@@ -113,6 +119,7 @@
\renewcommand{\texteuro}{\euro}%
}
+
% Taken from
% <http://groups.google.de/groups?selm=1i0n5tgtplti420e1omp4pctlv19jpuhbb%404ax.com>
% and modified. Used with permission.
@@ -413,6 +420,21 @@
\csname D\DEVparent subtitle\endcsname{#1}%
}
+\providecommand{\pynumber}[1]{\color{purple} #1}
+\providecommand{\pyoperator}[1]{{\bfseries\textcolor{purple}{#1}}}
+\providecommand{\pystring}[1]{{\rmfamily\textcolor{blue}{#1}}}
+\providecommand{\pycomment}[1]{{\slshape\textcolor{darkgreen}{#1}}}
+\providecommand{\pyerror}[1]{{\bfseries\textcolor{red}{#1}}}
+\providecommand{\pykeyword}[1]{{\sffamily\bfseries\textcolor{darkblue}{#1}}}
+\providecommand{\pytext}[1]{{\sffamily #1}}
+\providecommand{\DNcodeblock}[1]{%
+\fcolorbox{black}{lightblue}{%
+\begin{minipage}{\linewidth}%
+\small%
+#1
+\end{minipage}%
+}
+}
\providecommand{\DNliteralblock}[1]{%
\Dmakelistenvironment{}{%
\ifthenelse{\equal{\Dinsidetabular}{true}}{%
Index: docutils/docutils/nodes.py
===================================================================
--- docutils/docutils/nodes.py (revision 4799)
+++ docutils/docutils/nodes.py (working copy)
@@ -1267,6 +1267,7 @@
class option_string(Part, TextElement): pass
class description(Part, Element): pass
class literal_block(General, FixedTextElement): pass
+class code_block(General, FixedTextElement): pass
class doctest_block(General, FixedTextElement): pass
class line_block(General, Element): pass
@@ -1447,8 +1448,8 @@
abbreviation acronym address admonition attention attribution author
authors
block_quote bullet_list
- caption caution citation citation_reference classifier colspec comment
- compound contact container copyright
+ caption caution citation citation_reference classifier code_blockcolspec
+ comment compound contact container copyright
danger date decoration definition definition_list definition_list_item
description docinfo doctest_block document
emphasis entry enumerated_list error
More information about the Doc-SIG
mailing list