From b035e12e3c875de72d154f273499913ce23c98be Mon Sep 17 00:00:00 2001 From: jfbu <2589111+jfbu@users.noreply.github.com> Date: Sat, 18 Jun 2022 23:38:58 +0200 Subject: [PATCH] LaTeX: fix #8686 Text can fall out of code-block at end of page --- sphinx/texinputs/sphinxlatexliterals.sty | 107 +++++++++++++---------- 1 file changed, 60 insertions(+), 47 deletions(-) diff --git a/sphinx/texinputs/sphinxlatexliterals.sty b/sphinx/texinputs/sphinxlatexliterals.sty index cc768c25ba1..7c05bdef701 100644 --- a/sphinx/texinputs/sphinxlatexliterals.sty +++ b/sphinx/texinputs/sphinxlatexliterals.sty @@ -1,7 +1,7 @@ %% LITERAL BLOCKS % % change this info string if making any custom modification -\ProvidesFile{sphinxlatexliterals.sty}[2021/12/06 code-blocks and parsed literals] +\ProvidesFile{sphinxlatexliterals.sty}[2022/06/18 code-blocks and parsed literals] % Provides support for this output mark-up from Sphinx latex writer: % @@ -50,8 +50,8 @@ % 4- while still allowing expansion of Pygments latex mark-up % Other aspects such as framing, caption handling, codeline wrapping are % added on top of it. We should stop using fancyvrb and implement -% 1, 2, 3, 4 by own Sphinx fully native Verbatim. This would allow to solve -% limitations with wrapped long code line not allowing page break. +% 1, 2, 3, 4 by own Sphinx fully native Verbatim. This would greatly simply +% in particular wrapping long code lines in a way allowing page breaks. \RequirePackage{fancyvrb} % For parsed-literal blocks. \RequirePackage{alltt} @@ -60,6 +60,9 @@ % Skip to next page if not enough space at bottom \RequirePackage{needspace} +\newbox\spx@verb@tempboxa +\newbox\spx@verb@tempboxb + % Based on use of "fancyvrb.sty"'s Verbatim. % - with framing allowing page breaks ("framed.sty") % - with breaking of long lines (exploits Pygments mark-up), @@ -267,19 +270,42 @@ {\sphinxrestorefboxsep\sphinxVerbatimFormatLine{#1}}% % no need to restore \fboxsep here, as this ends up in a \hbox from fancyvrb }% -% \sphinxVerbatimFormatLine will be set locally to one of those two: -\newcommand\sphinxVerbatimFormatLineWrap{% - \hsize\linewidth - \ifspx@opt@verbatimforcewraps - \expandafter\spx@verb@FormatLineForceWrap - \else\expandafter\spx@verb@FormatLineWrap - \fi +\newcommand\sphinxVerbatimFormatLine[1]{\hb@xt@\linewidth{\strut #1\hss}}% +% The next two macros are a deep hack of fancyvrb.sty core line processing +% in order to wrap too long lines, either at spaces and natural break-points, +% (soft wrap) or optionally at any character (hard wrap). This requires +% deep hack to work around the \hbox'es wrappers of fancyverb.sty which +% prevents pagebreaks. +\def\spx@verb@@ProcessLines{% + \unskip + \unpenalty + \setbox\spx@verb@tempboxb\lastbox +\ifvoid\spx@verb@tempboxb\else + {\spx@verb@@ProcessLines}% + \FV@ProcessLine{\box\spx@verb@tempboxb\strut}% + \global\let\FV@ProcessLine\FV@ProcessLine + \global\setbox\@tempboxa=\box\@tempboxa +\fi }% -\newcommand\sphinxVerbatimFormatLineNoWrap[1]{\hb@xt@\linewidth{\strut #1\hss}}% -\long\def\spx@verb@FormatLineWrap#1{% - \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ +% This will replace \FV@@PreProcessLine +\def\spx@verb@@PreProcessLine{% + \FV@StepLineNo + \FV@Gobble + \def\spx@verb@FV@Line{\FV@Line}% + \ifspx@opt@verbatimforcewraps + \spx@verb@DecideIfWillForceWrap + \fi + \setbox\spx@verb@tempboxa=\vtop{\hsize\linewidth + \raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ \doublehyphendemerits\z@\finalhyphendemerits\z@ - \strut #1\strut}% + \strut\spx@verb@FV@Line\strut}% + \setbox\spx@verb@tempboxa=\vtop{\unvbox\spx@verb@tempboxa + \setbox\spx@verb@tempboxb\lastbox + {\spx@verb@@ProcessLines}% + \FV@ProcessLine{\box\spx@verb@tempboxb\strut}% + \global\let\FV@ProcessLine\FV@ProcessLine + \global\setbox\@tempboxa=\box\@tempboxa}% + \unvbox\spx@verb@tempboxa }% % % The normal line wrapping allows breaks at spaces and ascii non @@ -342,52 +368,49 @@ % character widths, or if the min width plus verbatimmaxunderfull character % widths is inferior to linewidth, then we apply the "force wrapping" with % potential line break at each character, else we don't. -\long\def\spx@verb@FormatLineForceWrap#1{% - % \spx@image@box is a scratch box register that we can use here +\long\def\spx@verb@DecideIfWillForceWrap{% \global\let\spx@verb@maxwidth\z@ \global\let\spx@verb@minwidth\linewidth - \setbox\spx@image@box + \setbox\spx@verb@tempboxa \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ \doublehyphendemerits\z@\finalhyphendemerits\z@ - \spx@everypar{}\noindent\strut #1\strut\spx@par + \spx@everypar{}\noindent\strut\FV@Line\strut\spx@par \spx@verb@getwidths}% \ifdim\spx@verb@maxwidth> \dimexpr\linewidth+\spx@opt@verbatimmaxoverfull\fontcharwd\font`X \relax - \spx@verb@FormatLineWrap{\spx@verb@wrapPYG #1\spx@verb@wrapPYG}% + \def\spx@verb@FV@Line{\expandafter\spx@verb@wrapPYG\FV@Line\spx@verb@wrapPYG}% \else \ifdim\spx@verb@minwidth< \dimexpr\linewidth-\spx@opt@verbatimmaxunderfull\fontcharwd\font`X \relax - \spx@verb@FormatLineWrap{\spx@verb@wrapPYG #1\spx@verb@wrapPYG}% - \else - \spx@verb@FormatLineWrap{#1}% - \fi\fi + \def\spx@verb@FV@Line{\expandafter\spx@verb@wrapPYG\FV@Line\spx@verb@wrapPYG}% + \fi + \fi }% % auxiliary paragraph dissector to get max and min widths % but minwidth must not take into account the last line -\newbox\spx@scratchbox \def\spx@verb@getwidths {% \unskip\unpenalty - \setbox\spx@scratchbox\lastbox - \ifvoid\spx@scratchbox + \setbox\spx@verb@tempboxb\lastbox + \ifvoid\spx@verb@tempboxb \else - \setbox\spx@scratchbox\hbox{\unhbox\spx@scratchbox}% - \ifdim\spx@verb@maxwidth<\wd\spx@scratchbox - \xdef\spx@verb@maxwidth{\number\wd\spx@scratchbox sp}% + \setbox\spx@verb@tempboxb\hbox{\unhbox\spx@verb@tempboxb}% + \ifdim\spx@verb@maxwidth<\wd\spx@verb@tempboxb + \xdef\spx@verb@maxwidth{\number\wd\spx@verb@tempboxb sp}% \fi \expandafter\spx@verb@getwidths@loop \fi }% \def\spx@verb@getwidths@loop {% \unskip\unpenalty - \setbox\spx@scratchbox\lastbox - \ifvoid\spx@scratchbox + \setbox\spx@verb@tempboxb\lastbox + \ifvoid\spx@verb@tempboxb \else - \setbox\spx@scratchbox\hbox{\unhbox\spx@scratchbox}% - \ifdim\spx@verb@maxwidth<\wd\spx@scratchbox - \xdef\spx@verb@maxwidth{\number\wd\spx@scratchbox sp}% + \setbox\spx@verb@tempboxb\hbox{\unhbox\spx@verb@tempboxb}% + \ifdim\spx@verb@maxwidth<\wd\spx@verb@tempboxb + \xdef\spx@verb@maxwidth{\number\wd\spx@verb@tempboxb sp}% \fi - \ifdim\spx@verb@minwidth>\wd\spx@scratchbox - \xdef\spx@verb@minwidth{\number\wd\spx@scratchbox sp}% + \ifdim\spx@verb@minwidth>\wd\spx@verb@tempboxb + \xdef\spx@verb@minwidth{\number\wd\spx@verb@tempboxb sp}% \fi \expandafter\spx@verb@getwidths@loop \fi @@ -544,22 +567,12 @@ \let\sphinxVerbatim@Continues\@empty \fi \ifspx@opt@verbatimwrapslines - % fancyvrb's Verbatim puts each input line in (unbreakable) horizontal boxes. - % This customization wraps each line from the input in a \vtop, thus - % allowing it to wrap and display on two or more lines in the latex output. - % - The codeline counter will be increased only once. - % - The wrapped material will not break across pages, it is impossible - % to achieve this without extensive rewrite of fancyvrb. - % - The (not used in sphinx) obeytabs option to Verbatim is - % broken by this change (showtabs and tabspace work). - \let\sphinxVerbatimFormatLine\sphinxVerbatimFormatLineWrap + \let\FV@@PreProcessLine\spx@verb@@PreProcessLine \let\FV@Space\spx@verbatim@space % Allow breaks at special characters using \PYG... macros. \sphinxbreaksatspecials % Breaks at punctuation characters . , ; ? ! and / (needs catcode activation) \fvset{codes*=\sphinxbreaksviaactive}% - \else % end of conditional code for wrapping long code lines - \let\sphinxVerbatimFormatLine\sphinxVerbatimFormatLineNoWrap \fi \let\FancyVerbFormatLine\sphinxFancyVerbFormatLine \VerbatimEnvironment