aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2016-01-08 12:15:31 -0800
committerJohn MacFarlane <jgm@berkeley.edu>2016-01-10 21:32:21 -0800
commit2413d436ed98866e9a70fbd4070a5da52dd97cd5 (patch)
tree0cacf842df8115e93e3de1ce9a1613cee13474be /tools
parent1357f2859ecb128636ea7a764b70407dca4e4015 (diff)
New format for spec tests, new lua formatter for specs.
The format for the spec examples has changed from . markdown . html . to ```````````````````````````````` example markdown . html ```````````````````````````````` One advantage of this is that `spec.txt` becomes a valid Markdown file. `tests/spec_test.py` has been changed to use the new format. The old `tools/makespec.py` has been replaced by a lua program, `tools/make_spec.lua`, which uses the `lcmark` rock (and indirectly libcmark). It can generate html, latex, and commonmark versions of the spec. Pandoc is no longer needed for the latex/PDF version. And, since the new program uses the cmark API and operates directly on the parse tree, we avoid certain bad results we got with the regex replacements done by the python script.
Diffstat (limited to 'tools')
-rw-r--r--tools/make_spec.lua292
-rwxr-xr-xtools/makespec.py172
-rwxr-xr-xtools/specfilter.hs39
-rw-r--r--tools/template.commonmark9
-rw-r--r--tools/template.html21
-rw-r--r--tools/template.latex95
-rw-r--r--tools/template.tex207
7 files changed, 410 insertions, 425 deletions
diff --git a/tools/make_spec.lua b/tools/make_spec.lua
new file mode 100644
index 0000000..3425f35
--- /dev/null
+++ b/tools/make_spec.lua
@@ -0,0 +1,292 @@
+local lcmark = require('lcmark')
+local cmark = require('cmark')
+
+local format = arg[1] or 'html'
+
+local trim = function(s)
+ return s:gsub("^%s+",""):gsub("%s+$","")
+end
+
+local warn = function(s)
+ io.stderr:write('WARNING: ' .. s .. '\n')
+end
+
+local to_identifier = function(s)
+ return trim(s):lower():gsub('[^%w]+', ' '):gsub('[%s]+', '-')
+end
+
+local render_number = function(tbl)
+ local buf = {}
+ for i,x in ipairs(tbl) do
+ buf[i] = tostring(x)
+ end
+ return table.concat(buf, '.')
+end
+
+local extract_references = function(doc)
+ local cur, entering, node_type
+ local refs = {}
+ for cur, entering, node_type in cmark.walk(doc) do
+ if not entering and
+ ((node_type == cmark.NODE_LINK and cmark.node_get_url(cur) == '@') or
+ node_type == cmark.NODE_HEADING) then
+ local children = cmark.node_first_child(cur)
+ local label = trim(cmark.render_commonmark(children, OPT_DEFAULT, 0))
+ local ident = to_identifier(label)
+ if refs[label] then
+ warn("duplicate reference " .. label)
+ end
+ refs[label] = ident
+ if not refs[label .. 's'] then
+ -- plural too
+ refs[label .. 's'] = ident
+ end
+ end
+ end
+ -- check for duplicate IDs
+ local idents = {}
+ for _,id in ipairs(refs) do
+ if idents[id] then
+ warn("duplicate identifier " .. id)
+ end
+ idents[#idents + 1] = id
+ end
+ return refs
+end
+
+local make_toc = function(toc)
+ -- we create a commonmark string, then parse it
+ local toclines = {}
+ for _,entry in ipairs(toc) do
+ if entry.level <= 2 then
+ local indent = string.rep(' ', entry.level - 1)
+ toclines[#toclines + 1] = indent .. '* [' ..
+ (entry.number == '' and ''
+ or '<span class="number">' .. entry.number .. '</span>') ..
+ entry.label .. '](#' .. entry.ident .. ')'
+ end
+ end
+ -- now parse our cm list and return the resulting list node:
+ local doc = cmark.parse_string(table.concat(toclines, '\n'), cmark.OPT_SMART)
+ return cmark.node_first_child(doc)
+end
+
+local make_html_element = function(block, tagname, attrs)
+ local div = cmark.node_new(block and cmark.NODE_CUSTOM_BLOCK or
+ cmark.NODE_CUSTOM_INLINE)
+ local attribs = {}
+ for _,attr in ipairs(attrs) do
+ attribs[#attribs + 1] = ' ' .. attr[1] .. '="' .. attr[2] .. '"'
+ end
+ local opentag = '<' .. tagname .. table.concat(attribs, '') .. '>'
+ local closetag = '</' .. tagname .. '>'
+ cmark.node_set_on_enter(div, opentag)
+ cmark.node_set_on_exit(div, closetag)
+ return div
+end
+
+local make_html_block = function(tagname, attrs)
+ return make_html_element(true, tagname, attrs)
+end
+
+local make_html_inline = function(tagname, attrs)
+ return make_html_element(false, tagname, attrs)
+end
+
+local make_latex = function(spec)
+ local latex = cmark.node_new(spec.block and cmark.NODE_CUSTOM_BLOCK or
+ cmark.NODE_CUSTOM_INLINE)
+ cmark.node_set_on_enter(latex, spec.start)
+ cmark.node_set_on_exit(latex, spec.stop)
+ return latex
+end
+
+local make_text = function(s)
+ local text = cmark.node_new(cmark.NODE_TEXT)
+ cmark.node_set_literal(text, s)
+ return text
+end
+
+local create_anchors = function(doc, meta, to)
+ local cur, entering, node_type
+ local toc = {}
+ local number = {0}
+ local example = 0
+ for cur, entering, node_type in cmark.walk(doc) do
+ if not entering and
+ ((node_type == cmark.NODE_LINK and cmark.node_get_url(cur) == '@') or
+ node_type == cmark.NODE_HEADING) then
+
+ local anchor
+ local children = cmark.node_first_child(cur)
+ local label = trim(cmark.render_commonmark(children, OPT_DEFAULT, 0))
+ local ident = to_identifier(label)
+ if node_type == cmark.NODE_LINK then
+ if format == 'latex' then
+ anchor = make_latex({start="\\hypertarget{" .. ident .. "}{",
+ stop="\\label{" .. ident .. "}}",
+ block = true})
+ else
+ anchor = make_html_inline('a', {{'id', ident}, {'href', '#'..ident},
+ {'class', 'definition'}})
+ end
+
+ else -- NODE_HEADING
+
+ local level = cmark.node_get_heading_level(cur)
+ local last_level = #toc == 0 and 1 or toc[#toc].level
+ if #number > 0 then
+ if level > last_level then -- subhead
+ number[level] = 1
+ else
+ while last_level > level do
+ number[last_level] = nil
+ last_level = last_level - 1
+ end
+ number[level] = number[level] + 1
+ end
+ end
+ table.insert(toc, { label = label, ident = ident, level = level, number = render_number(number) })
+ local num = render_number(number)
+ local section_cmds = {"\\section", "\\subsection",
+ "\\subsubsection", "\\chapter"}
+ if format == 'latex' then
+ anchor = make_latex({start="\\hypertarget{" .. ident .. "}{" ..
+ section_cmds[level] .. "{",
+ stop="}\\label{" .. ident .. "}}",
+ block = true})
+ else
+ anchor = make_html_block('h' .. tostring(level),
+ {{'id', ident},
+ {'href', '#'..ident},
+ {'class', 'definition'}})
+ if num ~= '' then
+ local numspan = make_html_inline('span', {{'class','number'}})
+ node_append_child(numspan, make_text(num))
+ node_append_child(anchor, numspan)
+ end
+ end
+ end
+ while children do
+ node_append_child(anchor, children)
+ children = cmark.node_next(children)
+ end
+ cmark.node_insert_before(cur, anchor)
+ cmark.node_unlink(cur)
+ elseif entering and node_type == cmark.NODE_CODE_BLOCK and
+ cmark.node_get_fence_info(cur) == 'example' then
+ example = example + 1
+ -- split into two code blocks
+ local code = cmark.node_get_literal(cur)
+ local sepstart, sepend = code:find("[\n\r]+%.[\n\r]+")
+ if not sepstart then
+ warn("Could not find separator in:\n" .. contents)
+ end
+ local markdown_code = cmark.node_new(cmark.NODE_CODE_BLOCK)
+ local html_code = cmark.node_new(cmark.NODE_CODE_BLOCK)
+ -- note: we replace the ␣ with a special span after rendering
+ local markdown_code_string = code:sub(1, sepstart):gsub(' ', '␣')
+ local html_code_string = code:sub(sepend + 1):gsub(' ', '␣')
+ cmark.node_set_literal(markdown_code, markdown_code_string)
+ cmark.node_set_fence_info(markdown_code, 'markdown')
+ cmark.node_set_literal(html_code, html_code_string)
+ cmark.node_set_fence_info(html_code, 'html')
+
+ local example_div, leftcol_div, rightcol_div
+ if format == 'latex' then
+ example_div = make_latex({start = '\\begin{minipage}[t]{\\textwidth}\n{\\scriptsize Example ' .. tostring(example) .. '}\n\n\\vspace{-0.4em}\n', stop = '\\end{minipage}', block = true})
+ leftcol_div = make_latex({start = "\\begin{minipage}[t]{0.49\\textwidth}\n\\definecolor{shadecolor}{gray}{0.85}\n\\begin{snugshade}\\small\n", stop = "\\end{snugshade}\n\\end{minipage}\n\\hfill", block = true})
+ rightcol_div = make_latex({start = "\\begin{minipage}[t]{0.49\\textwidth}\n\\definecolor{shadecolor}{gray}{0.95}\n\\begin{snugshade}\\small\n", stop = "\\end{snugshade}\n\\end{minipage}\n\\vspace{0.8em}", block = true})
+ cmark.node_append_child(leftcol_div, markdown_code)
+ cmark.node_append_child(rightcol_div, html_code)
+ cmark.node_append_child(example_div, leftcol_div)
+ cmark.node_append_child(example_div, rightcol_div)
+ else
+ leftcol_div = make_html_block('div', {{'class','column'}})
+ rightcol_div = make_html_block('div', {{'class', 'column'}})
+ cmark.node_append_child(leftcol_div, markdown_code)
+ cmark.node_append_child(rightcol_div, html_code)
+ local examplenum_div = make_html_block('div', {{'class', 'examplenum'}})
+ local interact_link = make_html_inline('a', {{'class', 'dingus'},
+ {'title', 'open in interactive dingus'}})
+ cmark.node_append_child(interact_link, make_text("(interact)"))
+ local examplenum_link = cmark.node_new(cmark.NODE_LINK)
+ cmark.node_set_url(examplenum_link, '#example-' .. tostring(example))
+ cmark.node_append_child(examplenum_link,
+ make_text("Example " .. tostring(example)))
+ cmark.node_append_child(examplenum_div, examplenum_link)
+ if format == 'html' then
+ cmark.node_append_child(examplenum_div, interact_link)
+ end
+ example_div = make_html_block('div', {{'class', 'example'},
+ {'id','example-' .. tostring(example)}})
+ cmark.node_append_child(example_div, examplenum_div)
+ cmark.node_append_child(example_div, leftcol_div)
+ cmark.node_append_child(example_div, rightcol_div)
+ end
+ cmark.node_insert_before(cur, example_div)
+ cmark.node_unlink(cur)
+ cmark.node_free(cur)
+ elseif node_type == cmark.NODE_HTML_BLOCK and
+ cmark.node_get_literal(cur) == '<!-- END TESTS -->\n' then
+ -- change numbering
+ number = {}
+ if format ~= 'latex' then
+ local appendices = make_html_block('div', {{'class','appendices'}})
+ cmark.node_insert_after(cur, appendices)
+ -- put the remaining sections in an appendix
+ local tmp = cmark.node_next(appendices)
+ while tmp do
+ cmark.node_append_child(appendices, tmp)
+ tmp = cmark.node_next(tmp)
+ end
+ end
+ end
+ end
+ meta.toc = make_toc(toc)
+end
+
+local to_ref = function(ref)
+ return '[' .. ref.label .. ']: #' .. ref.indent .. '\n'
+end
+
+local inp = io.read("*a")
+local doc1 = cmark.parse_string(inp, cmark.OPT_DEFAULT)
+local refs = extract_references(doc1)
+local refblock = '\n'
+for lab,ident in pairs(refs) do
+ refblock = refblock .. '[' .. lab .. ']: #' .. ident .. '\n'
+ -- refblock = refblock .. '[' .. lab .. 's]: #' .. ident .. '\n'
+end
+-- append references and parse again
+local contents, meta, msg = lcmark.convert(inp .. refblock, format,
+ { smart = true,
+ yaml_metadata = true,
+ safe = false,
+ filters = { create_anchors }
+ })
+
+if contents then
+ local f = io.open("tools/template." .. format, 'r')
+ if not f then
+ io.stderr:write("Could not find template!")
+ os.exit(1)
+ end
+ local template = f:read("*a")
+
+ if format == 'html' then
+ contents = contents:gsub('␣', '<span class="space"> </span>')
+ end
+ meta.body = contents
+ local rendered, msg = lcmark.render_template(template, meta)
+ if not rendered then
+ io.stderr:write(msg)
+ os.exit(1)
+ end
+ io.write(rendered)
+ os.exit(0)
+else
+ io.stderr:write(msg)
+ os.exit(1)
+end
+
diff --git a/tools/makespec.py b/tools/makespec.py
deleted file mode 100755
index 0ef924a..0000000
--- a/tools/makespec.py
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-
-import re
-import sys
-from subprocess import *
-from string import Template
-
-def out(str):
- sys.stdout.buffer.write(str.encode('utf-8'))
-
-def err(str):
- sys.stderr.buffer.write(str.encode('utf-8'))
-
-if len(sys.argv) == 2:
- specformat = sys.argv[1]
- if not (specformat in ["html", "markdown"]):
- err("Format must be html or markdown\n")
- exit(1)
-else:
- err("Usage: makespec.py [html|markdown]\n")
- exit(1)
-
-def toIdentifier(s):
- return re.sub(r'\s+', '-', re.sub(r'\W+', ' ', s.strip().lower()))
-
-def parseYaml(yaml):
- metadata = {}
- def parseField(match):
- key = match.group(1)
- val = match.group(2).strip()
- if re.match(r'^\'', val):
- val = val[1:len(val) - 1]
- metadata[key] = val
- fieldre = re.compile('^(\w+):(.*)$', re.MULTILINE)
- re.sub(fieldre, parseField, yaml)
- return metadata
-
-def pipe_through_prog(prog, text):
- result = check_output(prog.split(), input=text.encode('utf-8'))
- return result.decode('utf-8')
-
-def replaceAnchor(match):
- refs.append("[{0}]: #{1}".format(match.group(1), match.group(2)))
- if specformat == "html":
- return '<a id="{1}" href="#{1}" class="definition">{0}</a>'.format(match.group(1), match.group(2))
- else:
- return match.group(0)
-
-stage = 0
-example = 0
-section = ""
-sections = []
-mdlines = []
-refs = []
-lastnum = []
-finishedMeta = False
-yamllines = []
-
-with open('spec.txt', 'r', encoding='utf-8') as spec:
- for ln in spec:
- if not finishedMeta:
- yamllines.append(ln)
- if re.match(r'^\.\.\.$', ln):
- finishedMeta = True
- elif re.match(r'^\.$', ln):
- if stage == 0:
- example += 1
- mdlines.append("\n<div class=\"example\" id=\"example-{0}\" data-section=\"{1}\">\n".format(example, section))
- mdlines.append("<div class=\"examplenum\"><a href=\"#example-{0}\">Example {0}</a>".format(example))
- if specformat == "html":
- mdlines.append("&nbsp;&nbsp;<a class=\"dingus\" title=\"open in interactive dingus\">(interact)</a>")
- mdlines.append("</div>\n<div class=\"column\">\n\n")
- mdlines.append("````````````````````````````````````````````````````````` markdown\n")
- stage = 1
- elif stage == 1:
- mdlines.append("`````````````````````````````````````````````````````````\n\n")
- mdlines.append("\n</div>\n\n<div class=\"column\">\n\n")
- mdlines.append("````````````````````````````````````````````````````````` html\n")
- stage = 2
- elif stage == 2:
- mdlines.append("`````````````````````````````````````````````````````````\n\n")
- mdlines.append("</div>\n</div>\n")
- stage = 0
- else:
- sys.stderr.out("Encountered unknown stage {0}\n".format(stage))
- sys.exit(1)
- else:
- if stage == 0:
- match = re.match(r'^(#{1,6}) *(.*)', ln)
- if match:
- section = match.group(2)
- lastlevel = len(lastnum)
- level = len(match.group(1))
- if re.search(r'{-}$', section):
- section = re.sub(r' *{-} *$', '', section)
- if specformat == 'html':
- ln = re.sub(r' *{-} *$', '', ln)
- number = ''
- else:
- if lastlevel == level:
- lastnum[level - 1] = lastnum[level - 1] + 1
- elif lastlevel < level:
- while len(lastnum) < level:
- lastnum.append(1)
- else: # lastlevel > level
- lastnum = lastnum[0:level]
- lastnum[level - 1] = lastnum[level - 1] + 1
- number = '.'.join([str(x) for x in lastnum])
- ident = toIdentifier(section)
- ln = re.sub(r' ', ' <span class="number">' + number + '</span> ', ln, count=1)
- sections.append(dict(level=level,
- contents=section,
- ident=ident,
- number=number))
- refs.append("[{0}]: #{1}".format(section, ident))
- ln = re.sub(r'# +', '# <a id="{0}"></a>'.format(ident),
- ln, count=1)
- else:
- ln = re.sub(r' ', '␣', ln)
- mdlines.append(ln)
-
-mdtext = re.sub(r'\[([^]]*)\]\(@([^)]*)\)', replaceAnchor,
- ''.join(mdlines)) + '\n\n' + '\n'.join(refs) + '\n'
-yaml = ''.join(yamllines)
-metadata = parseYaml(yaml)
-
-if specformat == "markdown":
- out(yaml + '\n\n' + mdtext)
-elif specformat == "html":
- with open("tools/template.html", "r", encoding="utf-8") as templatefile:
- template = Template(templatefile.read())
- toclines = []
- for section in sections:
- if section['level'] <= 2:
- indent = ' ' * (section['level'] - 1)
- toclines.append(indent + '* [' + section['number'] + ' ' +
- section['contents'] + '](#' + section['ident'] + ')')
- toc = '<div id="TOC">\n\n' + '\n'.join(toclines) + '\n\n</div>\n\n'
- prog = "cmark --smart"
- result = pipe_through_prog(prog, toc + mdtext)
- if result == '':
- err("Error converting markdown version of spec to HTML.\n")
- exit(1)
- else:
- result = re.sub(r'␣', '<span class="space"> </span>', result)
- result = re.sub(r'<h([1-6])><a id="([^\"]*)"><\/a> ',
- "<h\\1 id=\"\\2\">", result)
- # put plural s inside links for better visuals:
- result = re.sub(r'<\/a>s', "s</a>", result)
- out(template.substitute(metadata, body=result))
-
- # check for errors:
- idents = []
- for ident in re.findall(r'id="([^"]*)"', result):
- if ident in idents:
- err("WARNING: duplicate identifier '" + ident + "'\n")
- else:
- idents.append(ident)
- for href in re.findall(r'href="#([^"]*)"', result):
- if not (href in idents):
- err("WARNING: internal link with no anchor '" + href + "'\n")
- reftexts = []
- for ref in refs:
- ref = re.sub('].*',']',ref).upper()
- if ref in reftexts:
- err("WARNING: duplicate reference link '" + ref + "'\n")
- else:
- reftexts.append(ref)
-
-
-exit(0)
diff --git a/tools/specfilter.hs b/tools/specfilter.hs
deleted file mode 100755
index 304e463..0000000
--- a/tools/specfilter.hs
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env runhaskell
-
-import Text.Pandoc.JSON
-import Text.Pandoc.Walk
-import Text.Pandoc.Generic
-
-main = toJSONFilter go
- where go :: Pandoc -> Pandoc
- go = bottomUp exampleDivs . bottomUp (concatMap anchors)
-
-exampleDivs :: Block -> Block
-exampleDivs (Div (ident, ["example"], kvs)
- [ d@(Div (_,["examplenum"],_) _),
- d1@(Div (_,["column"],_) _),
- d2@(Div (_,["column"],_) _)
- ]) = Div (ident, ["example"], kvs)
- [ rawtex "\\begin{minipage}[t]{\\textwidth}\n{\\scriptsize "
- , d
- , rawtex "}\\vspace{-0.4em}\n"
- , rawtex "\\begin{minipage}[t]{0.49\\textwidth}\n\\definecolor{shadecolor}{gray}{0.85}\n\\begin{snugshade}\\small\n"
- , walk addBreaks d1
- , rawtex "\\end{snugshade}\n\\end{minipage}\n\\hfill\n\\begin{minipage}[t]{0.49\\textwidth}\n\\definecolor{shadecolor}{gray}{0.95}\n\\begin{snugshade}\\small\n"
- , walk addBreaks d2
- , rawtex "\\end{snugshade}\n\\end{minipage}\n\\end{minipage}"
- ]
- where rawtex = RawBlock (Format "latex")
- addBreaks (CodeBlock attrs code) = CodeBlock attrs $ addBreaks' code
- addBreaks x = x
- addBreaks' code =
- if length code > 49
- then take 49 code ++ ('\n':addBreaks' (drop 49 code))
- else code
-exampleDivs x = x
-
-anchors :: Inline -> [Inline]
-anchors (Link text ('@':lab,_)) =
- [RawInline (Format "latex") ("\\hyperdef{}{" ++ lab ++ "}{\\label{" ++ lab ++ "}}"), Strong text]
-anchors (Span ("",["number"],[]) xs) = [] -- remove sect numbers
-anchors x = [x]
diff --git a/tools/template.commonmark b/tools/template.commonmark
new file mode 100644
index 0000000..b866378
--- /dev/null
+++ b/tools/template.commonmark
@@ -0,0 +1,9 @@
+---
+title: $title$
+author: $author$
+version: $version$
+date: '$date$'
+license: '$license$'
+...
+
+$body$
diff --git a/tools/template.html b/tools/template.html
index fd2e56b..ca63146 100644
--- a/tools/template.html
+++ b/tools/template.html
@@ -2,7 +2,7 @@
<html>
<head>
<meta charset="UTF-8">
-<title>${title}</title>
+<title>$title$</title>
<style type="text/css">
body { font-family: Helvetica, arial, freesans, clean, sans-serif;
line-height: 1.4;
@@ -19,6 +19,7 @@ h3 { font-size: 110%; font-weight: bold; }
h4 { font-size: 100%; font-weight: bold; }
a.definition { font-weight: bold; }
span.space { position: relative; }
+span.number:after { content: "  " }
span.space:after {
content: "·";
position: absolute;
@@ -59,7 +60,7 @@ div.example > div:nth-child(3) { clear:right; background-color: #C9CaCE; }
color: white;
}
#watermark a { color: white; }
-a.dingus { color: red; cursor: pointer; }
+a.dingus { margin-left: 1em; color: red; cursor: pointer; }
a.footnoteRef > sup:before {
content: "[";
}
@@ -85,7 +86,7 @@ a.footnoteRef > sup {
a.dingus { display: none; }
}
</style>
-<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
+<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script type="text/javascript">
$$(document).ready(function() {
$$("div.example").each(function(e) {
@@ -102,10 +103,10 @@ $$(document).ready(function() {
</script>
</head>
<body>
-<h1 class="title">${title}</h1>
-<div class="version">Version ${version} (${date})</div>
+<h1 class="title">$title$</h1>
+<div class="version">Version $version$ ($date$)</div>
<div class="authors">
- <span class="author">${author}</span>
+ <span class="author">$author$</span>
</div>
<div class="license">
<a rel="license"
@@ -123,6 +124,12 @@ $$(document).ready(function() {
Commons Attribution-ShareAlike 4.0 International License</a>.</span>
</div>
<div id="watermark"></div>
-${body}
+
+<div id="TOC">
+$toc$
+</div>
+
+$body$
+
</body>
</html>
diff --git a/tools/template.latex b/tools/template.latex
new file mode 100644
index 0000000..66fb997
--- /dev/null
+++ b/tools/template.latex
@@ -0,0 +1,95 @@
+\documentclass[10pt,letterpaper,twosides]{report}
+\usepackage{lmodern}
+\usepackage{amssymb,amsmath}
+\usepackage{ifxetex,ifluatex}
+\usepackage{fixltx2e} % provides \textsubscript
+\usepackage[margin=1in]{geometry}
+\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
+ \usepackage[T1]{fontenc}
+ \usepackage[utf8]{inputenc}
+\else % if luatex or xelatex
+ \ifxetex
+ \usepackage{mathspec}
+ \usepackage{xltxtra,xunicode}
+ \else
+ \usepackage{fontspec}
+ \fi
+ \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase}
+ \newcommand{\euro}{€}
+\fi
+% use upquote if available, for straight quotes in verbatim environments
+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
+% use microtype if available
+\IfFileExists{microtype.sty}{%
+\usepackage{microtype}
+\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
+}{}
+\usepackage{framed} % code examples
+\usepackage{color}
+$if(geometry)$
+\usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry}
+$endif$
+\usepackage{hyperref}
+$if(colorlinks)$
+\PassOptionsToPackage{usenames,dvipsnames}{color} % color is loaded by hyperref
+$endif$
+\hypersetup{unicode=true,
+$if(title-meta)$
+ pdftitle={$title-meta$},
+$endif$
+$if(author-meta)$
+ pdfauthor={$author-meta$},
+$endif$
+$if(keywords)$
+ pdfkeywords={$for(keywords)$$keywords$$sep$; $endfor$},
+$endif$
+$if(colorlinks)$
+ colorlinks=true,
+ linkcolor=$if(linkcolor)$$linkcolor$$else$Maroon$endif$,
+ citecolor=$if(citecolor)$$citecolor$$else$Blue$endif$,
+ urlcolor=$if(urlcolor)$$urlcolor$$else$Blue$endif$,
+$else$
+ pdfborder={0 0 0},
+$endif$
+ breaklinks=true}
+\urlstyle{same} % don't use monospace font for urls
+\usepackage{fancyvrb}
+\VerbatimFootnotes % allows verbatim text in footnotes
+$if(links-as-notes)$
+% Make links footnotes instead of hotlinks:
+\renewcommand{\href}[2]{#2\footnote{\url{#1}}}
+$endif$
+$if(indent)$
+$else$
+\IfFileExists{parskip.sty}{%
+\usepackage{parskip}
+}{% else
+\setlength{\parindent}{0pt}
+\setlength{\parskip}{6pt plus 2pt minus 1pt}
+}
+$endif$
+\setlength{\emergencystretch}{3em} % prevent overfull lines
+\providecommand{\tightlist}{%
+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
+$if(numbersections)$
+\setcounter{secnumdepth}{5}
+$else$
+\setcounter{secnumdepth}{0}
+$endif$
+
+\title{$title$$if(thanks)$\thanks{$thanks$}$endif$}
+\author{$for(author)$$author$$sep$ \and $endfor$}
+\date{$date$}
+
+\begin{document}
+\maketitle
+
+{
+\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$black$endif$}
+\setcounter{tocdepth}{2}
+\tableofcontents
+}
+
+$body$
+
+\end{document}
diff --git a/tools/template.tex b/tools/template.tex
deleted file mode 100644
index 13d38a3..0000000
--- a/tools/template.tex
+++ /dev/null
@@ -1,207 +0,0 @@
-\documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$lang$,$endif$$if(papersize)$$papersize$,$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$}
-$if(fontfamily)$
-\usepackage{$fontfamily$}
-$else$
-\usepackage{lmodern}
-$endif$
-$if(linestretch)$
-\usepackage{setspace}
-\setstretch{$linestretch$}
-$endif$
-\usepackage{amssymb,amsmath}
-\usepackage{ifxetex,ifluatex}
-\usepackage{fixltx2e} % provides \textsubscript
-\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
- \usepackage[T1]{fontenc}
- \usepackage[utf8]{inputenc}
-$if(euro)$
- \usepackage{eurosym}
-$endif$
-\else % if luatex or xelatex
- \ifxetex
- \usepackage{mathspec}
- \usepackage{xltxtra,xunicode}
- \else
- \usepackage{fontspec}
- \fi
- \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase}
- \newcommand{\euro}{€}
-$if(mainfont)$
- \setmainfont{$mainfont$}
-$endif$
-$if(sansfont)$
- \setsansfont{$sansfont$}
-$endif$
-$if(monofont)$
- \setmonofont[Mapping=tex-ansi]{$monofont$}
-$endif$
-$if(mathfont)$
- \setmathfont(Digits,Latin,Greek){$mathfont$}
-$endif$
-\fi
-% use upquote if available, for straight quotes in verbatim environments
-\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
-% use microtype if available
-\IfFileExists{microtype.sty}{\usepackage{microtype}}{}
-\usepackage[margin=1in]{geometry}
-\providecommand{\tightlist}{%
- \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
-$if(natbib)$
-\usepackage{natbib}
-\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$}
-$endif$
-$if(biblatex)$
-\usepackage{biblatex}
-$if(biblio-files)$
-\bibliography{$biblio-files$}
-$endif$
-$endif$
-$if(listings)$
-\usepackage{listings}
-$endif$
-$if(lhs)$
-\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}
-$endif$
-\usepackage{fancyvrb}
-$if(highlighting-macros)$
-$highlighting-macros$
-$endif$
-\usepackage{color,framed}
-$if(verbatim-in-note)$
-\usepackage{fancyvrb}
-$endif$
-$if(tables)$
-\usepackage{longtable,booktabs}
-$endif$
-$if(graphics)$
-\usepackage{graphicx}
-\makeatletter
-\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}
-\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}
-\makeatother
-% Scale images if necessary, so that they will not overflow the page
-% margins by default, and it is still possible to overwrite the defaults
-% using explicit options in \includegraphics[width, height, ...]{}
-\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}
-$endif$
-\ifxetex
- \usepackage[setpagesize=false, % page size defined by xetex
- unicode=false, % unicode breaks when used with xetex
- xetex]{hyperref}
-\else
- \usepackage[unicode=true]{hyperref}
-\fi
-\hypersetup{breaklinks=true,
- bookmarks=true,
- pdfauthor={$author-meta$},
- pdftitle={$title-meta$},
- colorlinks=true,
- citecolor=$if(citecolor)$$citecolor$$else$blue$endif$,
- urlcolor=$if(urlcolor)$$urlcolor$$else$blue$endif$,
- linkcolor=$if(linkcolor)$$linkcolor$$else$magenta$endif$,
- pdfborder={0 0 0}}
-\urlstyle{same} % don't use monospace font for urls
-$if(links-as-notes)$
-% Make links footnotes instead of hotlinks:
-\renewcommand{\href}[2]{#2\footnote{\url{#1}}}
-$endif$
-$if(strikeout)$
-\usepackage[normalem]{ulem}
-% avoid problems with \sout in headers with hyperref:
-\pdfstringdefDisableCommands{\renewcommand{\sout}{}}
-$endif$
-\setlength{\parindent}{0pt}
-\setlength{\parskip}{6pt plus 2pt minus 1pt}
-\setlength{\emergencystretch}{3em} % prevent overfull lines
-$if(numbersections)$
-\setcounter{secnumdepth}{5}
-$else$
-\setcounter{secnumdepth}{0}
-$endif$
-$if(verbatim-in-note)$
-\VerbatimFootnotes % allows verbatim text in footnotes
-$endif$
-$if(lang)$
-\ifxetex
- \usepackage{polyglossia}
- \setmainlanguage{$mainlang$}
-\else
- \usepackage[$lang$]{babel}
-\fi
-$endif$
-
-\usepackage[small]{titlesec}
-\titleformat{\chapter}
- {\Large\bfseries} % format
- {\Large\thechapter} % label
- {0pt} % sep
- {\Large} % before-code
-
-
-\usepackage{fancyhdr}
-\pagestyle{fancy}
-\pagenumbering{arabic}
-\lhead{\itshape $title$}
-\chead{}
-\rhead{\itshape{\nouppercase{\rightmark}}}
-\lfoot{v$version$ ($date$)}
-\cfoot{}
-\rfoot{\thepage}
-
-$if(title)$
-\title{$title$\\
-Version $version$}
-$endif$
-$if(author)$
-\author{$for(author)$$author$$sep$ \and $endfor$}
-$endif$
-\date{$date$}
-$for(header-includes)$
-$header-includes$
-$endfor$
-
-\begin{document}
-$if(title)$
-\maketitle
-$endif$
-$if(abstract)$
-\begin{abstract}
-$abstract$
-\end{abstract}
-$endif$
-
-$for(include-before)$
-$include-before$
-
-$endfor$
-$if(toc)$
-{
-\hypersetup{linkcolor=black}
-\setcounter{tocdepth}{$toc-depth$}
-\tableofcontents
-}
-$endif$
-$body$
-
-$if(natbib)$
-$if(biblio-files)$
-$if(biblio-title)$
-$if(book-class)$
-\renewcommand\bibname{$biblio-title$}
-$else$
-\renewcommand\refname{$biblio-title$}
-$endif$
-$endif$
-\bibliography{$biblio-files$}
-
-$endif$
-$endif$
-$if(biblatex)$
-\printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$
-
-$endif$
-$for(include-after)$
-$include-after$
-
-$endfor$
-\end{document}