-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathflatten.py
executable file
·150 lines (122 loc) · 4.62 KB
/
flatten.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env python3
import argparse, fnmatch, os, re
from shutil import copy
# SETUP
##################################################
parser = argparse.ArgumentParser(description="Flatten a target latex file")
parser.add_argument(
"filename",
type=str,
help="Input filename",
)
parser.add_argument(
"-d",
"--directory",
type=str,
help="Target (output) directory; defaults to original file's directory",
default=None
)
parser.add_argument(
"-s",
"--suffix",
type=str,
help="Suffix for new tex file",
default="-flat"
)
## Parse arguments
args = parser.parse_args()
dir_base = os.path.abspath(os.path.dirname(args.filename))
if args.directory is None:
dir_target = dir_base
else:
dir_target = os.path.abspath(args.directory)
filename_in = os.path.abspath(args.filename)
filename_out = os.path.join(
dir_target,
re.sub(r"\.tex", args.suffix + ".tex", os.path.basename(filename_in))
)
# Helper functions
# --------------------------------------------------
# Find files at a path
def find_file(pattern, path):
r"""Search for files at a given path
Args:
pattern (str): Filename pattern to match
path (str): Path to search
Returns:
list: Filename matches
Examples:
>>> import os
>>> find_file("foo.txt", os.path.abspath("."))
"""
result = []
for root, dirs, files in os.walk(path):
for name in files:
if fnmatch.fnmatch(name, pattern):
result.append(os.path.join(root, name))
return result
# Execute
##################################################
with open(filename_in, 'r') as file_in:
with open(filename_out, 'w') as file_out:
## Image directory name; to be replaced if \graphicspath found
dirname = "."
for line in file_in.readlines():
## Pass-through a commented line
if not (re.search(r"^\s*\%\%", line) is None):
file_out.write(line)
## Replace the graphicspath with local directory
elif not (re.search(r"^\\graphicspath", line) is None):
dirname = re.search("\{.*\}", line).group(0)
dirname = re.sub("[\{\}]", "", dirname)
modline = re.sub("\{.*\}", "{{.}}", line)
file_out.write(modline)
## Copy all images
elif not (re.search("includegraphics", line) is None):
## Find the image
imagename = re.search("\{.*\}", line).group(0)
imagename = re.sub("[\{\}]", "", imagename)
image_matches = find_file(
imagename + ".*",
os.path.abspath(os.path.join(dir_base, dirname))
)
## Copy the first match
try:
copy(image_matches[0], dir_target)
except IndexError:
raise ValueError("Image {} not found".format(imagename))
## Echo the original line
file_out.write(line)
## Copy imported listings
elif not (re.search(r"^\\lstinputlisting", line) is None):
## Find the code file
codename = re.search("\{.*\}", line).group(0)
codename = re.sub("[\{\}]", "", codename)
codeabspath = os.path.abspath(
os.path.join(dir_base, codename)
)
## Copy the sole match
copy(codeabspath, dir_target)
## Replace original absolute path with new relative path
codeline = re.sub("\{.*\}", "{" + os.path.basename(codeabspath) + "}", line)
file_out.write(codeline)
## Copy input
elif not (re.search(r"\\input", line) is None):
## Check that file is in other directory
if (re.search(r"\.", line) is None):
file_out.write(line)
else:
## Find the code file
codename = re.search("\{.*\}", line).group(0)
codename = re.sub("[\{\}]", "", codename)
codeabspath = os.path.abspath(
os.path.join(dir_base, codename)
)
## Copy the sole match
copy(codeabspath, dir_target)
## Replace original absolute path with new relative path
codeline = re.sub("\{.*\}", "{" + os.path.basename(codeabspath) + "}", line)
file_out.write(codeline)
## Echo an unmatched line
else:
file_out.write(line)