From e9b3f8ed43faeed909cac3f95338232bb0bf30c7 Mon Sep 17 00:00:00 2001 From: matistjati Date: Sun, 18 Aug 2024 02:00:47 +0200 Subject: [PATCH] Interactive samples for pdf --- problemtools/md2html.py | 2 +- problemtools/problem2pdf.py | 16 ++-- problemtools/statement_common.py | 74 +++++++++++++++---- .../templates/markdown_pdf/fix_tables.md | 2 + 4 files changed, 68 insertions(+), 26 deletions(-) diff --git a/problemtools/md2html.py b/problemtools/md2html.py index f9190ff..d764b4f 100644 --- a/problemtools/md2html.py +++ b/problemtools/md2html.py @@ -54,7 +54,7 @@ def convert(problem: str, options: argparse.Namespace) -> None: title=problem_name or "Missing problem name", problemid=problembase) - samples = "".join(statement_common.samples_to_html(problem)) + samples = "".join(statement_common.format_samples(problem, to_pdf=False)) html_template = inject_samples(html_template, samples) html_template = replace_hr_in_footnotes(html_template) diff --git a/problemtools/problem2pdf.py b/problemtools/problem2pdf.py index d65ea43..77081f8 100644 --- a/problemtools/problem2pdf.py +++ b/problemtools/problem2pdf.py @@ -38,22 +38,20 @@ def convert(options: argparse.Namespace) -> bool: with open(statement_path, "r") as f: statement_md = f.read() + # Add code that adds vertical and horizontal lines to all tables statement_md = table_fix + statement_md # Hacky: html samples -> md. Then we append to the markdown document - samples = "".join(statement_common.samples_to_html(problem_root)) - with tempfile.NamedTemporaryFile(mode='w', suffix=".html") as temp_file: - temp_file.write(samples) - temp_file.flush() - samples_md = os.popen(f"pandoc {temp_file.name} -t latex").read() - statement_md += samples_md + samples = "\n".join(statement_common.format_samples(problem_root, to_pdf=True)) + + # If we don't add newline, the table might get attached to a footnote + statement_md += "\n" + samples - #statement_md += samples_md with tempfile.NamedTemporaryFile(mode='w', suffix=".md") as temp_file: temp_file.write(statement_md) temp_file.flush() - # Do .read so that the file isn't deleted until pandoc is done - os.popen(f"pandoc --verbose {temp_file.name} -o {problembase}.pdf --resource-path={statement_dir}").read() + # Do .read so that the temp file isn't deleted until pandoc is done + os.popen(f"pandoc {temp_file.name} -o {problembase}.pdf --resource-path={statement_dir}").read() else: # Set up template if necessary diff --git a/problemtools/statement_common.py b/problemtools/statement_common.py index 0667e92..cb6960f 100644 --- a/problemtools/statement_common.py +++ b/problemtools/statement_common.py @@ -1,6 +1,7 @@ import os from typing import Optional, List import html +import tempfile from . import verifyproblem @@ -49,8 +50,7 @@ def get_problem_name(problem: str, language: Optional[str]) -> Optional[str]: with verifyproblem.Problem(problem) as prob: config = verifyproblem.ProblemConfig(prob) if not config.check(None): - print("Please add problem name to problem.yaml when using markdown") - return None + raise Exception(f"Invalid problem.yaml") names = config.get("name") # If there is only one language, per the spec that is the one we want if len(names) == 1: @@ -61,44 +61,78 @@ def get_problem_name(problem: str, language: Optional[str]) -> Optional[str]: return names[language] -def samples_to_html(problem_root: str) -> List[str]: - """Read all samples from the problem directory and convert them to HTML +def format_samples(problem_root: str, to_pdf: bool = False) -> List[str]: + """Read all samples from the problem directory and convert them to pandoc-valid markdown Args: problem_root: path to root of problem + to_pdf: whether the outputted samples should be valid for for html or pdf Returns: - List[str]: All samples, converted to html. Ordered lexicographically by file names + List[str]: All samples, converted to a format appropriate to be pasted into + a markdown file. Ordered lexicographically by file names """ sample_path = os.path.join(problem_root, "data", "sample") + if not os.path.isdir(sample_path): + print("WARNING!! no sample folder") + return [] samples = [] casenum = 1 for sample in sorted(os.listdir(sample_path)): if sample.endswith(".interaction"): - lines = [f""" + if to_pdf: + line = r"""\begin{tabular}{p{0.3\textwidth} p{0.5\textwidth} p{0.0\textwidth}} +\textbf{Read} & \textbf{Sample Interaction %i} & \textbf{Write} \\ +\end{tabular}""" % casenum + else: + line = f""" +
-
Read Sample Interaction {casenum} Write
"""] + """ + with open(os.path.join(sample_path, sample), "r", encoding="utf-8") as infile: sample_interaction = infile.readlines() + lines = [] for interaction in sample_interaction: data = interaction[1:] - line_type = "" - if interaction[0] == '>': - line_type = "sampleinteractionwrite" - elif interaction[0] == '<': - line_type = "sampleinteractionread" + if to_pdf: + if interaction[0] == '>': + left = True + elif interaction[0] == '<': + left = False + else: + print(f"Warning: Interaction had unknown prefix {interaction[0]}") + lines.append(r""" + \begin{table}[H] + %(justify)s\begin{tabular}{|p{0.6\textwidth}|} + \hline + %(text)s \\ + \hline + \end{tabular} + \end{table}""" % {"justify": "" if left else "\\hspace*{\\fill}\n", + "text": data}) else: - print(f"Warning: Interaction had unknown prefix {interaction[0]}") - lines.append(f"""
{data}
""") - - samples.append(''.join(lines)) + line_type = "" + if interaction[0] == '>': + line_type = "sampleinteractionwrite" + elif interaction[0] == '<': + line_type = "sampleinteractionread" + else: + print(f"Warning: Interaction had unknown prefix {interaction[0]}") + lines.append(f"""
{data}
""") + + if to_pdf: + samples.append(line + '\\vspace{-15pt}'.join(lines)) + else: + samples.append(line + ''.join(lines)) casenum += 1 continue + if not sample.endswith(".in"): continue sample_name = sample[:-3] @@ -124,6 +158,14 @@ def samples_to_html(problem_root: str) -> List[str]: """ % ({"case": casenum, "input": html.escape(sample_input), "output": html.escape(sample_output)})) + + if to_pdf: + # If pdf, convert to markdown + with tempfile.NamedTemporaryFile(mode='w', suffix=".html") as temp_file: + temp_file.write(samples[-1]) + temp_file.flush() + samples[-1] = os.popen(f"pandoc {temp_file.name} -t markdown").read() + casenum += 1 return samples diff --git a/problemtools/templates/markdown_pdf/fix_tables.md b/problemtools/templates/markdown_pdf/fix_tables.md index fd59772..1b04614 100644 --- a/problemtools/templates/markdown_pdf/fix_tables.md +++ b/problemtools/templates/markdown_pdf/fix_tables.md @@ -1,5 +1,7 @@ --- header-includes: + - '\usepackage{float}' + - '\usepackage{booktabs}' - '\usepackage{xstring}' - '\setlength{\aboverulesep}{0pt}' - '\setlength{\belowrulesep}{0pt}'