|
25 | 25 | from pathlib import Path
|
26 | 26 | import re
|
27 | 27 | import struct
|
| 28 | +import subprocess |
28 | 29 | import sys
|
29 | 30 | import textwrap
|
30 | 31 |
|
@@ -1040,6 +1041,28 @@ def _parse_enc(path):
|
1040 | 1041 | "Failed to parse {} as Postscript encoding".format(path))
|
1041 | 1042 |
|
1042 | 1043 |
|
| 1044 | +class _LuatexKpsewhich: |
| 1045 | + @lru_cache() # A singleton. |
| 1046 | + def __new__(cls): |
| 1047 | + self = object.__new__(cls) |
| 1048 | + self._proc = self._new_proc() |
| 1049 | + return self |
| 1050 | + |
| 1051 | + def _new_proc(self): |
| 1052 | + return subprocess.Popen( |
| 1053 | + ["luatex", "--luaonly", |
| 1054 | + str(cbook._get_data_path("kpsewhich.lua"))], |
| 1055 | + stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
| 1056 | + |
| 1057 | + def search(self, filename): |
| 1058 | + if self._proc.poll() is not None: # Dead, restart it. |
| 1059 | + self._proc = self._new_proc() |
| 1060 | + self._proc.stdin.write(os.fsencode(filename) + b"\n") |
| 1061 | + self._proc.stdin.flush() |
| 1062 | + out = self._proc.stdout.readline().rstrip() |
| 1063 | + return "" if out == b"nil" else os.fsdecode(out) |
| 1064 | + |
| 1065 | + |
1043 | 1066 | @lru_cache()
|
1044 | 1067 | def find_tex_file(filename, format=None):
|
1045 | 1068 | """
|
@@ -1072,6 +1095,14 @@ def find_tex_file(filename, format=None):
|
1072 | 1095 | if isinstance(format, bytes):
|
1073 | 1096 | format = format.decode('utf-8', errors='replace')
|
1074 | 1097 |
|
| 1098 | + try: |
| 1099 | + lk = _LuatexKpsewhich() |
| 1100 | + except FileNotFoundError: |
| 1101 | + pass # Fallback to directly calling kpsewhich, as below. |
| 1102 | + else: |
| 1103 | + return lk.search( |
| 1104 | + f"{filename}.{format}" if format is not None else filename) |
| 1105 | + |
1075 | 1106 | if os.name == 'nt':
|
1076 | 1107 | # On Windows only, kpathsea can use utf-8 for cmd args and output.
|
1077 | 1108 | # The `command_line_encoding` environment variable is set to force it
|
|
0 commit comments