From de6f3b252e4bfd0fb8291f79a417eb1d46e5aeba Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 19 May 2018 14:15:02 +0900 Subject: [PATCH] Fix #4979: latex: Incorrect escaping of curly braces in index entries --- CHANGES | 1 + sphinx/texinputs/sphinx.sty | 4 ++++ sphinx/writers/latex.py | 17 +++++++++++------ tests/roots/test-latex-index/index.rst | 4 ++++ tests/test_build_latex.py | 1 + 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index f0da26db9..be395cf22 100644 --- a/CHANGES +++ b/CHANGES @@ -30,6 +30,7 @@ Bugs fixed * #4969: autodoc: constructor method should not have return annotation * latex: deeply nested enumerated list which is beginning with non-1 causes LaTeX engine crashed +* #4979: latex: Incorrect escaping of curly braces in index entries Testing -------- diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index e323b2a5d..6a885c3f5 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -1608,6 +1608,10 @@ % figure legend comes after caption and may contain arbitrary body elements \newenvironment{sphinxlegend}{\par\small}{\par} +% For curly braces inside \index macro +\def\sphinxleftcurlybrace{\{} +\def\sphinxrightcurlybrace{\}} + % Declare Unicode characters used by linux tree command to pdflatex utf8/utf8x \def\spx@bd#1#2{% \leavevmode diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index d4deb49ac..419a75a79 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1949,6 +1949,12 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_index(self, node, scre=re.compile(r';\s*')): # type: (nodes.Node, Pattern) -> None + def escape(value): + value = self.encode(value) + value = value.replace(r'\{', r'\sphinxleftcurlybrace') + value = value.replace(r'\}', r'\sphinxrightcurlybrace') + return value + if not node.get('inline', True): self.body.append('\n') entries = node['entries'] @@ -1958,24 +1964,23 @@ class LaTeXTranslator(nodes.NodeVisitor): m = '|textbf' try: if type == 'single': - p = scre.sub('!', self.encode(string)) + p = scre.sub('!', escape(string)) self.body.append(r'\index{%s%s}' % (p, m)) elif type == 'pair': - p1, p2 = [self.encode(x) for x in split_into(2, 'pair', string)] + p1, p2 = [escape(x) for x in split_into(2, 'pair', string)] self.body.append(r'\index{%s!%s%s}\index{%s!%s%s}' % (p1, p2, m, p2, p1, m)) elif type == 'triple': - p1, p2, p3 = [self.encode(x) - for x in split_into(3, 'triple', string)] + p1, p2, p3 = [escape(x) for x in split_into(3, 'triple', string)] self.body.append( r'\index{%s!%s %s%s}\index{%s!%s, %s%s}' r'\index{%s!%s %s%s}' % (p1, p2, p3, m, p2, p3, p1, m, p3, p1, p2, m)) elif type == 'see': - p1, p2 = [self.encode(x) for x in split_into(2, 'see', string)] + p1, p2 = [escape(x) for x in split_into(2, 'see', string)] self.body.append(r'\index{%s|see{%s}}' % (p1, p2)) elif type == 'seealso': - p1, p2 = [self.encode(x) for x in split_into(2, 'seealso', string)] + p1, p2 = [escape(x) for x in split_into(2, 'seealso', string)] self.body.append(r'\index{%s|see{%s}}' % (p1, p2)) else: logger.warning('unknown index entry type %s found', type) diff --git a/tests/roots/test-latex-index/index.rst b/tests/roots/test-latex-index/index.rst index 3c1bb46f9..5b612798f 100644 --- a/tests/roots/test-latex-index/index.rst +++ b/tests/roots/test-latex-index/index.rst @@ -10,3 +10,7 @@ A :index:`famous` :index:`equation`: .. index:: Einstein, relativity and some text. + +.. index:: main { + +An index entry containing non paired curly brace diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index 75515cf64..1a038c309 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -1209,6 +1209,7 @@ def test_latex_index(app, status, warning): result = (app.outdir / 'Python.tex').text(encoding='utf8') assert 'A \\index{famous}famous \\index{equation}equation:\n' in result assert '\n\\index{Einstein}\\index{relativity}\\ignorespaces \nand' in result + assert '\n\\index{main \\sphinxleftcurlybrace}\\ignorespaces ' in result @pytest.mark.sphinx('latex', testroot='latex-equations')