-
Notifications
You must be signed in to change notification settings - Fork 1
/
ziptex.sh
executable file
·325 lines (291 loc) · 9.34 KB
/
ziptex.sh
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
#!/bin/bash
# If you use a custom class file, put it here
CUSTOM_CLASS="${HOME}/Documents/work/Manuscripts/BibLaTex-Template/rcclab.cls"
#SET OUTPUT AND TMP DIRECTORY#####
OUTDIR="${HOME}/Desktop/"
TMPDIR="LaTeX"
# MISC
LC_CTYPE=C
BASENAME=$(basename "$PWD")
STATUS="OK"
##########################
RED=$(tput setaf 1 2>/dev/null)
GREEN=$(tput setaf 2 2>/dev/null)
YELLOW=$(tput setaf 3 2>/dev/null)
LIME_YELLOW=$(tput setaf 190 2>/dev/null)
POWDER_BLUE=$(tput setaf 153 2>/dev/null)
BLUE=$(tput setaf 4 2>/dev/null)
#MAGENTA=$(tput setaf 5 2>/dev/null)
#CYAN=$(tput setaf 6 2>/dev/null)
#WHITE=$(tput setaf 7 2>/dev/null)
#BRIGHT=$(tput bold 2>/dev/null)
#BLINK=$(tput blink 2>/dev/null)
#REVERSE=$(tput smso 2>/dev/null)
#UNDERLINE=$(tput smul 2>/dev/null)
RS=$(tput sgr0 2>/dev/null)
#######################
#
# NOTE: May not work if filenames have spaces in them!
#
# NOTE: To remove BibLaTex: https://tex.stackexchange.com/questions/12175/biblatex-submitting-to-a-journal
#
# In the preamble, after the biblatex package is loaded via \usepackage[...]{biblatex}:
#
# \usepackage{biblatex2bibitem}
# At the very end of document:
#
# \printbibitembibliography
# The desired bibitems will be written directly to the PDF file.
#
# When it's time to switch to bibitems (e.g. before sending the paper to the journal), just copy them to your .tex file, remove biblatex commands and load cite package.
#
usage() {
echo "${LIME_YELLOW}Usage: $0 [ -f] [ -z ] [ -j ] [ -o OUTDIR ] .tex <.tex> ... ${RS}"
}
exit_abnormal() {
if [[ -n "$1" ]]
then
echo "$1"
else
usage
fi
exit 1
}
finddeps() {
if pdflatex -draft -record -halt-on-error "$1" >/dev/null
then
awk '!x[$0]++' "${1%.tex}.fls" | sed '/^INPUT \/.*/d' | sed '/^OUTPUT .*/d' | sed '/^PWD .*/d' | sed 's/^INPUT //g'
else
exit_abnormal "Error finding deps for $1"
fi
}
checktex() { # This function should only be called from $TMPDIR
TMPLOG="/tmp/ziptex.log"
local __texok=0
for TEX in "${TEXFILES[@]}"; do
if pdflatex -draft -halt-on-error "${TEX}" > "$TMPLOG"; then
echo "${GREEN}${TEX} is OK.${RS}"
else
echo "${RED}${TEX} is NOT OK.${RS}"
cat "$TMPLOG"
__texok=1
fi
done
rm "$TMPLOG"
return $__texok
}
catclass() { # This function should only be called from $TMPDIR
echo "${BLUE}Looking for cls files to concatenate.${RS}"
# Check for CUSTOM_CLASS
[[ -z ${CUSTOM_CLASS} ]] && return
# If a copy of the cls file exists locally, use that one
[[ -f "$(basename "${CUSTOM_CLASS}")" ]] && classfile="$(basename "${CUSTOM_CLASS}")" || classfile=${CUSTOM_CLASS}
for TEX in "${TEXFILES[@]}"; do
if grep '\\documentclass' "${TEX}" | grep -q "$(basename "${classfile}" | sed 's/\.cls//g')"; then
echo "${LIME_YELLOW}Concatenating $(basename "${classfile}") into ${TEX} for portability.${RS}"
mv "${TEX}" "${TEX}.orig"
printf "\\\begin{filecontents}{%s}\n" "$(basename "${classfile}")" > "${TEX}"
{ cat "${classfile}"; printf "\\\end{filecontents}\n"; cat "${TEX}.orig"; } >> "${TEX}"
rm "${TEX}.orig"
[[ "$classfile" != "${CUSTOM_CLASS}" ]] && echo "$classfile" >> .todel
fi
done
}
cataux() { # This function should only be called from $TMPDIR
echo "${BLUE}Looking for aux files to concatenate.${RS}"
for TEX in "${TEXFILES[@]}"; do
find . -type f -iname "*.aux" | sed "s|^\./||" | while read -r aux; do
if grep -Eq ".*?\{\s*${aux%.*}\s*\}.*?" "${TEX}"; then
echo "${LIME_YELLOW}Concatenating $(basename "${aux}") into ${TEX} files for portability.${RS}"
mv "${TEX}" "${TEX}.orig"
printf "\\\begin{filecontents}{%s}\n" "$(basename "${aux}")" > "${TEX}"
{ cat "${aux}"; printf "\\\end{filecontents}\n"; cat "${TEX}.orig"; } >> "${TEX}"
rm "${TEX}.orig"
echo "${aux}" >> .todel
fi
done
done
}
flattentex() { # This function should only be called fom $TMPDIR
echo "${BLUE}Looking for tex files to concatenate.${RS}"
for TEX in "${TEXFILES[@]}"; do
echo "${LIME_YELLOW}Flattening \input and \include statements in ${TEX}.${RS}"
mv "${TEX}" "${TEX}_tmp.tex"
if [[ -f "${TEX%.*}.bbl" ]]; then
latexpand --verbose --fatal --expand-usepackage --expand-bbl "${TEX%.*}.bbl" -o "${TEX}" "${TEX}_tmp.tex"
_result=$?
else
latexpand --verbose --fatal --expand-usepackage -o "${TEX}" "${TEX}_tmp.tex"
_result=$?
fi
rm "${TEX}_tmp.tex" 2>/dev/null
if [[ ${_result} == 0 ]]; then
echo "${GREEN}${TEX} flattened.${RS}"
else
echo "${RED}latexpand failed for ${TEX}.${RS}"
exit_abnormal
fi
done
}
flattendirs() { # This function should only be called from $TMPDIR
for TEX in "${TEXFILES[@]}"; do
echo "${LIME_YELLOW}Flattening directory structure for ${TEX}.${RS}"
_gfxpath=$(grep graphicspath "${TEX}"| cut -d '{' -f '2-' | tr -d '{}')
_gfxpath=${_gfxpath%/}
if [[ ! -d "${_gfxpath}" ]]; then
ls
echo "${RED} Warning: graphicspath \"${_gfxpath}\" not found (could be a case-sensitivity issue!"
else
find "$_gfxpath" \
-depth -type f -exec mv -v "{}" ./ \;
fi
sed -i.bak '/\\graphicspath.*/d' "${TEX}"
done
find ./ -depth -type d -empty -delete
}
findbadchars() { # Find unicode characters that break pdflatex
cat "${1%.*}.log" | egrep 'There is no . (.*?) in font' | cut -d '(' -f 1 | cut -d ' ' -f 6
}
if [ -z "$1" ]; then
usage
exit 0
fi
if ! which latexpand; then
echo "The latexpand command was not found in your path, it should be included with texlive..."
exit 0
fi
ZIP=0
BZ=0
FORCE=0
while getopts ":o:zjf" options; do
case "${options}" in
z)
ZIP=1
;;
j)
BZ=1
;;
f)
FORCE=1
;;
o)
OUTDIR="${OPTARG}"
;;
:)
echo "${RED}Error: -${OPTARG} requires an argument.${RS}"
exit_abnormal
;;
*)
exit_abnormal
;;
esac
done
# Convert OUTDIR to absolute path
# shellcheck disable=SC2164
OUTDIR=$(cd "${OUTDIR}"; pwd)
if [[ ! -d "$OUTDIR" ]]; then
echo "${RED}${OUTDIR} is not a directory!${RS}"
exit_abnormal
fi
if [[ $ZIP == 0 && $BZ == 0 ]]; then
echo "${RED}You must pick at least one archive option, -z / -j.${RS}"
exit_abnormal
fi
if [[ ! -d "${TMPDIR}" ]]; then
if ! mkdir "${TMPDIR}"; then
echo "Error creating ${TMPDIR} exiting."
exit_abnormal
fi
fi
TEXFILES=()
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for TEX in "$@"
do
if [[ -d "${TEX}" ]]; then
if [[ "$OUTDIR" != $(cd "$TEX"; pwd) ]]; then
echo "${YELLOW}Skipping directory ${TEX}${RS}"
fi
continue
fi
if echo "${TEX}" | grep -q \.tex && [[ -f "${TEX}" ]]; then
echo "${YELLOW}Checking for bad characters in ${TEX%.*}.log${RS}."
BADCHRS=0
while read -r chr
do
BADCHRS=1
printf "*** '$chr' ***:\n"
grep -H "$chr" *.tex 2>/dev/null
grep -H "$chr" *.bib 2>/dev/null
grep -H "$chr" *.bbl 2>/dev/null
done< <(cat "${TEX%.*}.log" | egrep 'There is no . (.*?) in font' | cut -d '(' -f 1 | cut -d ' ' -f 6)
if [[ $BADCHRS == 1 ]]
then
exit_abnormal "${RED}Cannot continue parsing ${TEX}${RS}."
fi
echo "${YELLOW}Parsing ${TEX}${RS}."
TEXFILES+=("${TEX}")
echo "Checking deps for ${TEX}"
finddeps "${TEX}"
echo "Finding deps for ${TEX}"
finddeps "${TEX}" | xargs -n 1 -I % rsync -q --relative % "${TMPDIR}"
if [[ $STATUS != "OK" ]]
then
echo "${RED}${STATUS} for ${TEX}.${RS}"
fi
BIB=$(grep '\\bibliography' "${TEX}" | cut -d '{' -f 2 | sed 's+}+.bib+')
if [[ -f "$BIB" ]] ; then
echo "${POWDER_BLUE}Adding ${BIB}${RS}"
cp "${BIB}" "${TMPDIR}"
fi
elif [[ -f "${TEX}" ]]; then
cp "${TEX}" "${TMPDIR}"
fi
done
IFS=$SAVEIFS
if [[ ${#TEXFILES[@]} == 0 ]]; then
echo "${RED}No tex files to parse.${RS}"
exit 0
fi
if cd "${TMPDIR}"
then
flattentex # Fold all \include and \input statements
cataux # Cat any aux files required to render the tex file for portability
catclass # Cat the custom class file into the tex file for portability
#echo "${LIME_YELLOW}Removing comments from *.tex${RS}"
#printf '%s\0' *.tex | xargs -0 -n 1 sed -i.bak '/^%.*$/d'
flattendirs # Get rid of graphicspath and flatten directory structure
checktex # Make sure the cleaned tex files are OK
texok=$?
[[ $FORCE == 1 ]] && texok=0
# Get deps from concatenated tex file
for TEX in "${TEXFILES[@]}"; do
finddeps "${TEX}" | sed 's+\./++g' >> .tozip
done
# Cleanup files that were concatenated
while read -r todel; do
echo "${BLUE}Cleaning up $todel."
rm "$todel"
sed -i.bak "/${todel}/d" .tozip
done < <(cat .todel)
sed -i.bak '/.*\.out/d' .tozip
rm ./*.out ./*.bak .todel 2>/dev/null
if [[ $ZIP == 1 ]] && [[ $texok == 0 ]]; then
echo "${POWDER_BLUE}Compressing files to ${OUTDIR}/${BASENAME}.zip${RS}"
# .tozip has one file per line and sed quotes them already
# shellcheck disable=SC2046
zip -r9 "${OUTDIR}/${BASENAME}.zip" $(uniq .tozip | sed 's+\(.*?\)+"\1"+g') ./*.bib 2>/dev/null
fi
if [[ $BZ == 1 ]] && [[ $texok == 0 ]]; then
echo "${POWDER_BLUE}Compressing files to ${OUTDIR}/${BASENAME}.tar.bz2${RS}"
# .tozip has one file per line and sed quotes them already
# shellcheck disable=SC2046
tar -cjvf "${OUTDIR}/${BASENAME}.tar.bz2" $(uniq .tozip | sed 's+\(.*?\)+"\1"+g') ./*.bib
fi
rm .tozip 2>/dev/null
cd ..
rm -fr "${TMPDIR}"
else
echo "${RED}Error enterting temp dir ${TMPDIR}${RS}"
exit_abnormal
fi