Skip to content

Commit 1556394

Browse files
Update pandoc_fe to insert a title page
Only when generating slide decks for distribution
1 parent 18b51fa commit 1556394

File tree

2 files changed

+171
-6
lines changed

2 files changed

+171
-6
lines changed

pandoc/pandoc_fe.py

Lines changed: 155 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,19 @@
22
import os
33
import sys
44
import subprocess
5+
import tempfile
56
import multiprocessing
67
from pathlib import Path
78

9+
"""
10+
Keys for content information in title page file.
11+
If no key is specified on a line in the file,
12+
the first item in this list will be used as the key.
13+
"""
14+
TITLE_KEYS = ["COPYRIGHT", "TITLE", "PRESENTER", "DATE", "OTHER"]
15+
16+
TITLE_FILE_NAME = None
17+
818

919
def windows():
1020
return sys.platform.startswith("win")
@@ -23,6 +33,135 @@ def fix_file_case(filename):
2333
return filename
2434

2535

36+
def title_parse(line):
37+
key = "COPYRIGHT"
38+
pieces = line.split(":", 1)
39+
if pieces[0] in TITLE_KEYS:
40+
return pieces[0], pieces[1].strip()
41+
else:
42+
return TITLE_KEYS[0], line.strip()
43+
44+
45+
def default_title(source):
46+
"""
47+
If not title is specified, use the folder name to determine title
48+
"""
49+
50+
title = os.path.basename(os.path.dirname(os.path.abspath(source)))
51+
pieces = title.split("_")
52+
title = ""
53+
for piece in pieces:
54+
title = title + piece[0].upper() + piece[1:] + " "
55+
return title.strip()
56+
57+
58+
def parse_title_file(args):
59+
title_source = args.title.strip()
60+
61+
retval = {}
62+
for key in TITLE_KEYS:
63+
if key == "COPYRIGHT":
64+
retval[key] = []
65+
else:
66+
retval[key] = ""
67+
68+
try:
69+
fp = None
70+
if os.path.exists(title_source):
71+
fp = open(title_source, "r")
72+
else:
73+
fp = open(os.path.join(os.path.dirname(__file__), "title_page.txt"), "r")
74+
for line in fp:
75+
key, content = title_parse(line.strip())
76+
if len(content) > 0 or key == "COPYRIGHT":
77+
if key == "COPYRIGHT":
78+
retval[key].append(content)
79+
else:
80+
retval[key] = content
81+
82+
if len(retval["TITLE"]) == 0:
83+
retval["TITLE"] = default_title(args.source[0])
84+
85+
except:
86+
pass
87+
88+
return retval
89+
90+
91+
def print_content(tfp, title_info, prefix=""):
92+
if len(title_info) > 0:
93+
if title_info is list:
94+
for item in title_info:
95+
tfp.write(
96+
" \\small{\\textit{" + prefix + "} \\textbf{" + item + "}}\n\n"
97+
)
98+
else:
99+
tfp.write(
100+
" \\small{\\textit{" + prefix + "} \\textbf{" + title_info + "}}\n\n"
101+
)
102+
103+
104+
def prepare_title_file(args):
105+
"""
106+
If the "source" command line argument is only one TXT file, then we
107+
assume we are producing a slide deck (anything else is just trying
108+
to build from individual RST files).
109+
In that case, we want to build a title slide for the deck,
110+
consisting of the title for the course, possibly the presenter, date
111+
and/or other information, and then copyright information.
112+
This information will come from the "title_page.txt" file in the
113+
"pandoc" folder OR from the "--title" option from the command line.
114+
"""
115+
116+
global TITLE_FILE_NAME
117+
118+
TITLE_FILE_NAME = None
119+
if len(args.source) == 1 and args.source[0].lower().endswith(".txt"):
120+
tmp = tempfile.NamedTemporaryFile(delete=False)
121+
TITLE_FILE_NAME = tmp.name + ".rst"
122+
title_info = parse_title_file(args)
123+
124+
with open(TITLE_FILE_NAME, "w") as tfp:
125+
126+
"""
127+
This is the actual title page for the beamer slide deck
128+
"""
129+
separator = "#" * (2 + len(title_info["TITLE"]))
130+
tfp.write(separator + "\n")
131+
tfp.write(title_info["TITLE"] + "\n")
132+
tfp.write(separator + "\n\n")
133+
134+
"""
135+
This is the copyright page (which will include any other user-specified
136+
information) that appears after the document title page and before
137+
the document actually begins.
138+
"""
139+
140+
tfp.write(".. raw:: latex\n\n")
141+
tfp.write(" \\begin{center}\n")
142+
143+
tfp.write(" \\colorbox{adacore3}\n")
144+
tfp.write(
145+
" {\\color{adacore1}{\\huge{\\textit{\\textbf{"
146+
+ title_info["TITLE"]
147+
+ "}}}}}\n\n"
148+
)
149+
150+
print_content(tfp, title_info["PRESENTER"], prefix="Presented by")
151+
print_content(tfp, title_info["DATE"])
152+
print_content(tfp, title_info["OTHER"])
153+
154+
tfp.write(" \\end{center}\n\n")
155+
156+
tfp.write(" \\vspace{3cm}\n\n")
157+
158+
if len(title_info["COPYRIGHT"]) > 0:
159+
tfp.write(" \\tiny{\n")
160+
for line in title_info["COPYRIGHT"]:
161+
tfp.write(" " + line + "\n")
162+
tfp.write(" }\n")
163+
164+
26165
def to_texinputs_path(path):
27166
abspath = fix_file_case(os.path.abspath(path))
28167
if path.endswith("//"):
@@ -182,13 +321,17 @@ def parse_rst_list_file(dirname, f):
182321

