From 634d76faf195c6783d6e9f803e6c6d3e91454a2f Mon Sep 17 00:00:00 2001 From: jfbu Date: Fri, 16 Jun 2017 14:24:40 +0200 Subject: [PATCH] latex: add option to put literal block captions before or after According to ``literalblockcappos`` setting in ``'sphinxsetup'``, (t)op or (b)ottom, the caption will be typeset before or after the literal block. If typeset above, its distance to frame is now identical to the setting used for captions of tables (one half of the baseline). Further keys ``verbatimcontinuedalign`` and ``verbatimcontinuesalign`` allow to horizontally align the continuation hints relative to the literal block contents: either (l)eft, (c)enter, or (r)ight. --- doc/latex.rst | 26 ++++-- sphinx/texinputs/sphinx.sty | 167 ++++++++++++++++++++++-------------- sphinx/writers/latex.py | 4 - tests/test_build_latex.py | 3 +- 4 files changed, 121 insertions(+), 79 deletions(-) diff --git a/doc/latex.rst b/doc/latex.rst index 3965afee2..ff79cc574 100644 --- a/doc/latex.rst +++ b/doc/latex.rst @@ -189,14 +189,25 @@ The available styling options default ``true``. Tells whether long lines in :rst:dir:`code-block`\ 's contents should wrap. +``literalblockcappos`` + default ``t`` for "top". Decides the caption position. Alternative is + ``b`` ("bottom"). + + .. versionadded:: 1.7 + ``verbatimhintsturnover`` - default ``false``. If ``true``, code-blocks display "continued on next + default ``true``. If ``true``, code-blocks display "continued on next page", "continued from previous page" hints in case of pagebreaks. .. versionadded:: 1.6.3 - the default will change to ``true`` at 1.7 and horizontal positioning - of continuation hints (currently right aligned only) will be - customizable. + .. versionchanged:: 1.7 + the default changed from ``false`` to ``true``. + +``verbatimcontinuedalign``, ``verbatimcontinuesalign`` + default ``c``. Horizontal position relative to the framed contents: + either ``l`` (left aligned), ``r`` (right aligned) or ``c`` (centered). + + .. versionadded:: 1.7 ``parsedliteralwraps`` default ``true``. Tells whether long lines in :dudir:`parsed-literal`\ 's @@ -356,10 +367,9 @@ Macros with LaTeX packages. - more text styling: ``\sphinxstyle`` with ```` one of ``indexentry``, ``indexextra``, ``indexpageref``, ``topictitle``, - ``sidebartitle``, ``othertitle``, ``sidebarsubtitle``, - ``theadfamily``, ``emphasis``, ``literalemphasis``, ``strong``, - ``literalstrong``, ``abbreviation``, ``literalintitle``, ``codecontinued``, - ``codecontinues``. + ``sidebartitle``, ``othertitle``, ``sidebarsubtitle``, ``theadfamily``, + ``emphasis``, ``literalemphasis``, ``strong``, ``literalstrong``, + ``abbreviation``, ``literalintitle``, ``codecontinued``, ``codecontinues`` .. versionadded:: 1.5 these macros were formerly hard-coded as non customizable ``\texttt``, diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index fa2be7d93..c8d6103bb 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -114,19 +114,25 @@ % move back vertically to compensate space inserted by next paragraph \vskip-\baselineskip\vskip-\parskip }% +% use \LTcapwidth (default is 4in) to wrap caption (if line width is bigger) \newcommand\sphinxcaption[2][\LTcapwidth]{% \noindent\hb@xt@\linewidth{\hss \vtop{\@tempdima\dimexpr#1\relax % don't exceed linewidth for the caption width \ifdim\@tempdima>\linewidth\hsize\linewidth\else\hsize\@tempdima\fi -% longtable ignores \abovecaptionskip/\belowcaptionskip, so do the same here - \abovecaptionskip\z@skip - \belowcaptionskip\z@skip +% longtable ignores \abovecaptionskip/\belowcaptionskip, so add hooks here +% to uniformize control of caption distance to tables + \abovecaptionskip\sphinxabovecaptionskip + \belowcaptionskip\sphinxbelowcaptionskip \caption[{#2}]% {\strut\ignorespaces#2\ifhmode\unskip\@finalstrut\strutbox\fi}% }\hss}% \par\prevdepth\dp\strutbox }% +\def\spx@abovecaptionskip{\abovecaptionskip} +\newcommand*\sphinxabovecaptionskip{\z@skip} +\newcommand*\sphinxbelowcaptionskip{\z@skip} + \newcommand\sphinxaftercaption {% this default definition serves with a caption *above* a table, to make sure % its last baseline is \sphinxbelowcaptionspace above table top @@ -256,8 +262,11 @@ % verbatim \DeclareBoolOption[true]{verbatimwithframe} \DeclareBoolOption[true]{verbatimwrapslines} -\DeclareBoolOption[false]{verbatimhintsturnover} +\DeclareBoolOption[true]{verbatimhintsturnover} \DeclareBoolOption[true]{inlineliteralwraps} +\DeclareStringOption[t]{literalblockcappos} +\DeclareStringOption[r]{verbatimcontinuedalign} +\DeclareStringOption[r]{verbatimcontinuesalign} % parsed literal \DeclareBoolOption[true]{parsedliteralwraps} % \textvisiblespace for compatibility with fontspec+XeTeX/LuaTeX @@ -678,22 +687,27 @@ \newif\ifspx@inframed % flag set if we are already in a framed environment % if forced use of minipage encapsulation is needed (e.g. table cells) \newif\ifsphinxverbatimwithminipage \sphinxverbatimwithminipagefalse -\long\def\spx@colorbox #1#2#3{% -% let the framing obey the current indentation (adapted from framed.sty's code). + +% Framing macro for use with framed.sty's \FrameCommand +% - it obeys current indentation, +% - frame is \fboxsep separated from the contents, +% - the contents use the full available text width, +% - #1 = color of frame, #2 = color of background, +% - #3 = above frame, #4 = below frame, #5 = within frame, +% - #3 and #4 must be already typeset boxes; they must issue \normalcolor +% or similar, else, they are under scope of color #1 +\long\def\spx@fcolorbox #1#2#3#4#5{% \hskip\@totalleftmargin \hskip-\fboxsep\hskip-\fboxrule - \spx@fcolorbox{VerbatimBorderColor}{VerbatimColor}{#1}{#2}{#3}% + % use of \color@b@x here is compatible with both xcolor.sty and color.sty + \color@b@x {\color{#1}\spx@CustomFBox{#3}{#4}}{\color{#2}}{#5}% \hskip-\fboxsep\hskip-\fboxrule \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth -} -% use of \color@b@x here is compatible with both xcolor.sty and color.sty -\long\def\spx@fcolorbox #1#2#3#4% - {\color@b@x {\color{#1}\spx@VerbatimFBox{#3}{#4}}{\color{#2}}}% -% Frame drawing macro -% #1 = used by default for title above frame, may contain "continued" hint -% #2 = for material underneath frame, used for "continues on next page" hint -% #3 = actual contents with background color -\long\def\spx@VerbatimFBox#1#2#3{% +}% +% #1 = for material above frame, such as a caption or a "continued" hint +% #2 = for material below frame, such as a caption or "continues on next page" +% #3 = actual contents, which will be typeset with a background color +\long\def\spx@CustomFBox#1#2#3{% \leavevmode \begingroup \setbox\@tempboxa\hbox{{#3}}% inner braces to avoid color leaks @@ -717,37 +731,40 @@ }% }% \endgroup -} - -% Customize framed.sty \MakeFramed to glue caption to literal block -% and add optional hint "continued on next page" -\def\spx@Verbatim@FrameCommand - {\spx@colorbox\spx@Verbatim@Title{}}% -% Macros for a frame with page breaks: -\def\spx@Verbatim@FirstFrameCommand - {\spx@colorbox\spx@Verbatim@Title\spx@Verbatim@Continues}% -\def\spx@Verbatim@MidFrameCommand - {\spx@colorbox\spx@Verbatim@Continued\spx@Verbatim@Continues}% -\def\spx@Verbatim@LastFrameCommand - {\spx@colorbox\spx@Verbatim@Continued{}}% - -\def\spx@Verbatim@Title{% hide width from framed.sty measuring - \moveright\dimexpr\fboxrule+.5\wd\@tempboxa - \hb@xt@\z@{\hss\unhcopy\spx@Verbatim@TitleBox\hss}% }% -\def\spx@Verbatim@Continued{% - \moveright\dimexpr\fboxrule+\wd\@tempboxa-\fboxsep - \hb@xt@\z@{\hss - {\normalcolor\sphinxstylecodecontinued\literalblockcontinuedname}}% +\def\spx@fcolorbox@put@c#1{% hide width from framed.sty measuring + \moveright\dimexpr\fboxrule+.5\wd\@tempboxa\hb@xt@\z@{\hss#1\hss}% }% -\def\spx@Verbatim@Continues{% - \moveright\dimexpr\fboxrule+\wd\@tempboxa-\fboxsep - \hb@xt@\z@{\hss - {\normalcolor\sphinxstylecodecontinues\literalblockcontinuesname}}% +\def\spx@fcolorbox@put@r#1{% right align with contents, width hidden + \moveright\dimexpr\fboxrule+\wd\@tempboxa-\fboxsep\hb@xt@\z@{\hss#1}% }% +\def\spx@fcolorbox@put@l#1{% left align with contents, width hidden + \moveright\dimexpr\fboxrule+\fboxsep\hb@xt@\z@{#1\hss}% +}% +% +\def\sphinxVerbatim@Continued + {\csname spx@fcolorbox@put@\spx@opt@verbatimcontinuedalign\endcsname + {\normalcolor\sphinxstylecodecontinued\literalblockcontinuedname}}% +\def\sphinxVerbatim@Continues + {\csname spx@fcolorbox@put@\spx@opt@verbatimcontinuesalign\endcsname + {\normalcolor\sphinxstylecodecontinues\literalblockcontinuesname}}% +\def\sphinxVerbatim@Title + {\spx@fcolorbox@put@c{\unhcopy\sphinxVerbatim@TitleBox}}% +\let\sphinxVerbatim@Before\@empty +\let\sphinxVerbatim@After\@empty % Defaults are redefined in document preamble according to language \newcommand*\literalblockcontinuedname{continued from previous page}% \newcommand*\literalblockcontinuesname{continues on next page}% +% +\def\spx@verbatimfcolorbox{\spx@fcolorbox{VerbatimBorderColor}{VerbatimColor}}% +\def\sphinxVerbatim@FrameCommand + {\spx@verbatimfcolorbox\sphinxVerbatim@Before\sphinxVerbatim@After}% +\def\sphinxVerbatim@FirstFrameCommand + {\spx@verbatimfcolorbox\sphinxVerbatim@Before\sphinxVerbatim@Continues}% +\def\sphinxVerbatim@MidFrameCommand + {\spx@verbatimfcolorbox\sphinxVerbatim@Continued\sphinxVerbatim@Continues}% +\def\sphinxVerbatim@LastFrameCommand + {\spx@verbatimfcolorbox\sphinxVerbatim@Continued\sphinxVerbatim@After}% % For linebreaks inside Verbatim environment from package fancyvrb. \newbox\sphinxcontinuationbox @@ -832,21 +849,19 @@ \newcommand*\sphinxSetupCodeBlockInFootnote {% \fvset{fontsize=\footnotesize}\let\caption\sphinxfigcaption \sphinxverbatimwithminipagetrue % reduces vertical spaces - % we counteract \caption issueing \@normalsize - % this all happens in a group + % we counteract (this is in a group) the \@normalsize from \caption \let\normalsize\footnotesize\let\@parboxrestore\relax - \abovecaptionskip \smallskipamount \belowcaptionskip \z@skip + \def\spx@abovecaptionskip{\sphinxverbatimsmallskipamount}% } % needed to create wrapper environments of fancyvrb's Verbatim \newcommand*{\sphinxVerbatimEnvironment}{\gdef\FV@EnvironName{sphinxVerbatim}} -% Sphinx <1.5 optional argument was in fact mandatory. It is now really -% optional and handled by original Verbatim. +\newcommand*{\sphinxverbatimsmallskipamount}{\smallskipamount} \newenvironment{sphinxVerbatim}{% % first, let's check if there is a caption \ifx\sphinxVerbatimTitle\empty \sphinxvspacefixafterfrenchlists \parskip\z@skip - \smallskip + \vskip\sphinxverbatimsmallskipamount % there was no caption. Check if nevertheless a label was set. \ifx\sphinxLiteralBlockLabel\empty\else % we require some space to be sure hyperlink target from \phantomsection @@ -854,25 +869,37 @@ \needspace{\sphinxliteralblockwithoutcaptionneedspace}% \phantomsection\sphinxLiteralBlockLabel \fi - \let\spx@Verbatim@Title\@empty \else \parskip\z@skip - % non-empty \sphinxVerbatimTitle has label inside it (in case there is one) - \setbox\spx@Verbatim@TitleBox + \if t\spx@opt@literalblockcappos + \vskip\spx@abovecaptionskip + \def\sphinxVerbatim@Before + {\sphinxVerbatim@Title\nointerlineskip + \kern\dimexpr-\dp\strutbox+\sphinxbelowcaptionspace\relax}% + \else + \vskip\sphinxverbatimsmallskipamount + \def\sphinxVerbatim@After + {\nointerlineskip\kern\dp\strutbox\sphinxVerbatim@Title}% + \fi + \def\@captype{literalblock}% + \capstart + % \sphinxVerbatimTitle must reset color + \setbox\sphinxVerbatim@TitleBox \hbox{\begin{minipage}{\linewidth}% \sphinxVerbatimTitle \end{minipage}}% \fi + \global\let\sphinxLiteralBlockLabel\empty + \global\let\sphinxVerbatimTitle\empty \fboxsep\sphinxverbatimsep \fboxrule\sphinxverbatimborder - % setting borderwidth to zero is simplest for no-frame effect with same pagebreaks \ifspx@opt@verbatimwithframe\else\fboxrule\z@\fi - \let\FrameCommand \spx@Verbatim@FrameCommand - \let\FirstFrameCommand\spx@Verbatim@FirstFrameCommand - \let\MidFrameCommand \spx@Verbatim@MidFrameCommand - \let\LastFrameCommand \spx@Verbatim@LastFrameCommand + \let\FrameCommand \sphinxVerbatim@FrameCommand + \let\FirstFrameCommand\sphinxVerbatim@FirstFrameCommand + \let\MidFrameCommand \sphinxVerbatim@MidFrameCommand + \let\LastFrameCommand \sphinxVerbatim@LastFrameCommand \ifspx@opt@verbatimhintsturnover\else - \let\spx@Verbatim@Continued\@empty - \let\spx@Verbatim@Continues\@empty + \let\sphinxVerbatim@Continued\@empty + \let\sphinxVerbatim@Continues\@empty \fi \ifspx@opt@verbatimwrapslines % fancyvrb's Verbatim puts each input line in (unbreakable) horizontal boxes. @@ -903,13 +930,21 @@ \def\@toodeep {\advance\@listdepth\@ne}% % The list environment is needed to control perfectly the vertical space. % Note: \OuterFrameSep used by framed.sty is later set to \topsep hence 0pt. - % - if caption: vertical space above caption = (\abovecaptionskip + D) with - % D = \baselineskip-\FrameHeightAdjust, and then \smallskip above frame. - % - if no caption: (\smallskip + D) above frame. By default D=6pt. - % Use trivlist rather than list to avoid possible "too deeply nested" error. + % - if caption: distance from last text baseline to caption baseline is + % A+(B-F)+\ht\strutbox, A = \abovecaptionskip (default 10pt), B = + % \baselineskip, F is the framed.sty \FrameHeightAdjust macro, default 6pt. + % Formula valid for F < 10pt. + % - distance of baseline of caption to top of frame is like for tables: + % \sphinxbelowcaptionspace (=0.5\baselineskip) + % - if no caption: distance of last text baseline to code frame is S+(B-F), + % with S = \sphinxverbatimtopskip (=\smallskip) + % - and distance from bottom of frame to next text baseline is + % \baselineskip+\parskip. + % The \trivlist is used to avoid possible "too deeply nested" error. \itemsep \z@skip \topsep \z@skip - \partopsep \z@skip% trivlist will set \parsep to \parskip = zero (see above) + \partopsep \z@skip + % trivlist will set \parsep to \parskip = zero % \leftmargin will be set to zero by trivlist \rightmargin\z@ \parindent \z@% becomes \itemindent. Default zero, but perhaps overwritten. @@ -945,10 +980,12 @@ {% don't use a frame if in a table cell \spx@opt@verbatimwithframefalse \sphinxverbatimwithminipagetrue - % counteract longtable redefinition of caption + % the literal block caption uses \sphinxcaption which is wrapper of \caption, + % but \caption must be modified because longtable redefines it to work only + % for the own table caption, and tabulary has multiple passes \let\caption\sphinxfigcaption - % reduce above caption space if in a table cell - \abovecaptionskip\smallskipamount + % reduce above caption skip + \def\spx@abovecaptionskip{\sphinxverbatimsmallskipamount}% \def\sphinxVerbatimEnvironment{\gdef\FV@EnvironName{sphinxVerbatimintable}}% \begin{sphinxVerbatim}} {\end{sphinxVerbatim}} diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 8d0b7759b..0f06b385a 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -2284,8 +2284,6 @@ class LaTeXTranslator(nodes.NodeVisitor): else: hlcode += '\\end{sphinxVerbatim}' self.body.append('\n' + hlcode + '\n') - if ids: - self.body.append('\\let\\sphinxLiteralBlockLabel\\empty\n') raise nodes.SkipNode def depart_literal_block(self, node): @@ -2488,8 +2486,6 @@ class LaTeXTranslator(nodes.NodeVisitor): # type: (nodes.Node) -> None if node.get('literal_block'): self.in_container_literal_block -= 1 - self.body.append('\\let\\sphinxVerbatimTitle\\empty\n') - self.body.append('\\let\\sphinxLiteralBlockLabel\\empty\n') def visit_decoration(self, node): # type: (nodes.Node) -> None diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index 441f12d0d..d32c4f4da 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -542,8 +542,7 @@ def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning): assert ('&\nThis is one more footnote with some code in it %\n' '\\begin{footnote}[10]\\sphinxAtStartFootnote\n' 'Third footnote in longtable\n') in result - assert ('\\end{sphinxVerbatim}\n\\let\\sphinxVerbatimTitle\\empty\n' - '\\let\\sphinxLiteralBlockLabel\\empty\n%\n\\end{footnote}.\n') in result + assert ('\\end{sphinxVerbatim}\n%\n\\end{footnote}.\n') in result assert '\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]' in result