From 309f38a91fcbb8405a7f3d8c13fe4bce65b0b230 Mon Sep 17 00:00:00 2001 From: jfbu Date: Tue, 2 Jan 2018 23:11:19 +0100 Subject: [PATCH] Split out fancy LaTeX macros from ``\sphinxcode`` into ``\sphinxupquote`` Since #2627 (1.4.4), `\code`, and then again at #3116 (1.5) `\sphinxcode` which is the new name has become more complicated than the original `\texttt{#1}`. This was to obtain straight quotes in PDF output, and to allow long inline literals to break across lines. This means though that users who want to customize `\sphinxcode`, for example to not only do `\texttt` but to use some colour, have to copy about 10 lines of complicated LaTeX macros which should be not modified in any way. This commit moves all the code out of `\sphinxcode` into a separate macro `\sphinxupquote`. The LaTeX writer will output `\sphinxcode{\sphinxupquote{foo}}` in place of former `\sphinxcode{foo}`. Moving the `\texttt` from innermost to outermost level is with no consequence. --- sphinx/texinputs/sphinx.sty | 15 ++++++++------- sphinx/writers/latex.py | 26 +++++++++++++------------- tests/test_markup.py | 12 ++++++------ 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 890ef60f7..8de263a52 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -1459,8 +1459,8 @@ % \newenvironment{productionlist}{% % \def\sphinxoptional##1{{\Large[}##1{\Large]}} - \def\production##1##2{\\\sphinxcode{##1}&::=&\sphinxcode{##2}}% - \def\productioncont##1{\\& &\sphinxcode{##1}}% + \def\production##1##2{\\\sphinxcode{\sphinxupquote{##1}}&::=&\sphinxcode{\sphinxupquote{##2}}}% + \def\productioncont##1{\\& &\sphinxcode{\sphinxupquote{##1}}}% \parindent=2em \indent \setlength{\LTpre}{0pt}% @@ -1541,15 +1541,13 @@ %% TEXT STYLING % -% Some custom font markup commands. -\protected\def\sphinxstrong#1{{\textbf{#1}}} % to obtain straight quotes we execute \@noligs as patched by upquote, and % \scantokens is needed in cases where it would be too late for the macro to % first set catcodes and then fetch its argument. We also make the contents % breakable at non-escaped . , ; ? ! / using \sphinxbreaksviaactive. % the macro must be protected if it ends up used in moving arguments, % in 'alltt' \@noligs is done already, and the \scantokens must be avoided. -\protected\def\sphinxcode#1{{\def\@tempa{alltt}% +\protected\def\sphinxupquote#1{{\def\@tempa{alltt}% \ifx\@tempa\@currenvir\else \ifspx@opt@inlineliteralwraps \sphinxbreaksviaactive\let\sphinxafterbreak\empty @@ -1560,12 +1558,15 @@ \let\do@noligs\sphinx@do@noligs \@noligs\endlinechar\m@ne\everyeof{}% (<- in case inside \sphinxhref) \expandafter\scantokens - \fi {\texttt{#1}}}} + \fi {#1}}} \def\sphinx@do@noligs #1{\catcode`#1\active\begingroup\lccode`\~`#1\relax \lowercase{\endgroup\def~{\leavevmode\kern\z@\char`#1 }}} \def\sphinx@literal@nolig@list {\do\`\do\<\do\>\do\'\do\-}% -\protected\def\sphinxbfcode#1{\sphinxcode{\bfseries{}#1}} +% Some custom font markup commands. +\protected\def\sphinxstrong#1{\textbf{#1}} +\protected\def\sphinxcode#1{\texttt{#1}} +\protected\def\sphinxbfcode#1{\textbf{\sphinxcode{#1}}} \protected\def\sphinxemail#1{\textsf{#1}} \protected\def\sphinxtablecontinued#1{\textsf{#1}} \protected\def\sphinxtitleref#1{\emph{#1}} diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 9a3c0e5cd..de472b36c 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1216,12 +1216,12 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_desc_addname(self, node): # type: (nodes.Node) -> None - self.body.append(r'\sphinxcode{') + self.body.append(r'\sphinxcode{\sphinxupquote{') self.literal_whitespace += 1 def depart_desc_addname(self, node): # type: (nodes.Node) -> None - self.body.append('}') + self.body.append('}}') self.literal_whitespace -= 1 def visit_desc_type(self, node): @@ -1242,13 +1242,13 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_desc_name(self, node): # type: (nodes.Node) -> None - self.body.append(r'\sphinxbfcode{') + self.body.append(r'\sphinxbfcode{\sphinxupquote{') self.no_contractions += 1 self.literal_whitespace += 1 def depart_desc_name(self, node): # type: (nodes.Node) -> None - self.body.append('}') + self.body.append('}}') self.literal_whitespace -= 1 self.no_contractions -= 1 @@ -1287,11 +1287,11 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_desc_annotation(self, node): # type: (nodes.Node) -> None - self.body.append(r'\sphinxbfcode{') + self.body.append(r'\sphinxbfcode{\sphinxupquote{') def depart_desc_annotation(self, node): # type: (nodes.Node) -> None - self.body.append('}') + self.body.append('}}') def visit_desc_content(self, node): # type: (nodes.Node) -> None @@ -2177,12 +2177,12 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_literal_emphasis(self, node): # type: (nodes.Node) -> None - self.body.append(r'\sphinxstyleliteralemphasis{') + self.body.append(r'\sphinxstyleliteralemphasis{\sphinxupquote{') self.no_contractions += 1 def depart_literal_emphasis(self, node): # type: (nodes.Node) -> None - self.body.append('}') + self.body.append('}}') self.no_contractions -= 1 def visit_strong(self, node): @@ -2195,12 +2195,12 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_literal_strong(self, node): # type: (nodes.Node) -> None - self.body.append(r'\sphinxstyleliteralstrong{') + self.body.append(r'\sphinxstyleliteralstrong{\sphinxupquote{') self.no_contractions += 1 def depart_literal_strong(self, node): # type: (nodes.Node) -> None - self.body.append('}') + self.body.append('}}') self.no_contractions -= 1 def visit_abbreviation(self, node): @@ -2259,14 +2259,14 @@ class LaTeXTranslator(nodes.NodeVisitor): # type: (nodes.Node) -> None self.no_contractions += 1 if self.in_title: - self.body.append(r'\sphinxstyleliteralintitle{') + self.body.append(r'\sphinxstyleliteralintitle{\sphinxupquote{') else: - self.body.append(r'\sphinxcode{') + self.body.append(r'\sphinxcode{\sphinxupquote{') def depart_literal(self, node): # type: (nodes.Node) -> None self.no_contractions -= 1 - self.body.append('}') + self.body.append('}}') def visit_footnote_reference(self, node): # type: (nodes.Node) -> None diff --git a/tests/test_markup.py b/tests/test_markup.py index 34ab1405d..c48096e34 100644 --- a/tests/test_markup.py +++ b/tests/test_markup.py @@ -135,7 +135,7 @@ def get_verifier(verify, verify_re): '``code sample``', ('

