[Python-checkins] r65630 - in doctools/trunk: Makefile doc/markup/inline.rst sphinx/builder.py sphinx/environment.py sphinx/highlighting.py sphinx/latexwriter.py sphinx/util/texescape.py tests/test_markup.py
georg.brandl
python-checkins at python.org
Sun Aug 10 18:59:28 CEST 2008
Author: georg.brandl
Date: Sun Aug 10 18:59:27 2008
New Revision: 65630
Log:
Merged revisions 65566-65567,65623,65625 via svnmerge from
svn+ssh://pythondev@svn.python.org/doctools/branches/0.4.x
........
r65566 | georg.brandl | 2008-08-07 09:11:11 +0000 (Thu, 07 Aug 2008) | 2 lines
Clarification for the ref role.
........
r65567 | georg.brandl | 2008-08-07 09:11:25 +0000 (Thu, 07 Aug 2008) | 2 lines
Rebuild everything if extensions change.
........
r65623 | georg.brandl | 2008-08-10 11:18:42 +0000 (Sun, 10 Aug 2008) | 2 lines
Unify handling of LaTeX escaping, and add some more replacements.
........
r65625 | georg.brandl | 2008-08-10 11:25:41 +0000 (Sun, 10 Aug 2008) | 2 lines
Make tex escapes a module.
........
Added:
doctools/trunk/sphinx/util/texescape.py
- copied unchanged from r65625, /doctools/branches/0.4.x/sphinx/util/texescape.py
Modified:
doctools/trunk/ (props changed)
doctools/trunk/Makefile
doctools/trunk/doc/markup/inline.rst
doctools/trunk/sphinx/builder.py
doctools/trunk/sphinx/environment.py
doctools/trunk/sphinx/highlighting.py
doctools/trunk/sphinx/latexwriter.py
doctools/trunk/tests/test_markup.py
Modified: doctools/trunk/Makefile
==============================================================================
--- doctools/trunk/Makefile (original)
+++ doctools/trunk/Makefile Sun Aug 10 18:59:27 2008
@@ -4,7 +4,7 @@
.PHONY: all check clean clean-pyc clean-patchfiles pylint reindent test
-all: clean-pyc check
+all: clean-pyc check test
check:
@$(PYTHON) utils/check_sources.py -i sphinx/style/jquery.js sphinx
Modified: doctools/trunk/doc/markup/inline.rst
==============================================================================
--- doctools/trunk/doc/markup/inline.rst (original)
+++ doctools/trunk/doc/markup/inline.rst Sun Aug 10 18:59:27 2008
@@ -182,10 +182,12 @@
Cross-referencing arbitrary locations
-------------------------------------
-To support cross-referencing to arbitrary locations in the documentation, the
-standard reST labels used. Of course, for this to work label names must be
-unique throughout the entire documentation. There are two ways in which you can
-refer to labels:
+.. index:: pair: ref; role
+
+To support cross-referencing to arbitrary locations in any document, the
+standard reST labels are used. For this to work label names must be unique
+throughout the entire documentation. There are two ways in which you can refer
+to labels:
* If you place a label directly before a section title, you can reference to it
with ``:ref:`label-name```. Example::
@@ -200,12 +202,17 @@
It refers to the section itself, see :ref:`my-reference-label`.
The ``:ref:`` role would then generate a link to the section, with the link
- title being "Section to cross-reference".
+ title being "Section to cross-reference". This works just as well when
+ section and reference are in different source files.
* Labels that aren't placed before a section title can still be referenced to,
but you must give the link an explicit title, using this syntax: ``:ref:`Link
title <label-name>```.
+Using :role:`ref` is advised over standard reStructuredText links to sections
+(like ```Section title`_``) because it works across files, when section headings
+are changed, and for all builders that support cross-references.
+
Other semantic markup
---------------------
Modified: doctools/trunk/sphinx/builder.py
==============================================================================
--- doctools/trunk/sphinx/builder.py (original)
+++ doctools/trunk/sphinx/builder.py Sun Aug 10 18:59:27 2008
@@ -26,7 +26,7 @@
from docutils.readers.doctree import Reader as DoctreeReader
from sphinx import addnodes, locale, __version__
-from sphinx.util import ensuredir, relative_uri, SEP, os_path, json
+from sphinx.util import ensuredir, relative_uri, SEP, os_path, json, texescape
from sphinx.htmlhelp import build_hhx
from sphinx.htmlwriter import HTMLWriter, HTMLTranslator, SmartyPantsHTMLTranslator
from sphinx.textwriter import TextWriter
@@ -899,6 +899,7 @@
def init(self):
self.docnames = []
self.document_data = []
+ texescape.init()
def get_outdated_docs(self):
return 'all documents' # for now
Modified: doctools/trunk/sphinx/environment.py
==============================================================================
--- doctools/trunk/sphinx/environment.py (original)
+++ doctools/trunk/sphinx/environment.py Sun Aug 10 18:59:27 2008
@@ -418,6 +418,11 @@
break
else:
msg = ''
+ # this value is not covered by the above loop because it is handled
+ # specially by the config class
+ if self.config.extensions != config.extensions:
+ msg = '[extensions changed] '
+ config_changed = True
# the source and doctree directories may have been relocated
self.srcdir = srcdir
self.doctreedir = doctreedir
Modified: doctools/trunk/sphinx/highlighting.py
==============================================================================
--- doctools/trunk/sphinx/highlighting.py (original)
+++ doctools/trunk/sphinx/highlighting.py Sun Aug 10 18:59:27 2008
@@ -14,6 +14,8 @@
import re
import parser
+from sphinx.util.texescape import tex_hl_escape_map
+
try:
import pygments
from pygments import highlight
@@ -56,14 +58,9 @@
_lexer.add_filter('raiseonerror')
-
-def escape_tex(text):
- return text.replace('@', '\x00'). \
- replace('[', '\x01'). \
- replace(']', '\x02'). \
- replace('\x00', '@at[]').\
- replace('\x01', '@lb[]').\
- replace('\x02', '@rb[]')
+escape_hl_chars = {ord(u'@'): u'@at[]',
+ ord(u'['): u'@lb[]',
+ ord(u']'): u'@rb[]'}
# used if Pygments is not available
_LATEX_STYLES = r'''
@@ -98,15 +95,20 @@
True: LatexFormatter(style=style, linenos=True,
commandprefix='PYG')}
+ def unhighlighted(self, source):
+ if self.dest == 'html':
+ return '<pre>' + cgi.escape(source) + '</pre>\n'
+ else:
+ # first, escape highlighting characters like Pygments does
+ source = source.translate(escape_hl_chars)
+ # then, escape all characters nonrepresentable in LaTeX
+ source = source.translate(tex_hl_escape_map)
+ return '\\begin{Verbatim}[commandchars=@\\[\\]]\n' + \
+ source + '\\end{Verbatim}\n'
+
def highlight_block(self, source, lang, linenos=False):
- def unhighlighted():
- if self.dest == 'html':
- return '<pre>' + cgi.escape(source) + '</pre>\n'
- else:
- return '\\begin{Verbatim}[commandchars=@\\[\\]]\n' + \
- escape_tex(source) + '\\end{Verbatim}\n'
if not pygments:
- return unhighlighted()
+ return self.unhighlighted(source)
if lang == 'python':
if source.startswith('>>>'):
# interactive session
@@ -138,7 +140,7 @@
try:
parser.suite(src)
except parsing_exceptions:
- return unhighlighted()
+ return self.unhighlighted(source)
else:
lexer = lexers['python']
else:
@@ -148,12 +150,15 @@
lexer = lexers[lang] = get_lexer_by_name(lang)
lexer.add_filter('raiseonerror')
try:
- fmter = (self.dest == 'html' and self.hfmter or self.lfmter)[bool(linenos)]
- return highlight(source, lexer, fmter)
+ if self.dest == 'html':
+ return highlight(source, lexer, self.hfmter[bool(linenos)])
+ else:
+ hlsource = highlight(source, lexer, self.lfmter[bool(linenos)])
+ return hlsource.translate(tex_hl_escape_map)
except ErrorToken:
# this is most probably not the selected language,
# so let it pass unhighlighted
- return unhighlighted()
+ return self.unhighlighted(source)
def get_stylesheet(self):
if not pygments:
Modified: doctools/trunk/sphinx/latexwriter.py
==============================================================================
--- doctools/trunk/sphinx/latexwriter.py (original)
+++ doctools/trunk/sphinx/latexwriter.py Sun Aug 10 18:59:27 2008
@@ -23,6 +23,7 @@
from sphinx import addnodes
from sphinx import highlighting
from sphinx.locale import admonitionlabels, versionlabels
+from sphinx.util.texescape import tex_escape_map
from sphinx.util.smartypants import educateQuotesLatex
HEADER = r'''%% Generated by Sphinx.
@@ -42,7 +43,7 @@
BEGIN_DOC = r'''
\begin{document}
-\shorthandoff{"}
+%(shorthandoff)s
\maketitle
\tableofcontents
'''
@@ -87,6 +88,13 @@
# Helper classes
+class ExtBabel(Babel):
+ def get_shorthandoff(self):
+ if self.language == 'de':
+ return '\\shorthandoff{"}'
+ return ''
+
+
class Table(object):
def __init__(self):
self.col = 0
@@ -120,7 +128,7 @@
paper = 'letterpaper'
date = time.strftime(builder.config.today_fmt or _('%B %d, %Y'))
logo = (builder.config.latex_logo and
- "\\includegraphics{%s}\\par" % path.basename(builder.config.latex_logo)
+ '\\includegraphics{%s}\\par' % path.basename(builder.config.latex_logo)
or '')
self.options = {'docclass': docclass,
'papersize': paper,
@@ -135,11 +143,13 @@
'releasename': _('Release'),
'logo': logo,
'date': date,
- 'classoptions': '',
+ 'classoptions': ',english',
+ 'shorthandoff': '',
}
if builder.config.language:
- babel = Babel(builder.config.language)
+ babel = ExtBabel(builder.config.language)
self.options['classoptions'] += ',' + babel.get_language()
+ self.shorthandoff = babel.get_shorthandoff()
self.highlighter = highlighting.PygmentsBridge(
'latex', builder.config.pygments_style)
self.context = []
@@ -1045,42 +1055,12 @@
# text handling
- replacements = [
- (u"\\", u"\x00"),
- (u"$", ur"\$"),
- (r"%", ur"\%"),
- (u"&", ur"\&"),
- (u"#", ur"\#"),
- (u"_", ur"\_"),
- (u"{", ur"\{"),
- (u"}", ur"\}"),
- (u"[", ur"{[}"),
- (u"]", ur"{]}"),
- (u"¶", ur"\P{}"),
- (u"§", ur"\S{}"),
- (u"∞", ur"$\infty$"),
- (u"±", ur"$\pm$"),
- (u"‣", ur"$\rightarrow$"),
- (u"Ω", ur"$\Omega$"),
- (u"Ω", ur"$\Omega$"),
- (u"φ", ur"$\phi$"),
- (u"π", ur"$\pi$"),
- (u"~", ur"\textasciitilde{}"),
- (u"€", ur"\texteuro{}"),
- (u"<", ur"\textless{}"),
- (u">", ur"\textgreater{}"),
- (u"^", ur"\textasciicircum{}"),
- (u"\x00", ur"\textbackslash{}"),
- (u"\N{RIGHTWARDS ARROW}", ur"$\rightarrow$"),
- ]
-
def encode(self, text):
- for x, y in self.replacements:
- text = text.replace(x, y)
+ text = unicode(text).translate(tex_escape_map)
if self.literal_whitespace:
# Insert a blank before the newline, to avoid
# ! LaTeX Error: There's no line here to end.
- text = text.replace("\n", '~\\\\\n').replace(" ", "~")
+ text = text.replace(u'\n', u'~\\\\\n').replace(u' ', u'~')
return text
def visit_Text(self, node):
@@ -1101,4 +1081,4 @@
self.body.append('\n')
def unknown_visit(self, node):
- raise NotImplementedError("Unknown node: " + node.__class__.__name__)
+ raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
Modified: doctools/trunk/tests/test_markup.py
==============================================================================
--- doctools/trunk/tests/test_markup.py (original)
+++ doctools/trunk/tests/test_markup.py Sun Aug 10 18:59:27 2008
@@ -63,10 +63,14 @@
latex_translator.first_document = -1 # don't write \begin{document}
document.walkabout(latex_translator)
latex_translated = ''.join(latex_translator.body).strip()
- assert re.match(latex_expected, latex_translated), 'from ' + rst
+ assert re.match(latex_expected, latex_translated), 'from ' + repr(rst)
def verify(rst, html_expected, latex_expected):
- verify_re(rst, re.escape(html_expected) + '$', re.escape(latex_expected) + '$')
+ if html_expected:
+ html_expected = re.escape(html_expected) + '$'
+ if latex_expected:
+ latex_expected = re.escape(latex_expected) + '$'
+ verify_re(rst, html_expected, latex_expected)
def test_inline():
@@ -85,7 +89,7 @@
# interpolation of arrows in menuselection
verify(':menuselection:`a --> b`',
u'<p><em>a \N{TRIANGULAR BULLET} b</em></p>',
- '\\emph{a $\\rightarrow$ b}')
+ '\\emph{a \\(\\rightarrow\\) b}')
# non-interpolation of dashes in option role
verify_re(':option:`--with-option`',
@@ -99,3 +103,12 @@
'<p><tt class="docutils literal"><span class="pre">'
'"John"</span></tt></p>',
'\\code{"John"}')
+
+def test_latex_escaping():
+ # correct escaping in normal mode
+ verify(u'Γ\\\\∞$', None, ur'\(\Gamma\)\textbackslash{}\(\infty\)\$')
+ # in verbatim code fragments
+ verify(u'::\n\n @Γ\\∞$[]', None,
+ u'\\begin{Verbatim}[commandchars=@\\[\\]]\n'
+ u'@at[]@(@Gamma@)\\@(@infty@)@$@lb[]@rb[]\n'
+ u'\\end{Verbatim}')
More information about the Python-checkins
mailing list