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 re
import sys
import string import string
import posixpath import posixpath
from os import path from os import path
@ -613,15 +614,42 @@ centered_directive.arguments = (1, 0, 1)
directives.register_directive('centered', centered_directive) directives.register_directive('centered', centered_directive)
# ------ highlightlanguage directive ------------------------------------------------ # ------ highlight directive --------------------------------------------------------
def highlightlang_directive(name, arguments, options, content, lineno, def highlightlang_directive(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine): 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.content = 0
highlightlang_directive.arguments = (1, 0, 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 --------------------------------------------------- # ------ literalinclude directive ---------------------------------------------------

View File

@ -19,8 +19,10 @@ try:
from pygments import highlight from pygments import highlight
from pygments.lexers import PythonLexer, PythonConsoleLexer, CLexer, \ from pygments.lexers import PythonLexer, PythonConsoleLexer, CLexer, \
TextLexer, RstLexer TextLexer, RstLexer
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter, LatexFormatter from pygments.formatters import HtmlFormatter, LatexFormatter
from pygments.filters import ErrorToken from pygments.filters import ErrorToken
from pygments.util import ClassNotFound
from pygments.style import Style from pygments.style import Style
from pygments.styles import get_style_by_name from pygments.styles import get_style_by_name
from pygments.styles.friendly import FriendlyStyle from pygments.styles.friendly import FriendlyStyle
@ -74,10 +76,12 @@ class PygmentsBridge(object):
style = SphinxStyle style = SphinxStyle
else: else:
style = get_style_by_name(stylename) style = get_style_by_name(stylename)
self.hfmter = HtmlFormatter(style=style) self.hfmter = {False: HtmlFormatter(style=style),
self.lfmter = LatexFormatter(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(): def unhighlighted():
if self.dest == 'html': if self.dest == 'html':
return '<pre>' + cgi.escape(source) + '</pre>\n' return '<pre>' + cgi.escape(source) + '</pre>\n'
@ -114,9 +118,14 @@ class PygmentsBridge(object):
else: else:
lexer = lexers['python'] lexer = lexers['python']
else: else:
if lang in lexers:
lexer = lexers[lang] lexer = lexers[lang]
else:
lexer = lexers[lang] = get_lexer_by_name(lang)
lexer.add_filter('raiseonerror')
try: 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: except ErrorToken:
# this is most probably not the selected language, so let it pass unhighlighted # this is most probably not the selected language, so let it pass unhighlighted
return unhighlighted() return unhighlighted()
@ -124,4 +133,4 @@ class PygmentsBridge(object):
def get_stylesheet(self): def get_stylesheet(self):
if not pygments: if not pygments:
return '' 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. :license: BSD.
""" """
import sys
from docutils import nodes from docutils import nodes
from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator
@ -50,6 +52,7 @@ class HTMLTranslator(BaseTranslator):
self.no_smarty = 0 self.no_smarty = 0
self.builder = builder self.builder = builder
self.highlightlang = 'python' self.highlightlang = 'python'
self.highlightlinenothreshold = sys.maxint
self.language.labels['warning'] = 'Caveat' self.language.labels['warning'] = 'Caveat'
def visit_desc(self, node): def visit_desc(self, node):
@ -175,8 +178,13 @@ class HTMLTranslator(BaseTranslator):
# overwritten # overwritten
def visit_literal_block(self, node): def visit_literal_block(self, node):
self.body.append(self.highlighter.highlight_block(node.rawsource, lang = self.highlightlang
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 raise nodes.SkipNode
# overwritten # overwritten
@ -224,6 +232,7 @@ class HTMLTranslator(BaseTranslator):
def visit_highlightlang(self, node): def visit_highlightlang(self, node):
self.highlightlang = node['lang'] self.highlightlang = node['lang']
self.highlightlinenothreshold = node['linenothreshold']
def depart_highlightlang(self, node): def depart_highlightlang(self, node):
pass pass

View File

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

View File

@ -704,6 +704,21 @@ pre {
border-right: none; 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 { tt {
background-color: #ecf0f3; background-color: #ecf0f3;
padding: 0 1px 0 1px; padding: 0 1px 0 1px;

View File

@ -37,6 +37,21 @@ pre {
background-color: #f8f8f8; 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 { cite, code, tt {
font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
font-size: 0.95em; font-size: 0.95em;