' 'code   sample

'), - r'\\sphinxcode{code sample}', + r'\\sphinxcode{\\sphinxupquote{code sample}}', ), ( # correct interpretation of code with whitespace @@ -143,7 +143,7 @@ def get_verifier(verify, verify_re): ':samp:`code sample`', ('

' 'code   sample

'), - r'\\sphinxcode{code sample}', + r'\\sphinxcode{\\sphinxupquote{code sample}}', ), ( # interpolation of braces in samp and file roles (HTML only) @@ -152,7 +152,7 @@ def get_verifier(verify, verify_re): ('

a' 'b' 'c

'), - '\\sphinxcode{a\\sphinxstyleemphasis{b}c}', + '\\sphinxcode{\\sphinxupquote{a\\sphinxstyleemphasis{b}c}}', ), ( # interpolation of arrows in menuselection @@ -175,7 +175,7 @@ def get_verifier(verify, verify_re): ':option:`--with-option`', ('

' '--with-option

$'), - r'\\sphinxcode{-{-}with-option}$', + r'\\sphinxcode{\\sphinxupquote{-{-}with-option}}$', ), ( # verify smarty-pants quotes @@ -190,14 +190,14 @@ def get_verifier(verify, verify_re): '``"John"``', ('

' '"John"

'), - '\\sphinxcode{"John"}', + '\\sphinxcode{\\sphinxupquote{"John"}}', ), ( # verify classes for inline roles 'verify', ':manpage:`mp(1)`', '

mp(1)

', - '\\sphinxstyleliteralemphasis{mp(1)}', + '\\sphinxstyleliteralemphasis{\\sphinxupquote{mp(1)}}', ), ( # correct escaping in normal mode