Skip to content

Commit

Permalink
Add support for booktabs-style tables to LaTeX builder
Browse files Browse the repository at this point in the history
Render tables without vertical rules and horizontal rules of varying
thickness (with additional space above and below) using the booktabs
package.
  • Loading branch information
Stefan Wiehler committed Aug 21, 2019
1 parent 3261b87 commit bd10782
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 11 deletions.
8 changes: 8 additions & 0 deletions doc/usage/configuration.rst
Expand Up @@ -2004,6 +2004,14 @@ These options influence LaTeX output.

.. versionadded:: 1.8

.. confval:: latex_booktabs

If ``True``, render tables without vertical rules and horizontal rules of
varying thickness (with additional space above and below) using the
``booktabs`` package.

.. versionadded:: 2.1

.. confval:: latex_elements

.. versionadded:: 0.5
Expand Down
1 change: 1 addition & 0 deletions sphinx/builders/latex/__init__.py
Expand Up @@ -458,6 +458,7 @@ 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)
app.add_config_value('latex_booktabs', 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])
Expand Down
26 changes: 26 additions & 0 deletions sphinx/templates/latex/longtable.tex_t
Expand Up @@ -10,25 +10,51 @@
<%- if table.caption -%>
\sphinxthelongtablecaptionisattop
\caption{<%= ''.join(table.caption) %>\strut}<%= labels %>\\*[\sphinxlongtablecapskipadjust]
<%- if table.booktabs -%>
\toprule
<% else -%>
\hline
<% endif -%>
<% elif labels -%>
<%- if table.booktabs -%>
\toprule\noalign{\phantomsection<%= labels %>}%
<% else -%>
\hline\noalign{\phantomsection<%= labels %>}%
<% endif -%>
<% else -%>
<%- if table.booktabs -%>
\toprule
<% else -%>
\hline
<% endif -%>
<% endif -%>
<%= ''.join(table.header) %>
\endfirsthead

\multicolumn{<%= table.colcount %>}{c}%
{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} -- <%= _('continued from previous page') %>}}}\\
<%- if table.booktabs -%>
\toprule
<% else -%>
\hline
<% endif -%>
<%= ''.join(table.header) %>
<%- if table.header and table.booktabs -%>
\midrule
<% endif -%>
\endhead

<%- if table.booktabs -%>
\bottomrule
<% else -%>
\hline
<% endif -%>
\multicolumn{<%= table.colcount %>}{r}{\makebox[0pt][r]{\sphinxtablecontinued{<%= _('continues on next page') %>}}}\\
\endfoot

\endlastfoot
<%= ''.join(table.body) %>
<%- if table.booktabs -%>
\bottomrule
<% endif -%>
\end{longtable}\sphinxatlongtableend\end{savenotes}
10 changes: 10 additions & 0 deletions sphinx/templates/latex/tabular.tex_t
Expand Up @@ -19,9 +19,19 @@
\phantomsection<%= labels %>\nobreak
<% endif -%>
\begin{tabular}[t]<%= table.get_colspec() -%>
<%- if table.booktabs -%>
\toprule
<%- else -%>
\hline
<%- endif -%>
<%= ''.join(table.header) %>
<%- if table.header and table.booktabs -%>
\midrule
<%- endif -%>
<%=- ''.join(table.body) %>
<%- if table.booktabs -%>
\bottomrule
<%- endif -%>
\end{tabular}
\par
\sphinxattableend\end{savenotes}
10 changes: 10 additions & 0 deletions sphinx/templates/latex/tabulary.tex_t
Expand Up @@ -19,9 +19,19 @@
\phantomsection<%= labels %>\nobreak
<% endif -%>
\begin{tabulary}{\linewidth}[t]<%= table.get_colspec() -%>
<%- if table.booktabs -%>
\toprule
<%- else -%>
\hline
<%- endif -%>
<%= ''.join(table.header) %>
<%- if table.header and table.booktabs -%>
\midrule
<%- endif -%>
<%=- ''.join(table.body) %>
<%- if table.booktabs -%>
\bottomrule
<%- endif -%>
\end{tabulary}
\par
\sphinxattableend\end{savenotes}
1 change: 1 addition & 0 deletions sphinx/texinputs/sphinx.sty
Expand Up @@ -65,6 +65,7 @@
\fi
}%
}{}
\RequirePackage{booktabs}
\RequirePackage{tabulary}
% tabulary has a bug with its re-definition of \multicolumn in its first pass
% which is not \long. But now Sphinx does not use LaTeX's \multicolumn but its
Expand Down
39 changes: 28 additions & 11 deletions sphinx/writers/latex.py
Expand Up @@ -330,16 +330,20 @@ def get_colspec(self):
elif self.colwidths and 'colwidths-given' in self.classes:
total = sum(self.colwidths)
colspecs = ['\\X{%d}{%d}' % (width, total) for width in self.colwidths]
return '{|%s|}\n' % '|'.join(colspecs)
return '{%s%s%s}\n' % (self.colsep, self.colsep.join(colspecs),
self.colsep)

