Skip to content

Commit 152dec5

Browse files
authored
Allow compiling LaTeX with lualatex (#282)
This is necessary to use some TeX features, such as TikZ's graph drawing library. As there isn't a reasonable way of detecting the necessity of using lualatex, the --latex-compiler option is now also exposed through config.yml, to make it possible to export the package if the statement only compiles with the right latex compiler.
1 parent e592a2d commit 152dec5

File tree

9 files changed

+84
-10
lines changed

9 files changed

+84
-10
lines changed

example_package/config.yml

+7
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ sinol_task_id: __ID__
7373
# See README.md for more information.
7474
sinol_contest_type: oi
7575

76+
# You can configure how sinol-make will compile the LaTeX in `doc/`. By default,
77+
# it will attempt to choose an option that makes sense based on the presence
78+
# of *.ps/*.eps figures. You can choose between `pdflatex`, `lualatex` and
79+
# `latex_dvi`.
80+
# This option can be overridden by passing `--latex_compiler` to `sinol-make doc`.
81+
sinol_latex_compiler: auto
82+
7683
# You can specify which tests are static (handwritten). This allows sinol-make to differentiate between
7784
# old and handwritten tests. If this key is not present old tests won't be removed.
7885
# This key is optional and should be a list of tests.

src/sinol_make/commands/doc/__init__.py

+20-10
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import subprocess
55

66
from sinol_make import util
7-
from sinol_make.helpers import paths
7+
from sinol_make.helpers import package_util, paths
88
from sinol_make.interfaces.BaseCommand import BaseCommand
99

1010

@@ -37,11 +37,11 @@ def compile_file_latex_div(self, file_path):
3737
print(util.info(f'Compilation successful for file {os.path.basename(file_path)}.'))
3838
return True
3939

40-
def compile_pdf_latex(self, file_path):
41-
print(f'Compiling {os.path.basename(file_path)} (pdflatex)...')
40+
def compile_pdf_latex(self, file_path, compiler='pdflatex'):
41+
print(f'Compiling {os.path.basename(file_path)} ({compiler})...')
4242
os.chdir(os.path.dirname(file_path))
4343
for _ in range(3):
44-
subprocess.run(['pdflatex', file_path])
44+
subprocess.run([compiler, file_path])
4545
pdf_file = os.path.splitext(file_path)[0] + '.pdf'
4646
pdf_file_path = os.path.join(os.path.dirname(file_path), pdf_file)
4747
if not os.path.exists(pdf_file_path):
@@ -53,8 +53,8 @@ def make_file(self, file_path):
5353
"""
5454
Compile the file two times to get the references right.
5555
"""
56-
if self.compilation_method == 'pdflatex':
57-
return self.compile_pdf_latex(file_path)
56+
if self.compilation_method in ('pdflatex', 'lualatex'):
57+
return self.compile_pdf_latex(file_path, self.compilation_method)
5858
else:
5959
if not self.compile_file_latex_div(file_path):
6060
return False
@@ -73,22 +73,32 @@ def configure_subparser(self, subparser: argparse.ArgumentParser):
7373
help='Compile latex files to pdf',
7474
description='Compiles latex files to pdf. By default compiles all files in the `doc` directory.\n'
7575
'You can also specify files to compile.')
76-
parser.add_argument('--latex-compiler', dest='latex_compiler', choices=['auto', 'pdflatex', 'latex_dvi'],
76+
parser.add_argument('--latex-compiler', dest='latex_compiler', choices=['auto', 'pdflatex', 'latex_dvi', 'lualatex'],
7777
help='Compiler used to compile documents. Available options:\n'
78-
' auto - uses the compiler based on the image types (default option).\n'
78+
' auto - uses the compiler based on the image types (default option, if not configured in config.yml).\n'
7979
' pdflatex - uses pdflatex. Works with .png and .jpg images.\n'
80-
' latex_dvi - uses latex and dvipdf. Works with .ps and .eps images.', default='auto')
80+
' lualatex - uses lualatex. Like pdflatex, but supports the graph drawing library of TikZ.\n'
81+
' latex_dvi - uses latex and dvipdf. Works with .ps and .eps images.', default=argparse.SUPPRESS)
8182
parser.add_argument('files', type=str, nargs='*', help='files to compile')
8283
return parser
8384

