Skip to content

Commit 74c1686

Browse files
committed
LaTeX: improve the table column widths computed by LaTeX itself
Fix #3447 Fix #8228 With this patch the legacy notion of "problematic cell" is almost entirely removed, and LaTeX package tabulary will be used more often so that column widths in tables may get better fit to actual contents. This works well when the column contains cells with multiple paragraphs, bullet lists, enumerated lists, or line blocks. For cells with object descriptions or admonitions, the column may not fit tightly to the contents, but other columns will probably be improved.
1 parent a15c149 commit 74c1686

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1324
-986
lines changed

CHANGES.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ Features added
6262
Bugs fixed
6363
----------
6464

65+
* #3447: LaTeX: when assigning longtable class to table for PDF, it may render
66+
"horizontally" and overflow in right margin.
67+
Patch by Jean-François B.
68+
* #8828: LaTeX: adding a footnote to a longtable cell causes table to occupy
69+
full width.
70+
Patch by Jean-François B.
6571
* #11498: LaTeX: Table in cell fails to build if it has many rows.
6672
Patch by Jean-François B.
6773
* #11515: LaTeX: longtable does not allow nested table.

doc/usage/restructuredtext/directives.rst

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,60 +1483,72 @@ Check the :confval:`latex_table_style`.
14831483

14841484
.. rst:directive:: .. tabularcolumns:: column spec
14851485
1486-
This directive influences only the LaTeX output for the next table in
1487-
source. The mandatory argument is a column specification (known as an
1488-
"alignment preamble" in LaTeX idiom). Please refer to a LaTeX
1486+
This directive influences only the LaTeX output, and only for the next
1487+
table in source. The mandatory argument is a column specification (known
1488+
as an "alignment preamble" in LaTeX idiom). Please refer to a LaTeX
14891489
documentation, such as the `wiki page`_, for basics of such a column
14901490
specification.
14911491

14921492
.. _wiki page: https://en.wikibooks.org/wiki/LaTeX/Tables
14931493

14941494
.. versionadded:: 0.3
14951495

1496-
.. note::
1496+
Sphinx renders tables with at most 30 rows using ``tabulary`` (or
1497+
``tabular`` if at least one cell contains either a code-block or a nested
1498+
table), and those with more rows with ``longtable``. The advantage of
1499+
using ``tabulary`` is that it tries to compute automatically (internally to
1500+
LaTeX) suitable column widths.
1501+
1502+
:rst:dir:`tabularcolumns` can serve to provide one's own "colspec" choice.
1503+
Here is an advanced example:
1504+
1505+
.. code-block:: latex
14971506

1498-
:rst:dir:`tabularcolumns` conflicts with ``:widths:`` option of table
1499-
directives. If both are specified, ``:widths:`` option will be ignored.
1507+
.. tabularcolumns:: >{\raggedright}\Y{.4}>{\centering}\Y{.1}>{\sphinxcolorblend{!95!red}\centering\noindent\bfseries\color{red}}\Y{.12}>{\raggedright\arraybackslash}\Y{.38}
15001508

1501-
Sphinx renders tables with at most 30 rows using ``tabulary``, and those
1502-
with more rows with ``longtable``.
1509+
This is used in Sphinx own PDF docs at :ref:`dev-deprecated-apis`.
1510+
Regarding column widths, this "colspec" achieves the same as would
1511+
``:widths:`` option set to ``40 10 12 38`` but it injects extra effects.
15031512

1504-
``tabulary`` tries to compute automatically (internally to LaTeX) suitable
1505-
column widths. However, cells are then not allowed to contain
1506-
"problematic" elements such as lists, object descriptions,
1507-
blockquotes... Sphinx will fall back to using ``tabular`` if such a cell is
1508-
encountered (or a nested ``tabulary``). In such a case the table will have
1509-
a tendency to try to fill the whole available line width.
1513+
.. note::
15101514

