mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-06-07 13:15:53 +02:00
RST now parses tables.
This commit is contained in:
@@ -2,3 +2,5 @@
|
|||||||
\usepackage[T1]{fontenc}
|
\usepackage[T1]{fontenc}
|
||||||
\usepackage[utf8]{inputenc}
|
\usepackage[utf8]{inputenc}
|
||||||
\usepackage{alltt}
|
\usepackage{alltt}
|
||||||
|
|
||||||
|
\usepackage{supertabular}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
from docutils.writers.latex2e import Writer, Table, LaTeXTranslator
|
||||||
|
|
||||||
|
|
||||||
|
class LatexWriter(Writer):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.translator_class = DNDTranslator
|
||||||
|
|
||||||
|
|
||||||
|
class DNDTable(Table):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DNDTranslator(LaTeXTranslator):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.settings.table_style = ["borderless"]
|
||||||
|
self.active_table = DNDTable(self, "supertabular")
|
||||||
@@ -20,6 +20,7 @@ from sphinx.util.docstrings import prepare_docstring
|
|||||||
from dungeonsheets import character as _char
|
from dungeonsheets import character as _char
|
||||||
from dungeonsheets import exceptions, classes, readers
|
from dungeonsheets import exceptions, classes, readers
|
||||||
from dungeonsheets.stats import mod_str
|
from dungeonsheets.stats import mod_str
|
||||||
|
from dungeonsheets.latex import LatexWriter
|
||||||
|
|
||||||
|
|
||||||
"""Program to take character definitions and build a PDF of the
|
"""Program to take character definitions and build a PDF of the
|
||||||
@@ -29,7 +30,7 @@ bold_re = re.compile(r'\*\*([^*]+)\*\*')
|
|||||||
it_re = re.compile(r'\*([^*]+)\*')
|
it_re = re.compile(r'\*([^*]+)\*')
|
||||||
verb_re = re.compile(r'``([^`]+)``')
|
verb_re = re.compile(r'``([^`]+)``')
|
||||||
heading_re = re.compile(r'^[ \t\r\f\v]*(.+)\n\s*([-=\^]+)$', flags=re.MULTILINE)
|
heading_re = re.compile(r'^[ \t\r\f\v]*(.+)\n\s*([-=\^]+)$', flags=re.MULTILINE)
|
||||||
# A dice string, with optinal backticks: ``1d6 + 3``
|
# A dice string, with optional backticks: ``1d6 + 3``
|
||||||
dice_re = re.compile(r'`*(\d+d\d+(?:\s*\+\s*\d+)?)`*')
|
dice_re = re.compile(r'`*(\d+d\d+(?:\s*\+\s*\d+)?)`*')
|
||||||
# What defines a list in reST:
|
# What defines a list in reST:
|
||||||
# - a blank line
|
# - a blank line
|
||||||
@@ -70,6 +71,7 @@ def _parse_rst_lists(rst):
|
|||||||
list_items = [item.replace('\n', ' ').strip() for item in list_items]
|
list_items = [item.replace('\n', ' ').strip() for item in list_items]
|
||||||
yield list_rst, list_items
|
yield list_rst, list_items
|
||||||
|
|
||||||
|
|
||||||
def _parse_rst_headings(rst):
|
def _parse_rst_headings(rst):
|
||||||
"""Read headings in reST and iterate.
|
"""Read headings in reST and iterate.
|
||||||
|
|
||||||
@@ -136,13 +138,45 @@ def latex_parts(input_string, source_path=None, destination_path=None,
|
|||||||
overrides = {'input_encoding': input_encoding,
|
overrides = {'input_encoding': input_encoding,
|
||||||
'doctitle_xform': doctitle,
|
'doctitle_xform': doctitle,
|
||||||
'initial_header_level': initial_header_level}
|
'initial_header_level': initial_header_level}
|
||||||
|
writer = LatexWriter()
|
||||||
parts = core.publish_parts(
|
parts = core.publish_parts(
|
||||||
source=input_string, source_path=source_path,
|
source=input_string, source_path=source_path,
|
||||||
destination_path=destination_path,
|
destination_path=destination_path,
|
||||||
writer_name='latex', settings_overrides=overrides)
|
writer=writer, settings_overrides=overrides)
|
||||||
return parts
|
return parts
|
||||||
|
|
||||||
|
|
||||||
|
def fixed_latex_table_lines(tex):
|
||||||
|
"""Replace the longtable package with supertabular package.
|
||||||
|
|
||||||
|
longtable doesn't work in two column mode, but supertabular does,
|
||||||
|
so we need to replace long-table specific formatting with the
|
||||||
|
supertabular equivalent.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if "longtable" in tex and False:
|
||||||
|
begin_re = re.compile(r"\\begin{longtable\*?}" # Beginning of the environment
|
||||||
|
r"(\[.*\])?" # Optional arguments
|
||||||
|
r"{(.*)}" # Parameters
|
||||||
|
)
|
||||||
|
end_re = re.compile(r"\\end{longtable\*?}")
|
||||||
|
foot_re = re.compile(r"(\\endhead\n)(.*)\\endfoot\n\\endlastfoot", flags=(re.MULTILINE|re.DOTALL))
|
||||||
|
head_re = re.compile(r"(\\endfirsthead\n)(.*)\\endhead", flags=(re.MULTILINE|re.DOTALL))
|
||||||
|
firsthead_re = re.compile(r"(\\hline.*)\\endfirsthead", flags=(re.MULTILINE|re.DOTALL))
|
||||||
|
# Convert opening and closing environment
|
||||||
|
tex = begin_re.sub(r"\\begin{supertabular}\1{\2}", tex)
|
||||||
|
tex = end_re.sub(r"\\end{supertabular}", tex)
|
||||||
|
# Convert table headings
|
||||||
|
# Order matters for these substitutions
|
||||||
|
def printlines(t):
|
||||||
|
for l in t.split("\n"): print(l)
|
||||||
|
# import pdb; pdb.set_trace()
|
||||||
|
tex = foot_re.sub(r"\1\\tabletail{%\n\2}", tex)
|
||||||
|
tex = head_re.sub(r"\1\\tablehead{%\n\2}", tex)
|
||||||
|
tex = firsthead_re.sub(r"\\tablefirsthead{\1}", tex)
|
||||||
|
return tex
|
||||||
|
|
||||||
|
|
||||||
def rst_to_latex(rst, top_heading_level=0):
|
def rst_to_latex(rst, top_heading_level=0):
|
||||||
"""Basic markup of reST to LaTeX code.
|
"""Basic markup of reST to LaTeX code.
|
||||||
|
|
||||||
@@ -174,7 +208,8 @@ def rst_to_latex(rst, top_heading_level=0):
|
|||||||
tex_parts = latex_parts(rst)
|
tex_parts = latex_parts(rst)
|
||||||
tex = tex_parts['body']
|
tex = tex_parts['body']
|
||||||
# Check for currently un-supported LaTeX commands
|
# Check for currently un-supported LaTeX commands
|
||||||
assert "longtable" not in tex
|
tex = fixed_latex_table_lines(tex)
|
||||||
|
# assert "longtable" not in tex
|
||||||
return tex
|
return tex
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -117,4 +117,22 @@ class MarkdownTestCase(unittest.TestCase):
|
|||||||
tex = make_sheets.rst_to_latex(md_list)
|
tex = make_sheets.rst_to_latex(md_list)
|
||||||
self.assertIn("\\begin{itemize}", tex)
|
self.assertIn("\\begin{itemize}", tex)
|
||||||
|
|
||||||
|
def test_simple_table(self):
|
||||||
|
table_rst = """
|
||||||
|
===== ===== =======
|
||||||
|
A B A and B
|
||||||
|
===== ===== =======
|
||||||
|
False False False
|
||||||
|
True False False
|
||||||
|
False True False
|
||||||
|
True True True
|
||||||
|
===== ===== =======
|
||||||
|
"""
|
||||||
|
tex = make_sheets.rst_to_latex(table_rst)
|
||||||
|
# Check begin/end environment is fixed
|
||||||
|
self.assertNotIn("longtable", tex)
|
||||||
|
self.assertIn("supertabular", tex)
|
||||||
|
# Check headers and footers are fixed
|
||||||
|
self.assertNotIn("endfoot", tex)
|
||||||
|
self.assertNotIn("endhead", tex)
|
||||||
|
self.assertNotIn("endfirsthead", tex)
|
||||||
|
|||||||
Reference in New Issue
Block a user