Skip to content

Commit

Permalink
Fix LaTeX writer's handling of multirow table cells
Browse files Browse the repository at this point in the history
Originally the LaTeX writer could only handle one multirow cell per
row. This commit fixes that and adds support for cells spanning both
rows and columns.
  • Loading branch information
EricFromCanada committed Jan 6, 2015
1 parent 649e2cd commit 5d96523
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 27 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Features added
Bugs fixed
----------

* LaTeX writer now generates correct markup for cells spanning multiple rows.


Release 1.3b2 (released Dec 5, 2014)
====================================
Expand Down
71 changes: 52 additions & 19 deletions sphinx/writers/latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,8 @@ def declare_package(packagename, options=None):
self.no_contractions = 0
self.compact_list = 0
self.first_param = 0
self.previous_spanning_row = 0
self.previous_spanning_column = 0
self.remember_multirow = {}
self.remember_multirowcol = {}

def format_docclass(self, docclass):
""" prepends prefix to sphinx document classes
Expand Down Expand Up @@ -767,32 +766,49 @@ def visit_tbody(self, node):
self.visit_thead(node)
self.body = self.tablebody
def depart_tbody(self, node):
pass
self.remember_multirow = {}
self.remember_multirowcol = {}

def visit_row(self, node):
self.table.col = 0
for key,value in self.remember_multirow.items():
if not value and key in self.remember_multirowcol:
del self.remember_multirowcol[key]
def depart_row(self, node):
if self.previous_spanning_row == 1:
self.previous_spanning_row = 0
self.body.append('\\\\\n')
self.body.append('\\hline')
if any(self.remember_multirow.values()):
linestart = 1
for col in range(1, self.table.col + 1):
if self.remember_multirow.get(col):
if linestart != col:
linerange = str(linestart) + '-' + str(col - 1)
self.body.append('\\cline{' + linerange + '}')
linestart = col + 1
if self.remember_multirowcol.get(col, 0):
linestart += self.remember_multirowcol[col]
if linestart <= col:
linerange = str(linestart) + '-' + str(col)
self.body.append('\\cline{' + linerange + '}')
else:
self.body.append('\\hline')
self.table.rowcount += 1

def visit_entry(self, node):
if self.table.col > 0:
self.body.append(' & ')
elif self.remember_multirow.get(1, 0) > 1:
self.remember_multirow[1] -= 1
if self.table.col == 0:
while self.remember_multirow.get(self.table.col + 1, 0):
self.table.col += 1
self.remember_multirow[self.table.col] -= 1
if self.remember_multirowcol.get(self.table.col, 0):
extracols = self.remember_multirowcol[self.table.col]
self.body.append(' \multicolumn{')
self.body.append(str(extracols + 1))
self.body.append('}{|l|}{}')
self.table.col += extracols
self.body.append(' & ')
else:
self.body.append(' & ')
self.table.col += 1
context = ''
if 'morerows' in node:
self.body.append(' \multirow{')
self.previous_spanning_row = 1
self.body.append(str(node.get('morerows') + 1))
self.body.append('}{*}{')
context += '}'
self.remember_multirow[self.table.col] = node.get('morerows') + 1
if 'morecols' in node:
self.body.append(' \multicolumn{')
self.body.append(str(node.get('morecols') + 1))
Expand All @@ -801,12 +817,29 @@ def visit_entry(self, node):
else:
self.body.append('}{l|}{')
context += '}'
if 'morerows' in node:
self.body.append(' \multirow{')
self.body.append(str(node.get('morerows') + 1))
self.body.append('}{*}{')
context += '}'
self.remember_multirow[self.table.col] = node.get('morerows')
if 'morecols' in node:
if 'morerows' in node:
self.remember_multirowcol[self.table.col] = node.get('morecols')
self.table.col += node.get('morecols')
if isinstance(node.parent.parent, nodes.thead):
self.body.append('\\textsf{\\relax ')
context += '}'
if self.remember_multirow.get(self.table.col + 1, 0) > 1:
self.remember_multirow[self.table.col + 1] -= 1
while self.remember_multirow.get(self.table.col + 1, 0):
self.table.col += 1
self.remember_multirow[self.table.col] -= 1
context += ' & '
if self.remember_multirowcol.get(self.table.col, 0):
extracols = self.remember_multirowcol[self.table.col]
context += ' \multicolumn{'
context += str(extracols + 1)
context += '}{l|}{}'
self.table.col += extracols
self.context.append(context)
def depart_entry(self, node):
self.body.append(self.context.pop()) # header
Expand Down
16 changes: 8 additions & 8 deletions tests/root/markup.txt
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,17 @@ Tables
| 2 | Empty cells: | |
+----+----------------+----+

Table with multicol:
Table with multirow and multicol:

.. only:: latex

+----+---------------------+
| 1 | test! |
+----+---------+------+----+
| 2 | col | col | c |
| y +---------+------+----+
| x | test |
+----+---------------------+
+----+----------------+---------+
| 1 | test! | c |
+----+---------+------+ |
| 2 | col | col | |
| y +---------+------+----+----+
| x | multi-column cell | x |
+----+---------------------+----+


Figures
Expand Down

0 comments on commit 5d96523

Please sign in to comment.