Add code-block directive, to simplify integrating snippets

in other languages, and with line numbers.
This commit is contained in:
Georg Brandl 2008-03-09 19:45:54 +00:00
parent 910e488e39
commit f2ff0419bd
6 changed files with 100 additions and 16 deletions

View File

@ -10,6 +10,7 @@
"""
import re
import sys
import string
import posixpath
from os import path
@ -613,15 +614,42 @@ centered_directive.arguments = (1, 0, 1)
directives.register_directive('centered', centered_directive)
# ------ highlightlanguage directive ------------------------------------------------
# ------ highlight directive --------------------------------------------------------
def highlightlang_directive(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
return [addnodes.highlightlang(lang=arguments[0].strip())]
if 'linenothreshold' in options:
try:
linenothreshold = int(options['linenothreshold'])
except Exception:
linenothreshold = 10
else:
linenothreshold = sys.maxint
return [addnodes.highlightlang(lang=arguments[0].strip(),
linenothreshold=linenothreshold)]
highlightlang_directive.content = 0
highlightlang_directive.arguments = (1, 0, 0)
directives.register_directive('highlightlang', highlightlang_directive)
highlightlang_directive.options = {'linenothreshold': directives.unchanged}
directives.register_directive('highlight', highlightlang_directive)
directives.register_directive('highlightlang', highlightlang_directive) # old name
# ------ code-block directive -------------------------------------------------------
def codeblock_directive(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
code = u'\n'.join(content)
literal = nodes.literal_block(code, code)
literal['language'] = arguments[0]
literal['linenos'] = 'linenos' in options
return [literal]
codeblock_directive.content = 1
codeblock_directive.arguments = (1, 0, 0)
codeblock_directive.options = {'linenos': directives.flag}
directives.register_directive('code-block', codeblock_directive)
directives.register_directive('sourcecode', codeblock_directive)
# ------ literalinclude directive ---------------------------------------------------

View File

@ -19,8 +19,10 @@ try:
from pygments import highlight
from pygments.lexers import PythonLexer, PythonConsoleLexer, CLexer, \
TextLexer, RstLexer
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter, LatexFormatter
from pygments.filters import ErrorToken
from pygments.util import ClassNotFound
from pygments.style import Style
from pygments.styles import get_style_by_name
from pygments.styles.friendly import FriendlyStyle
@ -74,10 +76,12 @@ class PygmentsBridge(object):
style = SphinxStyle
else:
style = get_style_by_name(stylename)
self.hfmter = HtmlFormatter(style=style)
self.lfmter = LatexFormatter(style=style)
self.hfmter = {False: HtmlFormatter(style=style),
True: HtmlFormatter(style=style, linenos=True)}
self.lfmter = {False: LatexFormatter(style=style),
True: LatexFormatter(style=style, linenos=True)}
def highlight_block(self, source, lang):
def highlight_block(self, source, lang, linenos=False):
def unhighlighted():
if self.dest == 'html':
return '<pre>' + cgi.escape(source) + '</pre>\n'
@ -114,9 +118,14 @@ class PygmentsBridge(object):
else:
lexer = lexers['python']
else:
lexer = lexers[lang]
if lang in lexers:
lexer = lexers[lang]
else:
lexer = lexers[lang] = get_lexer_by_name(lang)
lexer.add_filter('raiseonerror')
try:
return highlight(source, lexer, self.dest == 'html' and self.hfmter or self.lfmter)
fmter = (self.dest == 'html' and self.hfmter or self.lfmter)[bool(linenos)]
return highlight(source, lexer, fmter)
except ErrorToken:
# this is most probably not the selected language, so let it pass unhighlighted
return unhighlighted()
@ -124,4 +133,4 @@ class PygmentsBridge(object):
def get_stylesheet(self):
if not pygments:
return ''
return (self.dest == 'html' and self.hfmter or self.lfmter).get_style_defs()
return (self.dest == 'html' and self.hfmter or self.lfmter)[0].get_style_defs()

View File

@ -9,6 +9,8 @@
:license: BSD.
"""
import sys
from docutils import nodes
from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator
@ -50,6 +52,7 @@ class HTMLTranslator(BaseTranslator):
self.no_smarty = 0
self.builder = builder
self.highlightlang = 'python'
self.highlightlinenothreshold = sys.maxint
self.language.labels['warning'] = 'Caveat'
def visit_desc(self, node):
@ -175,8 +178,13 @@ class HTMLTranslator(BaseTranslator):
# overwritten
def visit_literal_block(self, node):
self.body.append(self.highlighter.highlight_block(node.rawsource,
self.highlightlang))
lang = self.highlightlang
linenos = node.rawsource.count('\n') >= self.highlightlinenothreshold - 1
if node.has_key('language'):
# code-block directives
lang = node['language']
linenos = node['linenos']
self.body.append(self.highlighter.highlight_block(node.rawsource, lang, linenos))
raise nodes.SkipNode
# overwritten
@ -224,6 +232,7 @@ class HTMLTranslator(BaseTranslator):
def visit_highlightlang(self, node):
self.highlightlang = node['lang']
self.highlightlinenothreshold = node['linenothreshold']
def depart_highlightlang(self, node):
pass

View File

@ -13,6 +13,7 @@
"""
import re
import sys
import time
from docutils import nodes, writers
@ -76,7 +77,7 @@ class TableSpec:
class Desc:
def __init__(self, node):
self.env = LaTeXTranslator.desc_map[node['desctype']]
self.env = LaTeXTranslator.desc_map.get(node['desctype'], 'describe')
self.ni = node['noindex']
self.type = self.cls = self.name = self.params = ''
self.count = 0
@ -109,6 +110,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.context = []
self.descstack = []
self.highlightlang = 'python'
self.highlightlinenothreshold = sys.maxint
self.written_ids = set()
if docclass == 'manual':
self.top_sectionlevel = 0
@ -141,6 +143,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_highlightlang(self, node):
self.highlightlang = node['lang']
self.highlightlinenothreshold = node['linenothreshold']
raise nodes.SkipNode
def visit_comment(self, node):
@ -239,8 +242,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
'cvar': 'cvardesc',
'describe': 'describe',
'cmdoption': 'describe',
'envvar': 'describe',
# and all others are 'describe' too
}
def visit_desc(self, node):
@ -646,8 +648,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_literal_block(self, node):
self.verbatim = ''
def depart_literal_block(self, node):
hlcode = self.highlighter.highlight_block(self.verbatim.rstrip('\n'),
self.highlightlang)
code = self.verbatim.rstrip('\n')
lang = self.highlightlang
linenos = code.count('\n') >= self.highlightlinenothreshold - 1
if node.has_key('language'):
# code-block directives
lang = node['language']
linenos = node['linenos']
hlcode = self.highlighter.highlight_block(code, lang, linenos)
# workaround for Unicode issue
hlcode = hlcode.replace(u'', u'@texteuro[]')
# workaround for Pygments bug

View File

@ -704,6 +704,21 @@ pre {
border-right: none;
}
td.linenos pre {
padding: 0;
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
margin-left: 0.5em;
}
table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
tt {
background-color: #ecf0f3;
padding: 0 1px 0 1px;

View File

@ -37,6 +37,21 @@ pre {
background-color: #f8f8f8;
}
td.linenos pre {
padding: 0;
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
margin-left: 0.5em;
}
table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
cite, code, tt {
font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
font-size: 0.95em;