1511-
:rst:dir:`tabularcolumns` can help in coercing the usage of ``tabulary`` if
1512-
one is careful to not employ the ``tabulary`` column types (``L``, ``R``,
1513-
``C`` or ``J``) for those columns with at least one "problematic" cell, but
1514-
only LaTeX's ``p{<width>}`` or Sphinx ``\X`` and ``\Y`` (described next).
1515+
In case both :rst:dir:`tabularcolumns` and ``:widths:`` option of table
1516+
directives are used, ``:widths:`` option will be ignored by the LaTeX
1517+
builder. Of course it is obeyed by other builders.
15151518

1516-
Literal blocks do not work at all with ``tabulary``. Sphinx will fall back
1517-
to ``tabular`` or ``longtable`` environments depending on the number of
1518-
rows. It will employ the :rst:dir:`tabularcolumns` specification only if it
1519-
contains no usage of the ``tabulary`` specific types.
1519+
Literal blocks do not work at all with ``tabulary`` and Sphinx will then
1520+
fall back to ``tabular`` LaTeX environment. It will employ the
1521+
:rst:dir:`tabularcolumns` specification in that case only if it contains no
1522+
usage of the ``tabulary`` specific column types (which are ``L``, ``R``,
1523+
``C`` and ``J``).
15201524

15211525
Besides the LaTeX ``l``, ``r``, ``c`` and ``p{width}`` column specifiers,
1522-
one can also use ``\X{a}{b}`` which configures the column width to be a
1523-
fraction ``a/b`` of the total line width and ``\Y{f}`` where ``f`` is a
1524-
decimal: for example ``\Y{0.2}`` means that the column will occupy ``0.2``
1525-
times the line width.
1526+
and the ``tabulary`` specific ``L``, ``R``, ``C`` and ``J``, one can also
1527+
use (with all table types) ``\X{a}{b}`` which configures the column width
1528+
to be a fraction ``a/b`` of the total line width and ``\Y{f}`` where ``f``
1529+
is a decimal: for example ``\Y{0.2}`` means that the column will occupy
1530+
``0.2`` times the line width.
15261531

15271532
.. versionchanged:: 1.6
15281533

1529-
Use ``J`` (justified) by default with ``tabulary``, not ``L``
1534+
Sphinx uses ``J`` (justified) by default with ``tabulary``, not ``L``
15301535
(flushed-left). To revert, include ``\newcolumntype{T}{L}`` in the LaTeX
15311536
preamble, as in fact Sphinx uses ``T`` and sets it by default to be an
15321537
alias of ``J``.
15331538

1534-
.. hint::
1539+
.. versionchanged:: 8.3.0
15351540

1536-
A frequent issue with ``tabulary`` is that columns with little contents
1537-
appear to be "squeezed". One can add to the LaTeX preamble for example
1538-
``\setlength{\tymin}{40pt}`` to ensure a minimal column width of ``40pt``,
1539-
the ``tabulary`` default of ``10pt`` being too small.
1541+
Formerly, Sphinx did not use ``tabulary`` if the table had at least one
1542+
cell containing "problematic" elements such as lists, object descriptions,
1543+
blockquotes (etc...) because such contents are not out-of-the-box
1544+
compatible with ``tabulary``. At ``8.3.0`` a technique, which was already
1545+
in use for merged cells, was extended to such cases, and the sole
1546+
"problematic" contents are code-blocks and nested tables. So tables
1547+
containing (only) cells with mutliple paragraphs, bullet or enumerated
1548+
lists, or line blocks, will now better fit to their contents (if not
1549+
rendered by ``longtable``). Cells with object descriptions or admonitions
1550+
will still have a tendency to induce the table to fill the full text area
1551+
width, but columns in that table with no such contents will be tighter.
15401552

15411553
.. hint::
15421554

sphinx/texinputs/sphinxlatextables.sty

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
%% TABLES (WITH SUPPORT FOR MERGED CELLS OF GENERAL CONTENTS)
22
%
33
% change this info string if making any custom modification
4-
\ProvidesPackage{sphinxlatextables}[2025/06/09 v8.3.0 tables]%
4+
\ProvidesPackage{sphinxlatextables}[2025/06/30 v8.3.0 tables]%
55

