Permalink
Cannot retrieve contributors at this time
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?
pandisso/pandisso.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
143 lines (118 sloc)
6.63 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |