All examples now build, plus added examples to travis build.

This commit is contained in:
Mark Wolfman
2020-05-03 22:56:35 -05:00
parent 22c3e4dbeb
commit 33817135a0
5 changed files with 66 additions and 52 deletions
+1
View File
@@ -1,6 +1,7 @@
# Generated output PDFs (and intermediate files) # Generated output PDFs (and intermediate files)
examples/*.pdf examples/*.pdf
examples/*.aux examples/*.aux
examples/*.tex
# Emacs temp files # Emacs temp files
*~ *~
+4
View File
@@ -3,6 +3,10 @@ python:
- "3.6" - "3.6"
- "3.7" - "3.7"
- "3.8" - "3.8"
before_install:
- sudo add-apt-repository -y ppa:malteworld/ppa
- sudo apt -q update
- sudo apt-get -y install pdftk
# command to install dependencies # command to install dependencies
install: install:
- pip install -r requirements.txt - pip install -r requirements.txt
+24 -19
View File
@@ -24,10 +24,11 @@ character sheet."""
bold_re = re.compile(r'\*\*([^*]+)\*\*') bold_re = re.compile(r'\*\*([^*]+)\*\*')
it_re = re.compile(r'\*([^*]+)\*') it_re = re.compile(r'\*([^*]+)\*')
tt_re = re.compile(r'``([^`]+)``') verb_re = re.compile(r'``([^`]+)``')
# A dice string, with optinal backticks: ``1d6 + 3`` # A dice string, with optinal 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+)?)`*')
def rst_to_latex(rst): def rst_to_latex(rst):
"""Basic markup of RST to LaTeX code.""" """Basic markup of RST to LaTeX code."""
if rst is None: if rst is None:
@@ -38,10 +39,11 @@ def rst_to_latex(rst):
tex = tex.replace(c, '\\' + c) tex = tex.replace(c, '\\' + c)
tex = bold_re.sub(r'\\textbf{\1}', tex) tex = bold_re.sub(r'\\textbf{\1}', tex)
tex = it_re.sub(r'\\textit{\1}', tex) tex = it_re.sub(r'\\textit{\1}', tex)
tex = verb_re.sub(r'\\begin{verbatim}{\1}\\end{verbatim}', tex)
tex = dice_re.sub(r'\\texttt{\1}', tex) tex = dice_re.sub(r'\\texttt{\1}', tex)
tex = tt_re.sub(r'\\texttt{\1}', tex)
for c in ['#', '$', '%', '&', '~', '_', '^']: for c in ['#', '$', '%', '&', '~', '_', '^']:
tex = tex.replace(c, '\\' + c) tex = tex.replace(c, '\\' + c)
return tex return tex
@@ -70,22 +72,22 @@ def text_box(string):
return new_string return new_string
def create_druid_shapes_pdf(character, basename): def create_druid_shapes_pdf(character, basename, keep_temp_files=False):
template = jinja_env.get_template('druid_shapes_template.tex') template = jinja_env.get_template('druid_shapes_template.tex')
return create_latex_pdf(character, basename, template) return create_latex_pdf(character, basename, template, keep_temp_files=keep_temp_files)
def create_spellbook_pdf(character, basename): def create_spellbook_pdf(character, basename, keep_temp_files=False):
template = jinja_env.get_template('spellbook_template.tex') template = jinja_env.get_template('spellbook_template.tex')
return create_latex_pdf(character, basename, template) return create_latex_pdf(character, basename, template, keep_temp_files=keep_temp_files)
def create_features_pdf(character, basename): def create_features_pdf(character, basename, keep_temp_files=False):
template = jinja_env.get_template('features_template.tex') template = jinja_env.get_template('features_template.tex')
return create_latex_pdf(character, basename, template) return create_latex_pdf(character, basename, template, keep_temp_files=keep_temp_files)
def create_latex_pdf(character, basename, template): def create_latex_pdf(character, basename, template, keep_temp_files=False):
tex = template.render(character=character) tex = template.render(character=character)
# Create tex document # Create tex document
tex_file = f'{basename}.tex' tex_file = f'{basename}.tex'
@@ -109,19 +111,22 @@ def create_latex_pdf(character, basename, template):
# Compile the PDF # Compile the PDF
pdf_file = f'{basename}.pdf' pdf_file = f'{basename}.pdf'
output_dir = os.path.abspath(os.path.dirname(pdf_file)) output_dir = os.path.abspath(os.path.dirname(pdf_file))
tex_command_line = ['pdflatex', '--output-directory', output_dir,
'-halt-on-error', '-interaction=nonstopmode',
tex_file]
try: try:
result = subprocess.run(['pdflatex', '--output-directory', result = subprocess.run(tex_command_line,
output_dir, tex_file, '-halt-on-error'],
stdout=subprocess.DEVNULL, timeout=30) stdout=subprocess.DEVNULL, timeout=30)
except FileNotFoundError: except FileNotFoundError:
# Remove temporary files # Remove temporary files
remove_temp_files(basename) remove_temp_files(basename)
raise exceptions.LatexNotFoundError() raise exceptions.LatexNotFoundError()
else: else:
if result.returncode == 0: if result.returncode == 0 and not keep_temp_files:
remove_temp_files(basename) remove_temp_files(basename)
else: if result.returncode != 0:
raise exceptions.LatexError(f'Processing of {basename}.tex failed.') raise exceptions.LatexError(f'Processing of {basename}.tex failed.'
f' See {basename}.log for details.')
def create_spells_pdf(character, basename, flatten=False): def create_spells_pdf(character, basename, flatten=False):
@@ -431,7 +436,7 @@ def _make_pdf_pdftk(fields, src_pdf, basename, flatten=False):
os.remove(fdfname) os.remove(fdfname)
def make_sheet(character_file, character=None, flatten=False): def make_sheet(character_file, character=None, flatten=False, debug=False):
"""Prepare a PDF character sheet from the given character file. """Prepare a PDF character sheet from the given character file.
Parameters Parameters
@@ -463,7 +468,7 @@ def make_sheet(character_file, character=None, flatten=False):
feat_base = '{:s}_feats'.format( feat_base = '{:s}_feats'.format(
os.path.splitext(character_file)[0]) os.path.splitext(character_file)[0])
try: try:
create_features_pdf(character=character, basename=feat_base) create_features_pdf(character=character, basename=feat_base, keep_temp_files=debug)
except exceptions.LatexNotFoundError as e: except exceptions.LatexNotFoundError as e:
log.warning('``pdflatex`` not available. Skipping features book ' log.warning('``pdflatex`` not available. Skipping features book '
f'for {character.name}') f'for {character.name}')
@@ -473,7 +478,7 @@ def make_sheet(character_file, character=None, flatten=False):
# Create spell book # Create spell book
spellbook_base = os.path.splitext(character_file)[0] + '_spellbook' spellbook_base = os.path.splitext(character_file)[0] + '_spellbook'
try: try:
create_spellbook_pdf(character=character, basename=spellbook_base) create_spellbook_pdf(character=character, basename=spellbook_base, keep_temp_files=debug)
except exceptions.LatexNotFoundError as e: except exceptions.LatexNotFoundError as e:
log.warning('``pdflatex`` not available. Skipping spellbook ' log.warning('``pdflatex`` not available. Skipping spellbook '
f'for {character.name}') f'for {character.name}')
@@ -484,7 +489,7 @@ def make_sheet(character_file, character=None, flatten=False):
if len(wild_shapes) > 0: if len(wild_shapes) > 0:
shapes_base = os.path.splitext(character_file)[0] + '_wild_shapes' shapes_base = os.path.splitext(character_file)[0] + '_wild_shapes'
try: try:
create_druid_shapes_pdf(character=character, basename=shapes_base) create_druid_shapes_pdf(character=character, basename=shapes_base, keep_temp_files=debug)
except exceptions.LatexNotFoundError as e: except exceptions.LatexNotFoundError as e:
log.warning('``pdflatex`` not available. Skipping wild shapes list ' log.warning('``pdflatex`` not available. Skipping wild shapes list '
f'for {character.name}') f'for {character.name}')
@@ -546,7 +551,7 @@ def main():
for filename in filenames: for filename in filenames:
print(f"Processing {os.path.splitext(filename)[0]}...", end='') print(f"Processing {os.path.splitext(filename)[0]}...", end='')
try: try:
make_sheet(character_file=filename, flatten=(not args.editable)) make_sheet(character_file=filename, flatten=(not args.editable), debug=args.debug)
except exceptions.CharacterFileFormatError as e: except exceptions.CharacterFileFormatError as e:
# Only raise the failed exception if this file is explicitly given # Only raise the failed exception if this file is explicitly given
print('invalid') print('invalid')
+29 -29
View File
@@ -87,39 +87,39 @@ class ScorchingRay(Spell):
class Scrying(Spell): class Scrying(Spell):
"""You can see and hear a particular creature you choose that is on the same plane """You can see and hear a particular creature you choose that is on
of existence as you. The target must make a W isdom saving throw, which is the same plane of existence as you. The target must make a W isdom
modified by how well you know the target and the sort of physical connection you saving throw, which is modified by how well you know the target
have to it. If a target knows you're casting this spell, it can fail the saving and the sort of physical connection you have to it. If a target
throw voluntarily if it wants to be observed. knows you're casting this spell, it can fail the saving throw
voluntarily if it wants to be observed.
Knowledge  Save Knowledge - Save Modifier
Modifier =========================
Secondhand (you have heard of the target)+5 Secondhand (you have heard of the target) - +5
Firsthand (you have met Firsthand (you have met the target) - +0
the target)  +0 Familiar (you know the target well) - -5
Familiar (you know the target well)-5
Connection Connection - Save Modifier
Save Modifier ==========================
Likeness or picture   -2 Likeness or picture - -2
Posession or Possession or garment - -4
garment -4 Body part, lock of hair, bit of nail, or the like - -10
Body part, lock of hair, bit of nail, or the like-10
On On a successful save, the target isn't affected, and you can't use
a successful save, the target isn't affected, and you can't use this spell this spell against it again for 24 hours.
against it again for 24 hours.
On a failed save, the spell creates an invisible On a failed save, the spell creates an invisible sensor within 10
sensor within 10 feet of the target. You can see and hear through the sensor as feet of the target. You can see and hear through the sensor as if
if you w ere there. The sensor moves with the target, remaining within 10 feet you w ere there. The sensor moves with the target, remaining
of it for the duration. A creature that can see invisible objects sees the within 10 feet of it for the duration. A creature that can see
sensor as a luminous orb about the size of your fist. invisible objects sees the sensor as a luminous orb about the size
of your fist.
Instead of targeting a creature, you can choose a location you
have seen before as the target of this spell. When you do, the
sensor appears at that location and doesn't move.
Instead of targeting a
creature, you can choose a location you have seen before as the target of this
spell. When you do, the sensor appears at that location and doesn't move.
""" """
name = "Scrying" name = "Scrying"
level = 5 level = 5
@@ -1508,7 +1508,7 @@ class Symbol(Spell):
Each target must make a Wisdom saving throw and becomes frightened Each target must make a Wisdom saving throw and becomes frightened
for 1 minute on a failed save. While frightened, the target drops whatever it is for 1 minute on a failed save. While frightened, the target drops whatever it is
holding and must move at least 20 feet away from the glyph on each of ist holding and must move at least 20 feet away from the glyph on each of ist
turns, if able.  turns, if able.
Hopelessness Hopelessness
Each target must make a Charisma saving throw. On Each target must make a Charisma saving throw. On
+4
View File
@@ -47,3 +47,7 @@ class MarkdownTestCase(unittest.TestCase):
def test_no_text(self): def test_no_text(self):
text = make_sheets.rst_to_latex(None) text = make_sheets.rst_to_latex(None)
self.assertEqual(text, '') self.assertEqual(text, '')
def test_verbatim(self):
text = make_sheets.rst_to_latex('``hello, world``')
self.assertIn(r'\begin{verbatim}', text)