From bfc84dea25a33b8dd5752be441388fead3df7a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20B?= <2589111+jfbu@users.noreply.github.com> Date: Mon, 8 Aug 2022 19:19:53 +0200 Subject: [PATCH] latex_book_style configuration, support booktabs, colorrows, borderless This is a combination of 28 commits... - Simplify a bit a conditional in the longtable template This also puts the target for a longtable with a label but no caption above the toprule for better hyperlinking (testing shows hyperlink target can not end up alone at bottom of previous page). - Refactor and trim doc about LaTeX tables... to make room for more, later - Enlarge allowed syntax for colour assignments via 'sphinxsetup' - latex_table_style new configuration value and coloured rows For the user interface tried to look for inspiration in https://docutils.sourceforge.io/docs/user/config.html#table-style which mentions booktabs and borderless. They also mention captionbelow which we can implement later, now that architecture is here. They don't mention coloured rows. - Test on our own document... looks fine! - Update LaTeX table tests and templates Modify longtable templates to put LaTeX macros each on its line Table body insertion without removing previous EOL may give output which contain some empty lines but longtable defines \par token to be same as \empty. - Work-around an incompatibility of \cline with row colours, improve docs - Reverse priority of classes to allow overruling booktabs by standard after parsing source but before letting LaTeX writer act - Closes #8220 Commit https://github.com/sphinx-doc/sphinx/commit/bb859c669679baebd8cc8d10c99382478c0d1647 already improved a bit, this finishes it (as :rst:dir:`rst-class` was actually not linking to anywhere). - Update CHANGES for PR #10759 - Let booktabs style defaults to *not* using \cmidrule. They actually don't make much sense there, as all \hline's are removed. - Enhance customizability at LaTeX code level (via code executed prior to table rendering, e.g. from a container class environment). - Patch booktabs \cmidrule, as if it used via \sphinxcline, there is a vertical space problem in case of there are two in the same row due to booktabs \futurelet not knowing \sphinxcline - Add \sphinxnorowcolor which allows construct such as this one in a tabularcolumns directive: >{\columncolor{blue}\sphinxnorowcolor} else LaTeX always overrides column colour by row colour - Add TableMergeColorHeader, TableMergeColorOdd, TableMergeColorEven so single-row merged cells can be styled especially - Extend row colours to all header rows not only the first one (all header rows will share same colour settings) - Auto-adjust to a no '|'-colspec for optimal handling of merged cell - Add \sphinxcolorblend - Needed to also detect if a '|' is in tabularcolumns, tests updated - Fix refactoring in this series which broke table.colsep update - Add test which would have shown regression regarding table.colsep - Fix another regression regarding \sphinxcline + booktabs Can not add test for that, because it shows only after PDF build. - Final testing and code comments update --- CHANGES | 2 + doc/conf.py | 3 +- doc/extdev/deprecated.rst | 4 +- doc/latex.rst | 71 ++- doc/usage/configuration.rst | 114 +++- doc/usage/restructuredtext/basics.rst | 17 +- doc/usage/restructuredtext/directives.rst | 147 ++--- doc/usage/theming.rst | 2 +- sphinx/builders/latex/__init__.py | 7 +- sphinx/templates/latex/latex.tex_t | 8 +- sphinx/templates/latex/longtable.tex_t | 38 +- sphinx/templates/latex/tabular.tex_t | 27 +- sphinx/templates/latex/tabulary.tex_t | 27 +- sphinx/texinputs/sphinx.sty | 115 ++-- sphinx/texinputs/sphinxlatextables.sty | 586 ++++++++++++++++-- sphinx/writers/latex.py | 55 +- tests/roots/test-latex-table/complex.rst | 23 + .../expects/complex_spanning_cell.tex | 6 +- .../test-latex-table/expects/gridtable.tex | 5 +- .../expects/gridtable_with_tabularcolumn.tex | 73 +++ .../test-latex-table/expects/longtable.tex | 12 +- .../expects/longtable_having_align.tex | 11 +- .../expects/longtable_having_caption.tex | 11 +- .../longtable_having_problematic_cell.tex | 11 +- ...ving_stub_columns_and_problematic_cell.tex | 11 +- .../expects/longtable_having_verbatim.tex | 11 +- .../expects/longtable_having_widths.tex | 14 +- ...ble_having_widths_and_problematic_cell.tex | 11 +- .../expects/longtable_with_tabularcolumn.tex | 12 +- .../test-latex-table/expects/simple_table.tex | 4 +- .../expects/table_having_caption.tex | 4 +- .../expects/table_having_problematic_cell.tex | 6 +- ...ving_stub_columns_and_problematic_cell.tex | 6 +- ...ving_threeparagraphs_cell_in_first_col.tex | 4 +- .../expects/table_having_verbatim.tex | 4 +- .../expects/table_having_widths.tex | 8 +- ...ble_having_widths_and_problematic_cell.tex | 6 +- .../expects/tabular_having_widths.tex | 4 +- .../expects/tabularcolumn.tex | 7 +- .../expects/tabulary_having_widths.tex | 4 +- tests/roots/test-latex-table/longtable.rst | 2 +- tests/roots/test-latex-table/tabular.rst | 3 +- tests/test_build_latex.py | 29 +- 43 files changed, 1215 insertions(+), 310 deletions(-) create mode 100644 tests/roots/test-latex-table/expects/gridtable_with_tabularcolumn.tex diff --git a/CHANGES b/CHANGES index 6bffea6940c..5ee400a751d 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,8 @@ Features added - #10286: C++, support requires clauses not just between the template parameter lists and the declaration. +- #10759: LaTeX: add :confval:`latex_table_style` and support the + ``'booktabs'``, ``'borderless'``, and ``'colorrows'`` styles. Bugs fixed ---------- diff --git a/doc/conf.py b/doc/conf.py index a721508debf..e146bbd0cae 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -77,7 +77,7 @@ {\begin{sphinxtheindex}\end{sphinxtheindex}} ''', 'sphinxsetup': """% -VerbatimColor={RGB}{242,242,242},% +VerbatimColor=black!5,% tests 5.2.0 extended syntax VerbatimBorderColor={RGB}{32,32,32},% pre_border-radius=3pt,% pre_box-decoration-break=slice,% @@ -85,6 +85,7 @@ } latex_show_urls = 'footnote' latex_use_xindy = True +latex_table_style = ['booktabs', 'colorrows'] autodoc_member_order = 'groupwise' autosummary_generate = False diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst index 18b0e6d04e3..ef34f2b87d3 100644 --- a/doc/extdev/deprecated.rst +++ b/doc/extdev/deprecated.rst @@ -10,7 +10,7 @@ major versions (for more details, please see :ref:`deprecation-policy`). The following is a list of deprecated interfaces. -.. tabularcolumns:: |>{\raggedright}\Y{.4}|>{\centering}\Y{.1}|>{\centering}\Y{.12}|>{\raggedright\arraybackslash}\Y{.38}| +.. tabularcolumns:: >{\raggedright}\Y{.4}>{\centering}\Y{.1}>{\sphinxcolorblend{!95!red}\centering\noindent\bfseries\color{red}}\Y{.12}>{\raggedright\arraybackslash}\Y{.38} .. list-table:: deprecated APIs :header-rows: 1 @@ -19,7 +19,7 @@ The following is a list of deprecated interfaces. * - Target - Deprecated - - (will be) Removed + - Removed - Alternatives * - ``sphinx.util.path_stabilize`` diff --git a/doc/latex.rst b/doc/latex.rst index 17698fcce85..56a9a7807b4 100644 --- a/doc/latex.rst +++ b/doc/latex.rst @@ -819,16 +819,31 @@ Do not use quotes to enclose values, whether numerical or strings. definition of the continuation symbol was changed at 1.5 to accommodate various font sizes (e.g. code-blocks can be in footnotes). +.. note:: + + Values for colour keys must either: + + - obey the syntax of the ``\definecolor`` LaTeX command, e.g. something + such as ``VerbatimColor={rgb}{0.2,0.3,0.5}`` or ``{RGB}{37,23,255}`` or + ``{gray}{0.75}`` or (only with package ``xcolor``) ``{HTML}{808080}`` or + ... + + - or obey the syntax of the ``\colorlet`` command from package ``xcolor`` + (which then must exist in the LaTeX installation), + e.g. ``VerbatimColor=red!10`` or ``red!50!green`` or ``-red!75`` or + ``MyPreviouslyDefinedColour`` or... Refer to xcolor_ documentation for + this syntax. + + .. _xcolor: https://ctan.org/pkg/xcolor + + .. versionchanged:: 5.2.0 + Formerly only the ``\definecolor`` syntax was accepted. + ``TitleColor`` The colour for titles (as configured via use of package "titlesec".) Default: ``{rgb}{0.126,0.263,0.361}`` - .. warning:: - - Colours set via ``'sphinxsetup'`` must obey the syntax of the - argument of the ``color/xcolor`` packages ``\definecolor`` command. - ``InnerLinkColor`` A colour passed to ``hyperref`` as value of ``linkcolor`` and ``citecolor``. @@ -841,18 +856,6 @@ Do not use quotes to enclose values, whether numerical or strings. Default: ``{rgb}{0.216,0.439,0.388}`` -``RowEvenColor`` - default ``{rgb}{0.85,0.85,0.85}``. Background color for even rows in - tables, if option :confval:`latex_zebra_stripes` is set to ``True``. - - .. versionadded:: 2.1 - -``RowOddColor`` - default ``{rgb}{1,1,1}``. Background color for odd rows in tables, if - option :confval:`latex_zebra_stripes` is set to ``True``. - - .. versionadded:: 2.1 - ``VerbatimColor`` The background colour for :rst:dir:`code-block`\ s. @@ -875,6 +878,40 @@ Do not use quotes to enclose values, whether numerical or strings. Starting with this colour, and for all others following, the names declared to "color" or "xcolor" are prefixed with "sphinx". +``TableRowColorHeader`` + Background colour for (all) the header rows. This (as the next + ``Table...`` colours) applies conditionnally + on either ``'colorrows'`` being contained in :confval:`latex_table_style` + or on the table receiving ``colorrows`` as class. + + Default: ``{gray}{0.86}`` + + There is also ``TableMergeColorHeader`` which as long as it is not + defined (either globally via ``'sphinxsetup'`` interface or locally + via :dudir:`raw` directive and ``\sphinxsetup`` LaTeX macro) will keep + in sync with ``TableRowColorHeader``. + + .. versionadded:: 5.2.0 + +``TableRowColorOdd`` + Background colour for odd rows in tables (the row count starts at ``1`` + at the first non-header row). + + Default: ``{gray}{0.92}`` + + There is also ``TableMergeColorOdd``. + + .. versionadded:: 5.2.0 + +``TableRowColorEven`` + Background colour for even rows in tables. + + Default ``{gray}{0.98}`` + + There is also ``TableMergeColorEven``. + + .. versionadded:: 5.2.0 + ``verbatimsep`` The separation between code lines and the frame. diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index 898d2fa4825..38234873c15 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -2210,6 +2210,101 @@ These options influence LaTeX output. .. versionadded:: 1.6 +.. confval:: latex_table_style + + A list of styling classes (strings). Currently supported: + + - ``'booktabs'``: no vertical lines, and only 2 or 3 horizontal lines (the + latter if there is a header), using the booktabs_ package. + + - ``'borderless'``: no lines whatsoever. + + - ``'colorrows'``: the body rows are rendered with alternating background + colours, see the :ref:`latexsphinxsetup` keys ``TableRowColorOdd`` and + ``TableRowColorEven`` for configuration. And ``TableRowColorHeader`` + for the header rows. + + Default: ``[]`` + + .. versionadded:: 5.2.0 + + If using ``'booktabs'`` or ``'borderless'`` it seems recommended to also + opt for ``'colorrows'``... + + Each table can override the global style via ``:class:`` option, or + ``.. rst-class::`` for no-directive tables (cf. :ref:`table-directives`). + Currently recognized classes are ``booktabs``, ``borderless``, + ``standard``, ``colorrows``, ``nocolorrows``. The latter two can be + combined with any of the first three. The ``standard`` class produces + tables with both horizontal and vertical lines (as has been the default so + far with Sphinx). + + A single-row multi-column merged cell will obey the row colour, if it is + set. See also ``TableMergeColor{Header,Odd,Even}`` in the + :ref:`latexsphinxsetup` section. + + .. note:: + + - It is hard-coded in LaTeX that a single cell will obey the row colour + even if there is a column colour set via ``\columncolor`` from a + column specification (see :rst:dir:`tabularcolumns`). Sphinx provides + ``\sphinxnorowcolor`` which can be used like this: + + .. code-block:: latex + + >{\columncolor{blue}\sphinxnorowcolor} + + in a table column specification. + + - Sphinx also provides ``\sphinxcolorblend`` which however requires the + xcolor_ package. Here is an example: + + .. code-block:: latex + + >{\sphinxcolorblend{!95!red}} + + It means that in this column, the row colours will be slightly tinted + by red; refer to xcolor_ documentation for more on the syntax of its + ``\blendcolors`` command (a ``\blendcolors`` in place of + ``\sphinxcolorblend`` would modify colours of the cell *contents*, not + of the cell *background colour panel*...). You can find an example of + usage in the :ref:`dev-deprecated-apis` section of this document in + PDF format. + + .. hint:: + + If you want to use a special colour for the *contents* of the + cells of a given column use ``>{\noindent\color{}}``, + possibly in addition to the above. + + - Multi-row merged cells, whether single column or multi-column + currently ignore any set column, row, or cell colour. + + - It is possible for a simple cell to set a custom colour via the + :dudir:`raw` directive and the ``\cellcolor`` LaTeX command used + anywhere in the cell contents. This currently is without effect + in a merged cell, whatever its kind. + + .. hint:: + + In a document not using ``'booktabs'`` globally, it is possible to style + an individual table via the ``booktabs`` class, but it will be necessary + to add ``r'\usepackage{booktabs}'`` to the LaTeX preamble. + + On the other hand one can use ``colorrows`` class for individual tables + with no extra package (as Sphinx since 5.2.0 always loads colortbl_). + + When using both ``'booktabs'`` and ``'colorrows'`` there is a small + white gap between the bottom row and the bottom rule, and between the + first body row and the (mid or top) rule above it. It is possible to + extend the background colouring to touch the rules, via some extra LaTeX + coding. This may be added to Sphinx in case of feature request, but + this whitespace is considered currently a quality rather than a defect. + + .. _booktabs: https://ctan.org/pkg/booktabs + .. _colortbl: https://ctan.org/pkg/colortbl + .. _xcolor: https://ctan.org/pkg/xcolor + .. confval:: latex_use_xindy If ``True``, the PDF build from the LaTeX files created by Sphinx @@ -2241,25 +2336,6 @@ These options influence LaTeX output. .. versionadded:: 1.8 -.. confval:: latex_use_booktabs - - If ``True``, render tables without vertical rules and horizontal rules of - varying thickness (with additional space above and below) using the - booktabs_ package. - - .. _booktabs: https://ctan.org/pkg/booktabs - - .. versionadded:: 5.2.0 - -.. confval:: latex_zebra_stripes - - If ``True``, render tables with alternating background colors for even and - odd rows (so called "zebra striping"). See :ref:`latexsphinxsetup` - ``RowEvenColor`` and ``RowOddColor`` for changing the default white-grey - color scheme. - - .. versionadded:: 2.1 - .. confval:: latex_elements .. versionadded:: 0.5 diff --git a/doc/usage/restructuredtext/basics.rst b/doc/usage/restructuredtext/basics.rst index c846dc145f6..824b59ee2c2 100644 --- a/doc/usage/restructuredtext/basics.rst +++ b/doc/usage/restructuredtext/basics.rst @@ -370,7 +370,15 @@ Docutils supports the following directives: - :dudir:`include` (include reStructuredText from another file) -- in Sphinx, when given an absolute include file path, this directive takes it as relative to the source directory - - :dudir:`class` (assign a class attribute to the next element) [1]_ + + .. _rstclass: + + - :dudir:`class` (assign a class attribute to the next element) + + .. note:: + + When the default domain contains a ``class`` directive, this directive + will be shadowed. Therefore, Sphinx re-exports it as ``rst-class``. * HTML specifics: @@ -621,10 +629,3 @@ There are some problems one commonly runs into while authoring reST documents: * **No nested inline markup:** Something like ``*see :func:`foo`*`` is not possible. - - -.. rubric:: Footnotes - -.. [1] When the default domain contains a :rst:dir:`class` directive, this - directive will be shadowed. Therefore, Sphinx re-exports it as - :rst:dir:`rst-class`. diff --git a/doc/usage/restructuredtext/directives.rst b/doc/usage/restructuredtext/directives.rst index 4029b04e67b..44e4b5ffead 100644 --- a/doc/usage/restructuredtext/directives.rst +++ b/doc/usage/restructuredtext/directives.rst @@ -371,8 +371,9 @@ units as well as normal text. .. centered:: LICENSE AGREEMENT .. deprecated:: 1.1 - This presentation-only directive is a legacy from older versions. Use a - :rst:dir:`rst-class` directive instead and add an appropriate style. + This presentation-only directive is a legacy from older versions. + Use a :ref:`rst-class ` directive instead and add an + appropriate style. .. rst:directive:: hlist @@ -1045,114 +1046,78 @@ Use :ref:`reStructuredText tables `, i.e. either The :dudir:`table` directive serves as optional wrapper of the *grid* and *simple* syntaxes. -They work fine in HTML output, however there are some gotchas when using tables -in LaTeX: the column width is hard to determine correctly automatically. For -this reason, the following directive exists: +They work fine in HTML output, but rendering tables to LaTeX is complex. +Check the :confval:`latex_table_style`. -.. rst:directive:: .. tabularcolumns:: column spec - - This directive gives a "column spec" for the next table occurring in the - source file. The spec is the second argument to the LaTeX ``tabulary`` - package's environment (which Sphinx uses to translate tables). It can have - values like :: - - |l|l|l| - - which means three left-adjusted, nonbreaking columns. For columns with - longer text that should automatically be broken, use either the standard - ``p{width}`` construct, or tabulary's automatic specifiers: +.. versionchanged:: 1.6 + Merged cells (multi-row, multi-column, both) from grid tables containing + complex contents such as multiple paragraphs, blockquotes, lists, literal + blocks, will render correctly to LaTeX output. - +-----+------------------------------------------+ - |``L``| flush left column with automatic width | - +-----+------------------------------------------+ - |``R``| flush right column with automatic width | - +-----+------------------------------------------+ - |``C``| centered column with automatic width | - +-----+------------------------------------------+ - |``J``| justified column with automatic width | - +-----+------------------------------------------+ +.. rst:directive:: .. tabularcolumns:: column spec - The automatic widths of the ``LRCJ`` columns are attributed by ``tabulary`` - in proportion to the observed shares in a first pass where the table cells - are rendered at their natural "horizontal" widths. + This directive influences only the LaTeX output for the next table in + source. The mandatory argument is a column specification (known as an + "alignment preamble" in LaTeX idiom). Please refer to a LaTeX + documentation, such as the `wiki page`_, for basics of such a column + specification. - By default, Sphinx uses a table layout with ``J`` for every column. + .. _wiki page: https://en.wikibooks.org/wiki/LaTeX/Tables .. versionadded:: 0.3 - .. versionchanged:: 1.6 - Merged cells may now contain multiple paragraphs and are much better - handled, thanks to custom Sphinx LaTeX macros. This novel situation - motivated the switch to ``J`` specifier and not ``L`` by default. - - .. hint:: + .. note:: - Sphinx actually uses ``T`` specifier having done ``\newcolumntype{T}{J}``. - To revert to previous default, insert ``\newcolumntype{T}{L}`` in the - LaTeX preamble (see :confval:`latex_elements`). + :rst:dir:`tabularcolumns` conflicts with ``:widths:`` option of table + directives. If both are specified, ``:widths:`` option will be ignored. - A frequent issue with tabulary is that columns with little contents are - "squeezed". The minimal column width is a tabulary parameter called - ``\tymin``. You may set it globally in the LaTeX preamble via - ``\setlength{\tymin}{40pt}`` for example. + Sphinx will render tables with more than 30 rows with ``longtable``. + Besides the ``l``, ``r``, ``c`` and ``p{width}`` column specifiers, one can + also use ``\X{a}{b}`` (new in version 1.5) which configures the column + width to be a fraction ``a/b`` of the total line width and ``\Y{f}`` (new + in version 1.6) where ``f`` is a decimal: for example ``\Y{0.2}`` means that + the column will occupy ``0.2`` times the line width. - Else, use the :rst:dir:`tabularcolumns` directive with an explicit - ``p{40pt}`` (for example) for that column. You may use also ``l`` - specifier but this makes the task of setting column widths more difficult - if some merged cell intersects that column. + When this directive is used for a table with at most 30 rows, Sphinx will + render it with ``tabulary``. One can then use specific column types ``L`` + (left), ``R`` (right), ``C`` (centered) and ``J`` (justified). They have + the effect of a ``p{width}`` (i.e. each cell is a LaTeX ``\parbox``) with + the specified internal text alignment and an automatically computed + ``width``. .. warning:: - Tables with more than 30 rows are rendered using ``longtable``, not - ``tabulary``, in order to allow pagebreaks. The ``L``, ``R``, ... - specifiers do not work for these tables. - - Tables that contain list-like elements such as object descriptions, - blockquotes or any kind of lists cannot be set out of the box with - ``tabulary``. They are therefore set with the standard LaTeX ``tabular`` - (or ``longtable``) environment if you don't give a ``tabularcolumns`` - directive. If you do, the table will be set with ``tabulary`` but you - must use the ``p{width}`` construct (or Sphinx's ``\X`` and ``\Y`` - specifiers described below) for the columns containing these elements. - - Literal blocks do not work with ``tabulary`` at all, so tables containing - a literal block are always set with ``tabular``. The verbatim environment - used for literal blocks only works in ``p{width}`` (and ``\X`` or ``\Y``) - columns, hence Sphinx generates such column specs for tables containing - literal blocks. - - Since Sphinx 1.5, the ``\X{a}{b}`` specifier is used (there *is* a backslash - in the specifier letter). It is like ``p{width}`` with the width set to a - fraction ``a/b`` of the current line width. You can use it in the - :rst:dir:`tabularcolumns` (it is not a problem if some LaTeX macro is also - called ``\X``.) - - It is *not* needed for ``b`` to be the total number of columns, nor for the - sum of the fractions of the ``\X`` specifiers to add up to one. For example - ``|\X{2}{5}|\X{1}{5}|\X{1}{5}|`` is legitimate and the table will occupy - 80% of the line width, the first of its three columns having the same width - as the sum of the next two. - - This is used by the ``:widths:`` option of the :dudir:`table` directive. - - Since Sphinx 1.6, there is also the ``\Y{f}`` specifier which admits a - decimal argument, such has ``\Y{0.15}``: this would have the same effect as - ``\X{3}{20}``. + - Cells that contain list-like elements such as object descriptions, + blockquotes or any kind of lists are not compatible with the ``LRCJ`` + column types. The column type must then be some ``p{width}`` with an + explicit ``width`` (or ``\X{a}{b}`` or ``\Y{f}``). - .. versionchanged:: 1.6 + - Literal blocks do not work with ``tabulary`` at all. Sphinx will + fall back to ``tabular`` or ``longtable`` environments and generate a + suitable column specification. - Merged cells from complex grid tables (either multi-row, multi-column, or - both) now allow blockquotes, lists, literal blocks, ... as do regular - cells. +In absence of the :rst:dir:`tabularcolumns` directive, and for a table with at +most 30 rows and no problematic cells as described in the above warning, +Sphinx uses ``tabulary`` and the ``J`` column-type for every column. - Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, - ``\Y{f}`` and tabulary's columns. +.. versionchanged:: 1.6 - .. note:: + Formerly, the ``L`` column-type was used (text is flushed-left). To revert + to this, include ``\newcolumntype{T}{L}`` in the LaTeX preamble, as in fact + Sphinx uses ``T`` and sets it by default to be an alias of ``J``. - :rst:dir:`tabularcolumns` conflicts with ``:widths:`` option of table - directives. If both are specified, ``:widths:`` option will be ignored. +.. hint:: + + A frequent issue with ``tabulary`` is that columns with little contents + appear to be "squeezed". One can add to the LaTeX preamble for example + ``\setlength{\tymin}{40pt}`` to ensure a minimal column width of ``40pt``, + the ``tabulary`` default of ``10pt`` being too small. + +.. hint:: + To force usage of the LaTeX ``longtable`` environment pass ``longtable`` as + a ``:class:`` option to :dudir:`table`, :dudir:`csv-table`, or + :dudir:`list-table`. Use :ref:`rst-class ` for other tables. Math ---- diff --git a/doc/usage/theming.rst b/doc/usage/theming.rst index 0e4b4a64dde..c33c7d4770d 100644 --- a/doc/usage/theming.rst +++ b/doc/usage/theming.rst @@ -88,7 +88,7 @@ writing your own themes, refer to :doc:`/development/theming`. Builtin themes ~~~~~~~~~~~~~~ -.. cssclass:: longtable +.. cssclass:: longtable, standard +--------------------+--------------------+ | **Theme overview** | | diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index a2478ad9684..da2a5dfc2eb 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -170,7 +170,9 @@ def init_context(self) -> None: self.context.update(self.config.latex_elements) self.context['release'] = self.config.release self.context['use_xindy'] = self.config.latex_use_xindy - self.context['use_booktabs'] = self.config.latex_use_booktabs + self.context['booktabs'] = 'booktabs' in self.config.latex_table_style + self.context['borderless'] = 'borderless' in self.config.latex_table_style + self.context['colorrows'] = 'colorrows' in self.config.latex_table_style if self.config.today: self.context['date'] = self.config.today @@ -518,8 +520,6 @@ def setup(app: Sphinx) -> Dict[str, Any]: app.add_config_value('latex_appendices', [], None) app.add_config_value('latex_use_latex_multicolumn', False, None) app.add_config_value('latex_use_xindy', default_latex_use_xindy, None, [bool]) - app.add_config_value('latex_use_booktabs', False, None) - app.add_config_value('latex_zebra_stripes', False, None) app.add_config_value('latex_toplevel_sectioning', None, None, ENUM(None, 'part', 'chapter', 'section')) app.add_config_value('latex_domain_indices', True, None, [list]) @@ -527,6 +527,7 @@ def setup(app: Sphinx) -> Dict[str, Any]: app.add_config_value('latex_show_pagerefs', False, None) app.add_config_value('latex_elements', {}, None) app.add_config_value('latex_additional_files', [], None) + app.add_config_value('latex_table_style', [], None, [list]) app.add_config_value('latex_theme', 'manual', None, [str]) app.add_config_value('latex_theme_options', {}, None) app.add_config_value('latex_theme_path', [], None, [list]) diff --git a/sphinx/templates/latex/latex.tex_t b/sphinx/templates/latex/latex.tex_t index 1cebac93418..deb030504db 100644 --- a/sphinx/templates/latex/latex.tex_t +++ b/sphinx/templates/latex/latex.tex_t @@ -26,9 +26,15 @@ \makeatletter\@ifclassloaded{memoir} {\ifdefined\memhyperindexfalse\memhyperindexfalse\fi}{}\makeatother <% endif %> -<% if use_booktabs -%> +<% if booktabs -%> \PassOptionsToPackage{booktabs}{sphinx} <% endif -%> +<% if borderless -%> +\PassOptionsToPackage{borderless}{sphinx} +<% endif -%> +<% if colorrows -%> +\PassOptionsToPackage{colorrows}{sphinx} +<% endif -%> <%= passoptionstopackages %> \PassOptionsToPackage{warn}{textcomp} <%= inputenc %> diff --git a/sphinx/templates/latex/longtable.tex_t b/sphinx/templates/latex/longtable.tex_t index a96c2003775..9f722a71387 100644 --- a/sphinx/templates/latex/longtable.tex_t +++ b/sphinx/templates/latex/longtable.tex_t @@ -1,4 +1,28 @@ -\begin{savenotes}\sphinxatlongtablestart\begin{longtable} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +<% if 'booktabs' in table.styles -%> +\sphinxthistablewithbooktabsstyle +<% endif -%> +<% if 'borderless' in table.styles -%> +\sphinxthistablewithborderlessstyle +<% endif -%> +<% if 'standard' in table.styles -%> +\sphinxthistablewithstandardstyle +<% endif -%> +<% if 'vlines' in table.styles -%> +\sphinxthistablewithvlinesstyle +<% endif -%> +<% if 'novlines' in table.styles -%> +\sphinxthistablewithnovlinesstyle +<% endif -%> +<% if 'colorrows' in table.styles -%> +\sphinxthistablewithcolorrowsstyle +<% endif -%> +<% if 'nocolorrows' in table.styles -%> +\sphinxthistablewithnocolorrowsstyle +<% endif -%> +\begin{longtable} <%- if table.align in ('center', 'default') -%> [c] <%- elif table.align == 'left' -%> @@ -10,12 +34,10 @@ <%- if table.caption -%> \sphinxthelongtablecaptionisattop \caption{<%= ''.join(table.caption) %>\strut}<%= labels %>\\*[\sphinxlongtablecapskipadjust] -\sphinxtoprule <% elif labels -%> -\sphinxtoprule\noalign{\phantomsection<%= labels %>}% -<% else -%> -\sphinxtoprule +\noalign{\phantomsection<%= labels %>}% <% endif -%> +\sphinxtoprule <%= ''.join(table.header) -%> <%- if table.header -%> \sphinxmidrule @@ -36,6 +58,10 @@ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook <%= ''.join(table.body) -%> \sphinxbottomrule -\end{longtable}\sphinxatlongtableend\end{savenotes} +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/sphinx/templates/latex/tabular.tex_t b/sphinx/templates/latex/tabular.tex_t index d1a0b97f488..0a9310a5ed2 100644 --- a/sphinx/templates/latex/tabular.tex_t +++ b/sphinx/templates/latex/tabular.tex_t @@ -1,4 +1,26 @@ \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +<% if 'booktabs' in table.styles -%> +\sphinxthistablewithbooktabsstyle +<% endif -%> +<% if 'borderless' in table.styles -%> +\sphinxthistablewithborderlessstyle +<% endif -%> +<% if 'standard' in table.styles -%> +\sphinxthistablewithstandardstyle +<% endif -%> +<% if 'vlines' in table.styles -%> +\sphinxthistablewithvlinesstyle +<% endif -%> +<% if 'novlines' in table.styles -%> +\sphinxthistablewithnovlinesstyle +<% endif -%> +<% if 'colorrows' in table.styles -%> +\sphinxthistablewithcolorrowsstyle +<% endif -%> +<% if 'nocolorrows' in table.styles -%> +\sphinxthistablewithnocolorrowsstyle +<% endif -%> <% if table.align -%> <%- if table.align in ('center', 'default') -%> \centering @@ -23,9 +45,10 @@ <%= ''.join(table.header) -%> <%- if table.header -%> \sphinxmidrule -<%- endif -%> +<% endif -%> +\sphinxtableatstartofbodyhook <%=- ''.join(table.body) -%> \sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/sphinx/templates/latex/tabulary.tex_t b/sphinx/templates/latex/tabulary.tex_t index f71214f5491..6ebcec6d264 100644 --- a/sphinx/templates/latex/tabulary.tex_t +++ b/sphinx/templates/latex/tabulary.tex_t @@ -1,4 +1,26 @@ \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +<% if 'booktabs' in table.styles -%> +\sphinxthistablewithbooktabsstyle +<% endif -%> +<% if 'borderless' in table.styles -%> +\sphinxthistablewithborderlessstyle +<% endif -%> +<% if 'standard' in table.styles -%> +\sphinxthistablewithstandardstyle +<% endif -%> +<% if 'vlines' in table.styles -%> +\sphinxthistablewithvlinesstyle +<% endif -%> +<% if 'novlines' in table.styles -%> +\sphinxthistablewithnovlinesstyle +<% endif -%> +<% if 'colorrows' in table.styles -%> +\sphinxthistablewithcolorrowsstyle +<% endif -%> +<% if 'nocolorrows' in table.styles -%> +\sphinxthistablewithnocolorrowsstyle +<% endif -%> <% if table.align -%> <%- if table.align in ('center', 'default') -%> \centering @@ -23,9 +45,10 @@ <%= ''.join(table.header) -%> <%- if table.header -%> \sphinxmidrule -<%- endif -%> +<% endif -%> +\sphinxtableatstartofbodyhook <%=- ''.join(table.body) -%> \sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 0077543d999..be8965e2561 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -6,7 +6,7 @@ % \NeedsTeXFormat{LaTeX2e}[1995/12/01] -\ProvidesPackage{sphinx}[2022/06/30 v5.1.0 LaTeX package (Sphinx markup)] +\ProvidesPackage{sphinx}[2022/08/10 v5.2.0 LaTeX package (Sphinx markup)] % provides \ltx@ifundefined % (many packages load ltxcmds: graphicx does for pdftex and lualatex but @@ -43,15 +43,40 @@ % checked at 5.0.0) \fcolorbox is used for admonitions (sphinxheavybox) % and appears also in Pygmentize output mark-up. \IfFileExists{xcolor.sty}{ - \RequirePackage[table]{xcolor} + \RequirePackage{xcolor} }{ \RequirePackage{color} } -% the \colorlet of xcolor (if at all loaded) is overkill for our use case + +% the \colorlet of xcolor (if at all loaded) is overkill for our internal use \newcommand{\sphinxcolorlet}[2] {\expandafter\let\csname\@backslashchar color@#1\expandafter\endcsname \csname\@backslashchar color@#2\endcsname } +% (5.2.0) allow colour options to use both the \definecolor and the \colorlet +% syntaxes, for example VerbatimColor={gray}{0.9} or VerbatimColor=red!10 +% In the latter case we need the real \colorlet from xcolor package. +\def\spx@defineorletcolor#1{% + \def\spx@definedcolor{{#1}}% + \futurelet\spx@token\spx@defineorlet} +\def\spx@defineorlet{% + \ifx\spx@token\bgroup + \expandafter\spx@definecolor\else\expandafter\spx@colorlet\fi} +\def\spx@colorlet#1\relax{\expandafter\colorlet\spx@definedcolor{#1}} +\def\spx@definecolor{\expandafter\definecolor\spx@definedcolor} +% +\@ifpackageloaded{xcolor}% + {}% + {% xcolor not loaded +\def\spx@colorlet#1\relax{% + \PackageWarning{sphinx}{% +Sorry, defining \spx@definedcolor\space to be #1\MessageBreak +via \protect\colorlet syntax requires package xcolor.sty.\MessageBreak +The color \spx@definedcolor\space will be set to {rgb}{0,0,1}\MessageBreak +\protect\definecolor}% + \expandafter\definecolor\spx@definedcolor{rgb}{0,0,1}}% + }% end of xcolor not found branch + % Handle options via "kvoptions" (later loaded by hyperref anyhow) \RequirePackage{kvoptions} @@ -59,6 +84,9 @@ % Optional usage of booktabs package for tables \DeclareBoolOption[false]{booktabs} +\DeclareBoolOption[false]{borderless} +% Coloured table rows +\DeclareBoolOption[false]{colorrows} % Sphinx legacy text layout: 1in margins on all four sides \ifx\@jsc@uplatextrue\@undefined \DeclareStringOption[1in]{hmargin} @@ -146,21 +174,41 @@ % first, some colours with no prefix, for backwards compatibility \newcommand*{\sphinxDeclareColorOption}[2]{% \definecolor{#1}#2% - \define@key{sphinx}{#1}{\definecolor{#1}##1}% + \define@key{sphinx}{#1}{\spx@defineorletcolor{#1}##1\relax}% }% +% only \definecolor syntax for the defaults here! \sphinxDeclareColorOption{TitleColor}{{rgb}{0.126,0.263,0.361}} \sphinxDeclareColorOption{InnerLinkColor}{{rgb}{0.208,0.374,0.486}} \sphinxDeclareColorOption{OuterLinkColor}{{rgb}{0.216,0.439,0.388}} \sphinxDeclareColorOption{VerbatimColor}{{rgb}{1,1,1}} \sphinxDeclareColorOption{VerbatimBorderColor}{{rgb}{0,0,0}} -\sphinxDeclareColorOption{RowEvenColor}{{rgb}{0.85,0.85,0.85}} -\sphinxDeclareColorOption{RowOddColor}{{rgb}{1,1,1}} % now the colours defined with "sphinx" prefix in their names \newcommand*{\sphinxDeclareSphinxColorOption}[2]{% % set the initial default \definecolor{sphinx#1}#2% % set the key handler. The "value" ##1 must be acceptable by \definecolor. - \define@key{sphinx}{#1}{\definecolor{sphinx#1}##1}% + \define@key{sphinx}{#1}{\spx@defineorletcolor{sphinx#1}##1\relax}% +}% +% only \definecolor syntax for the defaults here! +% table row colors +\sphinxDeclareSphinxColorOption{TableRowColorHeader}{{gray}{0.86}} +\sphinxDeclareSphinxColorOption{TableRowColorOdd}{{gray}{0.92}} +\sphinxDeclareSphinxColorOption{TableRowColorEven}{{gray}{0.98}} +% if not defined "MergeColor" will keep in sync with "RowColor" +\def\sphinxTableMergeColorHeader{sphinxTableRowColorHeader} +\define@key{sphinx}{TableMergeColorHeader}{% + \spx@defineorletcolor{sphinxTableMergeColorHeader}#1\relax + \def\sphinxTableMergeColorHeader{sphinxTableMergeColorHeader}% +}% +\def\sphinxTableMergeColorOdd{sphinxTableRowColorOdd} +\define@key{sphinx}{TableMergeColorOdd}{% + \spx@defineorletcolor{sphinxTableMergeColorOdd}#1\relax + \def\sphinxTableMergeColorOdd{sphinxTableMergeColorOdd}% +}% +\def\sphinxTableMergeColorEven{sphinxTableRowColorEven} +\define@key{sphinx}{TableMergeColorEven}{% + \spx@defineorletcolor{sphinxTableMergeColorEven}#1\relax + \def\sphinxTableMergeColorEven{sphinxTableMergeColorEven}% }% % Default color chosen to be as in minted.sty LaTeX package! \sphinxDeclareSphinxColorOption{VerbatimHighlightColor}{{rgb}{0.878,1,1}} @@ -296,21 +344,21 @@ \newif\ifspx@pre@withbordercolor \define@key{sphinx}{pre_border-TeXcolor}{% \spx@pre@withbordercolortrue - \definecolor{VerbatimBorderColor}#1% legacy colour name with no sphinx prefix + \spx@defineorletcolor{VerbatimBorderColor}#1\relax } \expandafter\let\expandafter\KV@sphinx@VerbatimBorderColor \csname KV@sphinx@pre_border-TeXcolor\endcsname \newif\ifspx@pre@withbackgroundcolor \define@key{sphinx}{pre_background-TeXcolor}{% \spx@pre@withbackgroundcolortrue - \definecolor{VerbatimColor}#1% legacy colour name with no sphinx prefix + \spx@defineorletcolor{VerbatimColor}#1\relax } \expandafter\let\expandafter\KV@sphinx@VerbatimColor \csname KV@sphinx@pre_background-TeXcolor\endcsname \newif\ifspx@pre@withshadowcolor \define@key{sphinx}{pre_box-shadow-TeXcolor}{% \spx@pre@withshadowcolortrue - \definecolor{sphinxVerbatimShadowColor}#1% + \spx@defineorletcolor{sphinxVerbatimShadowColor}#1\relax } \definecolor{sphinxVerbatimShadowColor}{rgb}{0,0,0} % topics @@ -416,17 +464,17 @@ \newif\ifspx@topic@withbordercolor \define@key{sphinx}{div.topic_border-TeXcolor}{% \spx@topic@withbordercolortrue - \definecolor{sphinxTopicBorderColor}#1% + \spx@defineorletcolor{sphinxTopicBorderColor}#1\relax } \newif\ifspx@topic@withbackgroundcolor \define@key{sphinx}{div.topic_background-TeXcolor}{% \spx@topic@withbackgroundcolortrue - \definecolor{sphinxTopicBackgroundColor}#1% + \spx@defineorletcolor{sphinxTopicBackgroundColor}#1\relax } \newif\ifspx@topic@withshadowcolor \define@key{sphinx}{div.topic_box-shadow-TeXcolor}{% \spx@topic@withshadowcolortrue - \definecolor{sphinxTopicShadowColor}#1% + \spx@defineorletcolor{sphinxTopicShadowColor}#1\relax } % warning, caution, attention, danger, error \def\spx@tempa#1{% @@ -576,9 +624,12 @@ \definecolor{sphinx#4BorderColor}{rgb}{0,0,0}% \definecolor{sphinx#4BgColor}{rgb}{1,1,1}% \definecolor{sphinx#4ShadowColor}{rgb}{0,0,0}% - \define@key{sphinx}{div.#4_border-TeXcolor}{#1\definecolor{sphinx#4BorderColor}##1}% - \define@key{sphinx}{div.#4_background-TeXcolor}{#2\definecolor{sphinx#4BgColor}##1}% - \define@key{sphinx}{div.#4_box-shadow-TeXcolor}{#3\definecolor{sphinx#4ShadowColor}##1}% + \define@key{sphinx}{div.#4_border-TeXcolor}% + {#1\spx@defineorletcolor{sphinx#4BorderColor}##1\relax}% + \define@key{sphinx}{div.#4_background-TeXcolor}% + {#2\spx@defineorletcolor{sphinx#4BgColor}##1\relax}% + \define@key{sphinx}{div.#4_box-shadow-TeXcolor}% + {#3\spx@defineorletcolor{sphinx#4ShadowColor}##1\relax}% \expandafter\let\csname KV@sphinx@#4BorderColor\expandafter\endcsname \csname KV@sphinx@div.#4_border-TeXcolor\endcsname \expandafter\let\csname KV@sphinx@#4BgColor\expandafter\endcsname @@ -599,6 +650,8 @@ \DisableKeyvalOption{sphinx}{nonumfigreset} \DisableKeyvalOption{sphinx}{mathnumfig} \DisableKeyvalOption{sphinx}{booktabs} +\DisableKeyvalOption{sphinx}{borderless} +\DisableKeyvalOption{sphinx}{rowcolors} % FIXME: this is unrelated to an option, move this elsewhere % To allow hyphenation of first word in narrow contexts; no option, % customization to be done via 'preamble' key @@ -729,36 +782,6 @@ %% TABLES % \input{sphinxlatextables.sty} -% Those two are produced by the latex writer -\def\sphinxhline{\hline} -\def\sphinxcline{\cline} -% Those three are inserted by the table templates -\def\sphinxtoprule{\hline} -\def\sphinxmidrule{\hline} -\def\sphinxbottomrule{\hline} -% \def\sphinxarrayrulewidth{\arrayrulewidth}% already done -\ifspx@opt@booktabs - \RequirePackage{booktabs} - \def\sphinxarrayrulewidth{\z@}% (attention! Do NOT assign to \sphinxarrayrulewidth - % this would modify \z@ and break all of LaTeX...) - \let\sphinxhline\@empty - \def\sphinxcline{\cmidrule(lr)}% - \def\sphinxtoprule{\toprule}% - \def\sphinxmidrule{\midrule}% - \def\sphinxbottomrule{\bottomrule}% -\fi -\AtBeginDocument -{\@ifpackageloaded{booktabs}% - {\ifspx@opt@booktabs\else - \AtEndDocument{% -\PackageWarningNoLine{sphinx}{% - Package booktabs is detected but configuration option\MessageBreak - latex_use_booktabs is False. Tables will not use booktabs styling}% -}% - \fi}% - {}% -}% - %% NUMBERING OF FIGURES, TABLES, AND LITERAL BLOCKS diff --git a/sphinx/texinputs/sphinxlatextables.sty b/sphinx/texinputs/sphinxlatextables.sty index bc4cdc44583..76d29d1c719 100644 --- a/sphinx/texinputs/sphinxlatextables.sty +++ b/sphinx/texinputs/sphinxlatextables.sty @@ -1,7 +1,7 @@ %% TABLES (WITH SUPPORT FOR MERGED CELLS OF GENERAL CONTENTS) % % change this info string if making any custom modification -\ProvidesFile{sphinxlatextables.sty}[2022/08/07 tables]% +\ProvidesFile{sphinxlatextables.sty}[2022/08/10 tables]% % Provides support for this output mark-up from Sphinx latex writer % and table templates: @@ -25,12 +25,28 @@ % - \sphinxtablestrut % - \sphinxthecaptionisattop % - \sphinxthelongtablecaptionisattop +% - \sphinxhline +% - \sphinxcline +% - \sphinxtoprule +% - \sphinxmidrule +% - \sphinxbottomrule +% - \sphinxtableatstartofbodyhook +% - \sphinxtableafterendhook +% - \sphinxthistablewithglobalstyle +% - \sphinxthistablewithbooktabsstyle +% - \sphinxthistablewithborderlessstyle +% - \sphinxthistablewithstandardstyle +% - \sphinxthistablewithcolorrowsstyle +% - \sphinxthistablewithnocolorrowsstyle +% - \sphinxthistablewithvlinesstyle +% - \sphinxthistablewithnovlinesstyle % % Executes \RequirePackage for: % % - tabulary % - longtable % - varwidth +% - colortbl % % Extends tabulary and longtable via patches and custom macros to support % merged cells possibly containing code-blocks in complex tables @@ -42,11 +58,14 @@ % sphinxpackagemulticell.sty % X or S (Sphinx) may have meanings if some table package is loaded hence % \X was chosen to avoid possibility of conflict -\def\sphinxarrayrulewidth{\arrayrulewidth}% will be set to \z@ if booktabs option \newcolumntype{\X}[2]{p{\dimexpr - (\linewidth-\sphinxarrayrulewidth)*#1/#2-\tw@\tabcolsep-\sphinxarrayrulewidth\relax}} + (\linewidth-\spx@arrayrulewidth)*#1/#2-\tw@\tabcolsep-\spx@arrayrulewidth\relax}} \newcolumntype{\Y}[1]{p{\dimexpr - #1\dimexpr\linewidth-\sphinxarrayrulewidth\relax-\tw@\tabcolsep-\sphinxarrayrulewidth\relax}} + #1\dimexpr\linewidth-\spx@arrayrulewidth\relax-\tw@\tabcolsep-\spx@arrayrulewidth\relax}} +% \spx@arrayrulewidth is used internally and its meaning will be set according +% to the table type; no extra user code should modify it. In particular any +% \setlength{\spx@arrayrulewidth}{...} may break all of LaTeX... (really...) +\def\spx@arrayrulewidth{\arrayrulewidth}% 5.2.0, to be adjusted by each table % using here T (for Tabulary) feels less of a problem than the X could be \newcolumntype{T}{J}% % For tables allowing pagebreaks @@ -168,6 +187,11 @@ \unexpanded\expandafter{\@vwid@setup}}% }% +% NOTA BENE: since the multicolumn and multirow code was written Sphinx +% decided to prefix non public internal macros by \spx@ and in fact all +% such macros here should now be prefixed by \spx@table@, but doing the +% update is delayed to later. (written at 5.2.0) + %%%%%%%%%%%%%%%%%%%%% % --- MULTICOLUMN --- % standard LaTeX's \multicolumn @@ -209,9 +233,15 @@ % \arrayrulewidth space for each column separation in its estimate of available % width). % -% EDIT: Sphinx 5.2.0 uses \sphinxarrayrulewidth which is \z@ if booktabs -% option has been used. Do not mix booktabs option with usage of | in -% tabularcolumns directive. +% Update at 5.2.0: code uses \spx@arrayrulewidth which is kept in sync with the +% table column specification (aka preamble): +% - no | in preamble: \spx@arrayrulewidth -> \z@ +% - at least a | in the preamble: \spx@arrayrulewidth -> \arrayrulewidth +% This is used for computation of merged cells widths. Mixed preambles using +% at least a | but not using it for all columns (as can be obtained via the +% tabularcolumns directive) may cause some merged cells contents to be slightly +% shifted to the left as they assume merged columns are | separated where in +% fact they perhaps are not. % % TN. 1b: as Sphinx multicolumn uses neither \omit nor \span, it can not % (easily) get rid of extra macros from >{...} or <{...} between columns. At @@ -234,7 +264,15 @@ % Sphinx generates no nested tables, and if some LaTeX macro uses internally a % tabular this will not have a \sphinxstartmulticolumn within it! % -\def\sphinxstartmulticolumn{% +% 5.2.0 adds a check for multirow as single-row multi-column will allow a row +% colour but multi-row multi-column should not. +\def\sphinxstartmulticolumn#1#2{% + \ifx\sphinxmultirow#2% #2 is either \sphinxmultirow or \begin + \def\spx@table@hackCT@inmergedcell{\spx@table@hackCT@nocolor}% + \fi + \sphinx@startmulticolumn{#1}#2% +}% +\def\sphinx@startmulticolumn{% \ifx\equation$% $ tabulary's first pass \expandafter\sphinx@TYI@start@multicolumn \else % either not tabulary or tabulary's second pass @@ -290,34 +328,23 @@ \else % if in an l, r, c type column, try and hope for the best \xdef\sphinx@tempb{\the\dimexpr(\ifx\TY@final\@undefined\linewidth\else - \sphinx@TY@tablewidth\fi-\sphinxarrayrulewidth)/\sphinx@tempa - -\tw@\tabcolsep-\sphinxarrayrulewidth\relax}% + \sphinx@TY@tablewidth\fi-\spx@arrayrulewidth)/\sphinx@tempa + -\tw@\tabcolsep-\spx@arrayrulewidth\relax}% \fi \noindent\kern\sphinx@tempb\relax \xdef\sphinx@multiwidth - {\the\dimexpr\sphinx@multiwidth+\sphinx@tempb+\tw@\tabcolsep+\sphinxarrayrulewidth}% - % hack the \vline and the colortbl macros - \sphinx@hack@vline\sphinx@hack@CT&\relax + {\the\dimexpr\sphinx@multiwidth+\sphinx@tempb+\tw@\tabcolsep+\spx@arrayrulewidth}% + % simulate the \vline added width + \spx@table@fakevline + % prevent column colours to interfere with our multi-column but allow row + % colour; sadly we can't infere a \cellcolor and propagate it to the + % merged cell as it has not be seen yet at this stage which is preparatory + % to the varwidth environment execution... and the background colour panels + % are injected by colortbl now when the & is met... + \spx@table@hackCT@inmergedcell&\relax % repeat \expandafter\sphinx@multispan\expandafter{\the\numexpr#1-\@ne}% }% -% packages like colortbl add group levels, we need to "climb back up" to be -% able to hack the \vline and also the colortbl inserted tokens. This creates -% empty space whether or not the columns were | separated: -% (5.2.0 sets \sphinxarrayrulewidth to expand to \z@ if booktabs option has been -% made use of, the \arrayrulewidth\z@ serves then nothing but shoud not hurt). -\def\sphinx@hack@vline{\ifnum\currentgrouptype=6\relax - \kern\sphinxarrayrulewidth\arrayrulewidth\z@\else\aftergroup\sphinx@hack@vline\fi}% -\def\sphinx@hack@CT{\ifnum\currentgrouptype=6\relax - \let\CT@setup\sphinx@CT@setup\else\aftergroup\sphinx@hack@CT\fi}% -% It turns out \CT@row@color is not expanded contrarily to \CT@column@color -% during LaTeX+colortbl preamble preparation, hence it would be possible for -% \sphinx@CT@setup to discard only the column color and choose to obey or not -% row color and cell color. It would even be possible to propagate cell color -% to row color for the duration of the Sphinx multicolumn... the (provisional?) -% choice has been made to cancel the colortbl colours for the multicolumn -% duration. -\def\sphinx@CT@setup #1\endgroup{\endgroup}% hack to remove colour commands \def\sphinx@multispan@end#1{% % first, trace back our steps horizontally \noindent\kern-\dimexpr\sphinx@multiwidth\relax @@ -327,11 +354,11 @@ \else \xdef\sphinx@multiwidth{\the\dimexpr\sphinx@multiwidth+ (\ifx\TY@final\@undefined\linewidth\else - \sphinx@TY@tablewidth\fi-\sphinxarrayrulewidth)/\sphinx@tempa - -\tw@\tabcolsep-\sphinxarrayrulewidth\relax}% + \sphinx@TY@tablewidth\fi-\spx@arrayrulewidth)/\sphinx@tempa + -\tw@\tabcolsep-\spx@arrayrulewidth\relax}% \fi % we need to remove colour set-up also for last cell of the multi-column - \aftergroup\sphinx@hack@CT + \aftergroup\spx@table@hackCT@inmergedcell }% \newcommand*\sphinxcolwidth[2]{% % this dimension will always be used for varwidth, and serves as maximum @@ -352,8 +379,8 @@ \linewidth \else % l, c, r columns. Do our best. - \dimexpr(\linewidth-\sphinxarrayrulewidth)/#2- - \tw@\tabcolsep-\sphinxarrayrulewidth\relax + \dimexpr(\linewidth-\spx@arrayrulewidth)/#2- + \tw@\tabcolsep-\spx@arrayrulewidth\relax \fi \else % in tabulary \ifx\equation$%$% first pass @@ -364,8 +391,8 @@ \linewidth % in a L, R, C, J column or a p, \X, \Y ... \else % we have hacked \TY@final to put in \sphinx@TY@tablewidth the table width - \dimexpr(\sphinx@TY@tablewidth-\sphinxarrayrulewidth)/#2- - \tw@\tabcolsep-\sphinxarrayrulewidth\relax + \dimexpr(\sphinx@TY@tablewidth-\spx@arrayrulewidth)/#2- + \tw@\tabcolsep-\spx@arrayrulewidth\relax \fi \fi \fi @@ -375,7 +402,140 @@ % \sphinxcolwidth will use this only inside LaTeX's standard \multicolumn \def\sphinx@multiwidth #1#2{\dimexpr % #1 to gobble the \@gobble (!) (\ifx\TY@final\@undefined\linewidth\else\sphinx@TY@tablewidth\fi - -\sphinxarrayrulewidth)*#2-\tw@\tabcolsep-\sphinxarrayrulewidth\relax}% + -\spx@arrayrulewidth)*#2-\tw@\tabcolsep-\spx@arrayrulewidth\relax}% + +% \spx@table@fakevline +% packages like colortbl add group levels, we need to "climb back up" to be +% able to hack the \vline and also the colortbl inserted tokens. The hack +% induces an empty space of the width corresponding to a \vline. Then it +% sets the \arrayrulewidth to \z@ to inhibit a | separator at right end +% of the cell, if present (our code does not use \omit so can not avoid the +% \vline insertion, but setting its width to zero makes it do nothing) +\def\spx@table@fakevline{\ifnum\currentgrouptype=6\relax + \kern\spx@arrayrulewidth\arrayrulewidth\z@\else\aftergroup\spx@table@fakevline\fi}% + +% hacking around colour matters +% Sphinx 1.6 comment: +% It turns out \CT@row@color is not expanded contrarily to \CT@column@color +% during LaTeX+colortbl preamble preparation, hence it would be possible for +% \CT@setup to discard only the column color and choose to obey or not +% row color and cell color. It would even be possible to propagate cell color +% to row color for the duration of the Sphinx multicolumn... the (provisional?) +% choice has been made to cancel the colortbl colours for the multicolumn +% duration. +% Sphinx 5.2.0 comment: +% - colortbl has no mechanism to disable colour background in a given cell: +% \cellcolor triggers one more \color, but has no possibility to revert +% a previously emitted \color, only to override it via an additional \color +% - prior to <5.2.0, Sphinx did not officially support colour in tables, +% but it did have a mechanism to protect merged cells from being partly +% covered by colour panels at various places. At 5.2.0 this mechanism +% is relaxed a bit to allow row colour for a single-row merged cell. +% +% \spx@table@hackCT@inmergedcell +% \spx@table@hackCT@nocolor +% \spx@table@hackCT@norowcolor +% +% \let\spx@original@CT@setup\CT@setup is done after the loading of colortbl +% package +% +% inmergedcell +\def\spx@table@hackCT@inmergedcell{\ifnum\currentgrouptype=6\relax + \let\CT@setup\spx@CT@setup@inmergedcell + \else\aftergroup\spx@table@hackCT@inmergedcell\fi +}% +\newif\ifspx@table@inmergedcell +\def\spx@CT@setup@inmergedcell #1\endgroup{% + % - obey only row color and disable effect of \sphinxblendcolor + % - turn on the inmergedcell boolean to signal to \CT@row@color + \spx@original@CT@setup + \spx@table@inmergedcelltrue % needed by \CT@row@color + % deactivate effect of \sphinxcolorblend if it happened at all + \ifdefined\blendcolors\blendcolors{}\fi + \CT@row@color + \CT@do@color + \global\let\CT@cell@color\relax + \endgroup +}% +% +% nocolor +\def\spx@table@hackCT@nocolor{\ifnum\currentgrouptype=6\relax +% sadly \CT@column@color is possibly already expanded so we can't +% simply do \let\CT@column@color\relax etc... +% admittedly we could perhaps hack \CT@color but well + \let\CT@setup\spx@CT@setup@nocolor + \else\aftergroup\spx@table@hackCT@nocolor\fi +} +\def\spx@CT@setup@nocolor#1\endgroup{% + \global\let\CT@cell@color\relax + % the above added at 5.2.0 + % formerly a \cellcolor added by a raw latex directive in the merged cell + % would have caused colour to apply to the *next* cell after the merged one + \endgroup} +% +% norowcolor +\def\spx@table@hackCT@norowcolor{% +% a bit easier although merged cells complicate the matter as they do need +% to keep the rowcolor; and we can't know yet if we are in a merged cell + \ifnum\currentgrouptype=6\relax + \ifx\CT@row@color\relax + \else + \let\spx@saved@CT@row@color\CT@row@color + \def\CT@row@color{% + \ifspx@table@inmergedcell\expandafter\spx@saved@CT@row@color\fi + }% + \fi + \else\aftergroup\spx@table@hackCT@norowcolor\fi +} +% +% sphinxcolormix (commented-out) +% this works but then I found out about \blendcolors in xcolor doc, so I provided +% rather \sphinxcolorblend, the code is kept in case it can be reused in future +% \@ifpackageloaded{xcolor}{% +% \def\spx@table@hackCT@colormix{% +% \ifnum\currentgrouptype=6\relax +% \ifx\CT@column@color\relax +% \else +% \ifx\CT@row@color\relax +% \else +% \let\spx@saved@CT@row@color\CT@row@color +% \def\CT@row@color{% +% \ifspx@table@inmergedcell +% \expandafter\spx@saved@CT@row@color +% \else +% \colorlet{spxcolumncolor}{.}% +% \spx@saved@CT@row@color +% \colorlet{spxrowcolor}{.}% +% \color{spxcolumncolor!\spx@colormixparam!spxrowcolor}% +% \fi +% }% patched \CT@row@color +% \fi +% \fi +% \else +% \aftergroup\spx@table@hackCT@colormix +% \fi +% }% +% }{\let\spx@table@hackCT@colormix\@empty}% no-op if no xcolor as \colorlet needed +% \def\sphinxcolormix#1{\gdef\spx@colormixparam{#1}\spx@table@hackCT@colormix} +% +% \sphinxcolorblend +\def\spx@table@hackCT@colorblend{% + \ifnum\currentgrouptype=6\relax + \expandafter\blendcolors\spx@colorblendparam + % merged cells will do a \blendcolors{} to cancel the effet + % we can not know here yet if in merged cell as the boolean + % \ifspx@table@inmergedcell is not yet updated + \else + \aftergroup\spx@table@hackCT@colorblend + \fi +} +% Either xcolor.sty exists on user system and has been loaded by sphinx.sty, +% or it does not exist, so we can use \@ifpackageloaded without delaying. +\@ifpackageloaded{xcolor}% + {}% + {\let\spx@table@hackCT@colorblend\@empty}% no-op if no xcolor +\def\sphinxcolorblend#1{\gdef\spx@colorblendparam{{#1}}\spx@table@hackCT@colorblend} + %%%%%%%%%%%%%%%%%% % --- MULTIROW --- @@ -397,9 +557,22 @@ % that the table rows have the needed height. The needed mark-up is done % by LaTeX writer, which has its own id for the merged cells. % -% The colour issue is solved by clearing colour panels in all cells, +% The colour issue is "solved" by clearing colour panels in all cells, % whether or not the multirow is single-column or multi-column. % +% MEMO at 5.2.0: to allow a multirow cell in a single column to react to +% \columncolor correctly, it seems only way is that the contents +% are inserted by bottom cell (this is mentioned in multirow.sty doc, too). +% Sphinx could at Python level "move" the contents to that cell. But the +% mechanism used here via \sphinxtablestrut to enlarge rows to make room for +% the contents if needed becomes more challenging yet, because \sphinxtablestrut +% mark-up will be parsed by TeX *before* it sees the contents of the merged +% cell.. So it seems the best way would be to actually store the contents into +% some owned-by-Sphinx box storage which needs to be globally allocated to +% that usage ; then we need multiple such boxes, say at least 5 to cover +% 99% or use case. Or perhaps some trick with storing in a \vbox and recovering +% via some \vsplit but this becomes complicated... perhaps in future. +% % In passing we obtain baseline alignements across rows (only if % \arraystretch is 1, as LaTeX's does not obey \arraystretch in "p" % multi-line contents, only first and last line...) @@ -417,6 +590,15 @@ \setbox\z@\hbox\bgroup\aftergroup\sphinx@@multirow\strut }% \def\sphinx@@multirow {% +% MEMO: we could check status of \CT@cell@color here, but unfortunately we +% can't know the exact height which will be covered by the cells in total +% (it may be more than our \box\z@ dimensions). We could use an \fcolorbox +% wrapper on \box\z@ but this will not extend precisely to the bottom rule. +% +% Only solution if we want to obey a raw \cellcolor, or a \columncolor, seems +% to delay unboxing the gathered contents as part of the bottom row with +% a suitable verticale adjustement... +% % The contents, which is a varwidth environment, has been captured in % \box0 (a \hbox). % We have with \sphinx@cellid an assigned unique id. The goal is to give @@ -482,7 +664,331 @@ \@width\z@ \endgroup % we need this to avoid colour panels hiding bottom parts of multirow text - \sphinx@hack@CT + % whether they originate in \columncolor or \rowcolor (or even \cellcolor + % even though it can be only in top cell, but we could hijack it). + \spx@table@hackCT@nocolor +}% + +%%%%%%%%%%%%%%%%%% +% --- STYLING --- +% + +% the initialization macros executed before the table environments +% their scope is limited by a wrapper "savenotes" environment +% +% 0) color support is enacted via adding code to three hooks: +% - \sphinxtabletoprulehook (implicit from \sphinxtoprule expansion) +% - \sphinxtableatstartofbodyhook (explicit from table templates) +% - \sphinxtableafterendhook (explicit from table templates) +% additionally special adjustment must be made in \sphinxcline +% +% 1) we manage these three hooks in a way allowing a custom user extra wrapper +% environment from a container class to use them as entry point for some +% custom code. The container code is done first, prior to table templates. +% So, the style macros will *prepend* the needed color-code to the existing +% custom user code, so the custom user code can override them. The custom +% user code should not redefine any of the 3 \sphinxtable...hook macros via a +% \global\def, but their contents can use \gdef. In fact they probably need +% to for the first two hooks which are executed from inside the table and +% a priori need their code to be in a \noalign which limits scope. +% +% 2) the table templates and LaTeX writer code make it so that only +% one of either +% \sphinxthistablewithcolorrowsstyle, +% or \sphinxthistablewithnocolorrowsstyle +% will be inserted explicitly depending on local :class: for table. +% The global 'colorrows' style in latex_table_style translates at bottom +% of this file into code for inserting \sphinxthistablewithcolorrowsstyle +% at end of \sphinxthistablewithglobalstyle. So it is impossible +% to have first \sphinxthistablewithnocolorrowsstyle, then +% \sphinxthistablewithcolorrowsstyle. Nevertheless we have written +% the code so that in this case colorrows would indeed activate (except +% if it was already executed before as it self-annihilates). +% +\let\sphinxtabletoprulehook \@empty +\let\sphinxtableatstartofbodyhook\@empty +\let\sphinxtableafterendhook \@empty +% +% Support for colour in table +% +% Core LaTeX package (very old, part of texlive-latex-base on Debian distr.) +% providing \columncolor, \rowcolor, \cellcolor and \arrayrulecolor. +\RequirePackage{colortbl} +\let\spx@original@CT@setup\CT@setup +% +% - passing option "table" to xcolor also loads colortbl but we needed to +% load color or xcolor prior to the handling of the options +% +% - the \rowcolors command from [table]{xcolor} has various problems: +% +% * it is rigid and does not out-of-the-box allow a more complex scheme +% such as colorA+colorB+colorC+colorB+colorC+colorB+colorC... suitable to +% distinguish a header row. +% +% * its code does not export the used colour, an information which we may +% need for example to colourize the rule via \arrayrulecolor in the +% appropriate manner, for example to colourize the booktabs induced vertical +% whitespace to avoid gaps (if one wants to). +% +% * incompatibility with tabulary: the output depends on parity of total +% number of rows! +% +% * problems with longtable: the caption will receive a background colour +% panel, if we do not deactivate the \rowcolors action during definition of +% the headers and footers; this requires extra mark-up. Besides if we +% deactivate using \hiderowcolors during header and footer formation, the +% parity of the body rows is shifted, \rownum is even, not odd, at first body +% row. And setting \rownum at start of first body row is too late for +% influencing the colour. +% +% * it has a global impact and must be reset at each table. We can not +% issue it only once and it provides no public interface (without @) to +% cancel its effect conveniently (\hiderowcolors can only be used from +% *inside* a table.) +% +% * its core mechanism which increments the row count is triggered +% if a \cline is encountered... so this offsets the alternating colours... +% ... or not if there are two \cline's in the row... +% (as we will use same mechanism we have to correct this increment). +% +% So we need our own code. + +% Provide \rownum and rownum LaTeX counter (code copied from colortbl v1.0f) +\ltx@ifundefined{rownum}{% + \ltx@ifundefined{c@rownum}% + {\newcount\rownum\let\c@rownum\rownum}% + {\let\rownum\c@rownum}% + }% +{\let\c@rownum\rownum} +\providecommand\therownum{\arabic{rownum}} + +% extra overhang for color panels to avoid visual artifacts in pdf viewers +% (particularly if borderless) +\def\sphinxcolorpanelextraoverhang{0.1pt} + +% set the colours according to row parity; a priori #1 is \rownum, but +% the macro can be used in user added code +\def\sphinxSwitchCaseRowColor#1{% + \ifodd#1\relax + \global\sphinxcolorlet{sphinxTableRowColor}{sphinxTableRowColorOdd}% + \global\sphinxcolorlet{sphinxTableMergeColor}{\sphinxTableMergeColorOdd}% + \else + \global\sphinxcolorlet{sphinxTableRowColor}{sphinxTableRowColorEven}% + \global\sphinxcolorlet{sphinxTableMergeColor}{\sphinxTableMergeColorEven}% + \fi +} + +% this will start the alternating colours, by letting \everycr increment the +% \rownum counter and reset the colours according to \sphinxSwitchCaseRowColor\rownum +\def\spx@table@@startbodycolorrows{% + \noalign{% + \global\CT@everycr{% Nota Bene: in a longtable with \hline the \everycr is + % done two extra times! but 2 is even, so this is ok + \noalign{\global\advance\rownum\@ne % the xcolor \rowcolors base trick +% MEMO: colortbl \CT@row@color is expanded *after* the cell contents have been +% gathered and measured, so it can't be used to expose e.g. the colour to the +% cell contents macro code. Of course if it is known how the colour is chosen +% the procedure could be done from inside the cell. Simpler to expose the colour +% in a public name sphinxTableRowColor at start of the row in this \noalign. + \sphinxSwitchCaseRowColor\rownum + }% + \the\everycr + }% + \global\rownum\@ne % is done from inside table so ok with tabulary two passes + \sphinxSwitchCaseRowColor\rownum % set up color for the first body row + \sphinxrowcolorON % has been done from \sphinxtoprule location but let's do + % it again in case \sphinxtabletoprulehook has been used + % to inihibit colours in the header rows + }% end of noalign contents +} + +\def\sphinxrowcolorON{% the colours here must have been defined, and this is done + % via \sphinxtabletoprulehook default action + \gdef\CT@row@color{\ifspx@table@inmergedcell + \CT@color{sphinxTableMergeColor}% + \else + \CT@color{sphinxTableRowColor}% + \fi + \@tempdimb\dimexpr\col@sep+\sphinxcolorpanelextraoverhang\relax + \@tempdimc\@tempdimb + }% }% +\def\sphinxrowcolorOFF{\global\let\CT@row@color\relax}% +\def\sphinxnorowcolor{\spx@table@hackCT@norowcolor}% inhibits row colour in one cell only +\def\spx@table@resetcolortbl{% can be executed from inside or outside a table + \global\let\CT@row@color\relax +% we should probably be more cautious and not hard-code here the colortbl set-up + \global\CT@everycr{\noalign{\global\let\CT@row@color\relax}\the\everycr}% +} + +\def\spx@table@@toprulehook{% + \noalign{% + % Because of tabulary 2-pass system, the colour set-up at end of table + % would contaminate the header colours at start of table, so must reset + % them here. We want all header rows to obey same colours, so we don't + % use original \CT@everycr which sets \CT@row@color to \relax. + \global\CT@everycr{\the\everycr}% + \global\sphinxcolorlet{sphinxTableRowColor}{sphinxTableRowColorHeader}% + \global\sphinxcolorlet{sphinxTableMergeColor}{\sphinxTableMergeColorHeader}% + \sphinxrowcolorON + }% +}% + +% this macro is needed in color tables as each \cline or \cmidrule (booktabs) +% consumes one \cr, offsetting the rownum parity. +\def\spx@table@@decrementrownum{\noalign{\global\advance\rownum\m@ne}} +\let\sphinxtabledecrementrownum\@empty + +% At last the style macros + +% \spx@toprule is what the styles define; the colorrows class will prepend +% some code in \sphinxtabletoprulehook +\def\sphinxtoprule{\spx@toprule\sphinxtabletoprulehook} + +% standard style +\def\sphinxthistablewithstandardstyle{% + % Those two are produced by the latex writer + \def\sphinxhline {\hline}% + % \sphinxtabledecrementrownum is a no-op which is redefined by colorrows + % to correct the \rownum increment induced by \cline in colorrows regime + \def\sphinxcline {\sphinxtabledecrementrownum\cline}% + % Those three are inserted by the table templates + \def\spx@toprule {\hline}% + \def\sphinxmidrule {\hline}% + \def\sphinxbottomrule {\hline}% + % Do not tamper with this internal + \def\spx@arrayrulewidth{\arrayrulewidth}% +} + +% booktabs style +% The \@xcmidrule patch below will do beyond its main stuff +% \sphinxadjustcmidrulebelowsep +% Indeed the poor booktabs spacing with \cmidrule (if \sphinxbooktabscmidrule +% defined below is overwritten to use it) is quite awful. Do +% \let\sphinxadjustcmidrulebelowsep\empty +% if you prefer booktabs defaults. +\def\sphinxadjustcmidrulebelowsep{\belowrulesep=\aboverulesep} +\AtBeginDocument{% patch booktabs to avoid extra vertical space from + % consecutive \sphinxcline, if defined to use \cmidrule + \ifdefined\@xcmidrule + \let\spx@original@@xcmidrule\@xcmidrule + \def\@xcmidrule{\sphinxadjustcmidrulebelowsep + % if we don't do that, two \sphinxcline in the same row + % will cause the second short rule to be shifted down + \ifx\@tempa\sphinxcline\let\@tempa\cmidrule\fi + \spx@original@@xcmidrule}% + \fi +} +% wrappers to allow ultimate customization, e.g. via a container class, of the +% widths (aka thickness) associated with the booktabs rule (advanced users may +% even employ \specialrule here to control vertical spacing). +\def\sphinxbooktabstoprule {\toprule} +\def\sphinxbooktabsmidrule {\midrule} +\def\sphinxbooktabsbottomrule{\bottomrule} +\let\sphinxbooktabscmidrule \@gobble % i.e. draw no short rules at all! +% You can redefine this to use \cmidrule with various options, such +% as \cmidrule(lr), but: +% Attention, if you want this to use \cmidrule (or \cline) you must +% also include the \sphinxtabledecrementrownum token like e.g. this +% \def\sphinxbooktabscmidrule{\sphinxtabledecrementrownum\cmidrule} +% and it must be first due to internals of the \cmidrule usage of \futurelet, +% if the table uses row colours. + +\def\sphinxthistablewithbooktabsstyle{% + \let\sphinxhline\@empty % there is no wrapper macro here so if you want to change that + % you will have to redefine \sphinxthistablewithbooktabsstyle + \def\sphinxcline {\sphinxbooktabscmidrule}% defaults to \@gobble + \def\spx@toprule {\sphinxbooktabstoprule}% + \def\sphinxmidrule {\sphinxbooktabsmidrule}% + \def\sphinxbottomrule{\sphinxbooktabsbottomrule}% + \def\spx@arrayrulewidth{\z@}% +} +\AtBeginDocument{\@ifpackageloaded{booktabs}% + {}% + {\def\sphinxthistablewithbooktabsstyle{% + \PackageWarning{sphinx}{% +Please add \string\usepackage{booktabs} to the preamble\MessageBreak +to allow local use of booktabs table style}% + \textcolor{red}{\bfseries ADD LOADING OF booktabs TO THE 'preamble' KEY OF + latex\textunderscore elements}\par + \sphinxthistablewithstandardstyle + }}% +}% + +% borderless style +\def\sphinxthistablewithborderlessstyle{% + \let\sphinxhline \@empty + \let\sphinxcline \@gobble + \let\spx@toprule \@empty + \let\sphinxmidrule \@empty + \let\sphinxbottomrule \@empty + \def\spx@arrayrulewidth{\z@}% +}% + +% colorrows style +% +% this is defined to auto-silence itself (in the surrounding scope-limiting +% environment) after one execution +\def\sphinxthistablewithcolorrowsstyle{% + \let\sphinxthistablewithcolorrowsstyle\@empty +% + \let\spx@table@toprulehook \spx@table@@toprulehook + \let\spx@table@startbodycolorrows \spx@table@@startbodycolorrows + \let\sphinxtabledecrementrownum \spx@table@@decrementrownum + \spx@prepend\spx@table@toprulehook \to\sphinxtabletoprulehook + \spx@prepend\spx@table@startbodycolorrows\to\sphinxtableatstartofbodyhook +% +% this one is not set to \@empty by nocolorrows, because it looks harmless +% to execute it always, as it simply resets to standard colortbl state after +% the table; so we don't need an @@ version for this one + \spx@prepend\spx@table@resetcolortbl\to\sphinxtableafterendhook +} +\def\spx@prepend#1\to#2{% attention about using this only with #2 "storage macro" + \toks@{#1}% + \toks@\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toks@#2}% + \edef#2{\the\toks@}% +}% + +\def\sphinxthistablewithnocolorrowsstyle{% +% rather than trying to remove the code added by 'colorrows' style, we +% simply make it no-op, without even checking if really it was activated. + \let\spx@table@toprulehook \@empty + \let\spx@table@startbodycolorrows\@empty + \let\sphinxtabledecrementrownum \@empty +% we don't worry about \sphinxtableafterendhook as the \spx@table@resetcolortbl +% done at end can not do harm; and also we could also have not bothered with the +% \sphinxtabledecrementrownum as its \rownum decrement, if active, is harmless +% in non-colorrows context +} + +% The \spx@arrayrulewidth is used for some complex matters of merged +% cells size computations +% tabularcolumns argument will override any global or local style and +% trigger the appropriate adjustement of \spx@arrayrulewidth +\def\sphinxthistablewithvlinesstyle{% + \def\spx@arrayrulewidth{\arrayrulewidth}% +}% +\def\sphinxthistablewithnovlinesstyle{% + \def\spx@arrayrulewidth{\z@}% +}% + +% default is the standard style +\def\sphinxthistablewithglobalstyle{\sphinxthistablewithstandardstyle} + +\ifspx@opt@booktabs + \RequirePackage{booktabs} + \def\sphinxthistablewithglobalstyle{\sphinxthistablewithbooktabsstyle} +\fi +\ifspx@opt@borderless + \def\sphinxthistablewithglobalstyle{\sphinxthistablewithborderlessstyle} +\fi +% colorrows appends to the current globalstyle (standard, booktabs, or borderless) +\ifspx@opt@colorrows % let the globalstyle trigger the colorrows style on top of it + \expandafter\def\expandafter\sphinxthistablewithglobalstyle\expandafter + {\sphinxthistablewithglobalstyle + \sphinxthistablewithcolorrowsstyle + } +\fi + \endinput diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index cd565e362db..730453cb5e0 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -97,9 +97,24 @@ def __init__(self, node: Element) -> None: self.body: List[str] = [] self.align = node.get('align', 'default') self.classes: List[str] = node.get('classes', []) + self.styles: List[str] = [] + if 'standard' in self.classes: + self.styles.append('standard') + elif 'borderless' in self.classes: + self.styles.append('borderless') + elif 'booktabs' in self.classes: + self.styles.append('booktabs') + if 'nocolorrows' in self.classes: + self.styles.append('nocolorrows') + elif 'colorrows' in self.classes: + self.styles.append('colorrows') self.colcount = 0 self.colspec: str = None - self.booktabs = False + self.colsep: str = None + if 'booktabs' in self.styles or 'borderless' in self.styles: + self.colsep = '' + elif 'standard' in self.styles: + self.colsep = '|' self.colwidths: List[int] = [] self.has_problematic = False self.has_oldproblematic = False @@ -152,7 +167,7 @@ def get_colspec(self) -> str: if self.colspec: return self.colspec - _colsep = '' if self.booktabs else '|' + _colsep = self.colsep if self.colwidths and 'colwidths-given' in self.classes: total = sum(self.colwidths) colspecs = [r'\X{%d}{%d}' % (width, total) for width in self.colwidths] @@ -865,16 +880,22 @@ def visit_table(self, node: Element) -> None: (self.curfilestack[-1], node.line or '')) self.tables.append(Table(node)) - self.table.booktabs = self.builder.config.latex_use_booktabs + if self.table.colsep is None: + self.table.colsep = '' if ( + 'booktabs' in self.builder.config.latex_table_style or + 'borderless' in self.builder.config.latex_table_style + ) else '|' if self.next_table_colspec: self.table.colspec = '{%s}' % self.next_table_colspec + CR + if '|' in self.table.colspec: + self.table.styles.append('vlines') + self.table.colsep = '|' + else: + self.table.styles.append('novlines') + self.table.colsep = '' if 'colwidths-given' in node.get('classes', []): logger.info(__('both tabularcolumns and :widths: option are given. ' ':widths: is ignored.'), location=node) - if '|' in self.table.colspec and self.table.booktabs: - logger.info(__('tabularcolumns argument contains | and ' - 'latex_use_booktabs is True. Expect gaps between vertical ' - 'and horizontal rules in this table.'), location=node) self.next_table_colspec = None def depart_table(self, node: Element) -> None: @@ -924,21 +945,7 @@ def depart_tbody(self, node: Element) -> None: def visit_row(self, node: Element) -> None: self.table.col = 0 - _colsep = '' if self.table.booktabs else '|' - - if ( - self.builder.config.latex_zebra_stripes and - not isinstance(node.parent, nodes.thead) - ): - if self.table.row % 2 == 0: - self.body.append( - '\\rowcolor{RowEvenColor}[\\dimexpr\\tabcolsep+0.1pt\\relax]' - ) - else: - self.body.append( - '\\rowcolor{RowOddColor}[\\dimexpr\\tabcolsep+0.1pt\\relax]' - ) - + _colsep = self.table.colsep # fill columns if the row starts with the bottom of multirow cell while True: cell = self.table.cell(self.table.row, self.table.col) @@ -978,7 +985,7 @@ def visit_entry(self, node: Element) -> None: self.table.add_cell(node.get('morerows', 0) + 1, node.get('morecols', 0) + 1) cell = self.table.cell() context = '' - _colsep = '' if self.table.booktabs else '|' + _colsep = self.table.colsep if cell.width > 1: if self.config.latex_use_latex_multicolumn: if self.table.col == 0: @@ -1025,7 +1032,7 @@ def depart_entry(self, node: Element) -> None: cell = self.table.cell() self.table.col += cell.width - _colsep = '' if self.table.booktabs else '|' + _colsep = self.table.colsep # fill columns if next ones are a bottom of wide-multirow cell while True: diff --git a/tests/roots/test-latex-table/complex.rst b/tests/roots/test-latex-table/complex.rst index fa84f8266cf..d648ff194c4 100644 --- a/tests/roots/test-latex-table/complex.rst +++ b/tests/roots/test-latex-table/complex.rst @@ -4,6 +4,27 @@ complex tables grid table ---------- +.. rst-class:: nocolorrows + ++---------+---------+---------+ +| header1 | header2 | header3 | ++=========+=========+=========+ +| cell1-1 | cell1-2 | cell1-3 | ++---------+ +---------+ +| cell2-1 | | cell2-3 | ++ +---------+---------+ +| | cell3-2-par1 | ++---------+ | +| cell4-1 | cell3-2-par2 | ++---------+---------+---------+ +| cell5-1 | ++---------+---------+---------+ + +grid table with tabularcolumns having no vline +---------------------------------------------- + +.. tabularcolumns:: TTT + +---------+---------+---------+ | header1 | header2 | header3 | +=========+=========+=========+ @@ -26,6 +47,8 @@ table having ... * consecutive multirow at top of row (1-1 and 1-2) * consecutive multirow at end of row (1-4 and 1-5) +.. rst-class:: standard + +-----------+-----------+-----------+-----------+-----------+ | | | cell1-3 | | | | | +-----------+ | cell1-5 | diff --git a/tests/roots/test-latex-table/expects/complex_spanning_cell.tex b/tests/roots/test-latex-table/expects/complex_spanning_cell.tex index 81fc939067b..b511b88dad0 100644 --- a/tests/roots/test-latex-table/expects/complex_spanning_cell.tex +++ b/tests/roots/test-latex-table/expects/complex_spanning_cell.tex @@ -14,10 +14,12 @@ \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithstandardstyle \centering \begin{tabulary}{\linewidth}[t]{|T|T|T|T|T|} \sphinxtoprule -\sphinxmultirow{3}{1}{% +\sphinxtableatstartofbodyhook\sphinxmultirow{3}{1}{% \begin{varwidth}[t]{\sphinxcolwidth{1}{5}} \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -63,5 +65,5 @@ \\ \sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/gridtable.tex b/tests/roots/test-latex-table/expects/gridtable.tex index f5780a5ea3c..8e37575c9df 100644 --- a/tests/roots/test-latex-table/expects/gridtable.tex +++ b/tests/roots/test-latex-table/expects/gridtable.tex @@ -1,6 +1,8 @@ \label{\detokenize{complex:grid-table}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithnocolorrowsstyle \centering \begin{tabulary}{\linewidth}[t]{|T|T|T|} \sphinxtoprule @@ -15,6 +17,7 @@ header3 \\ \sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 &\sphinxmultirow{2}{5}{% @@ -66,5 +69,5 @@ \\ \sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/gridtable_with_tabularcolumn.tex b/tests/roots/test-latex-table/expects/gridtable_with_tabularcolumn.tex new file mode 100644 index 00000000000..909879ae8a0 --- /dev/null +++ b/tests/roots/test-latex-table/expects/gridtable_with_tabularcolumn.tex @@ -0,0 +1,73 @@ +\label{\detokenize{complex:grid-table-with-tabularcolumns-having-no-vline}} + +\begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithnovlinesstyle +\centering +\begin{tabulary}{\linewidth}[t]{TTT} +\sphinxtoprule +\sphinxstyletheadfamily +\sphinxAtStartPar +header1 +&\sphinxstyletheadfamily +\sphinxAtStartPar +header2 +&\sphinxstyletheadfamily +\sphinxAtStartPar +header3 +\\ +\sphinxmidrule +\sphinxtableatstartofbodyhook +\sphinxAtStartPar +cell1\sphinxhyphen{}1 +&\sphinxmultirow{2}{5}{% +\begin{varwidth}[t]{\sphinxcolwidth{1}{3}} +\sphinxAtStartPar +cell1\sphinxhyphen{}2 +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +& +\sphinxAtStartPar +cell1\sphinxhyphen{}3 +\\ +\sphinxcline{1-1}\sphinxcline{3-3}\sphinxmultirow{2}{7}{% +\begin{varwidth}[t]{\sphinxcolwidth{1}{3}} +\sphinxAtStartPar +cell2\sphinxhyphen{}1 +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +&\sphinxtablestrut{5}& +\sphinxAtStartPar +cell2\sphinxhyphen{}3 +\\ +\sphinxcline{2-3}\sphinxtablestrut{7}&\sphinxstartmulticolumn{2}% +\sphinxmultirow{2}{9}{% +\begin{varwidth}[t]{\sphinxcolwidth{2}{3}} +\sphinxAtStartPar +cell3\sphinxhyphen{}2\sphinxhyphen{}par1 + +\sphinxAtStartPar +cell3\sphinxhyphen{}2\sphinxhyphen{}par2 +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +\sphinxstopmulticolumn +\\ +\sphinxcline{1-1} +\sphinxAtStartPar +cell4\sphinxhyphen{}1 +&\multicolumn{2}{l}{\sphinxtablestrut{9}}\\ +\sphinxhline\sphinxstartmulticolumn{3}% +\begin{varwidth}[t]{\sphinxcolwidth{3}{3}} +\sphinxAtStartPar +cell5\sphinxhyphen{}1 +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +\sphinxstopmulticolumn +\\ +\sphinxbottomrule +\end{tabulary} +\sphinxtableafterendhook\par +\sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable.tex b/tests/roots/test-latex-table/expects/longtable.tex index 2654962f523..7809aef464a 100644 --- a/tests/roots/test-latex-table/expects/longtable.tex +++ b/tests/roots/test-latex-table/expects/longtable.tex @@ -1,6 +1,10 @@ \label{\detokenize{longtable:longtable}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|l|l|} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithborderlessstyle +\begin{longtable}[c]{ll} \sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar @@ -30,6 +34,7 @@ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -52,4 +57,7 @@ cell3\sphinxhyphen{}2 \\ \sphinxbottomrule -\end{longtable}\sphinxatlongtableend\end{savenotes} +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_align.tex b/tests/roots/test-latex-table/expects/longtable_having_align.tex index 08819526218..68ffac40296 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_align.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_align.tex @@ -1,6 +1,9 @@ \label{\detokenize{longtable:longtable-having-align-option}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[r]{|l|l|} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[r]{|l|l|} \sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar @@ -30,6 +33,7 @@ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -52,4 +56,7 @@ cell3\sphinxhyphen{}2 \\ \sphinxbottomrule -\end{longtable}\sphinxatlongtableend\end{savenotes} +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_caption.tex b/tests/roots/test-latex-table/expects/longtable_having_caption.tex index 04f4e29d669..232e8ecca42 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_caption.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_caption.tex @@ -1,6 +1,9 @@ \label{\detokenize{longtable:longtable-having-caption}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|l|l|} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|l|l|} \sphinxthelongtablecaptionisattop \caption{caption for longtable\strut}\label{\detokenize{longtable:id1}}\\*[\sphinxlongtablecapskipadjust] \sphinxtoprule @@ -32,6 +35,7 @@ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -54,4 +58,7 @@ cell3\sphinxhyphen{}2 \\ \sphinxbottomrule -\end{longtable}\sphinxatlongtableend\end{savenotes} +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_problematic_cell.tex b/tests/roots/test-latex-table/expects/longtable_having_problematic_cell.tex index 810fd59d18c..9c15d319ea0 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_problematic_cell.tex @@ -1,6 +1,9 @@ \label{\detokenize{longtable:longtable-having-problematic-cell}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|*{2}{\X{1}{2}|}} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|*{2}{\X{1}{2}|}} \sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar @@ -30,6 +33,7 @@ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \begin{itemize} \item {} \sphinxAtStartPar @@ -59,4 +63,7 @@ cell3\sphinxhyphen{}2 \\ \sphinxbottomrule -\end{longtable}\sphinxatlongtableend\end{savenotes} +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_stub_columns_and_problematic_cell.tex b/tests/roots/test-latex-table/expects/longtable_having_stub_columns_and_problematic_cell.tex index 37309a892d1..21f36b50d78 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_stub_columns_and_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_stub_columns_and_problematic_cell.tex @@ -1,6 +1,9 @@ \label{\detokenize{longtable:longtable-having-both-stub-columns-and-problematic-cell}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|*{3}{\X{1}{3}|}} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|*{3}{\X{1}{3}|}} \sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar @@ -36,6 +39,7 @@ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxstyletheadfamily \begin{itemize} \item {} \sphinxAtStartPar @@ -64,4 +68,7 @@ cell2\sphinxhyphen{}3 \\ \sphinxbottomrule -\end{longtable}\sphinxatlongtableend\end{savenotes} +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex b/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex index 97ed0413374..4e66d9e91a1 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex @@ -1,6 +1,9 @@ \label{\detokenize{longtable:longtable-having-verbatim}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|*{2}{\X{1}{2}|}} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|*{2}{\X{1}{2}|}} \sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar @@ -30,6 +33,7 @@ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \begin{sphinxVerbatimintable}[commandchars=\\\{\}] \PYG{n}{hello} \PYG{n}{world} @@ -53,4 +57,7 @@ cell3\sphinxhyphen{}2 \\ \sphinxbottomrule -\end{longtable}\sphinxatlongtableend\end{savenotes} +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_widths.tex b/tests/roots/test-latex-table/expects/longtable_having_widths.tex index 43de6ffe65a..7b9cd11ba01 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_widths.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_widths.tex @@ -1,7 +1,11 @@ \label{\detokenize{longtable:longtable-having-widths-option}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|\X{30}{100}|\X{70}{100}|} -\sphinxtoprule\noalign{\phantomsection\label{\detokenize{longtable:namedlongtable}}\label{\detokenize{longtable:mylongtable}}}% +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|\X{30}{100}|\X{70}{100}|} +\noalign{\phantomsection\label{\detokenize{longtable:namedlongtable}}\label{\detokenize{longtable:mylongtable}}}% +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -30,6 +34,7 @@ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -52,7 +57,10 @@ cell3\sphinxhyphen{}2 \\ \sphinxbottomrule -\end{longtable}\sphinxatlongtableend\end{savenotes} +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} \sphinxAtStartPar See {\hyperref[\detokenize{longtable:mylongtable}]{\sphinxcrossref{mylongtable}}}, same as {\hyperref[\detokenize{longtable:namedlongtable}]{\sphinxcrossref{\DUrole{std,std-ref}{this one}}}}. diff --git a/tests/roots/test-latex-table/expects/longtable_having_widths_and_problematic_cell.tex b/tests/roots/test-latex-table/expects/longtable_having_widths_and_problematic_cell.tex index 5a193d7c909..6450a455d62 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_widths_and_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_widths_and_problematic_cell.tex @@ -1,6 +1,9 @@ \label{\detokenize{longtable:longtable-having-both-widths-and-problematic-cell}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|\X{30}{100}|\X{70}{100}|} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|\X{30}{100}|\X{70}{100}|} \sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar @@ -30,6 +33,7 @@ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \begin{itemize} \item {} \sphinxAtStartPar @@ -59,4 +63,7 @@ cell3\sphinxhyphen{}2 \\ \sphinxbottomrule -\end{longtable}\sphinxatlongtableend\end{savenotes} +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_with_tabularcolumn.tex b/tests/roots/test-latex-table/expects/longtable_with_tabularcolumn.tex index feab1f62e1c..40efe23e36b 100644 --- a/tests/roots/test-latex-table/expects/longtable_with_tabularcolumn.tex +++ b/tests/roots/test-latex-table/expects/longtable_with_tabularcolumn.tex @@ -1,6 +1,10 @@ \label{\detokenize{longtable:longtable-with-tabularcolumn}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|c|c|} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithvlinesstyle +\begin{longtable}[c]{|c|c|} \sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar @@ -30,6 +34,7 @@ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -52,4 +57,7 @@ cell3\sphinxhyphen{}2 \\ \sphinxbottomrule -\end{longtable}\sphinxatlongtableend\end{savenotes} +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/simple_table.tex b/tests/roots/test-latex-table/expects/simple_table.tex index 01ba7681608..7bd85c737b2 100644 --- a/tests/roots/test-latex-table/expects/simple_table.tex +++ b/tests/roots/test-latex-table/expects/simple_table.tex @@ -1,6 +1,7 @@ \label{\detokenize{tabular:simple-table}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabulary}{\linewidth}[t]{|T|T|} \sphinxtoprule @@ -12,6 +13,7 @@ header2 \\ \sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & @@ -34,5 +36,5 @@ \\ \sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_caption.tex b/tests/roots/test-latex-table/expects/table_having_caption.tex index e57f4725ffb..f2ce5536021 100644 --- a/tests/roots/test-latex-table/expects/table_having_caption.tex +++ b/tests/roots/test-latex-table/expects/table_having_caption.tex @@ -1,6 +1,7 @@ \label{\detokenize{tabular:table-having-caption}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \sphinxcapstartof{table} \sphinxthecaptionisattop @@ -16,6 +17,7 @@ header2 \\ \sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & @@ -38,5 +40,5 @@ \\ \sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_problematic_cell.tex b/tests/roots/test-latex-table/expects/table_having_problematic_cell.tex index e11a45f7290..7d7ad4b715b 100644 --- a/tests/roots/test-latex-table/expects/table_having_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/table_having_problematic_cell.tex @@ -1,6 +1,7 @@ \label{\detokenize{tabular:table-having-problematic-cell}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabular}[t]{|*{2}{\X{1}{2}|}} \sphinxtoprule @@ -11,7 +12,8 @@ \sphinxAtStartPar header2 \\ -\sphinxmidrule\begin{itemize} +\sphinxmidrule +\sphinxtableatstartofbodyhook\begin{itemize} \item {} \sphinxAtStartPar item1 @@ -41,5 +43,5 @@ \\ \sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_stub_columns_and_problematic_cell.tex b/tests/roots/test-latex-table/expects/table_having_stub_columns_and_problematic_cell.tex index 68a485519d4..fbd797a1bd3 100644 --- a/tests/roots/test-latex-table/expects/table_having_stub_columns_and_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/table_having_stub_columns_and_problematic_cell.tex @@ -1,6 +1,7 @@ \label{\detokenize{tabular:table-having-both-stub-columns-and-problematic-cell}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabular}[t]{|*{3}{\X{1}{3}|}} \sphinxtoprule @@ -14,7 +15,8 @@ \sphinxAtStartPar header3 \\ -\sphinxmidrule\sphinxstyletheadfamily \begin{itemize} +\sphinxmidrule +\sphinxtableatstartofbodyhook\sphinxstyletheadfamily \begin{itemize} \item {} \sphinxAtStartPar instub1\sphinxhyphen{}1a @@ -43,5 +45,5 @@ \\ \sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_threeparagraphs_cell_in_first_col.tex b/tests/roots/test-latex-table/expects/table_having_threeparagraphs_cell_in_first_col.tex index 2ea24d37309..9acd9a86d46 100644 --- a/tests/roots/test-latex-table/expects/table_having_threeparagraphs_cell_in_first_col.tex +++ b/tests/roots/test-latex-table/expects/table_having_threeparagraphs_cell_in_first_col.tex @@ -1,6 +1,7 @@ \label{\detokenize{tabular:table-with-cell-in-first-column-having-three-paragraphs}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabulary}{\linewidth}[t]{|T|} \sphinxtoprule @@ -9,6 +10,7 @@ header1 \\ \sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1\sphinxhyphen{}par1 @@ -20,5 +22,5 @@ \\ \sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_verbatim.tex b/tests/roots/test-latex-table/expects/table_having_verbatim.tex index de90c32b113..a002de58618 100644 --- a/tests/roots/test-latex-table/expects/table_having_verbatim.tex +++ b/tests/roots/test-latex-table/expects/table_having_verbatim.tex @@ -1,6 +1,7 @@ \label{\detokenize{tabular:table-having-verbatim}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabular}[t]{|*{2}{\X{1}{2}|}} \sphinxtoprule @@ -12,6 +13,7 @@ header2 \\ \sphinxmidrule +\sphinxtableatstartofbodyhook \begin{sphinxVerbatimintable}[commandchars=\\\{\}] \PYG{n}{hello} \PYG{n}{world} \end{sphinxVerbatimintable} @@ -35,5 +37,5 @@ \\ \sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_widths.tex b/tests/roots/test-latex-table/expects/table_having_widths.tex index 6891df9abde..fe5f4c44d72 100644 --- a/tests/roots/test-latex-table/expects/table_having_widths.tex +++ b/tests/roots/test-latex-table/expects/table_having_widths.tex @@ -1,9 +1,12 @@ \label{\detokenize{tabular:table-having-widths-option}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithbooktabsstyle +\sphinxthistablewithcolorrowsstyle \centering \phantomsection\label{\detokenize{tabular:namedtabular}}\label{\detokenize{tabular:mytabular}}\nobreak -\begin{tabular}[t]{|\X{30}{100}|\X{70}{100}|} +\begin{tabular}[t]{\X{30}{100}\X{70}{100}} \sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar @@ -13,6 +16,7 @@ header2 \\ \sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & @@ -35,7 +39,7 @@ \\ \sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} \sphinxAtStartPar diff --git a/tests/roots/test-latex-table/expects/table_having_widths_and_problematic_cell.tex b/tests/roots/test-latex-table/expects/table_having_widths_and_problematic_cell.tex index b81c9867b02..1baf92c1ae6 100644 --- a/tests/roots/test-latex-table/expects/table_having_widths_and_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/table_having_widths_and_problematic_cell.tex @@ -1,6 +1,7 @@ \label{\detokenize{tabular:table-having-both-widths-and-problematic-cell}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabular}[t]{|\X{30}{100}|\X{70}{100}|} \sphinxtoprule @@ -11,7 +12,8 @@ \sphinxAtStartPar header2 \\ -\sphinxmidrule\begin{itemize} +\sphinxmidrule +\sphinxtableatstartofbodyhook\begin{itemize} \item {} \sphinxAtStartPar item1 @@ -41,5 +43,5 @@ \\ \sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/tabular_having_widths.tex b/tests/roots/test-latex-table/expects/tabular_having_widths.tex index 90e6b9dc19e..15321d693cf 100644 --- a/tests/roots/test-latex-table/expects/tabular_having_widths.tex +++ b/tests/roots/test-latex-table/expects/tabular_having_widths.tex @@ -1,6 +1,7 @@ \label{\detokenize{tabular:table-having-align-option-tabular}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \raggedright \begin{tabular}[t]{|\X{30}{100}|\X{70}{100}|} \sphinxtoprule @@ -12,6 +13,7 @@ header2 \\ \sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & @@ -34,5 +36,5 @@ \\ \sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/tabularcolumn.tex b/tests/roots/test-latex-table/expects/tabularcolumn.tex index 8274ae2382c..fcb01be3f50 100644 --- a/tests/roots/test-latex-table/expects/tabularcolumn.tex +++ b/tests/roots/test-latex-table/expects/tabularcolumn.tex @@ -1,8 +1,10 @@ \label{\detokenize{tabular:table-with-tabularcolumn}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithnovlinesstyle \centering -\begin{tabulary}{\linewidth}[t]{|c|c|} +\begin{tabulary}{\linewidth}[t]{cc} \sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar @@ -12,6 +14,7 @@ header2 \\ \sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & @@ -34,5 +37,5 @@ \\ \sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/tabulary_having_widths.tex b/tests/roots/test-latex-table/expects/tabulary_having_widths.tex index 939a7f67a49..24634163010 100644 --- a/tests/roots/test-latex-table/expects/tabulary_having_widths.tex +++ b/tests/roots/test-latex-table/expects/tabulary_having_widths.tex @@ -1,6 +1,7 @@ \label{\detokenize{tabular:table-having-align-option-tabulary}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \raggedleft \begin{tabulary}{\linewidth}[t]{|T|T|} \sphinxtoprule @@ -12,6 +13,7 @@ header2 \\ \sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & @@ -34,5 +36,5 @@ \\ \sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/longtable.rst b/tests/roots/test-latex-table/longtable.rst index bace9d4d2d8..da6fa5c5cec 100644 --- a/tests/roots/test-latex-table/longtable.rst +++ b/tests/roots/test-latex-table/longtable.rst @@ -5,7 +5,7 @@ longtable --------- .. table:: - :class: longtable + :class: longtable, borderless ======= ======= header1 header2 diff --git a/tests/roots/test-latex-table/tabular.rst b/tests/roots/test-latex-table/tabular.rst index 7f090954004..15db823a05b 100644 --- a/tests/roots/test-latex-table/tabular.rst +++ b/tests/roots/test-latex-table/tabular.rst @@ -20,6 +20,7 @@ table having :widths: option .. table:: :widths: 30,70 :name: namedtabular + :class: booktabs, colorrows ======= ======= header1 header2 @@ -63,7 +64,7 @@ table having :align: option (tabular) table with tabularcolumn ------------------------ -.. tabularcolumns:: |c|c| +.. tabularcolumns:: cc ======= ======= header1 header2 diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index cf6b40d9756..db0e67fc4a4 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -92,7 +92,9 @@ def test_build_latex_doc(app, status, warning, engine, docclass): app.config.latex_engine = engine app.config.latex_documents = [app.config.latex_documents[0][:4] + (docclass,)] if engine == 'xelatex': - app.config.latex_use_booktabs = True + app.config.latex_table_style = ['booktabs'] + elif engine == 'lualatex': + app.config.latex_table_style = ['colorrows'] app.builder.init() LaTeXTranslator.ignore_missing_images = True @@ -726,7 +728,8 @@ def test_footnote(app, status, warning): assert '\\sphinxcite{footnote:bar}' in result assert ('\\bibitem[bar]{footnote:bar}\n\\sphinxAtStartPar\ncite\n') in result assert '\\sphinxcaption{Table caption \\sphinxfootnotemark[4]' in result - assert ('\\sphinxmidrule%\n\\begin{footnotetext}[4]\\sphinxAtStartFootnote\n' + assert ('\\sphinxmidrule\n\\sphinxtableatstartofbodyhook%\n' + '\\begin{footnotetext}[4]\\sphinxAtStartFootnote\n' 'footnote in table caption\n%\n\\end{footnotetext}\\ignorespaces %\n' '\\begin{footnotetext}[5]\\sphinxAtStartFootnote\n' 'footnote in table header\n%\n\\end{footnotetext}\\ignorespaces ' @@ -736,7 +739,7 @@ def test_footnote(app, status, warning): '\\begin{footnote}[6]\\sphinxAtStartFootnote\n' 'footnote in table not in header\n%\n\\end{footnote}\n\\\\\n' '\\sphinxbottomrule\n\\end{tabulary}\n' - '\\par\n\\sphinxattableend\\end{savenotes}\n') in result + '\\sphinxtableafterendhook\\par\n\\sphinxattableend\\end{savenotes}\n') in result @pytest.mark.sphinx('latex', testroot='footnotes') @@ -764,7 +767,8 @@ def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning): 'caption of normal table}\\label{\\detokenize{index:id36}}') in result assert ('\\caption{footnote \\sphinxfootnotemark[10] ' 'in caption \\sphinxfootnotemark[11] of longtable\\strut}') in result - assert ('\\endlastfoot\n%\n\\begin{footnotetext}[10]\\sphinxAtStartFootnote\n' + assert ('\\endlastfoot\n\\sphinxtableatstartofbodyhook\n%\n' + '\\begin{footnotetext}[10]\\sphinxAtStartFootnote\n' 'Foot note in longtable\n%\n\\end{footnotetext}\\ignorespaces %\n' '\\begin{footnotetext}[11]\\sphinxAtStartFootnote\n' 'Second footnote in caption of longtable\n') in result @@ -1312,6 +1316,13 @@ def get_expected(name): expected = get_expected('gridtable') assert actual == expected + # grid table with tabularcolumns + # MEMO: filename should end with tabularcolumns but tabularcolumn has been + # used in existing other cases + actual = tables['grid table with tabularcolumns having no vline'] + expected = get_expected('gridtable_with_tabularcolumn') + assert actual == expected + # complex spanning cell actual = tables['complex spanning cell'] expected = get_expected('complex_spanning_cell') @@ -1319,12 +1330,16 @@ def get_expected(name): @pytest.mark.sphinx('latex', testroot='latex-table', - confoverrides={'latex_use_booktabs': True}) -def test_latex_table_with_booktabs(app, status, warning): + confoverrides={'latex_table_style': ['booktabs', 'colorrows']}) +def test_latex_table_with_booktabs_and_colorrows(app, status, warning): app.builder.build_all() result = (app.outdir / 'python.tex').read_text(encoding='utf8') assert r'\PassOptionsToPackage{booktabs}{sphinx}' in result - assert r'\begin{tabulary}{\linewidth}[t]{TTTTT}' in result + assert r'\PassOptionsToPackage{colorrows}{sphinx}' in result + # tabularcolumns + assert r'\begin{longtable}[c]{|c|c|}' in result + # class: standard + assert r'\begin{tabulary}{\linewidth}[t]{|T|T|T|T|T|}' in result assert r'\begin{longtable}[c]{ll}' in result assert r'\begin{tabular}[t]{*{2}{\X{1}{2}}}' in result assert r'\begin{tabular}[t]{\X{30}{100}\X{70}{100}}' in result