elif self.has_problematic:
return '{|*{%d}{\\X{1}{%d}|}}\n' % (self.colcount, self.colcount)
return '{%s*{%d}{\\X{1}{%d}%s}}\n' % (self.colsep, self.colcount,
self.colcount, self.colsep)
elif self.get_table_type() == 'tabulary':
# sphinx.sty sets T to be J by default.
return '{|' + ('T|' * self.colcount) + '}\n'
return '{' + self.colsep + (('T' + self.colsep) * self.colcount) + '}\n'
elif self.has_oldproblematic:
return '{|*{%d}{\\X{1}{%d}|}}\n' % (self.colcount, self.colcount)
return '{%s*{%d}{\\X{1}{%d}%s}}\n' % (self.colsep, self.colcount,
self.colcount, self.colsep)
else:
return '{|' + ('l|' * self.colcount) + '}\n'
return '{' + self.colsep + (('l' + self.colsep) * self.colcount) + '}\n'

def add_cell(self, height, width):
# type: (int, int) -> None
Expand Down Expand Up @@ -1123,6 +1127,12 @@ def visit_table(self, node):
logger.info(__('both tabularcolumns and :widths: option are given. '
':widths: is ignored.'), location=node)
self.next_table_colspec = None
if self.builder.config.latex_booktabs:
self.table.booktabs = True
self.table.colsep = ''
else:
self.table.booktabs = False
self.table.colsep = '|'

def depart_table(self, node):
# type: (nodes.Element) -> None
Expand Down Expand Up @@ -1191,13 +1201,17 @@ def visit_row(self, node):
# insert suitable strut for equalizing row heights in given multirow
self.body.append('\\sphinxtablestrut{%d}' % cell.cell_id)
else: # use \multicolumn for wide multirow cell
self.body.append('\\multicolumn{%d}{|l|}'
self.body.append('\\multicolumn{%d}{%sl%s}'
'{\\sphinxtablestrut{%d}}' %
(cell.width, cell.cell_id))
(cell.width, self.table.colsep,
self.table.colsep, cell.cell_id))

def depart_row(self, node):
# type: (nodes.Element) -> None
self.body.append('\\\\\n')
if self.table.booktabs:
self.table.row += 1
return
cells = [self.table.cell(self.table.row, i) for i in range(self.table.colcount)]
underlined = [cell.row + cell.height == self.table.row + 1 for cell in cells]
if all(underlined):
Expand All @@ -1223,9 +1237,11 @@ def visit_entry(self, node):
if cell.width > 1:
if self.builder.config.latex_use_latex_multicolumn:
if self.table.col == 0:
self.body.append('\\multicolumn{%d}{|l|}{%%\n' % cell.width)
self.body.append('\\multicolumn{%d}{%sl%s}{%%\n' %
(cell.width, self.table.colsep, self.table.colsep))
else:
self.body.append('\\multicolumn{%d}{l|}{%%\n' % cell.width)
self.body.append('\\multicolumn{%d}{l%s}{%%\n' %
(cell.width, self.table.colsep))
context = '}%\n'
else:
self.body.append('\\sphinxstartmulticolumn{%d}%%\n' % cell.width)
Expand Down Expand Up @@ -1281,9 +1297,10 @@ def depart_entry(self, node):
self.body.append('\\sphinxtablestrut{%d}' % nextcell.cell_id)
else:
# use \multicolumn for wide multirow cell
self.body.append('\\multicolumn{%d}{l|}'
self.body.append('\\multicolumn{%d}{l%s}'
'{\\sphinxtablestrut{%d}}' %
(nextcell.width, nextcell.cell_id))
(nextcell.width, self.table.colsep,
nextcell.cell_id))

def visit_acks(self, node):
# type: (nodes.Element) -> None
Expand Down

0 comments on commit bd10782

Please sign in to comment.