8485
def run(self, args: argparse.Namespace):
8586
args = util.init_package_command(args)
8687

88+
# Note: when other commands call DocCommand as a subroutine, they provide
89+
# their own argparse.Namespace instead of going through the argparse
90+
# configuration in configure_subparser. To match their behavior,
91+
# we configure argparse to omit the latex_compiler attribute entirely
92+
# when it is not provided by the user, instead of using the default
93+
# behavior of defaulting to None.
8794
if not hasattr(args, 'latex_compiler'):
88-
args.latex_compiler = 'auto'
95+
config = package_util.get_config()
96+
args.latex_compiler = config.get('sinol_latex_compiler', 'auto')
8997

9098
if args.latex_compiler == 'pdflatex':
9199
self.compilation_method = 'pdflatex'
100+
elif args.latex_compiler == 'lualatex':
101+
self.compilation_method = 'lualatex'
92102
elif args.latex_compiler == 'latex_dvi':
93103
self.compilation_method = 'latex_dvi'
94104
elif args.latex_compiler == 'auto':

src/sinol_make/util.py

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def save_config(config):
9191
"title_en",
9292
"sinol_task_id",
9393
"sinol_contest_type",
94+
"sinol_latex_compiler",
9495
"sinol_static_tests",
9596
"sinol_undocumented_time_tool",
9697
"sinol_undocumented_test_limits",

tests/commands/doc/test_integration.py

+40
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,43 @@ def test_compilation_mode_2(capsys, create_package):
9595
expected="latex to dvi",
9696
not_expected="pdflatex"
9797
)
98+
99+
100+
@pytest.mark.parametrize("create_package", [util.get_doc_package_path()], indirect=True)
101+
def test_compilation_mode_3(capsys, create_package):
102+
"""
103+
Test `doc` with compilation mode directly specified.
104+
"""
105+
run_doc(
106+
capsys=capsys,
107+
command_args=["doc", "doc/doczad.tex", "--latex-compiler", "lualatex"],
108+
expected="lualatex",
109+
not_expected="pdflatex"
110+
)
111+
112+
113+
@pytest.mark.parametrize("create_package", [util.get_luadoc_package_path()], indirect=True)
114+
def test_compilation_mode_config(capsys, create_package):
115+
"""
116+
Test `doc` with compilation mode specified in the configuration file.
117+
"""
118+
run_doc(
119+
capsys=capsys,
120+
command_args=["doc"],
121+
expected="lualatex",
122+
not_expected="pdflatex"
123+
)
124+
125+
126+
@pytest.mark.parametrize("create_package", [util.get_luadoc_package_path()], indirect=True)
127+
def test_compilation_mode_config_override(capsys, create_package):
128+
"""
129+
Test `doc` with compilation mode specified in the configuration file, and
130+
then overridden on the command-line.
131+
"""
132+
run_doc(
133+
capsys=capsys,
134+
command_args=["doc", "--latex-compiler", "pdflatex"],
135+
expected="pdflatex",
136+
not_expected="lualatex"
137+
)

tests/packages/luadoc/config.yml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
title: Package for testing `doc` command
2+
time_limit: 1000
3+
memory_limit: 1024
4+
sinol_task_id: luadoc
5+
sinol_latex_compiler: lualatex

tests/packages/luadoc/doc/doczad.tex

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
\documentclass{article}
2+
\begin{document}
3+
Hello World!
4+
\end{document}

tests/packages/luadoc/in/.gitkeep

Whitespace-only changes.

tests/packages/luadoc/out/.gitkeep

Whitespace-only changes.

tests/util.py

+7
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,13 @@ def get_ps_doc_package_path():
108108
return os.path.join(os.path.dirname(__file__), "packages", "ps_doc")
109109

110110

111+
def get_luadoc_package_path():
112+
"""
113+
Get path to package for testing `doc` command (version that requests lualatex in config.yml) (/test/packages/luadoc)
114+
"""
115+
return os.path.join(os.path.dirname(__file__), "packages", "luadoc")
116+
117+
111118
def get_long_name_package_path():
112119
"""
113120
Get path to package with long name (/test/packages/long_package_name)

0 commit comments

Comments
 (0)