66
% Provides support for this output mark-up from Sphinx latex writer
77
% and table templates:
@@ -42,6 +42,13 @@
4242
% - \sphinxthistablewithnocolorrowsstyle
4343
% - \sphinxthistablewithvlinesstyle
4444
% - \sphinxthistablewithnovlinesstyle
45+
% - \sphinxbeforeendvarwidth
46+
47+
% At 8.3.0, ALL table cell contents are wrapped into a varwidth environment.
48+
% This helps solve issues such as #3447, #8828, and helps use tabulary
49+
% in many more cases hence obtain better looking tables.
50+
\def\sphinxbeforeendvarwidth{\par\vskip-\baselineskip\vbox{\hbox{\strut}}}
51+
4552
% These conditionals added at 8.3.0 for nested tables not to break row colors
4653
% (#13635). Nested tables are only partially supported by Sphinx LaTeX.
4754
% The method here is with no changes to neither writer nor templates.
@@ -251,7 +258,29 @@
251258
%
252259
% configuration of tabulary
253260
\setlength{\tymin}{3\fontcharwd\font`0 }% minimal width of "squeezed" columns
254-
\setlength{\tymax}{10000pt}% allow enough room for paragraphs to "compete"
261+
\setlength{\tymax}{2\textwidth}% allow enough room for paragraphs to "compete"
262+
%
263+
% MEMO: tabulary initially renders cell contents "horizontally" to measure
264+
% them and compare their relative importance. Its goal is to choose the
265+
% column width so that, roughly, all columns will look about evenly
266+
% filled. "Horizontal" rendering is incompatible with many LaTeX
267+
% structures such as lists, so prior to Sphinx 8.3.0 cells with such
268+
% "problematic" contents caused Sphinx to use tabular not tabulary; the
269+
% tabular would then render each column in absence of :widths: option or
270+
% tabularcolumns directive the same width equal to available text width
271+
% divided by number of columns. At 8.3.0, "problematic" contents is
272+
% wrapped into a "varwidth" environment, as was already done formerly
273+
% for merged cells, and this avoids tabulary causing errors such as
274+
% "incompatible with LR mode"; \sphinxcolwidth is used which sets
275+
% the initial horizontal width for "varwidth". In the first tabulary
276+
% pass, \sphinxcolwidth is configured (by us) to use \tymax.
277+
%
278+
% During testing, it was determined that our former 10000pt setting for
279+
% \tymax could cause "Dimension too large" TeX error if two columns or
280+
% more contained such cells. So we use now 2\textwidth which is more
281+
% than 10 times smaller but proves large enough for the tabulary
282+
% algorithm to provide reasonable results.
283+
%
255284
% we need access to tabulary's final computed width. \@tempdima is too volatile
256285
% to hope it has kept tabulary's value when \sphinxcolwidth needs it.
257286
\newdimen\sphinx@TY@tablewidth
@@ -302,9 +331,7 @@
302331
% **** TODO: clarify if next paragraph means we must raise an
303332
% **** if LaTeX writer detects a merged cell inside nested table.
304333
% MEMO about nesting: if sphinxmulticolumn is encountered in a nested tabular
305-
% inside a tabulary it will think to be at top level in the tabulary. But
306-
% Sphinx generates no nested tables, and if some LaTeX macro uses internally a
307-
% tabular this will not have a \sphinxstartmulticolumn within it!
334+
% inside a tabulary it will think to be at top level in the tabulary.
308335
%
309336
% 5.3.0 adds a check for multirow as single-row multi-column will allow a row
310337
% colour but multi-row multi-column should not.
@@ -407,8 +434,7 @@
407434
}%
408435
\newcommand*\sphinxcolwidth[2]{%
409436
% this dimension will always be used for varwidth, and serves as maximum
410-
% width when cells are merged either via multirow or multicolumn or both,
411-
% as always their contents is wrapped in varwidth environment.
437+
% width for cells whose contents are wrapped in varwidth environment.
412438
\ifnum#1>\@ne % multi-column (and possibly also multi-row)
413439
% we wrote our own multicolumn code especially to handle that (and allow
414440
% verbatim contents)

0 commit comments

Comments
 (0)