Skip to content

Commit a573e10

Browse files
committed
LaTeX: make sphinxVerbatim compatible with raw horizontal tabulations
They can not attow come from code-blocks contents, having been replaced with spaces prior to be recorded in the .tex file, during Docutils + Sphinx processing, but they can arise from literalinclude directive. However, only "top-level" TABs will obey tab stops. In a situation like this in some Python codeline in the mystring = "foo<tab>bar" the TAB will end-up inside a Pygments LaTeX macro and at that location it ends up being converted to spaces independently of its location respective to tab stops. This patch was rebased on the Sphinx master branch HEAD on Dec. 9, 2025.
1 parent a672c54 commit a573e10

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

sphinx/texinputs/sphinx.sty

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
% by the Sphinx LaTeX writer.
1010

1111
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
12-
\ProvidesPackage{sphinx}[2025/08/03 v9.0.0 Sphinx LaTeX package (sphinx-doc)]
12+
\ProvidesPackage{sphinx}[2025/11/16 v9.0.0 Sphinx LaTeX package (sphinx-doc)]
1313

1414
% provides \ltx@ifundefined
1515
% (many packages load ltxcmds: graphicx does for pdftex and lualatex but
@@ -1175,7 +1175,9 @@
11751175
%% PYGMENTS
11761176
% stylesheet for highlighting with pygments
11771177
\RequirePackage{sphinxhighlight}
1178-
1178+
\let\spx@PYG\PYG
1179+
% See sphinxlatexliterals.sty for \spx@FV@Tab
1180+
\protected\def\PYG#1#2{\spx@PYG{#1}{\let\FV@Tab\spx@FV@Tab#2}}
11791181

11801182
%% TABLES
11811183
%

sphinx/texinputs/sphinxlatexliterals.sty

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
%% LITERAL BLOCKS
22
%
33
% change this info string if making any custom modification
4-
\ProvidesPackage{sphinxlatexliterals}[2025/08/06 v9.0.0 code-blocks and parsed literals]
4+
\ProvidesPackage{sphinxlatexliterals}[2025/11/16 v9.0.0 code-blocks and parsed literals]
55

66
% Provides support for this output mark-up from Sphinx latex writer:
77
%
@@ -56,6 +56,25 @@
5656
% 1, 2, 3, 4 by own Sphinx fully native Verbatim. This would greatly simplify
5757
% in particular wrapping long code lines in a way allowing page breaks.
5858
\RequirePackage{fancyvrb}
59+
% Store a copy of the original \FV@Tab, i.e. the one for obeytabs=false.
60+
% But we need a version allowing a linebreak so we insert \allowbreak.
61+
% TODO: do something fancier with a \discretionary as we do for a space at
62+
% location where we wrap long codelines (see \spx@verbatim@space).
63+
% MEMO: \FV@TabChar does nothing without option showtabs. With
64+
% \fvset{showtabs} it draws something similar to a ->| at right end
65+
% of the inserted horizontal whitespace.
66+
\def\spx@FV@Tab{\allowbreak\hbox to\FancyVerbTabSize\fontdimen2\font{\hss\FV@TabChar}}
67+
% In sphinx.sty, the \PYG macro is modified to set raw TAB characters
68+
% in its second argument to use the above \FV@Tab, because the one defined
69+
% by fancyvrb.sty to obey tab stops only works at top-level.
70+
% (this is an uptream bug/fact of life).
71+
% MEMO: attow (2025/11/16), a raw TAB (possibly nested) can come from a
72+
% literalinclude directive but never from a code-block. In this latter
73+
% case, TABs have been replaced with spaces earlier (as is the case also
74+
% for HTML output, cf #14065). Now set sphinxVerbatim to obey tab stops
75+
% (defaut: every 8 characters).
76+
\fvset{obeytabs}
77+
5978
% For parsed-literal blocks.
6079
\RequirePackage{alltt}
6180
% Display "real" single quotes in literal blocks.
@@ -345,7 +364,8 @@
345364
% (cf \spx@verb@@PreProcessLine; refs: #8686)
346365
% MEMO: formerly we did something with \fboxsep in relation to the LaTeX
347366
% bug graphics/4524 for \colorbox, but as we don't use \colorbox...
348-
\setbox\z@\hb@xt@\linewidth{\strut#1\hss}%
367+
% MEMO: for \FV@ObeyTabs check comments after this macro definition.
368+
\setbox\z@\hb@xt@\linewidth{\FV@ObeyTabs{\strut#1}\hss}%
349369
% MEMO: \colorbox would lead to \color{sphinxVerbatimHighlightColor}
350370
% plus \color@block, which results in doubled (a color.sty feature)
351371
% color command send to device driver and more importantly has
@@ -362,13 +382,10 @@
362382
% we added a group only for \FV@RightListNumber not be influenced by the
363383
% \current@color, if \fvset has been used to set numbers to the right.
364384
}%
365-
% MEMO: fancyvrb has options obeytabs and tabsize. Anyhow tab characters
366-
% do not make it to the tex file, they have been converted to spaces earlier.
367-
% But, if this was not the case, the support would be implemented here via
368-
% \newcommand\sphinxVerbatimFormatLine[1]{\FV@ObeyTabs{\strut #1}}%
369-
\newcommand\sphinxVerbatimFormatLine[1]{\strut#1}%
370-
% MEMO: if verbatimwrapslines is set to true (default) the #1 above is
371-
% simply \box\spx@tempboxb, from the next two macros.
385+
% MEMO: if verbatimwrapslines is set to true (which is default) the #1 here is
386+
% already a box, and \FV@ObeyTabs does nothing of significance. The real job is
387+
% elsewhere, further down in the code next.
388+
\newcommand\sphinxVerbatimFormatLine[1]{\FV@ObeyTabs{\strut #1}}%
372389
% The next two macros are a deep hack of fancyvrb.sty core line processing in
373390
% order to wrap too long lines, either at spaces and natural break-points,
374391
% (soft wrap) or optionally at any character (hard wrap). This requires deep
@@ -412,6 +429,7 @@
412429
% need to worry about them. An additional initial measuring step is needed if
413430
% user issued verbatimforcewraps=true, which elaborates on the same technique.
414431
% If hard wraps get activated, they get implemented via hacked \PYG macros.
432+
\def\FV@@ObeyTabs#1{\setbox\FV@TabBox=\hbox{#1}\unhbox\FV@TabBox}
415433
\def\spx@verb@@PreProcessLine{%
416434
\FV@StepLineNo
417435
\FV@Gobble
@@ -424,13 +442,18 @@
424442
\setbox\spx@tempboxa=\vtop{\hsize\linewidth
425443
\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@
426444
\doublehyphendemerits\z@\finalhyphendemerits\z@
427-
% MEMO: fancyvrb has options obeytabs and tabsize. Anyhow tab characters
428-
% do not make it to the tex file, they have been converted to spaces earlier.
429-
% But, if this was not the case, the support would be implemented here via
430-
% \FV@ObeyTabs{\strut\spx@verb@FV@Line\strut}%
431-
% And one would need a similar change in the measuring phase done by
432-
% \spx@verb@DecideIfWillDoForceWrap
433-
\strut\spx@verb@FV@Line\strut
445+
% MEMO: attow (2025/11/26), raw tab characters from contents of code-block's
446+
% do not make it to the .tex file, but they do with literalinclude directive.
447+
% cf #13656, #14064, #14065. The \FV@ObeyTabs dynamically splits the
448+
% line at each encountered top level TAB char, and adds a suitable horizontal
449+
% displacement to position of next tab stop. However, the way it does this
450+
% is not compatible with a TAB char being in the argument of a macro, and
451+
% sphinx.sty modifies \PYG for the TAB to not attempts anything there.
452+
% MEMO: when a long source line wraps over multiple output lines, there is via
453+
% the sphinx.sty default for verbatimcontinued sphinxsetup option an indent of
454+
% width equal to two characters, but the tab stops were computed without
455+
% it. (check if this comment is really true).
456+
\FV@ObeyTabs{\strut\spx@verb@FV@Line\strut}%
434457
% MEMO: since LaTeX 2021-06-01, there might be some hooks executed at
435458
% start and end of paragraphs (in future: PDF tagging), but we need an
436459
% explicit \par here for that. Else the kernel hooks at start of paragraph
@@ -519,7 +542,7 @@
519542
% Avoid TeX reporting Overfull \hbox'es during this measuring phase. Setting
520543
% \hbadness to \@M to avoid Underfull reports is unneeded due to \raggedright.
521544
\hfuzz\maxdimen
522-
\spx@everypar{}\noindent\strut\FV@Line\strut\spx@par
545+
\spx@everypar{}\noindent\FV@ObeyTabs{\strut\FV@Line\strut}\spx@par
523546
\spx@verb@getwidths}%
524547
\ifdim\spx@verb@maxwidth>
525548
\dimexpr\linewidth+\spx@opt@verbatimmaxoverfull\fontcharwd\font`X \relax
@@ -563,6 +586,8 @@
563586
\fi
564587
}%
565588
% auxiliary macros to implement "cut long line even in middle of word"
589+
% MEMO: it is important that this is does not rely on any specific \PYG
590+
% meaning, it only relies on its presence in the mark-up, not its meaning.
566591
\catcode`Z=3 % safe delimiter
567592
\def\spx@verb@wrapPYG{%
568593
\futurelet\spx@nexttoken\spx@verb@wrapPYG@i

0 commit comments

Comments
 (0)