generator.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. <?php
  2. global $options;
  3. global $preamble;
  4. $preamble = "";
  5. global $kpsefiles;
  6. $kpsefiles = [];
  7. global $existing_commands;
  8. global $included_usepackages;
  9. $included_usepackages = [];
  10. global $additional_usepackages;
  11. $additional_usepackages = [];
  12. $steps = 10;
  13. function user_consent($msg,$defaultyes = null,$defaultno = null)
  14. {
  15. global $options;
  16. if (isset($options["-n"]))
  17. return false;
  18. if ($defaultyes !== null && isset($options[$defaultyes]))
  19. return true;
  20. if ($defaultno !== null && isset($options[$defaultno]))
  21. return false;
  22. $response = false;
  23. do
  24. {
  25. echo "$msg (y/n)\n";
  26. $response = rtrim(fgets(STDIN));
  27. if ($response === "n" || $response == "N")
  28. return false;
  29. } while ($response !== "y" && $response !== "Y" && $response !== "");
  30. return true;
  31. }
  32. function user_prompt($msg,$default)
  33. {
  34. global $options;
  35. echo "$msg [Default: $default]\n";
  36. $response = "";
  37. if (!isset($options["-n"]))
  38. $response = rtrim(fgets(STDIN));
  39. if ($response == "")
  40. $response = $default;
  41. echo "You entered: '$response'\n";
  42. return $response;
  43. }
  44. function print_help()
  45. {
  46. $name = basename(__FILE__);
  47. echo<<<END
  48. Usage: php $name /path/folder1/main.tex /path/folder2/article.tex ... /path/folderN/paper.tex\n
  49. Generate a thesis template from the provided paper tex files and folders.
  50. The absolute minimum for a cumulative thesis is currently 3 papers first-authored and 6 in total.
  51. --force-overwrite overwrite files and folders
  52. --no-overwrite do not overwrite files and folders
  53. --no-compile-check do not perform a compile check
  54. --use-backups restore backups before making changes
  55. --not-sloppy disable use of sloppypar around places that struggle without
  56. (mainly the bibliographies)
  57. --cv add a CV
  58. (unusual for PhD theses, required for habilitation theses)
  59. --no-stat-declaration do not add the statutory declaration
  60. (required for PhD thesis, unusual for habilitation theses)
  61. -n skip all prompts (implies --no-overwrite)
  62. --help display this help and exit
  63. END;
  64. exit(0);
  65. }
  66. function error_exit($msg,$usage = false)
  67. {
  68. echo "ERROR: $msg\n";
  69. if ($usage)
  70. echo "Usage: php ".basename(__FILE__)." /path/folder1/main.tex /path/folder2/article.tex ... /path/folderN/paper.tex\n";
  71. exit(-1);
  72. }
  73. function check_software()
  74. {
  75. if (strpos(shell_exec("latexmk --version"),"Latexmk,") === false)
  76. error_exit("latexmk not installed");
  77. if (!str_starts_with(shell_exec("pdftotext --help 2>&1"),"pdftotext version"))
  78. error_exit("pdftotext not installed");
  79. }
  80. function rrmdir($dir) {
  81. if (is_dir($dir)) {
  82. $files = scandir($dir);
  83. foreach ($files as $file)
  84. if ($file != "." && $file != "..") rrmdir("$dir/$file");
  85. rmdir($dir);
  86. }
  87. else if (file_exists($dir)) unlink($dir);
  88. }
  89. function rcopy($src, $dst) {
  90. if (file_exists($dst)) rrmdir($dst);
  91. if (is_dir($src)) {
  92. mkdir($dst);
  93. $files = scandir($src);
  94. foreach ($files as $file)
  95. if ($file != "." && $file != "..") rcopy("$src/$file", "$dst/$file");
  96. }
  97. else if (file_exists($src)) copy($src, $dst);
  98. }
  99. function rscandir($dir,$extensions = []) {
  100. $result = [];
  101. if (!str_ends_with($dir,"/"))
  102. $dir .= "/";
  103. if (str_ends_with($dir,"latex.out/"))
  104. return $result;
  105. $array = scandir($dir);
  106. foreach ($array as $item) {
  107. if (!str_starts_with($item,"."))
  108. {
  109. if (!is_dir($dir.$item))
  110. {
  111. $extension_match = true;
  112. if ($extensions != [])
  113. {
  114. $extension_match = false;
  115. foreach ($extensions as $e)
  116. {
  117. if (str_ends_with($item,"$e"))
  118. {
  119. $extension_match = true;
  120. }
  121. }
  122. }
  123. if ($extension_match)
  124. $result[] = $dir.$item;
  125. }
  126. else
  127. $result = array_merge($result, rscandir($dir.$item,$extensions));
  128. }
  129. }
  130. return $result;
  131. }
  132. function unique_targets($targets)
  133. {
  134. $parts_required = 1;
  135. $unique_targets = [];
  136. while (count($unique_targets) != count($targets))
  137. {
  138. foreach ($targets as $t)
  139. {
  140. $tparts = explode("/",$t);
  141. $tpcount = count($tparts);
  142. $tparts = array_splice($tparts,$tpcount-$parts_required,$parts_required);
  143. $t = implode("_",$tparts);
  144. if (isset($unique_targets[$t]))
  145. {
  146. $parts_required++;
  147. $unique_targets = [];
  148. break;
  149. }
  150. $unique_targets[$t] = 1;
  151. }
  152. }
  153. return array_keys($unique_targets);
  154. }
  155. function check_folders($argv)
  156. {
  157. $args = array_slice($argv,1);
  158. $sourcedirs = [];
  159. foreach ($args as $a)
  160. {
  161. if (!str_starts_with($a,"-"))
  162. $sourcedirs[] = $a;
  163. }
  164. if (count($sourcedirs) < 1)
  165. {
  166. error_exit("Too few papers. Need at least one paper to run this.",true);
  167. }
  168. if (count($sourcedirs) < 3)
  169. {
  170. echo "Warning: Too few papers. The statutes require as an absolute minimum for a cumulative thesis at least 3 first-author papers and at least 6 in total.";
  171. }
  172. if (count($sourcedirs) < 5)
  173. {
  174. echo "Warning: Few papers. Check your institute guidelines to see how many papers are recommended. Also the statutes require as an absolute minimum for a cumulative thesis at least 6 papers in total.";
  175. }
  176. $texfiles = [];
  177. for ($i = 0; $i < count($sourcedirs); $i++)
  178. {
  179. $texfiles[$i] = basename($sourcedirs[$i]);
  180. $sourcedirs[$i] = dirname($sourcedirs[$i]);
  181. }
  182. $targets = unique_targets($sourcedirs);
  183. return [$targets,$texfiles,$sourcedirs];
  184. }
  185. function check_and_copy_folders($argv)
  186. {
  187. [$targets,$texfiles,$sourcedirs] = check_folders($argv);
  188. //echo "Source -> Target Directory Mapping:\n";
  189. $n = count($sourcedirs);
  190. //print_r($mapping);
  191. for ($i = 0; $i < $n; $i++)
  192. {
  193. $s = $sourcedirs[$i];
  194. $t = $targets[$i];
  195. $f = $texfiles[$i];
  196. if (str_ends_with($f,".pdf"))
  197. {
  198. if (!file_exists("$s/$f"))
  199. error_exit("$s/$f not found");
  200. if (file_exists("$t/$f.pdf") && !user_consent("$t/$f.pdf already exists... overwrite?","--force-overwrite","--no-overwrite"))
  201. {
  202. echo "Skipping $s/$f, $t/$f.pdf already exists...\n";
  203. }
  204. else
  205. {
  206. echo "Copying $s/$f to $t/$f...\n";
  207. if (!file_exists($t)) mkdir($t);
  208. rcopy("$s/$f","$t/$f");
  209. }
  210. }
  211. else
  212. {
  213. if (!file_exists($s))
  214. error_exit("$s not found");
  215. if (file_exists($t) && !user_consent("$t already exists... overwrite?","--force-overwrite","--no-overwrite"))
  216. {
  217. echo "Skipping ".$s.", ".$t." already exists...\n";
  218. }
  219. else
  220. {
  221. echo "Copying ".$s." to ".$t."...\n";
  222. rcopy($s,$t);
  223. }
  224. }
  225. }
  226. return array_combine($targets,$texfiles);
  227. }
  228. function file_get_and_backup($f,$bak = ".orig_bak")
  229. {
  230. global $options;
  231. if (isset($options["--use-backups"]))
  232. {
  233. if (file_exists("$f$bak"))
  234. copy("$f$bak", $f);
  235. }
  236. $content = file_get_contents("$f");
  237. if (!file_exists("$f$bak"))
  238. file_put_contents("$f$bak",$content);
  239. return $content;
  240. }
  241. function adjust_references($papers,$extensions = [])
  242. {
  243. $bibresources = [];
  244. foreach ($papers as $d => $f)
  245. {
  246. if (str_ends_with($f,".pdf"))
  247. continue;
  248. $files = rscandir($d,$extensions);
  249. foreach ($files as $file)
  250. {
  251. if (str_ends_with($file,".bib"))
  252. {
  253. $bib = file_get_and_backup($file);
  254. $bib = preg_replace("/(^\s*@\s*[a-z]+\s*\{\s*)((?!$d)\S)/i",'${1}'.$d.':${2}',$bib);
  255. $bib = preg_replace("/(\n\s*@\s*[a-z]+\s*\{\s*)((?!$d)\S)/i",'${1}'.$d.':${2}',$bib);
  256. $bib = preg_replace("/([\{\"].*)[^\\\\]#(.*)/i",'${1}\#${2}',$bib);
  257. file_put_contents($file,$bib);
  258. $bibresources[$d] = $file;
  259. }
  260. else
  261. {
  262. $tex = file_get_and_backup($file);
  263. // labels of lstlistings etc
  264. $tex = preg_replace("/([\[,]\s*label\s*=\s*)((?!$d)[^\[,]+[\[,])/i",'${1}'.$d.':${2}',$tex);
  265. // normal labels
  266. $tex = preg_replace("/(\\\label\s*\{\s*)((?!$d)[^}]+\})/i",'${1}'.$d.':${2}',$tex);
  267. // cref ref autoref
  268. $refs = [];
  269. preg_match_all("/\\\(cref|ref|autoref)\s*\{\s*[^}]+\}/i",$tex,$refs);
  270. foreach ($refs[0] as $ref)
  271. {
  272. $oldref = $ref;
  273. $ref = preg_replace("/([{,])\s*((?!$d)[^,}]+[},])/i",'${1}'.$d.':${2}',$ref);
  274. $ref = preg_replace("/([{,])\s*((?!$d)[^,}]+[},])/i",'${1}'.$d.':${2}',$ref);
  275. $tex = str_replace($oldref,$ref,$tex);
  276. }
  277. // cite citeA citeauthor etc
  278. $cites = [];
  279. preg_match_all("/\\\([a-z]*cite[a-z]*)\s*\{\s*[^}]+\}/i",$tex,$cites);
  280. foreach ($cites[0] as $cite)
  281. {
  282. $oldcite = $cite;
  283. $cite = preg_replace("/([{,])\s*((?!$d)[^,}]+[},])/i",'${1}'.$d.':${2}',$cite);
  284. $cite = preg_replace("/([{,])\s*((?!$d)[^,}]+[},])/i",'${1}'.$d.':${2}',$cite);
  285. $tex = str_replace($oldcite,$cite,$tex);
  286. }
  287. file_put_contents($file,$tex);
  288. }
  289. }
  290. }
  291. return $bibresources;
  292. }
  293. function handle_appendix($tex)
  294. {
  295. $appendix = false;
  296. $lines = explode("\n",$tex);
  297. for ($i = 0; $i < count($lines); $i++)
  298. {
  299. if ($appendix)
  300. {
  301. $lines[$i] = str_replace(['\subsubsection','\subsection','\section'],['\paragraph','\subsubsection','\subsection'],$lines[$i]);
  302. }
  303. if (str_starts_with($lines[$i],'\appendices') || str_starts_with($lines[$i],'\appendix'))
  304. {
  305. $lines[$i] = '\section*{Appendix}';
  306. $appendix = true;
  307. }
  308. }
  309. $tex = implode("\n",$lines);
  310. return $tex;
  311. }
  312. function stripformatting($tex)
  313. {
  314. return str_ireplace(['\Large ','\bf ','\rm ','\\\\'],[' ',' ',' ',' '],$tex);
  315. }
  316. function getusepackages($tex)
  317. {
  318. $packages = [];
  319. preg_match_all("/\n\s*(\\\\usepackage([^{}]*)(?<R>{((?:[^{}]+|(?&R))*)}))/i",$tex,$packages);
  320. if (isset($packages[1]))
  321. {
  322. return [$packages[1],$packages[4]];
  323. }
  324. return [[],[]];
  325. }
  326. function getmathops($tex)
  327. {
  328. $mathops = [];
  329. preg_match_all("/\n\s*(\\\\DeclareMath(Operator|Alphabet)\\*?((?<R>{((?:[^{}]+|(?&R))*)})([^{}]*)|\\\\[^\{]*)(?<P>{((?:[^{}]+|(?&P))*)})(?<Q>{((?:[^{}]+|(?&Q))*)})?(?<S>{((?:[^{}]+|(?&S))*)})?(?<T>{((?:[^{}]+|(?&T))*)})?)/i",$tex,$mathops);
  330. if (isset($mathops[4]))
  331. return [$mathops[1],$mathops[3]];
  332. return [];
  333. }
  334. function getnewcommands($tex)
  335. {
  336. $newcommands = [];
  337. preg_match_all("/\n\s*(\\\\newcommand([^{}]*)(?<R>{((?:[^{}]+|(?&R))*)})([^{}]*)(?<P>{((?:[^{}]+|(?&P))*)}))/i",$tex,$newcommands);
  338. if (isset($newcommands[4]))
  339. return $newcommands[4];
  340. return [];
  341. }
  342. function adjust_papers($papers,$extensions = [])
  343. {
  344. $tex = "";
  345. $paper_fulltitle = "";
  346. $authors = "";
  347. $institute = "";
  348. foreach ($papers as $d => $f)
  349. {
  350. if (str_ends_with($f,".pdf"))
  351. {
  352. $paper_fulltitle = trim(user_prompt("Please enter the full title for the paper in folder '$d'","TODO"));
  353. $paper_shorttitle = trim(user_prompt("Please enter a short title for the paper in folder '$d'","TODO"));
  354. $authors = trim(user_prompt("Please enter the author list for paper '$d'","TODO"));
  355. $header=<<<END
  356. \chapter[$paper_shorttitle]{{$paper_fulltitle}}\label{chapter:$d}
  357. \section*{Publication Data}
  358. \\fullcite{TODO}
  359. \section*{Contributions}
  360. TODO
  361. \includepdf[pages=-]{{$d}/{$f}}
  362. END;
  363. file_put_contents("$d/main.tex",$header);
  364. }
  365. $files = rscandir($d,$extensions);
  366. $authors = "";
  367. $institute = "";
  368. $title = "";
  369. $paper_fulltitle = "";
  370. $paper_shorttitle = "";
  371. foreach ($files as $file)
  372. {
  373. if (!str_ends_with($file,".tex") && !str_ends_with($file,".tikz") && !str_ends_with($file,".sty"))
  374. continue;
  375. $tex = file_get_and_backup($file,".interm_bak");
  376. if ($authors == "" && preg_match("/\n\s*\\\\author/i",$tex) == 1)
  377. {
  378. preg_match_all("/\n\s*\\\\author\s*(?<R>{((?:[^{}]+|(?&R))*)})/i",$tex,$authors);
  379. if (isset($authors[2]) && isset($authors[2][0]))
  380. $authors = trim(stripformatting($authors[2][0]));
  381. }
  382. if ($institute == "" && preg_match("/\n\s*\\\\institute/i",$tex) == 1)
  383. {
  384. preg_match_all("/\n\s*\\\\institute\s*(?<R>{((?:[^{}]+|(?&R))*)})/i",$tex,$institute);
  385. if (isset($institute[2]) && isset($institute[2][0]))
  386. $institute = trim(stripformatting($institute[2][0]));
  387. }
  388. if ($paper_fulltitle == "" && preg_match("/\n\s*\\\\title/i",$tex) == 1)
  389. {
  390. preg_match_all("/\n\s*\\\\title\s*(?<R>{((?:[^{}]+|(?&R))*)})/i",$tex,$title);
  391. if (isset($title[2]) && isset($title[2][0]))
  392. $title = trim(stripformatting($title[2][0]));
  393. else
  394. $title = $d;
  395. $shorttitle = $title;
  396. if (strpos($title,":") !== false)
  397. $shorttitle = trim(explode(":",$title)[0]);
  398. $paper_fulltitle = trim(user_prompt("Please enter the full title for the paper in folder '$d'","$title"));
  399. $paper_shorttitle = trim(user_prompt("Please enter a short title for the paper in folder '$d'","$shorttitle"));
  400. }
  401. $header = "";
  402. if ($paper_fulltitle != "" && $authors != "")
  403. {
  404. $header=<<<END
  405. \chapter[$paper_shorttitle]{$paper_fulltitle}\label{chapter:$d}
  406. \section*{Publication Data}
  407. \\fullcite{TODO}
  408. \section*{Contributions}
  409. TODO
  410. \\newpage
  411. \begin{center}
  412. {\Large \\textbf{
  413. $paper_fulltitle%
  414. }}\\\\\
  415. \\vspace{0.6cm}
  416. {\large $authors%
  417. } % TODO: check author list
  418. {\large $institute%
  419. } % TODO: check author list
  420. \\end{center}
  421. END;
  422. }
  423. [$mathopsfull,$mathops] = getmathops($tex);
  424. global $existing_mathops;
  425. global $preamble;
  426. $addmathops = array_diff($mathops,$existing_mathops);
  427. foreach ($addmathops as $k => $v)
  428. {
  429. $preamble .= $mathopsfull[$k] . "\n";
  430. $existing_mathops[] = $v;
  431. }
  432. $tex = preg_replace("/\\\documentclass.*\\n/i","
  433. ",$tex);
  434. $tex = preg_replace("/\\\begin{document}/i",$header,$tex);
  435. $tex = preg_replace("/\\\begin{abstract}/i",'\section*{Abstract}',$tex);
  436. $tex = preg_replace("/\\\\newcommand/i",'\providecommand',$tex);
  437. $tex = preg_replace("/\\\\renewcommand/i",'\providecommand',$tex);
  438. $tex = preg_replace("/\\\\end{abstract}/i",'',$tex);
  439. $tex = preg_replace("/\\\\DeclareMathOperator/i",'%$0',$tex);
  440. $tex = preg_replace("/\\\\DeclareMathAlphabet/i",'%$0',$tex);
  441. $tex = preg_replace("/\\\\usepackage[cache=false]{minted}/i",'\usepackage{minted}',$tex);
  442. $tex = preg_replace("/\\\\thispagestyle{empty}/i",'',$tex);
  443. $tex = preg_replace("/\\\\PassOptionsToPackage\s*(?<R>{((?:[^{}]+|(?&R))*)})(?<Q>{((?:[^{}]+|(?&Q))*)})/i",'',$tex);
  444. $tex = preg_replace("/(\\\\csvautobooktabular\s*([^{}]*)\s*)(?<R>{((?:[^{}]+|(?&R))*)})/i","\\1{{$d}/\\4}",$tex);
  445. $tex = preg_replace("/\\\\bibliographystyle\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  446. $tex = preg_replace("/\\\\usetikzlibrary\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  447. $tex = preg_replace("/\\\\DeclareFloatFont\s*(?<R>{((?:[^{}]+|(?&R))*)})(?<Q>{((?:[^{}]+|(?&Q))*)})/i","",$tex);
  448. $tex = preg_replace("/\\\\captionsetup\s*(?<R>\[((?:[^\[\]]+|(?&R))*)\])?(?<Q>{((?:[^{}]+|(?&Q))*)})/i","",$tex);
  449. $tex = preg_replace("/\\\\tikzexternalize\s*(?<R>\[((?:[^\[\]]+|(?&R))*)\])/i","",$tex);
  450. $tex = preg_replace("/\\\\floatsetup\s*(?<R>\[((?:[^\[\]]+|(?&R))*)\])(?<Q>{((?:[^{}]+|(?&Q))*)})/i","",$tex);
  451. $tex = preg_replace("/\s*\\\\bibliography\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  452. $tex = preg_replace("/\\\\end{document}/i",'',$tex);
  453. $tex = preg_replace("/\n\s*\\\\author\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  454. $tex = preg_replace("/\n\s*\\\\authorrunning\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  455. $tex = preg_replace("/\n\s*\\\\institute\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  456. $tex = preg_replace("/\n\s*\\\\title\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  457. $tex = preg_replace("/\n\s*\\\\date\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  458. $tex = preg_replace("/\\\\includegraphics\s*(?<R>\[((?:[^\[\]]+|(?&R))*)\])(?<Q>{((?:[^{}]+|(?&Q))*)})/i",'\includegraphics${1}{'.$d.'/${4}}',$tex);
  459. $tex = preg_replace("/\n\s*\\\\maketitle/i","",$tex);
  460. $tex = preg_replace("/\\\\IEEEoverridecommandlockouts/i","",$tex);
  461. $tex = preg_replace("/\n\s*\\\\tikzexternalize/i","",$tex);
  462. [$ups,$ps] = getusepackages($tex);
  463. global $included_usepackages;
  464. global $additional_usepackages;
  465. foreach (array_diff($ps,$included_usepackages) as $k => $v) {
  466. if (in_array($v,['minted']))
  467. {
  468. $additional_usepackages[] = "\usepackage{minted}";
  469. $included_usepackages[] = $v;
  470. }
  471. else if (!in_array($v,['usenix','usenix,epsfig,endnotes','usenixbadges','cite','csvenhanced']) && !($v == 'floatrow' && in_array('float',$included_usepackages)))
  472. {
  473. $additional_usepackages[] = $ups[$k];
  474. $included_usepackages[] = $v;
  475. }
  476. }
  477. array_unique($additional_usepackages);
  478. $tex = preg_replace("/\n\s*\\\\usepackage([^{}]*)(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  479. $tex = preg_replace("/^\s*\\\\usepackage([^{}]*)(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  480. $newcommands = getnewcommands($tex);
  481. global $existing_commands;
  482. $rmcommands = array_intersect($newcommands,$existing_commands);
  483. foreach ($rmcommands as $rmc)
  484. {
  485. $tex = preg_replace("/\n\s*\\\\newcommand([^{}]*)({\s*\\".$rmc."\s*}.*\n)/i","\n",$tex);
  486. }
  487. $matches = [];
  488. $tex = preg_replace("/\n\s*\\\\pgfplotsset\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
  489. $tex = preg_replace("/\n\s*\\\\setlength{\s*\\\marginparwidth.*\n/i","\n",$tex);
  490. if (stripos($tex,"\appendices") !== false || stripos($tex,"\appendix") !== false)
  491. $tex = handle_appendix($tex);
  492. file_put_contents($file,$tex);
  493. }
  494. }
  495. return;
  496. }
  497. function check_options($argv)
  498. {
  499. $options = [];
  500. foreach ($argv as $a)
  501. {
  502. if (str_starts_with($a,"-"))
  503. $options[$a] = 1;
  504. if ($a == "-n")
  505. $options["--no-overwrite"] = 1;
  506. }
  507. return $options;
  508. }
  509. function compile_check($papers,$precopy = false)
  510. {
  511. //array_shift($papers); weird...
  512. if ($precopy)
  513. $papers = array_combine($papers,$papers);
  514. foreach ($papers as $p => $f)
  515. {
  516. if (str_ends_with($f,".pdf"))
  517. {
  518. echo "======= Skipping PDF: $f =======\n";
  519. continue;
  520. }
  521. echo "======= Paper $p -> $f START =======\n";
  522. if ($precopy)
  523. {
  524. echo "$p\n";
  525. if (strpos($p,"/") === false || str_starts_with($p,".") || !is_dir(dirname($p)))
  526. continue;
  527. $f = basename($p);
  528. $p = dirname($p);
  529. }
  530. else
  531. {
  532. shell_exec("cd $p; latexmk -c 2>/dev/null; latexmk -C 2>/dev/null; rm -f *.bbl");
  533. }
  534. $str = shell_exec("cd $p; latexmk -latexoption=\"-shell-escape\" -g -pdf $f 2>&1");
  535. $lines = explode("\n",$str);
  536. $skip = true;
  537. $failed = false;
  538. foreach($lines as $l)
  539. {
  540. if (str_starts_with($l,"Latexmk: ====List of undefined refs and citations:"))
  541. $skip = false;
  542. if ($skip)
  543. continue;
  544. if (stripos($l,"fail") !== false)
  545. $failed = true;
  546. echo "$l\n";
  547. }
  548. if ($failed || user_consent("Please check the PDF file. Are there any problems with invalid references to figures, tables or with the bibliography?","--","--no-overwrite"))
  549. error_exit("The paper did not compile properly, please fix the errors next before continuing.");
  550. echo "======= Paper $p -> $f END =======\n";
  551. }
  552. }
  553. function init_kpse()
  554. {
  555. global $kpsefiles;
  556. $kpsepath = shell_exec("kpsepath tex");
  557. $kpsepath = explode(":",$kpsepath);
  558. foreach ($kpsepath as $k)
  559. {
  560. $k = str_replace(["!!","\n","///","//"],["","","/","/"],$k);
  561. if (str_starts_with($k,"."))
  562. continue;
  563. $found = null;
  564. if (is_dir($k))
  565. $found = rscandir($k,[".sty"]);
  566. if ($found != null)
  567. {
  568. for ($i = 0; $i < count($found); $i++)
  569. $found[$i] = basename($found[$i]);
  570. $kpsefiles = array_unique(array_merge($kpsefiles,$found));
  571. }
  572. }
  573. sort($kpsefiles);
  574. }
  575. check_software();
  576. $options = check_options($argv);
  577. if (isset($options["--help"]))
  578. print_help();
  579. echo "\n=== Step 1/$steps: Check Folders ===\n\n";
  580. [$targets,$texfiles,$sourcedirs] = check_folders($argv);
  581. echo "\n=== Step 2/$steps: Pre-Copy Compile Check ===\n\n";
  582. $targets_exist = true;
  583. foreach ($targets as $t)
  584. if (!is_dir($t))
  585. $targets_exist = false;
  586. if (isset($options["--no-compile-check"]) || $targets_exist)
  587. echo "Skipping...\n";
  588. else
  589. compile_check($argv,true);
  590. echo "\n=== Step 3/$steps: Copying Files ===\n\n";
  591. $papers = check_and_copy_folders($argv);
  592. echo "\n=== Step 4/$steps: Adjusting References (in *.bib *.tex *.tikz) ===\n\n";
  593. $bibresources = adjust_references($papers,[".bib",".tex",".tikz"]);
  594. echo "\n=== Step 5/$steps: Compile Check ===\n\n";
  595. if (isset($options["--no-compile-check"]))
  596. echo "Skipping...\n";
  597. else
  598. compile_check($papers);
  599. [$_t,$usepackages1] = getusepackages(file_get_contents("main.tex.php"));
  600. [$_t,$usepackages2] = getusepackages(file_get_contents("tugraz_defaults.sty"));
  601. global $included_usepackages;
  602. $included_usepackages = array_unique(array_merge($usepackages1, $usepackages2));
  603. sort($included_usepackages);
  604. $cmds1 = getnewcommands(file_get_contents("main.tex.php"));
  605. $cmds2 = getnewcommands(file_get_contents("tugraz_defaults.sty"));
  606. global $existing_commands;
  607. $existing_commands = array_unique(array_merge($cmds1, $cmds2));
  608. [$del,$mathops1] = getmathops(file_get_contents("main.tex.php"));
  609. [$del,$mathops2] = getmathops(file_get_contents("tugraz_defaults.sty"));
  610. global $existing_mathops;
  611. $existing_mathops = array_unique(array_merge($mathops1, $mathops2));
  612. echo "\n=== Step 5/$steps: Adjusting Papers (checking *.tex and *.tikz files) ===\n\n";
  613. adjust_papers($papers,[".tex",".tikz",".sty"]);
  614. init_kpse();
  615. foreach ($papers as $k => $v)
  616. {
  617. if (str_ends_with($papers[$k],".pdf"))
  618. $papers[$k] = 'main.tex';
  619. else
  620. {
  621. $stys = rscandir($k,[".sty"]);
  622. foreach ($stys as $styf)
  623. {
  624. $styfb = basename($styf);
  625. if (in_array($styfb,$kpsefiles) === false && !file_exists("./$styfb"))
  626. {
  627. echo "Copying $styf to ./$styfb...\n";
  628. copy($styf,"./$styfb");
  629. }
  630. }
  631. }
  632. }
  633. echo "\n=== Step 6/$steps: Generate main.tex ===\n\n";
  634. $thesis_type = user_prompt("Enter Thesis Type ","PhD Thesis");
  635. $thesis_title = user_prompt("Enter Thesis Title ","Security of TODO");
  636. $thesis_part1_title = user_prompt("Enter Introductory Part Title ","Introduction to the Security of TODO");
  637. $thesis_author = user_prompt("Enter Your Name ","Harry Potter");
  638. $thesis_date = user_prompt("Enter Prospective Defense Month", "July 1998");
  639. $thesis_institute = user_prompt("Enter Your Institute","Institute for Applied Information Processing and Communications");
  640. $thesis_assessors = user_prompt("Enter Names of your Assessors (comma-separated)","Severus Snape, Minerva McGonagall");
  641. $num_publications_in_thesis = count($papers);
  642. $num_publications = user_prompt("How many publications did you co-author during your PhD? (6 is the absolute minimum for a cumulative thesis)","6");
  643. $sloppy_begin = "";
  644. $sloppy_end = "";
  645. if (!isset($options["--no-sloppy"]))
  646. {
  647. $sloppy_begin = '\begin{sloppypar}';
  648. $sloppy_end = '\end{sloppypar}';
  649. }
  650. ob_start();
  651. require "main.tex.php";
  652. $maintex_content = ob_get_contents();
  653. ob_end_clean();
  654. if (!file_exists("main.tex") || user_consent("main.tex already exists. overwrite?"))
  655. file_put_contents("main.tex",$maintex_content);
  656. if (!file_exists("mypreamble.sty") || user_consent("mypreamble.sty already exists... overwrite?","--force-overwrite","--no-overwrite"))
  657. file_put_contents("mypreamble.sty","\ProvidesPackage{mypreamble}\n\n".implode("\n",$additional_usepackages)."\n\n".$preamble);
  658. @mkdir("tikz");
  659. if (!file_exists("abstract.tex"))
  660. file_put_contents("abstract.tex","");
  661. if (!file_exists("intro.tex"))
  662. file_put_contents("intro.tex","");
  663. if (!file_exists("main.bib"))
  664. file_put_contents("main.bib","");
  665. if (isset($options["--cv"]))
  666. {
  667. if (!file_exists("cv.bib"))
  668. file_put_contents("cv.bib","");
  669. if (!file_exists("cv.tex"))
  670. file_put_contents("cv.tex","This is my CV! Thanks for checking it out!");
  671. }
  672. echo "=== done ===\nNext step, run this command:\nlatexmk -latexoption=\"-shell-escape\" -g -pdf main.tex\n";
  673. ?>