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