183322

184323
def expand_source(source_file):
324+
global TITLE_FILE_NAME
325+
185326
if source_file.lower().endswith(".rst"):
186327
return [os.path.abspath(source_file)]
187328
else:
188329
dirname = os.path.dirname(source_file)
189330
# Read lines from source file
190331
with open(source_file) as f:
191332
files = parse_rst_list_file(dirname, f)
333+
if TITLE_FILE_NAME != None:
334+
files.insert(0, TITLE_FILE_NAME)
192335
return files
193336

194337

@@ -212,11 +355,7 @@ def pandoc_prepare_run_single(n, source_or_source_list, args):
212355
if len(color) > 0:
213356
color = " -V colortheme=" + color
214357

215-
pandoc_title_arg = args.title
216-
if args.title:
217-
pandoc_title_arg = ' -V title="' + args.title.replace("_", " ") + '"'
218-
219-
input_file = args.title or source_or_source_list
358+
input_file = source_or_source_list
220359

221360
extension = args.extension
222361
if extension is None:
@@ -258,7 +397,6 @@ def pandoc_prepare_run_single(n, source_or_source_list, args):
258397
"--resource-path",
259398
texinputs,
260399
filter,
261-
pandoc_title_arg,
262400
theme,
263401
color,
264402
"--fail-if-warnings",
@@ -301,6 +439,13 @@ def run_pandoc(args):
301439
print(f"[end ] {task_name}")
302440

303441

442+
def delete_temp_file():
443+
global TITLE_FILE_NAME
444+
if TITLE_FILE_NAME != None and os.path.exists(TITLE_FILE_NAME):
445+
os.remove(TITLE_FILE_NAME)
446+
# print (TITLE_FILE_NAME)
447+
448+
304449
if __name__ == "__main__":
305450
PANDOC = Path(sys.argv[0]).resolve().parent
306451
ROOT = PANDOC.parent
@@ -371,10 +516,14 @@ def run_pandoc(args):
371516

372517
args = parser.parse_args()
373518

519+
prepare_title_file(args)
520+
374521
pandoc_prepared = pandoc_prepare_run(args)
375522

376523
try:
377524
with multiprocessing.Pool(None if args.jobs == 0 else args.jobs) as p:
378525
p.map(run_pandoc, pandoc_prepared)
526+
delete_temp_file()
379527
except subprocess.CalledProcessError as e:
528+
delete_temp_file()
380529
sys.exit(2)

pandoc/title_page.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
TITLE:
2+
PRESENTER: Foo Bar
3+
DATE: 26 Jul 2025
4+
OTHER:
5+
Copyright (C) 2018-2025, AdaCore under CC BY-SA
6+
7+
Published under a CC BY-SA license, which means that you can copy,
8+
redistribute, remix, transform, and build upon the content for any
9+
purpose, even commercially, as long as you give appropriate credit,
10+
provide a link to the license, and indicate if changes were made.
11+
If you remix, transform, or build upon the material, you must
12+
distribute your contributions under the same license as the
13+
original. You can find license details on this page
14+
http://creativecommons.org/licenses/by-sa/4.0
15+
16+

0 commit comments

Comments
 (0)