Skip to content
Permalink
main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
#!/usr/bin/env python3
"""
Python script to build a dissertation based on Markdown / Pandoc
=================================
Author: Ethan Smith-Coss
Original Author: Daniel Goldsmith
=================================
Disclaimer.
========================================================================================================
Majority of the original software has been modified to be compatible with modern versions of pandoc.
Software may not be backwards compatible pre-2.11. For the original source code by Original Author, see:
Source: https://github.coventry.ac.uk/aa9863/FYP-Project-Template
========================================================================================================
"""
import subprocess
import os
import sys
import getopt
help_msg = f"""Usage: {sys.argv[0]} [options] file...
Options:
-b, --bibliography=FILE Change bibliography file to read (default: 'include/bibliography')
--crossref Use the pandoc-crossref filter (external package, must exist on system and in PATH).
--engine= Change the PDF engine used by pandoc (default: pdflatex).
--include-path=PATH Change the include directory path (default: 'include').
--no-submodule Do not use submodules when compiling. --submodule-path and --include-path are ignored.
(Assumes all files are located in runtime directory.)
-o, --output=FILE Change the output file.
--pandoc=STRING Send native options to pandoc (string of options).
--submodule-path=PATH Change the submodule directory path (default: 'templates').
-h, --help Print this help message and exit.
Contacts: Please create an Issue on the project's GitHub repository for anything relevant to development of software.
"""
class Builder:
def __init__(self, OUT_FILE, *args, **kwargs):
self.SOURCE_FILES_PATH = "include"
self.SOURCE_FILES = ["Introduction.md"]
#Are you using the Recommended Submodule Approach
self.SUBMODULE = True
self.NO_BIBLIOGRAPHY = False
#If you rename the Templates repository, Let the script know.
self.TEMPLATE_PATH = "templates"
self.HEADER_FILE = "Header.md"
self.BIBLIOGRAPHY = "include/bibliography.bib"
# Pandoc Template
self.LATEX_TEMPLATE = "disso.latex"
self.OUTPUT_FILE = OUT_FILE # set the default output file
self.PDF_ENGINE = "pdflatex"
## Pandoc options when compiling
self.PANDOC_OPTS = ["--top-level-division=chapter",
"--pdf-engine={0}".format(self.PDF_ENGINE),]
def build(self, in_file):
"""Build the list that we send to pandoc"""
if self.SUBMODULE:
self.HEADER_FILE = os.path.join(self.TEMPLATE_PATH, self.HEADER_FILE)
self.LATEX_TEMPLATE = os.path.join(self.TEMPLATE_PATH, self.LATEX_TEMPLATE)
## build source files with appropriate path prefix
self.SOURCE_FILES = [os.path.join(self.SOURCE_FILES_PATH, f) for f in self.SOURCE_FILES]
## add the template to the Pandoc options list
self.PANDOC_OPTS.append("--template={0}".format(self.LATEX_TEMPLATE))
## if the user disabled bibliography generation, don't run this.
if not self.NO_BIBLIOGRAPHY:
self.PANDOC_OPTS.extend(["--bibliography={0}".format(self.BIBLIOGRAPHY), "--citeproc"])
#Actually Build the list
cmds = ["pandoc", *self.PANDOC_OPTS, in_file, self.HEADER_FILE,
*self.SOURCE_FILES, "-o", self.OUTPUT_FILE]
subprocess.run(cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def main():
## define how CLI arguments should be parsed into options and positionals
optlist, args = getopt.getopt(sys.argv[1:], 'b:o:h',
['pandoc=', 'help', 'no-submodule', 'include-path=', 'output=', 'bibliography=',
'no-bibliography', 'template-path=', 'crossref'])
## special handle to see if help is asked anywhere in the command before operating on STDIN
for option, _ in optlist:
if option in ('-h', '--help'):
print(help_msg)
sys.exit(0)
## if [FILE] is omitted (or argument is '-'), read from STDIN
if len(args) == 0 or args[0] == '-':
infile = sys.stdin.readline()
args.append(infile)
## get the basename of the file itself, split the extension and grab file name
in_file = os.path.basename(args[0]).split('.')[0]
builder = Builder(in_file+".pdf") # output is dependent on name of input (use same name as PDF)
## loop over all of our options we can have
## @:NOTE: `setattr` is only used to suppress the linter about changing "constant" attributes of the class.
## Technically the attributes of the class are "constant" during the build phase, but some CLI
## arguments change those "constants". (Python is chaotic neutral, don't worry about it.)
for option, value in optlist:
if option in ('-o', '--output'):
setattr(builder, 'OUTPUT_FILE', value) # change the output file to user-defined
elif option in ('-b', '--bibliography'):
setattr(builder, 'BIBLIOGRAPHY', value) # change the bibliography file
elif option == "--no-bibliography":
setattr(builder, 'NO_BIBLIOGRAPHY', True) # diasble bibliography generation
elif option == '--pandoc':
builder.PANDOC_OPTS.extend(value.split()) # commands to pandoc must be native (Q.E.D)
elif option == '--no-submodule':
setattr(builder, 'SUBMODULE', False) # disable submodules
elif option == '--include-path':
setattr(builder, 'SOURCE_FILES_PATH', value.rstrip("/")) # change the default path for source files
elif option == '--template-path':
setattr(builder, 'TEMPLATE_PATH', value.rstrip("/")) # change the default path for template files
elif option == "--crossref":
builder.PANDOC_OPTS.append("-F pandoc-crossref") # include the pandoc-crossref filter (external tool)
elif option == "--engine":
setattr(builder, 'PDF_ENGINE', value.strip())
else:
print(help_msg) # an unknown option was given
sys.exit(1)
## if we have more than one file, the others are additional source files.
## @:NOTE: assume the first file contains the required data to build a cover page correctly.
if len(args) > 1:
builder.SOURCE_FILES.extend(args[1:])
## call the builder with input file
builder.build(args[0])
if __name__ == "__main__":
#Build the damm thing
main()