Prezentprogramo 3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hovercraft/__init__.py +435 -0
- hovercraft/generate.py +473 -0
- hovercraft/parse.py +275 -0
- hovercraft/position.py +269 -0
- hovercraft/template.py +237 -0
- hovercraft/templates/default/css/highlight.css +61 -0
- hovercraft/templates/default/css/hovercraft.css +67 -0
- hovercraft/templates/default/js/MathJax/es5/a11y/assistive-mml.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/a11y/complexity.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/a11y/explorer.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/a11y/semantic-enrich.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/a11y/sre.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/adaptors/liteDOM.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/core.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/asciimath.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/mml/entities.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/mml/extensions/mml3.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/mml.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/action.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/all-packages.js +34 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/ams.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/amscd.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/autoload.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/bbox.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/boldsymbol.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/braket.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/bussproofs.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/cancel.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/cases.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/centernot.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/color.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/colortbl.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/colorv2.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/configmacros.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/empheq.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/enclose.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/extpfeil.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/gensymb.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/html.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/mathtools.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/mhchem.js +34 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/newcommand.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/noerrors.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/noundefined.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/physics.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/require.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/setoptions.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/tagformat.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/textcomp.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/textmacros.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/unicode.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/upgreek.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex/extensions/verb.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex-base.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex-full.js +34 -0
- hovercraft/templates/default/js/MathJax/es5/input/tex.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/latest.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/loader.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/mml-chtml.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/mml-svg.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/node-main.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/output/chtml/fonts/tex.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/output/chtml.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/output/svg/fonts/tex.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/output/svg.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/startup.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/tex-chtml-full-speech.js +34 -0
- hovercraft/templates/default/js/MathJax/es5/tex-chtml-full.js +34 -0
- hovercraft/templates/default/js/MathJax/es5/tex-chtml.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/tex-mml-chtml.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/tex-mml-svg.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/tex-svg-full.js +34 -0
- hovercraft/templates/default/js/MathJax/es5/tex-svg.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/ui/lazy.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/ui/menu.js +1 -0
- hovercraft/templates/default/js/MathJax/es5/ui/safe.js +1 -0
- hovercraft/templates/default/js/gotoSlide.js +51 -0
- hovercraft/templates/default/js/hovercraft.js +58 -0
- hovercraft/templates/default/js/impress.js +5009 -0
- hovercraft/templates/default/template.cfg +11 -0
- hovercraft/templates/default/template.xsl +161 -0
- hovercraft/templates/reST.xsl +535 -0
- hovercraft/templates/simple/css/highlight.css +61 -0
- hovercraft/templates/simple/css/hovercraft.css +67 -0
- hovercraft/templates/simple/js/hovercraft.js +58 -0
- hovercraft/templates/simple/js/impress.js +5009 -0
- hovercraft/templates/simple/template.cfg +10 -0
- hovercraft/templates/simple/template.xsl +162 -0
- prezentprogramo-3.1.dist-info/METADATA +143 -0
- prezentprogramo-3.1.dist-info/RECORD +94 -0
- prezentprogramo-3.1.dist-info/WHEEL +5 -0
- prezentprogramo-3.1.dist-info/entry_points.txt +5 -0
- prezentprogramo-3.1.dist-info/licenses/LICENSE.txt +254 -0
- prezentprogramo-3.1.dist-info/top_level.txt +1 -0
hovercraft/__init__.py
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import gettext
|
|
3
|
+
import os
|
|
4
|
+
import threading
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
# import pkg_resources
|
|
8
|
+
from importlib.metadata import version # , PackageNotFoundError
|
|
9
|
+
from packaging.requirements import Requirement
|
|
10
|
+
from packaging.version import parse as parse_version
|
|
11
|
+
|
|
12
|
+
from collections import defaultdict
|
|
13
|
+
from http.server import HTTPServer, SimpleHTTPRequestHandler
|
|
14
|
+
|
|
15
|
+
# from tempfile import TemporaryDirectory
|
|
16
|
+
from watchdog.observers import Observer
|
|
17
|
+
from watchdog.events import FileSystemEventHandler
|
|
18
|
+
from docutils import nodes
|
|
19
|
+
from docutils.parsers.rst import Directive, directives
|
|
20
|
+
from graphviz import Source
|
|
21
|
+
|
|
22
|
+
from .generate import generate, generate_pdf
|
|
23
|
+
|
|
24
|
+
import hashlib
|
|
25
|
+
|
|
26
|
+
# __version__ = "3.0.1" #pkg_resources.require("prezentprogramo")[0].version
|
|
27
|
+
__version__ = parse_version(version(Requirement("prezentprogramo").name))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class YoGraphvizDirective(Directive):
|
|
31
|
+
has_content = True
|
|
32
|
+
required_arguments = 0
|
|
33
|
+
optional_arguments = 0
|
|
34
|
+
option_spec = {
|
|
35
|
+
"alt": str,
|
|
36
|
+
"height": int,
|
|
37
|
+
"width": int,
|
|
38
|
+
"scale": float,
|
|
39
|
+
"align": str,
|
|
40
|
+
"class": str,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
count = 0
|
|
44
|
+
|
|
45
|
+
def run(self):
|
|
46
|
+
graphviz_code = "\n".join(self.content)
|
|
47
|
+
options = self.options
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
# Get the path of the input .rst file
|
|
51
|
+
rst_file_path = os.path.abspath(self.state.document.current_source)
|
|
52
|
+
rst_directory = os.path.dirname(rst_file_path)
|
|
53
|
+
rst_filename = os.path.splitext(os.path.basename(rst_file_path))[0]
|
|
54
|
+
|
|
55
|
+
# Create a 'img' directory inside the same directory as the input .rst file
|
|
56
|
+
graphs_directory = os.path.join(rst_directory, rst_filename, "img")
|
|
57
|
+
os.makedirs(graphs_directory, exist_ok=True)
|
|
58
|
+
|
|
59
|
+
# Generate the graph image using Graphviz and save it to the 'img' directory
|
|
60
|
+
dot = Source(graphviz_code)
|
|
61
|
+
dot.format = "png" # Output format
|
|
62
|
+
|
|
63
|
+
# Increment the count for each instance
|
|
64
|
+
self.__class__.count += 1
|
|
65
|
+
|
|
66
|
+
graph_filename = "yoo_graphviz_"
|
|
67
|
+
graph_filename += hashlib.md5(graphviz_code.encode("utf-8")).hexdigest()
|
|
68
|
+
|
|
69
|
+
graph_path = os.path.join(graphs_directory, graph_filename)
|
|
70
|
+
|
|
71
|
+
if not os.path.exists(graph_path):
|
|
72
|
+
dot.render(filename=graph_path, cleanup=True, format="png", quiet=True)
|
|
73
|
+
relative_image_path = os.path.relpath(graph_path, rst_directory)
|
|
74
|
+
|
|
75
|
+
if not relative_image_path.endswith(".png"):
|
|
76
|
+
relative_image_path = f"{relative_image_path}.png"
|
|
77
|
+
image_node = nodes.image(uri=relative_image_path, format="png")
|
|
78
|
+
|
|
79
|
+
# Apply options to the image node
|
|
80
|
+
if "alt" in options:
|
|
81
|
+
image_node["alt"] = options["alt"]
|
|
82
|
+
if "class" in options:
|
|
83
|
+
image_node["classes"] += options["class"].split()
|
|
84
|
+
if "width" in options:
|
|
85
|
+
image_node["width"] = options["width"]
|
|
86
|
+
if "height" in options:
|
|
87
|
+
image_node["height"] = options["height"]
|
|
88
|
+
if "scale" in options:
|
|
89
|
+
image_node["scale"] = options["scale"]
|
|
90
|
+
if "align" in options:
|
|
91
|
+
image_node["align"] = options["align"]
|
|
92
|
+
return [image_node]
|
|
93
|
+
|
|
94
|
+
except Exception as e:
|
|
95
|
+
error_node = nodes.error()
|
|
96
|
+
error_node += nodes.Text(f"Error generating Graphviz image: {str(e)}")
|
|
97
|
+
return [error_node]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
directives.register_directive("yographviz", YoGraphvizDirective)
|
|
101
|
+
|
|
102
|
+
'''
|
|
103
|
+
# https://github.com/liuyug/python-docutils-graphviz/blob/master/docutils_graphviz.py
|
|
104
|
+
# https://graphviz.readthedocs.io/en/stable/manual.html
|
|
105
|
+
# https://graphviz.readthedocs.io/en/stable/api.html#graphviz.Digraph.pipe
|
|
106
|
+
# https://pypi.org/project/beautifulsoup4/
|
|
107
|
+
# https://www.crummy.com/software/BeautifulSoup/
|
|
108
|
+
# https://www.crummy.com/software/BeautifulSoup/bs4/doc/
|
|
109
|
+
# https://stackabuse.com/parsing-xml-with-beautifulsoup-in-python/
|
|
110
|
+
# https://www.tutorialspoint.com/beautiful_soup/beautiful_soup_souping_the_page.htm
|
|
111
|
+
# https://developer.mozilla.org/en-US/docs/Web/SVG
|
|
112
|
+
# https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web
|
|
113
|
+
|
|
114
|
+
# pip3 install beautifulsoup4
|
|
115
|
+
|
|
116
|
+
import graphviz
|
|
117
|
+
from bs4 import BeautifulSoup
|
|
118
|
+
|
|
119
|
+
gfc="""
|
|
120
|
+
digraph {
|
|
121
|
+
rankdir = "LR";
|
|
122
|
+
node [shape=circle];
|
|
123
|
+
END [shape=doublecircle, label="2"];
|
|
124
|
+
B [shape=plaintext];
|
|
125
|
+
0 -> 1 [label="+"];
|
|
126
|
+
1 -> END [label="E"];
|
|
127
|
+
0 -> END [label="λ"];
|
|
128
|
+
}
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
dot = graphviz.Source(gfc)
|
|
132
|
+
fullDocTypeSvg = dot.pipe(encoding='utf-8', format='svg', quiet=True)
|
|
133
|
+
#soup = BeautifulSoup(fullDocTypeSvg, 'html.parser')
|
|
134
|
+
#soup = BeautifulSoup(fullDocTypeSvg, 'html5lib')
|
|
135
|
+
soup = BeautifulSoup(fullDocTypeSvg, 'xml')
|
|
136
|
+
soupJustSvg = soup.find('svg')
|
|
137
|
+
|
|
138
|
+
# https://developer.mozilla.org/en-US/docs/Web/SVG
|
|
139
|
+
|
|
140
|
+
if soupJustSvg:
|
|
141
|
+
if 'class' in options:
|
|
142
|
+
soupJustSvg.attrs['classes'] += options['class'].split()
|
|
143
|
+
if 'width' in options:
|
|
144
|
+
soupJustSvg.attrs['width'] = options['width']
|
|
145
|
+
if 'height' in options:
|
|
146
|
+
soupJustSvg.attrs['height'] = options['height']
|
|
147
|
+
if 'scale' in options:
|
|
148
|
+
soupJustSvg.attrs['scale'] = options['scale']
|
|
149
|
+
if 'align' in options:
|
|
150
|
+
soupJustSvg.attrs['align'] = options['align']
|
|
151
|
+
img = Str(soupJustSvg)
|
|
152
|
+
else:
|
|
153
|
+
img = 'It is not SVG'
|
|
154
|
+
|
|
155
|
+
return [nodes.raw('', img, format='html')]
|
|
156
|
+
'''
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class HovercraftEventHandler(FileSystemEventHandler):
|
|
160
|
+
def __init__(self, filelist):
|
|
161
|
+
self.filelist = filelist
|
|
162
|
+
self.quit = False
|
|
163
|
+
super().__init__()
|
|
164
|
+
|
|
165
|
+
def on_modified(self, event):
|
|
166
|
+
self._update(event.src_path)
|
|
167
|
+
|
|
168
|
+
def on_created(self, event):
|
|
169
|
+
self._update(event.src_path)
|
|
170
|
+
|
|
171
|
+
def on_moved(self, event):
|
|
172
|
+
self._update(event.dest_path)
|
|
173
|
+
|
|
174
|
+
def _update(self, src_path):
|
|
175
|
+
if self.quit:
|
|
176
|
+
return
|
|
177
|
+
if src_path in self.filelist:
|
|
178
|
+
print("File %s modified, update presentation" % src_path)
|
|
179
|
+
self.quit = True
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def generate_and_observe(args, event):
|
|
183
|
+
while event.isSet():
|
|
184
|
+
# Generate the presentation
|
|
185
|
+
monitor_list = generate(args)
|
|
186
|
+
print("Presentation generated.")
|
|
187
|
+
|
|
188
|
+
# Make a list of involved directories
|
|
189
|
+
directories = defaultdict(list)
|
|
190
|
+
for file in monitor_list:
|
|
191
|
+
directory, filename = os.path.split(file)
|
|
192
|
+
directories[directory].append(filename)
|
|
193
|
+
|
|
194
|
+
observer = Observer()
|
|
195
|
+
handler = HovercraftEventHandler(monitor_list)
|
|
196
|
+
for directory, files in directories.items():
|
|
197
|
+
observer.schedule(handler, directory, recursive=False)
|
|
198
|
+
|
|
199
|
+
observer.start()
|
|
200
|
+
while event.wait(1):
|
|
201
|
+
time.sleep(0.05)
|
|
202
|
+
if handler.quit:
|
|
203
|
+
break
|
|
204
|
+
|
|
205
|
+
observer.stop()
|
|
206
|
+
observer.join()
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def yoo_run_browser(bind: str, port: int):
|
|
210
|
+
time.sleep(0.1)
|
|
211
|
+
import webbrowser
|
|
212
|
+
|
|
213
|
+
webbrowser.open_new("http://" + bind + ":" + str(port))
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def main(args=None):
|
|
217
|
+
parser = create_arg_parser()
|
|
218
|
+
args = parser.parse_args(args=args)
|
|
219
|
+
|
|
220
|
+
if args.pdf_output_path: # Check if the -pdf switch is provided
|
|
221
|
+
generate_pdf(args)
|
|
222
|
+
else:
|
|
223
|
+
serve_presentation(args)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def create_arg_parser():
|
|
227
|
+
# That the argparse default strings are lowercase is ugly.
|
|
228
|
+
|
|
229
|
+
def my_gettext(s):
|
|
230
|
+
return s.capitalize()
|
|
231
|
+
|
|
232
|
+
gettext.gettext = my_gettext
|
|
233
|
+
|
|
234
|
+
parser = argparse.ArgumentParser(
|
|
235
|
+
description="Create impress.js presentations with reStructuredText",
|
|
236
|
+
add_help=False,
|
|
237
|
+
)
|
|
238
|
+
parser.add_argument(
|
|
239
|
+
"presentation",
|
|
240
|
+
metavar="<presentation>",
|
|
241
|
+
help="The path to the reStructuredText presentation file.",
|
|
242
|
+
)
|
|
243
|
+
parser.add_argument(
|
|
244
|
+
"targetdir",
|
|
245
|
+
metavar="<targetdir>",
|
|
246
|
+
nargs="?",
|
|
247
|
+
help=(
|
|
248
|
+
"The directory where the presentation is saved. Will be created "
|
|
249
|
+
"if it does not exist. If you do not specify a targetdir "
|
|
250
|
+
"prezentprogramo will instead start a webserver and serve the "
|
|
251
|
+
"presentation from that server."
|
|
252
|
+
),
|
|
253
|
+
)
|
|
254
|
+
parser.add_argument("-h", "--help", action="help", help="Show this help.")
|
|
255
|
+
parser.add_argument(
|
|
256
|
+
"-t",
|
|
257
|
+
"--template",
|
|
258
|
+
help=(
|
|
259
|
+
"Specify a template. Must be a .cfg file, or a directory with a "
|
|
260
|
+
"template.cfg file. If not given it will use a default template."
|
|
261
|
+
),
|
|
262
|
+
)
|
|
263
|
+
parser.add_argument(
|
|
264
|
+
"-c",
|
|
265
|
+
"--css",
|
|
266
|
+
help=(
|
|
267
|
+
"An additional css file for the presentation to use. "
|
|
268
|
+
"See also the ``:css:`` settings of the presentation."
|
|
269
|
+
),
|
|
270
|
+
)
|
|
271
|
+
parser.add_argument(
|
|
272
|
+
"-j",
|
|
273
|
+
"--js",
|
|
274
|
+
help=(
|
|
275
|
+
"An additional javascript file for the presentation to use. Added as a js-body script."
|
|
276
|
+
"See also the ``:js-body:`` settings of the presentation."
|
|
277
|
+
),
|
|
278
|
+
)
|
|
279
|
+
parser.add_argument(
|
|
280
|
+
"-a",
|
|
281
|
+
"--auto-console",
|
|
282
|
+
action="store_true",
|
|
283
|
+
help=(
|
|
284
|
+
"Open the presenter console automatically. This is useful when "
|
|
285
|
+
"you are rehearsing and making sure the presenter notes are "
|
|
286
|
+
"correct. You can also set this by having ``:auto-console: "
|
|
287
|
+
"true`` first in the presentation."
|
|
288
|
+
),
|
|
289
|
+
)
|
|
290
|
+
parser.add_argument(
|
|
291
|
+
"-s",
|
|
292
|
+
"--skip-help",
|
|
293
|
+
action="store_true",
|
|
294
|
+
help=("Do not show the initial help popup."),
|
|
295
|
+
)
|
|
296
|
+
parser.add_argument(
|
|
297
|
+
"-n",
|
|
298
|
+
"--skip-notes",
|
|
299
|
+
action="store_true",
|
|
300
|
+
help=("Do not include presenter notes in the output."),
|
|
301
|
+
)
|
|
302
|
+
parser.add_argument(
|
|
303
|
+
"-p",
|
|
304
|
+
"--port",
|
|
305
|
+
default="0.0.0.0:8000",
|
|
306
|
+
help=(
|
|
307
|
+
"The address and port that the server uses. "
|
|
308
|
+
"Ex 8080 or 127.0.0.1:9000. Defaults to 0.0.0.0:8000."
|
|
309
|
+
),
|
|
310
|
+
)
|
|
311
|
+
parser.add_argument(
|
|
312
|
+
"--mathjax",
|
|
313
|
+
default=os.environ.get(
|
|
314
|
+
"HOVERCRAFT_MATHJAX" "js/MathJax/es5/tex-mml-chtml.js",
|
|
315
|
+
# "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML",
|
|
316
|
+
),
|
|
317
|
+
help=(
|
|
318
|
+
"The URL to the mathjax library."
|
|
319
|
+
" (It will only be used if you have rST ``math::`` in your document)"
|
|
320
|
+
),
|
|
321
|
+
)
|
|
322
|
+
parser.add_argument(
|
|
323
|
+
"-N",
|
|
324
|
+
"--slide-numbers",
|
|
325
|
+
action="store_true",
|
|
326
|
+
help=("Show slide numbers during the presentation."),
|
|
327
|
+
)
|
|
328
|
+
parser.add_argument(
|
|
329
|
+
"-d",
|
|
330
|
+
"--default-movement",
|
|
331
|
+
help=(
|
|
332
|
+
"The default value of moving to the right in pixel during presentation execution."
|
|
333
|
+
),
|
|
334
|
+
)
|
|
335
|
+
parser.add_argument(
|
|
336
|
+
"-v",
|
|
337
|
+
"--version",
|
|
338
|
+
action="version",
|
|
339
|
+
# help=('Display version and exit.'),
|
|
340
|
+
version="prezentprogramo %s" % __version__,
|
|
341
|
+
)
|
|
342
|
+
parser.add_argument(
|
|
343
|
+
"-pdf",
|
|
344
|
+
"--pdf",
|
|
345
|
+
help="Path to the output PDF file",
|
|
346
|
+
action="store",
|
|
347
|
+
dest="pdf_output_path",
|
|
348
|
+
) # -pdf switch
|
|
349
|
+
|
|
350
|
+
return parser
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def serve_presentation(args):
|
|
354
|
+
|
|
355
|
+
# Check whether the file or folder as input exists.
|
|
356
|
+
if not os.path.exists(os.path.abspath(args.presentation)):
|
|
357
|
+
print(f"File or folder '{args.presentation}' does not exists.")
|
|
358
|
+
exit(-1)
|
|
359
|
+
|
|
360
|
+
# XXX Bit of a hack, clean this up, I check for this twice, also in the template.
|
|
361
|
+
if args.template and args.template not in ("simple", "default"):
|
|
362
|
+
args.template = os.path.abspath(args.template)
|
|
363
|
+
|
|
364
|
+
if args.targetdir:
|
|
365
|
+
# Generate the presentation
|
|
366
|
+
generate(args)
|
|
367
|
+
else:
|
|
368
|
+
# Server mode. Start a server that serves a temporary directory.
|
|
369
|
+
args.presentation = os.path.abspath(args.presentation)
|
|
370
|
+
dir_name = os.path.dirname(args.presentation)
|
|
371
|
+
file_name = os.path.basename(args.presentation)
|
|
372
|
+
targetdir_name = os.path.splitext(file_name)[0]
|
|
373
|
+
targetdir = os.path.join(dir_name, targetdir_name)
|
|
374
|
+
args.targetdir = targetdir
|
|
375
|
+
|
|
376
|
+
# Create the directory if it doesn't exist
|
|
377
|
+
if not os.path.exists(targetdir):
|
|
378
|
+
os.makedirs(targetdir)
|
|
379
|
+
|
|
380
|
+
# Set up watchdog to regenerate presentation if saved.
|
|
381
|
+
event = threading.Event()
|
|
382
|
+
event.set()
|
|
383
|
+
thread = threading.Thread(target=generate_and_observe, args=(args, event))
|
|
384
|
+
|
|
385
|
+
try:
|
|
386
|
+
# Serve presentation
|
|
387
|
+
if ":" in args.port:
|
|
388
|
+
bind, port = args.port.split(":")
|
|
389
|
+
else:
|
|
390
|
+
bind, port = "0.0.0.0", args.port
|
|
391
|
+
port = int(port)
|
|
392
|
+
|
|
393
|
+
# First create the server. This checks that we can connect to
|
|
394
|
+
# the port we want to.
|
|
395
|
+
os.chdir(targetdir)
|
|
396
|
+
server = HTTPServer((bind, port), SimpleHTTPRequestHandler)
|
|
397
|
+
print("Serving HTTP on", bind, "port", port, "...")
|
|
398
|
+
|
|
399
|
+
th1 = threading.Thread(
|
|
400
|
+
target=yoo_run_browser,
|
|
401
|
+
args=(
|
|
402
|
+
bind,
|
|
403
|
+
port,
|
|
404
|
+
),
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
try:
|
|
408
|
+
# Now generate the presentation
|
|
409
|
+
th1.start()
|
|
410
|
+
|
|
411
|
+
thread.start()
|
|
412
|
+
|
|
413
|
+
try:
|
|
414
|
+
# All is good, start the server
|
|
415
|
+
server.serve_forever()
|
|
416
|
+
except KeyboardInterrupt:
|
|
417
|
+
print("\nKeyboard interrupt received, exiting.")
|
|
418
|
+
finally:
|
|
419
|
+
# Server exited
|
|
420
|
+
server.server_close()
|
|
421
|
+
|
|
422
|
+
finally:
|
|
423
|
+
# Stop the generation thread
|
|
424
|
+
event.clear()
|
|
425
|
+
# Wait for it to end
|
|
426
|
+
thread.join()
|
|
427
|
+
th1.join()
|
|
428
|
+
|
|
429
|
+
except PermissionError:
|
|
430
|
+
print("Can't bind to port %s:%s: No permission" % (bind, port))
|
|
431
|
+
except OSError as e:
|
|
432
|
+
if e.errno == 98:
|
|
433
|
+
print("Can't bind to port %s:%s: port already in use" % (bind, port))
|
|
434
|
+
else:
|
|
435
|
+
raise
|