| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- <?php
- global $options;
- global $preamble;
- $preamble = "";
- global $existing_commands;
- global $included_usepackages;
- $included_usepackages = [];
- global $additional_usepackages;
- $additional_usepackages = [];
- $steps = 10;
- function user_consent($msg,$defaultyes = null,$defaultno = null)
- {
- global $options;
- if (isset($options["-n"]))
- return false;
- if ($defaultyes !== null && isset($options[$defaultyes]))
- return true;
- if ($defaultno !== null && isset($options[$defaultno]))
- return false;
- $response = false;
- do
- {
- echo "$msg (y/n)\n";
- $response = rtrim(fgets(STDIN));
- if ($response === "n" || $response == "N")
- return false;
- } while ($response !== "y" && $response !== "Y" && $response !== "");
- return true;
- }
- function user_prompt($msg,$default)
- {
- global $options;
- echo "$msg [Default: $default]\n";
- $response = "";
- if (!isset($options["-n"]))
- $response = rtrim(fgets(STDIN));
- if ($response == "")
- $response = $default;
- echo "You entered: '$response'\n";
- return $response;
- }
- function print_help()
- {
- $name = basename(__FILE__);
- echo<<<END
- Usage: php $name /path/folder1/main.tex /path/folder2/article.tex ... /path/folderN/paper.tex\n
- Generate a thesis template from the provided paper tex files and folders.
- The absolute minimum for a cumulative thesis is currently 3 papers first-authored and 6 in total.
- --force-overwrite overwrite files and folders
- --no-overwrite do not overwrite files and folders
- --no-compile-check do not perform a compile check
- --use-backups restore backups before making changes
- --not-sloppy disable use of sloppypar around places that struggle without
- (mainly the bibliographies)
- --cv add a CV
- (unusual for PhD theses, required for habilitation theses)
- --no-stat-declaration do not add the statutory declaration
- (required for PhD thesis, unusual for habilitation theses)
- -n skip all prompts (implies --no-overwrite)
- --help display this help and exit
- END;
- exit(0);
- }
- function error_exit($msg,$usage = false)
- {
- echo "ERROR: $msg\n";
- if ($usage)
- echo "Usage: php ".basename(__FILE__)." /path/folder1/main.tex /path/folder2/article.tex ... /path/folderN/paper.tex\n";
- exit(-1);
- }
- function check_software()
- {
- if (!str_starts_with(shell_exec("latexmk --version"),"Latexmk,"))
- error_exit("latexmk not installed");
- if (!str_starts_with(shell_exec("pdftotext --help 2>&1"),"pdftotext version"))
- error_exit("pdftotext not installed");
- }
- function rrmdir($dir) {
- if (is_dir($dir)) {
- $files = scandir($dir);
- foreach ($files as $file)
- if ($file != "." && $file != "..") rrmdir("$dir/$file");
- rmdir($dir);
- }
- else if (file_exists($dir)) unlink($dir);
- }
- function rcopy($src, $dst) {
- if (file_exists($dst)) rrmdir($dst);
- if (is_dir($src)) {
- mkdir($dst);
- $files = scandir($src);
- foreach ($files as $file)
- if ($file != "." && $file != "..") rcopy("$src/$file", "$dst/$file");
- }
- else if (file_exists($src)) copy($src, $dst);
- }
- function rscandir($dir,$extensions = []) {
- $result = [];
- if (!str_ends_with($dir,"/"))
- $dir .= "/";
- if (str_ends_with($dir,"latex.out/"))
- return $result;
- $array = scandir($dir);
- foreach ($array as $item) {
- if (!str_starts_with($item,"."))
- {
- if (!is_dir($dir.$item))
- {
- $extension_match = true;
- if ($extensions != [])
- {
- $extension_match = false;
- foreach ($extensions as $e)
- {
- if (str_ends_with($item,"$e"))
- {
- $extension_match = true;
- }
- }
- }
- if ($extension_match)
- $result[] = $dir.$item;
- }
- else
- $result = array_merge($result, rscandir($dir.$item,$extensions));
- }
- }
- return $result;
- }
- function unique_targets($targets)
- {
- $parts_required = 1;
- $unique_targets = [];
- while (count($unique_targets) != count($targets))
- {
- foreach ($targets as $t)
- {
- $tparts = explode("/",$t);
- $tpcount = count($tparts);
- $tparts = array_splice($tparts,$tpcount-$parts_required,$parts_required);
- $t = implode("_",$tparts);
- if (isset($unique_targets[$t]))
- {
- $parts_required++;
- $unique_targets = [];
- break;
- }
- $unique_targets[$t] = 1;
- }
- }
- return array_keys($unique_targets);
- }
- function check_folders($argv)
- {
- $args = array_slice($argv,1);
- $sourcedirs = [];
- foreach ($args as $a)
- {
- if (!str_starts_with($a,"-"))
- $sourcedirs[] = $a;
- }
- if (count($sourcedirs) < 1)
- {
- error_exit("Too few papers. Need at least one paper to run this.",true);
- }
- if (count($sourcedirs) < 3)
- {
- 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.";
- }
- if (count($sourcedirs) < 5)
- {
- 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.";
- }
- $texfiles = [];
- for ($i = 0; $i < count($sourcedirs); $i++)
- {
- $texfiles[$i] = basename($sourcedirs[$i]);
- $sourcedirs[$i] = dirname($sourcedirs[$i]);
- }
- $targets = unique_targets($sourcedirs);
- return [$targets,$texfiles,$sourcedirs];
- }
- function check_and_copy_folders($argv)
- {
- [$targets,$texfiles,$sourcedirs] = check_folders($argv);
- //echo "Source -> Target Directory Mapping:\n";
- $mapping = array_combine($sourcedirs,$targets);
- //print_r($mapping);
- foreach ($mapping as $s => $t)
- {
- if (!file_exists($s))
- error_exit("$s not found");
- if (file_exists($t) && !user_consent("$t already exists... overwrite?","--force-overwrite","--no-overwrite"))
- {
- echo "Skipping ".$s.", ".$t." already exists...\n";
- }
- else
- {
- echo "Copying ".$s." to ".$t."...\n";
- rcopy($s,$t);
- }
- }
- return array_combine($targets,$texfiles);
- }
- function file_get_and_backup($f,$bak = ".orig_bak")
- {
- global $options;
- if (isset($options["--use-backups"]))
- {
- if (file_exists("$f$bak"))
- copy("$f$bak", $f);
- }
- $content = file_get_contents("$f");
- if (!file_exists("$f$bak"))
- file_put_contents("$f$bak",$content);
- return $content;
- }
- function adjust_references($papers,$extensions = [])
- {
- $bibresources = [];
- foreach ($papers as $d => $f)
- {
- $files = rscandir($d,$extensions);
- foreach ($files as $file)
- {
- if (str_ends_with($file,".bib"))
- {
- $bib = file_get_and_backup($file);
- $bib = preg_replace("/(^\s*@\s*[a-z]+\s*\{\s*)((?!$d)\S)/i",'${1}'.$d.':${2}',$bib);
- $bib = preg_replace("/(\n\s*@\s*[a-z]+\s*\{\s*)((?!$d)\S)/i",'${1}'.$d.':${2}',$bib);
- file_put_contents($file,$bib);
- $bibresources[$d] = $file;
- }
- else
- {
- $tex = file_get_and_backup($file);
- // labels of lstlistings etc
- $tex = preg_replace("/([\[,]\s*label\s*=\s*)((?!$d)[^\[,]+[\[,])/i",'${1}'.$d.':${2}',$tex);
- // normal labels
- $tex = preg_replace("/(\\\label\s*\{\s*)((?!$d)[^}]+\})/i",'${1}'.$d.':${2}',$tex);
- // cref ref autoref
- $refs = [];
- preg_match_all("/\\\(cref|ref|autoref)\s*\{\s*[^}]+\}/i",$tex,$refs);
- foreach ($refs[0] as $ref)
- {
- $oldref = $ref;
- $ref = preg_replace("/([{,])\s*((?!$d)[^,}]+[},])/i",'${1}'.$d.':${2}',$ref);
- $ref = preg_replace("/([{,])\s*((?!$d)[^,}]+[},])/i",'${1}'.$d.':${2}',$ref);
- $tex = str_replace($oldref,$ref,$tex);
- }
- // cite citeA citeauthor etc
- $cites = [];
- preg_match_all("/\\\([a-z]*cite[a-z]*)\s*\{\s*[^}]+\}/i",$tex,$cites);
- foreach ($cites[0] as $cite)
- {
- $oldcite = $cite;
- $cite = preg_replace("/([{,])\s*((?!$d)[^,}]+[},])/i",'${1}'.$d.':${2}',$cite);
- $cite = preg_replace("/([{,])\s*((?!$d)[^,}]+[},])/i",'${1}'.$d.':${2}',$cite);
- $tex = str_replace($oldcite,$cite,$tex);
- }
- file_put_contents($file,$tex);
- }
- }
- }
- return $bibresources;
- }
- function stripformatting($tex)
- {
- return str_ireplace(['\Large ','\bf ','\rm ','\\\\'],[' ',' ',' ',' '],$tex);
- }
- function getusepackages($tex)
- {
- $packages = [];
- preg_match_all("/\n\s*(\\\\usepackage([^{}]*)(?<R>{((?:[^{}]+|(?&R))*)}))/i",$tex,$packages);
- if (isset($packages[1]))
- {
- return [$packages[1],$packages[4]];
- }
- return [[],[]];
- }
- function getmathops($tex)
- {
- $mathops = [];
- preg_match_all("/\n\s*(\\\\DeclareMathOperator([^{}]*)(?<R>{((?:[^{}]+|(?&R))*)})([^{}]*)(?<P>{((?:[^{}]+|(?&P))*)}))/i",$tex,$mathops);
- if (isset($mathops[4]))
- return [$mathops[1],$mathops[4]];
- return [];
- }
- function getnewcommands($tex)
- {
- $newcommands = [];
- preg_match_all("/\n\s*(\\\\newcommand([^{}]*)(?<R>{((?:[^{}]+|(?&R))*)})([^{}]*)(?<P>{((?:[^{}]+|(?&P))*)}))/i",$tex,$newcommands);
- if (isset($newcommands[4]))
- return $newcommands[4];
- return [];
- }
- function adjust_papers($papers,$extensions = [])
- {
- foreach ($papers as $d => $f)
- {
- $paper_fulltitle = "";
- $authors = "";
- $files = rscandir($d,$extensions);
- foreach ($files as $file)
- {
- if (!str_ends_with($file,"main.tex"))
- continue;
- $tex = file_get_and_backup($file,".interm_bak");
- if ($authors == "" && preg_match("/\n\s*\\\\author/i",$tex) == 1)
- {
- $authors = [];
- preg_match_all("/\n\s*\\\\author\s*(?<R>{((?:[^{}]+|(?&R))*)})/i",$tex,$authors);
- if (isset($authors[2]) && isset($authors[2][0]))
- $authors = trim(stripformatting($authors[2][0]));
- }
- if ($paper_fulltitle == "" && preg_match("/\n\s*\\\\title/i",$tex) == 1)
- {
- $title = [];
- preg_match_all("/\n\s*\\\\title\s*(?<R>{((?:[^{}]+|(?&R))*)})/i",$tex,$title);
- if (isset($title[2]) && isset($title[2][0]))
- $title = trim(stripformatting($title[2][0]));
- else
- $title = $d;
-
- $shorttitle = $title;
- if (strpos($title,":") !== false)
- $shorttitle = trim(explode(":",$title)[0]);
- $paper_fulltitle = trim(user_prompt("Please enter the full title for the paper in folder '$d'","$title"));
- $paper_shorttitle = trim(user_prompt("Please enter a short title for the paper in folder '$d'","$shorttitle"));
- }
- $header = "";
- if ($paper_fulltitle != "" && $authors != "")
- {
- $header=<<<END
- \chapter[$paper_shorttitle]{$paper_fulltitle}\label{chapter:$d}
- \section*{Publication Data}
- \\fullcite{TODO}
- \section*{Contributions}
- TODO
- \\newpage
- \begin{center}
- {\Large \\textbf{
- $paper_fulltitle%
- }}\\\\\
- \\vspace{0.6cm}
- {\large $authors%
- } % TODO: check author list
- \\end{center}
- END;
- }
- $tex = preg_replace("/\\\documentclass.*\\n/i",'',$tex);
- $tex = preg_replace("/\\\begin{document}/i",$header,$tex);
- $tex = preg_replace("/\\\begin{abstract}/i",'\section*{Abstract}',$tex);
- $tex = preg_replace("/\\\end{abstract}/i",'',$tex);
- $tex = preg_replace("/\\\end{document}/i",'',$tex);
- $tex = preg_replace("/\n\s*\\\\author\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
- $tex = preg_replace("/\n\s*\\\\title\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
- $tex = preg_replace("/\n\s*\\\\date\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
- $tex = preg_replace("/\n\s*\\\\maketitle/i","",$tex);
- [$ups,$ps] = getusepackages($tex);
- global $included_usepackages;
- global $additional_usepackages;
- foreach (array_diff($ps,$included_usepackages) as $k => $v) {
- if ($v != "usenix,epsfig,endnotes" && $v != "cite" && !($v == 'floatrow' && in_array('float',$included_usepackages)))
- {
- $additional_usepackages[] = $ups[$k];
- $included_usepackages[] = $v;
- }
- }
- $additional_usepackages = array_unique($additional_usepackages);
- sort($additional_usepackages);
- $tex = preg_replace("/\n\s*\\\\usepackage([^{}]*)(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
-
- $newcommands = getnewcommands($tex);
- global $existing_commands;
- $rmcommands = array_intersect($newcommands,$existing_commands);
- foreach ($rmcommands as $rmc)
- {
- $tex = preg_replace("/\n\s*\\\\newcommand([^{}]*)({\s*\\".$rmc."\s*}.*\n)/i","\n",$tex);
- }
- [$mathopsfull,$mathops] = getmathops($tex);
- global $existing_mathops;
- global $preamble;
- $addmathops = array_diff($mathops,$existing_mathops);
- foreach ($addmathops as $k => $v)
- {
- $preamble .= $mathopsfull[$k] . "\n";
- $existing_mathops[] = $v;
- }
- $rmmathops = array_intersect($mathops,$existing_mathops);
- foreach ($rmmathops as $rmo)
- {
- $tex = preg_replace("/\n\s*\\\\DeclareMathOperator([^{}]*)({\s*\\".$rmo."\s*}.*\n)/i","\n",$tex);
- }
- $matches = [];
- $tex = preg_replace("/\n\s*\\\\pgfplotsset\s*(?<R>{((?:[^{}]+|(?&R))*)})/i","",$tex);
- $tex = preg_replace("/\n\s*\\\\setlength{\s*\\\marginparwidth.*\n/i","\n",$tex);
- file_put_contents($file,$tex);
- }
- }
- return;
- }
- function check_options($argv)
- {
- $options = [];
- foreach ($argv as $a)
- {
- if (str_starts_with($a,"-"))
- $options[$a] = 1;
- if ($a == "-n")
- $options["--no-overwrite"] = 1;
- }
- return $options;
- }
- function compile_check($papers,$precopy = false)
- {
- if ($precopy)
- $papers = array_combine($papers,$papers);
- foreach ($papers as $p => $f)
- {
- echo "======= Paper $p -> $f START =======\n";
- if ($precopy)
- {
- echo "$p\n";
- if (strpos($p,"/") === false || str_starts_with($p,".") || !is_dir(dirname($p)))
- continue;
- $f = basename($p);
- $p = dirname($p);
- }
- else
- {
- shell_exec("cd $p; latexmk -c 2>/dev/null; latexmk -C 2>/dev/null; rm -f *.bbl");
- }
- $str = shell_exec("cd $p; latexmk -latexoption=\"-shell-escape\" -g -pdf $f 2>&1");
- $lines = explode("\n",$str);
- $skip = true;
- $failed = false;
- foreach($lines as $l)
- {
- if (str_starts_with($l,"Latexmk: ====List of undefined refs and citations:"))
- $skip = false;
- if ($skip)
- continue;
- if (stripos($l,"fail") !== false)
- $failed = true;
- echo "$l\n";
- }
- 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"))
- error_exit("The paper did not compile properly, please fix the errors next before continuing.");
- echo "======= Paper $p -> $f END =======\n";
- }
- }
- check_software();
- $options = check_options($argv);
- if (isset($options["--help"]))
- print_help();
- echo "\n=== Step 1/$steps: Check Folders ===\n\n";
- [$targets,$texfiles,$sourcedirs] = check_folders($argv);
- echo "\n=== Step 2/$steps: Pre-Copy Compile Check ===\n\n";
- $targets_exist = true;
- foreach ($targets as $t)
- if (!is_dir($t))
- $targets_exist = false;
- if (isset($options["--no-compile-check"]) || $targets_exist)
- echo "Skipping...\n";
- else
- compile_check($argv,true);
- echo "\n=== Step 3/$steps: Copying Files ===\n\n";
- $papers = check_and_copy_folders($argv);
- echo "\n=== Step 4/$steps: Adjusting References (in *.bib *.tex *.tikz) ===\n\n";
- $bibresources = adjust_references($papers,[".bib",".tex",".tikz"]);
- echo "\n=== Step 5/$steps: Compile Check ===\n\n";
- if (isset($options["--no-compile-check"]))
- echo "Skipping...\n";
- else
- compile_check($papers);
- [$_t,$usepackages1] = getusepackages(file_get_contents("main.tex.php"));
- [$_t,$usepackages2] = getusepackages(file_get_contents("tugraz_defaults.sty"));
- global $included_usepackages;
- $included_usepackages = array_unique(array_merge($usepackages1, $usepackages2));
- sort($included_usepackages);
- $cmds1 = getnewcommands(file_get_contents("main.tex.php"));
- $cmds2 = getnewcommands(file_get_contents("tugraz_defaults.sty"));
- global $existing_commands;
- $existing_commands = array_unique(array_merge($cmds1, $cmds2));
- [$del,$mathops1] = getmathops(file_get_contents("main.tex.php"));
- [$del,$mathops2] = getmathops(file_get_contents("tugraz_defaults.sty"));
- global $existing_mathops;
- $existing_mathops = array_unique(array_merge($mathops1, $mathops2));
- echo "\n=== Step 5/$steps: Adjusting Papers (checking only *.tex files) ===\n\n";
- adjust_papers($papers,[".tex"]);
- echo "\n=== Step 6/$steps: Generate main.tex ===\n\n";
- $thesis_type = user_prompt("Enter Thesis Type ","PhD Thesis");
- $thesis_title = user_prompt("Enter Thesis Title ","Security of TODO");
- $thesis_part1_title = user_prompt("Enter Introductory Part Title ","Introduction to the Security of TODO");
- $thesis_author = user_prompt("Enter Your Name ","Harry Potter");
- $thesis_date = user_prompt("Enter Prospective Defense Month", "July 1998");
- $thesis_institute = user_prompt("Enter Your Institute","Institute for Applied Information Processing and Communications");
- $thesis_assessors = user_prompt("Enter Names of your Assessors (comma-separated)","Severus Snape, Minerva McGonagall");
- $num_publications_in_thesis = count($papers);
- $num_publications = user_prompt("How many publications did you co-author during your PhD? (6 is the absolute minimum for a cumulative thesis)","6");
- $sloppy_begin = "";
- $sloppy_end = "";
- if (!isset($options["--no-sloppy"]))
- {
- $sloppy_begin = '\begin{sloppypar}';
- $sloppy_end = '\end{sloppypar}';
- }
- ob_start();
- require "main.tex.php";
- $maintex_content = ob_get_contents();
- ob_end_clean();
- //if (!file_exists("main.tex") || user_consent("main.tex already exists. overwrite?")) // TODO: enable this check
- file_put_contents("main.tex",$maintex_content);
- if (!file_exists("mypreamble.sty"))
- file_put_contents("mypreamble.sty","\ProvidesPackage{mypreamble}\n\n".implode("\n",$additional_usepackages)."\n\n".$preamble);
- @mkdir("tikz");
- if (!file_exists("abstract.tex"))
- file_put_contents("abstract.tex","");
- if (!file_exists("intro.tex"))
- file_put_contents("intro.tex","");
- if (!file_exists("main.bib"))
- file_put_contents("main.bib","");
- if (isset($options["--cv"]))
- {
- if (!file_exists("cv.bib"))
- file_put_contents("cv.bib","");
- if (!file_exists("cv.tex"))
- file_put_contents("cv.tex","This is my CV! Thanks for checking it out!");
- }
- ?>
|