This commit is contained in:
baldeau 2024-02-13 15:22:59 +01:00
commit 28fff1f37b
61 changed files with 1881 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
out/
mermaid-filter.err
_minted-input/

11
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"folder-path-color.folders": [
{ "path": "chapters/01", "symbol": "SR", "tooltip": "Source files" },
{ "path": "chapters/02", "symbol": "T", "tooltip": "Common" },
{ "path": "chapters/03", "symbol": "T", "tooltip": "Common" },
{ "path": "chapters/04", "symbol": "T", "tooltip": "Common" },
{ "path": "chapters/05", "symbol": "T", "tooltip": "Common" },
{ "path": "chapters/06", "symbol": "T", "tooltip": "Common" },
{ "path": "chapters/07", "symbol": "T", "tooltip": "Common" },
]
}

37
Bachelor.bib Normal file
View File

@ -0,0 +1,37 @@
@online{bizzottoComparisonPopularFlutter2023,
title = {A {{Comparison}} of {{Popular Flutter App Architectures}}},
author = {Bizzotto, Andrea},
date = {2023-09-01},
url = {https://codewithandrea.com/articles/comparison-flutter-app-architectures/},
urldate = {2023-11-19},
abstract = {Comparing my Riverpod App Architecture with other popular ones such as MVC, MVVM, Bloc, Stacked, Clean Architecture, and Android App Architecture.},
langid = {english},
organization = {{Code With Andrea}},
file = {/Users/fabian/Zotero/storage/DUDXBAGD/comparison-flutter-app-architectures.html}
}
@online{FlutterArchitecturalOverviewb,
title = {Flutter Architectural Overview},
url = {https://docs.flutter.dev/resources/architectural-overview},
urldate = {2024-02-12},
abstract = {A high-level overview of the architecture of Flutter, including the core principles and concepts that form its design.},
langid = {english},
file = {/Users/fabian/Zotero/storage/W67CJYBZ/architectural-overview.html}
}
@article{weiserComputer21stCentury1999,
title = {The Computer for the 21st Century},
author = {Weiser, Mark},
date = {1999-07-01},
journaltitle = {ACM SIGMOBILE Mobile Computing and Communications Review},
shortjournal = {SIGMOBILE Mob. Comput. Commun. Rev.},
volume = {3},
number = {3},
pages = {3--11},
issn = {1559-1662},
doi = {10.1145/329124.329126},
url = {https://dl.acm.org/doi/10.1145/329124.329126},
urldate = {2023-11-14},
abstract = {Specialized elements of hardware and software, connected by wires, radio waves and infrared, will be so ubiquitous that no one will notice their presence.},
file = {/Users/fabian/Zotero/storage/8CCSE83J/Weiser - 1999 - The computer for the 21st century.pdf}
}

21
Makefile Normal file
View File

@ -0,0 +1,21 @@
SHELL:=/bin/bash
MARKDOWN_FILES := $(shell find chapters -type f -name "*.md" | sort | tr '\n' ' ')
BACHELOR_TEXT := @cat $(MARKDOWN_FILES)
all: local
help:
@echo "Please choose an option!"
@echo "- Create pdf: make pdf"
dir:
mkdir -p out
bachelor: @cat $(MARKDOWN_FILES)
local: dir
@echo "Building paper"
MERMAID_FILTER_FORMAT=pdf pandoc -V colorlinks=true -V linkcolor=black -V urlcolor=black -f 'markdown+autolink_bare_uris' --pdf-engine=lualatex --pdf-engine-opt=-shell-escape --filter mermaid-filter --lua-filter columns.lua --citeproc -s $(MARKDOWN_FILES) -o ./out/bachelor.pdf -V lang=de-DE -V fontsize=11pt --highlight-style tango --reference-links --bibliography Bachelor.bib --csl=harvard-right.csl -M lang:de --number-sections
clean:
rm -rf out

BIN
assets/.DS_Store vendored Normal file

Binary file not shown.

BIN
assets/skizzen/dashgame.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

BIN
assets/skizzen/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

BIN
assets/skizzen/led.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

BIN
assets/skizzen/matrix.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

BIN
assets/skizzen/openapi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

BIN
assets/skizzen/redled.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
assets/skizzen/sparkfun.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

BIN
assets/skizzen/video.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
chapters/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,79 @@
---
header-includes: |
\usepackage[T1]{fontenc}
\usepackage[usefilenames,RMstyle={Text,Semibold},SSstyle={Text,Semibold},TTstyle={Text,Semibold},DefaultFeatures={Ligatures=Common}]{plex-otf}
\usepackage[a4paper,bindingoffset=0.2in,%
left=4cm,right=2cm,top=2cm,bottom=2cm,%
footskip=.25in]{geometry}
\usepackage{fancyhdr}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{snakes,arrows,shapes}
\usepackage{amsmath}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.8}
\usepackage{multicol,lipsum}
\usepackage{listings}
\usepackage{wrapfig}
\usepackage[font=small,labelfont=bf]{caption}
\usepackage{graphicx}
\usepackage{xcolor,stackengine}
\usepackage{colortbl}
\usepackage{tcolorbox}
\usepackage{lastpage}
\usepackage{subcaption}
\usepackage{tabularx}
\usepackage{biblatex}
\usepackage{float}
\usepackage{refract}
\usepackage{svg}
\usepackage{setspace}
\usepackage{titling}
\usepackage{fvextra}
\usepackage{emoji}
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{breaklines,commandchars=\\\{\}}
\newcommand{\hideFromPandoc}[1]{#1}
\hideFromPandoc{
\let\Begin\begin
\let\End\end
}
\makeatletter
\def\fps@figure{h}
\makeatother
nocite: |
@*
---
\setstretch{1.5}
\setemojifont{Twemoji Mozilla}
\renewcommand{\familydefault}{\sfdefault}
\graphicspath{ {./img/} }
\overfullrule=0pt
\newcolumntype{C}{>{\centering\arraybackslash}X}
\renewcommand{\comment}[1]{\hspace{2em}{\small\textit{#1}}\bigskip\par}
\newcommand\palbox[1]{{\sffamily\fboxsep=5pt\relax\fboxrule=1pt\relax\footnotesize%
\fcolorbox{gray!50}{gray!10}{%
\stackengine{4pt}{%
\colorbox[HTML]{#1}{\rule{30pt}{0pt}\rule{0pt}{30pt}}%
}{%
\color{black!60}\stackengine{6pt}{\##1}{\saycolors{#1}}{U}{l}{F}{F}{S}%
}{U}{l}{F}{F}{S}%
}%
}}
\newcommand\saycolors[1]{\relax}
\lstset{
basicstyle=\ttfamily,
columns=fullflexible,
frame=single,
breaklines=true,
postbreak=\mbox{\textcolor{red}{$\hookrightarrow$}\space},
}

View File

@ -0,0 +1,32 @@
\thispagestyle{empty}
\begin{titlepage}
\begin{center}
\Large Hochschule Rhein-Waal \\
\vspace{2.5cm}
\Large Proposal für die Bachelorarbeit \\
\vspace{2.5cm}
\huge \textbf{\textsc{Flutter als Entwicklungsplattform für eingebettete Linux Systeme: eine Fallstudie}} \\
\vspace{1.0cm}
\Large Fabian Baldeau \\
\vspace{2.5cm}
\vspace{0.25cm}
\textsc{Studiengang}\\
\vspace{0.25cm}
\textsc{Medieninformatik}\\
\vspace{2.5cm}
\textsc{Gutachter}\\
\vspace{0.25cm}
\textsc{Prof. Dr.-Ing. Ido Iurgel}\\
\vspace{0.25cm}
\textsc{Prof. Dr. Kai Essig}\\
\vspace{2cm}
\end{center}
\end{titlepage}
\pagenumbering{Roman}
\fancyhf{}
\fancyhead[C]{\thepage}
\renewcommand{\headrulewidth}{0pt}
\pagestyle{fancy}

View File

View File

@ -0,0 +1,23 @@
\tableofcontents
\pagebreak
<!-- \fzframelinU{
\centering
\Huge{Kurz-Exposé} \\
\Large{\emph{Subtitle}}\\
\vspace{0.25cm}
\small{University/School}\\
\small{Class}\\
\small{Name}
}
\vspace{8pt} -->
\renewcommand{\headrulewidth}{0pt}
\pagenumbering{arabic}
<!-- \fancyfoot[C]{Seite \thepage\ von \pageref{LastPage}} -->
\fancyhead[C]{}
\fancyfoot[R]{\thepage}

View File

@ -0,0 +1 @@

View File

View File

View File

View File

View File

View File

View File

View File

@ -0,0 +1,25 @@
<!-- TODO: Was ist Flutter? -->
# Flutter
Was ist Flutter [@FlutterArchitecturalOverviewb]
test [@weiserComputer21stCentury1999]
```{#test .dart .number-lines caption="Example Dart test"}
import 'package:retry/retry.dart';
final response = await retry(
// Make a GET request
() => http.get('https://google.com').timeout(Duration(seconds: 5)),
// Retry on SocketException or TimeoutException
retryIf: (e) => e is SocketException || e is TimeoutException,
);
print(response.body);
```
Nice Dart highlighting!
![](./assets/skizzen/led.png)
WORKING :)

BIN
chapters/05_yocto/.DS_Store vendored Normal file

Binary file not shown.

View File

View File

View File

View File

BIN
chapters/06_flutter/.DS_Store vendored Normal file

Binary file not shown.

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

BIN
chapters/07_fazit/.DS_Store vendored Normal file

Binary file not shown.

View File

View File

View File

@ -0,0 +1,3 @@
\pagebreak
# Literaturverzeichnis

941
columns.lua Normal file
View File

@ -0,0 +1,941 @@
--[[-- # Columns - multiple column support in Pandoc's markdown.
This Lua filter provides support for multiple columns in
latex and html outputs. For details, see README.md.
@author Julien Dutant <julien.dutant@kcl.ac.uk>
@copyright 2021 Julien Dutant
@license MIT - see LICENSE file for details.
@release 1.1.2
]]
-- # Version control
local required_version = '2.9.0'
local version_err_msg = "ERROR: pandoc >= " .. required_version
.. " required for columns filter"
-- pandoc 2.9 required for pandoc.List insert method
-- if PANDOC_VERSION == nil then -- if pandoc_version < 2.1
-- error(version_err_msg)
-- elseif PANDOC_VERSION[2] < 9 then
-- error(version_err_msg)
-- else
-- PANDOC_VERSION:must_be_at_least(required_version, version_err_msg)
-- end
local utils = require('pandoc.utils') -- this is superfluous in Pandoc >= 2.7 I think
-- # Internal settings
-- target_formats filter is triggered when those formats are targeted
local target_formats = {
"html.*",
"latex",
}
local options = {
raggedcolumns = false, -- global ragged columns option
}
-- # Helper functions
--- type: pandoc-friendly type function
-- panbdoc.utils.type is only defined in Pandoc >= 2.17
-- if it isn't, we extend Lua's type function to give the same values
-- as pandoc.utils.type on Meta objects: Inlines, Inline, Blocks, Block,
-- string and booleans
-- Caution: not to be used on non-Meta Pandoc elements, the
-- results will differ (only 'Block', 'Blocks', 'Inline', 'Inlines' in
-- >=2.17, the .t string in <2.17).
local type = utils.type or function(obj)
local tag = type(obj) == 'table' and obj.t and obj.t:gsub('^Meta', '')
return tag and tag ~= 'Map' and tag or type(obj)
end
--- Test whether the target format is in a given list.
-- @param formats list of formats to be matched
-- @return true if match, false otherwise
local function format_matches(formats)
for _, format in pairs(formats) do
if FORMAT:match(format) then
return true
end
end
return false
end
--- Add a block to the document's header-includes meta-data field.
-- @param meta the document's metadata block
-- @param block Pandoc block element (e.g. RawBlock or Para) to be added to header-includes
-- @return meta the modified metadata block
local function add_header_includes(meta, block)
local header_includes = pandoc.List:new()
-- use meta['header-includes']
if meta['header-includes'] then
if type(meta['header-includes']) == 'List' then
header_includes:extend(meta['header-includes'])
else
header_includes:insert(meta['header-includes'])
end
end
-- insert `block` in header-includes
header_includes:insert(pandoc.MetaBlocks({ block }))
-- save header-includes in the document's meta
meta['header-includes'] = header_includes
return meta
end
--- Add a class to an element.
-- @param element Pandoc AST element
-- @param class name of the class to be added (string)
-- @return the modified element, or the unmodified element if the element has no classes
local function add_class(element, class)
-- act only if the element has classes
if element.attr and element.attr.classes then
-- if the class is absent, add it
if not element.attr.classes:includes(class) then
element.attr.classes:insert(class)
end
end
return element
end
--- Removes a class from an element.
-- @param element Pandoc AST element
-- @param class name of the class to be removed (string)
-- @return the modified element, or the unmodified element if the element has no classes
local function remove_class(element, class)
-- act only if the element has classes
if element.attr and element.attr.classes then
-- if the class is present, remove it
if element.attr.classes:includes(class) then
element.attr.classes = element.attr.classes:filter(
function(x)
return not (x == class)
end
)
end
end
return element
end
--- Set the value of an element's attribute.
-- @param element Pandoc AST element to be modified
-- @param key name of the attribute to be set (string)
-- @param value value to be set. If nil, the attribute is removed.
-- @return the modified element, or the element if it's not an element with attributes.
local function set_attribute(element, key, value)
-- act only if the element has attributes
if element.attr and element.attr.attributes then
-- if `value` is `nil`, remove the attribute
if value == nil then
if element.attr.attributes[key] then
element.attr.attributes[key] = nil
end
-- otherwise set its value
else
element.attr.attributes[key] = value
end
end
return element
end
--- Add html style markup to an element's attributes.
-- @param element the Pandoc AST element to be modified
-- @param style the style markup to add (string in CSS)
-- @return the modified element, or the unmodified element if it's an element without attributes
local function add_to_html_style(element, style)
-- act only if the element has attributes
if element.attr and element.attr.attributes then
-- if the element has style markup, append
if element.attr.attributes['style'] then
element.attr.attributes['style'] =
element.attr.attributes['style'] .. '; ' .. style .. ' ;'
-- otherwise create
else
element.attr.attributes['style'] = style .. ' ;'
end
end
return element
end
--- Translate an English number name into a number.
-- Converts cardinals ("one") and numerals ("first").
-- Returns nil if the name isn't understood.
-- @param name an English number name (string)
-- @return number or nil
local function number_by_name(name)
local names = {
one = 1,
two = 2,
three = 3,
four = 4,
five = 5,
six = 6,
seven = 7,
eight = 8,
nine = 9,
ten = 10,
first = 1,
second = 2,
third = 3,
fourth = 4,
fifth = 5,
sixth = 6,
seventh = 7,
eighth = 8,
ninth = 9,
tenth = 10,
}
result = nil
if name and names[name] then
return names[name]
end
end
--- Convert some CSS values (lengths, colous) to LaTeX equivalents.
-- Example usage: `css_values_to_latex("1px solid black")` returns
-- `{ length = "1pt", color = "black", colour = "black"}`.
-- @param css_str a CSS string specifying a value
-- @return table with keys `length`, `color` (alias `colour`) if found
local function css_values_to_latex(css_str)
-- color conversion table
-- keys are CSS values, values are LaTeX equivalents
latex_colors = {
-- xcolor always available
black = 'black',
blue = 'blue',
brown = 'brown',
cyan = 'cyan',
darkgray = 'darkgray',
gray = 'gray',
green = 'green',
lightgray = 'lightgray',
lime = 'lime',
magenta = 'magenta',
olive = 'olive',
orange = 'orange',
pink = 'pink',
purple = 'purple',
red = 'red',
teal = 'teal',
violet = 'violet',
white = 'white',
yellow = 'yellow',
-- css1 colors
silver = 'lightgray',
fuschia = 'magenta',
aqua = 'cyan',
}
local result = {}
-- look for color values
-- by color name
-- rgb, etc.: to be added
local color = ''
-- space in front simplifies pattern matching
css_str = ' ' .. css_str
-- look for colour names
for text in string.gmatch(css_str, '[%s](%a+)') do
-- if we have LaTeX equivalent of `text`, store it
if latex_colors[text] then
result['color'] = latex_colors[text]
end
end
-- provide British spelling
if result['color'] then
result['colour'] = result['color']
end
-- look for lengths
-- 0 : converted to 0em
if string.find(css_str, '%s0%s') then
result['length'] = '0em'
end
-- px : converted to pt
for text in string.gmatch(css_str, '(%s%d+)px') do
result['length'] = text .. 'pt'
end
-- lengths units to be kept as is
-- nb, % must be escaped
-- nb, if several found, the latest type is preserved
keep_units = { '%%', 'pt', 'mm', 'cm', 'in', 'ex', 'em' }
for _, unit in pairs(keep_units) do
-- .11em format
for text in string.gmatch(css_str, '%s%.%d+' .. unit) do
result['length'] = text
end
-- 2em and 1.2em format
for text in string.gmatch(css_str, '%s%d+%.?%d*' .. unit) do
result['length'] = text
end
end
return result
end
--- Ensures that a string specifies a LaTeX length
-- @param text text to be checked
-- @return text if it is a LaTeX length, `nil` otherwise
local function ensures_latex_length(text)
-- LaTeX lengths units
-- nb, % must be escaped in lua patterns
units = { '%%', 'pt', 'mm', 'cm', 'in', 'ex', 'em' }
local result = nil
-- ignore spaces, controls and punctuation other than
-- dot, plus, minus
text = string.gsub(text, "[%s%c,;%(%)%[%]%*%?%%%^%$]+", "")
for _, unit in pairs(units) do
-- match .11em format and 1.2em format
if string.match(text, '^%.%d+' .. unit .. '$') or
string.match(text, '^%d+%.?%d*' .. unit .. '$') then
result = text
end
end
return result
end
-- # Filter-specific functions
--- Process the metadata block.
-- Adds any needed material to the document's metadata block.
-- @param meta the document's metadata element
local function process_meta(meta)
-- in LaTeX, require the `multicols` package
if FORMAT:match('latex') then
return add_header_includes(meta,
pandoc.RawBlock('latex', '\\usepackage{multicol}\n'))
end
-- in html, ensure that the first element of `columns` div
-- has a top margin of zero (otherwise we get white space
-- on the top of the first column)
-- idem for the first element after a `column-span` element
if FORMAT:match('html.*') then
html_header = [[
<style>
/* Styles added by the columns.lua pandoc filter */
.columns :first-child {margin-top: 0;}
.column-span + * {margin-top: 0;}
</style>
]]
return add_header_includes(meta, pandoc.RawBlock('html', html_header))
end
return meta
end
--- Convert explicit columnbreaks.
-- This function converts any explict columnbreak markup in an element
-- into a single syntax: a Div with class `columnbreak`.
-- Note: if there are `column` Divs in the element we keep them
-- in case they harbour further formatting (e.g. html classes). However
-- we remove their `column` class to avoid double-processing when
-- column fields are nested.
-- @param elem Pandoc native Div element
-- @return elem modified as needed
local function convert_explicit_columbreaks(elem)
-- if `elem` ends with a `column` Div, this last Div should
-- not generate a columnbreak. We tag it to make sure we don't convert it.
if elem.content[#elem.content] and elem.content[#elem.content].classes
and elem.content[#elem.content].classes:includes('column') then
elem.content[#elem.content] =
add_class(elem.content[#elem.content], 'column-div-in-last-position')
end
-- processes `column` Divs and `\columnbreak` LaTeX RawBlocks
filter = {
Div = function(el)
-- syntactic sugar: `column-break` converted to `columnbreak`
if el.classes:includes("column-break") then
el = add_class(el, "columnbreak")
el = remove_class(el, "column-break")
end
if el.classes:includes("column") then
-- with `column` Div, add a break if it's not in last position
if not el.classes:includes('column-div-in-last-position') then
local breaking_div = pandoc.Div({})
breaking_div = add_class(breaking_div, "columnbreak")
el.content:insert(breaking_div)
-- if it's in the last position, remove the custom tag
else
el = remove_class(el, 'column-div-in-last-position')
end
-- remove `column` classes, but leave the div and other
-- attributes the user might have added
el = remove_class(el, 'column')
end
return el
end,
RawBlock = function(el)
if el.format == "tex" and el.text == '\\columnbreak' then
local breaking_div = pandoc.Div({})
breaking_div = add_class(breaking_div, "columnbreak")
return breaking_div
else
return el
end
end
}
return pandoc.walk_block(elem, filter)
end
--- Tag an element with the number of explicit columnbreaks it contains.
-- Counts the number of epxlicit columnbreaks contained in an element and
-- tags the element with a `number_explicit_columnbreaks` attribute.
-- In the process columnbreaks are tagged with the class `columnbreak_already_counted`
-- in order to avoid double-counting when multi-columns are nested.
-- @param elem Pandoc element (native Div element of class `columns`)
-- @return elem with the attribute `number_explicit_columnbreaks` set.
local function tag_with_number_of_explicit_columnbreaks(elem)
local number_columnbreaks = 0
local filter = {
Div = function(el)
if el.classes:includes('columnbreak') and
not el.classes:includes('columnbreak_already_counted') then
number_columnbreaks = number_columnbreaks + 1
el = add_class(el, 'columnbreak_already_counted')
end
return el
end
}
elem = pandoc.walk_block(elem, filter)
elem = set_attribute(elem, 'number_explicit_columnbreaks',
number_columnbreaks)
return elem
end
--- Consolidate aliases for column attributes.
-- Provides syntacic sugar: unifies various ways of
-- specifying attributes of a multi-column environment.
-- When several specifications conflit, favours `column-gap` and
-- `column-rule` specifications.
-- @param elem Pandoc element (Div of class `columns`) with column attributes.
-- @return elem modified as needed.
local function consolidate_colattrib_aliases(elem)
if elem.attr and elem.attr.attributes then
-- `column-gap` if the preferred syntax is set, erase others
if elem.attr.attributes["column-gap"] then
elem = set_attribute(elem, "columngap", nil)
elem = set_attribute(elem, "column-sep", nil)
elem = set_attribute(elem, "columnsep", nil)
-- otherwise fetch and unset any alias
else
if elem.attr.attributes["columnsep"] then
elem = set_attribute(elem, "column-gap",
elem.attr.attributes["columnsep"])
elem = set_attribute(elem, "columnsep", nil)
end
if elem.attr.attributes["column-sep"] then
elem = set_attribute(elem, "column-gap",
elem.attr.attributes["column-sep"])
elem = set_attribute(elem, "column-sep", nil)
end
if elem.attr.attributes["columngap"] then
elem = set_attribute(elem, "column-gap",
elem.attr.attributes["columngap"])
elem = set_attribute(elem, "columngap", nil)
end
end
-- `column-rule` if the preferred syntax is set, erase others
if elem.attr.attributes["column-rule"] then
elem = set_attribute(elem, "columnrule", nil)
-- otherwise fetch and unset any alias
else
if elem.attr.attributes["columnrule"] then
elem = set_attribute(elem, "column-rule",
elem.attr.attributes["columnrule"])
elem = set_attribute(elem, "columnrule", nil)
end
end
end
return elem
end
--- Pre-process a Div of class `columns`.
-- Converts explicit column breaks into a unified syntax
-- and count the Div's number of columns.
-- When several columns are nested Pandoc will apply
-- this filter to the innermost `columns` Div first;
-- we use that feature to prevent double-counting.
-- @param elem Pandoc element to be processes (Div of class `columns`)
-- @return elem modified as needed
local function preprocess_columns(elem)
-- convert any explicit column syntax in a single format:
-- native Divs with class `columnbreak`
elem = convert_explicit_columbreaks(elem)
-- count explicit columnbreaks
elem = tag_with_number_of_explicit_columnbreaks(elem)
return elem
end
--- Determine the number of column in a `columns` Div.
-- Looks up two attributes in the Div: the user-specified
-- `columns-count` and the filter-generated `number_explicit_columnbreaks`
-- which is based on the number of explicit breaks specified.
-- The final number of columns will be 2 or whichever of `column-count` and
-- `number_explicit_columnbreaks` is the highest. This ensures there are
-- enough columns for all explicit columnbreaks.
-- This provides a single-column when the user specifies `column-count = 1` and
-- there are no explicit columnbreaks.
-- @param elem Pandoc element (Div of class `columns`) whose number of columns is to be determined.
-- @return number of columns (number, default 2).
local function determine_column_count(elem)
-- is there a specified column count?
local specified_column_count = 0
if elem.attr.attributes and elem.attr.attributes['column-count'] then
specified_column_count = tonumber(
elem.attr.attributes["column-count"])
end
-- is there an count of explicit columnbreaks?
local number_explicit_columnbreaks = 0
if elem.attr.attributes and elem.attr.attributes['number_explicit_columnbreaks'] then
number_explicit_columnbreaks = tonumber(
elem.attr.attributes['number_explicit_columnbreaks']
)
set_attribute(elem, 'number_explicit_columnbreaks', nil)
end
-- determines the number of columns
-- default 2
-- recall that number of columns = nb columnbreaks + 1
local number_columns = 2
if specified_column_count > 0 or number_explicit_columnbreaks > 0 then
if (number_explicit_columnbreaks + 1) > specified_column_count then
number_columns = number_explicit_columnbreaks + 1
else
number_columns = specified_column_count
end
end
return number_columns
end
--- Convert a pandoc Header to a list of inlines for latex output.
-- @param header Pandoc Header element
-- @return list of Inline elements
local function header_to_latex_and_inlines(header)
-- @todo check if level interpretation has been shifted, e.g. section is level 2
-- @todo we could check the Pandoc state to check whether hypertargets are required?
local latex_header = {
'section',
'subsection',
'subsubsection',
'paragraph',
'subparagraph',
}
-- create a list if the header's inlines
local inlines = pandoc.List:new(header.content)
-- wrap in a latex_header if available
if header.level and latex_header[header.level] then
inlines:insert(1, pandoc.RawInline('latex',
'\\' .. latex_header[header.level] .. '{'))
inlines:insert(pandoc.RawInline('latex', '}'))
end
-- wrap in a link if available
if header.identifier then
inlines:insert(1, pandoc.RawInline('latex',
'\\hypertarget{' .. header.identifier .. '}{%\n'))
inlines:insert(pandoc.RawInline('latex',
'\\label{' .. header.identifier .. '}}'))
end
return inlines
end
--- Format column span in LaTeX.
-- Formats a bit of text spanning across all columns for LaTeX output.
-- If the colspan is only one block, it is turned into an option
-- of a new `multicol` environment. Otherwise insert it is
-- inserted between the two `multicol` environments.
-- @param elem Pandoc element that is supposed to span across all
-- columns.
-- @param number_columns number of columns in the present environment.
-- @return a pandoc RawBlock element in LaTeX format
local function format_colspan_latex(elem, number_columns)
local result = pandoc.List:new()
-- does the content consists of a single header?
if #elem.content == 1 and elem.content[1].t == 'Header' then
-- create a list of inlines
inlines = pandoc.List:new()
inlines:insert(pandoc.RawInline('latex',
"\\end{multicols}\n"))
inlines:insert(pandoc.RawInline('latex',
"\\begin{multicols}{" .. number_columns .. "}["))
inlines:extend(header_to_latex_and_inlines(elem.content[1]))
inlines:insert(pandoc.RawInline('latex', "]\n"))
-- insert as a Plain block
result:insert(pandoc.Plain(inlines))
return result
else
result:insert(pandoc.RawBlock('latex',
"\\end{multicols}\n"))
result:extend(elem.content)
result:insert(pandoc.RawBlock('latex',
"\\begin{multicols}{" .. number_columns .. "}"))
return result
end
end
--- Format columns for LaTeX output
-- @param elem Pandoc element (Div of "columns" class) containing the
-- columns to be formatted.
-- @return elem with suitable RawBlocks in LaTeX added
local function format_columns_latex(elem)
-- make content into a List object
pandoc.List:new(elem.content)
-- how many columns?
number_columns = determine_column_count(elem)
-- set properties and insert LaTeX environment
-- we wrap the entire environment in `{...}` to
-- ensure properties (gap, rule) don't carry
-- over to following columns
local latex_begin = '{'
local latex_end = '}'
local ragged = options.raggedcolumns
-- override global ragged setting?
if elem.classes:includes('ragged')
or elem.classes:includes('raggedcolumns')
or elem.classes:includes('ragged-columns') then
ragged = true
elseif elem.classes:includes('justified')
or elem.classes:includes('justifiedcolumns')
or elem.classes:includes('justified-columns') then
ragged = false
end
if ragged then
latex_begin = latex_begin .. '\\raggedcolumns'
end
if elem.attr.attributes then
if elem.attr.attributes["column-gap"] then
local latex_value = ensures_latex_length(
elem.attr.attributes["column-gap"])
if latex_value then
latex_begin = latex_begin ..
"\\setlength{\\columnsep}{" .. latex_value .. "}\n"
end
-- remove the `column-gap` attribute
elem = set_attribute(elem, "column-gap", nil)
end
if elem.attr.attributes["column-rule"] then
-- converts CSS value string to LaTeX values
local latex_values = css_values_to_latex(
elem.attr.attributes["column-rule"])
if latex_values["length"] then
latex_begin = latex_begin ..
"\\setlength{\\columnseprule}{" ..
latex_values["length"] .. "}\n"
end
if latex_values["color"] then
latex_begin = latex_begin ..
"\\renewcommand{\\columnseprulecolor}{\\color{" ..
latex_values["color"] .. "}}\n"
end
-- remove the `column-rule` attribute
elem = set_attribute(elem, "column-rule", nil)
end
end
latex_begin = latex_begin ..
"\\begin{multicols}{" .. number_columns .. "}\n"
latex_end = "\\end{multicols}\n" .. latex_end
elem.content:insert(1, pandoc.RawBlock('latex', latex_begin))
elem.content:insert(pandoc.RawBlock('latex', latex_end))
-- process blocks contained in `elem`
-- turn any explicit columnbreaks into LaTeX markup
-- turn `column-span` Divs into LaTeX markup
filter = {
Div = function(el)
if el.classes:includes("columnbreak") then
return pandoc.RawBlock('latex', "\\columnbreak\n")
end
if el.classes:includes("column-span-to-be-processed") then
return format_colspan_latex(el, number_columns)
end
end
}
elem = pandoc.walk_block(elem, filter)
return elem
end
--- Formats columns for html output.
-- Uses CSS3 style added to the elements themselves.
-- @param elem Pandoc element (Div of `columns` style)
-- @return elem with suitable html attributes
local function format_columns_html(elem)
-- how many columns?
number_columns = determine_column_count(elem)
-- add properties to the `columns` Div
elem = add_to_html_style(elem, 'column-count: ' .. number_columns)
elem = set_attribute(elem, 'column-count', nil)
if elem.attr.attributes then
if elem.attr.attributes["column-gap"] then
elem = add_to_html_style(elem, 'column-gap: ' ..
elem.attr.attributes["column-gap"])
-- remove the `column-gap` attribute
elem = set_attribute(elem, "column-gap")
end
if elem.attr.attributes["column-rule"] then
elem = add_to_html_style(elem, 'column-rule: ' ..
elem.attr.attributes["column-rule"])
-- remove the `column-rule` attribute
elem = set_attribute(elem, "column-rule", nil)
end
end
-- convert any explicit columnbreaks in CSS markup
filter = {
Div = function(el)
-- format column-breaks
if el.classes:includes("columnbreak") then
el = add_to_html_style(el, 'break-after: column')
-- remove columbreaks class to avoid double processing
-- when nested
-- clean up already-counted tag
el = remove_class(el, "columnbreak")
el = remove_class(el, "columnbreak_already_counted")
-- format column-spans
elseif el.classes:includes("column-span-to-be-processed") then
el = add_to_html_style(el, 'column-span: all')
-- remove column-span-to-be-processed class to avoid double processing
-- add column-span class to allow for styling
el = add_class(el, "column-span")
el = remove_class(el, "column-span-to-be-processed")
end
return el
end
}
elem = pandoc.walk_block(elem, filter)
return elem
end
-- # Main filters
--- Formating filter.
-- Applied last, converts prepared columns in target output formats
-- @field Div looks for `columns` class
format_filter = {
Div = function(element)
-- pick up `columns` Divs for formatting
if element.classes:includes("columns") then
if FORMAT:match('latex') then
element = format_columns_latex(element)
elseif FORMAT:match('html.*') then
element = format_columns_html(element)
end
return element
end
end
}
--- Preprocessing filter.
-- Processes meta-data fields and walks the document to pre-process
-- columns blocks. Determine how many columns they contain, tags the
-- last column Div, etc. Avoids double-counting when columns environments
-- are nested.
-- @field Div looks for `columns` class
-- @field Meta processes the metadata block
preprocess_filter = {
Div = function(element)
-- send `columns` Divs to pre-processing
if element.classes:includes("columns") then
return preprocess_columns(element)
end
end,
Meta = function(meta)
return process_meta(meta)
end
}
--- Syntactic sugar filter.
-- Provides alternative ways of specifying columns properties.
-- Kept separate from the pre-processing filter for clarity.
-- @field Div looks for Div of classes `columns` (and related) and `column-span`
syntactic_sugar_filter = {
Div = function(element)
-- convert "two-columns" into `columns` Divs
for _, class in pairs(element.classes) do
-- match xxxcolumns, xxx_columns, xxx-columns
-- if xxx is the name of a number, make
-- a `columns` div and set its `column-count` attribute
local number = number_by_name(
string.match(class, '(%a+)[_%-]?columns$')
)
if number then
element = set_attribute(element,
"column-count", tostring(number))
element = remove_class(element, class)
element = add_class(element, "columns")
end
end
-- allows different ways of specifying `columns` attributes
if element.classes:includes('columns') then
element = consolidate_colattrib_aliases(element)
end
-- `column-span` syntax
-- mark up as "to-be-processed" to avoid
-- double processing when nested
if element.classes:includes('column-span') or
element.classes:includes('columnspan') then
element = add_class(element, 'column-span-to-be-processed')
element = remove_class(element, 'column-span')
element = remove_class(element, 'columnspan')
end
return element
end
}
--- Read options filter
read_options_filter = {
Meta = function(meta)
if not meta then return end
-- global vertical ragged / justified settings
if meta.raggedcolumns or meta['ragged-columns'] then
options.raggedcolumns = true
elseif meta.justifiedcolumns or meta['justified-columns'] then
options.raggedcolumns = false
end
end
}
-- Main statement returns filters only if the
-- target format matches our list. The filters
-- returned are applied in the following order:
-- 1. `syntatic_sugar_filter` deals with multiple syntax
-- 2. `preprocessing_filter` converts all explicit
-- columnbreaks into a common syntax and tags
-- those that are already counted. We must do
-- that for all `columns` environments before
-- turning any break back into LaTeX `\columnbreak` blocks
-- otherwise we mess up the count in nested `columns` Divs.
-- 3. `format_filter` formats the columns after the counting
-- has been done
if format_matches(target_formats) then
return {
read_options_filter,
syntactic_sugar_filter,
preprocess_filter,
format_filter
}
else
return
end

15
docker-compose.yml Normal file
View File

@ -0,0 +1,15 @@
version: "2.4"
services:
void:
# if you want to build your own container locally:
# container_name: paper-builder
# build: .
image: baldeau/paper-builder
platform: linux/amd64
volumes:
- ".:/paper"
environment:
- PATH=$PATH:~/.local/bin
- PATH=$PATH:~/.cabal/bin
- TERM=xterm-256color
command: bash -c "cd paper && ./docker_build.sh"

11
docker_build.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
shopt -s globstar # Enable recursive globbing
markdown_files=(chapters/**/*.md)
IFS=$'\n'
sorted_files=($(sort <<<"${markdown_files[*]}"));
unset IFS
echo "${sorted_files[@]}"
MERMAID_FILTER_FORMAT=pdf pandoc -V colorlinks=true -V linkcolor=black -V urlcolor=black -f 'markdown+autolink_bare_uris' --pdf-engine=lualatex --pdf-engine-opt=-shell-escape --filter mermaid-filter --lua-filter columns.lua --citeproc -s "${sorted_files[@]}" -o ./out/bachelor.pdf -V lang=de-DE -V fontsize=11pt --highlight-style tango --reference-links --bibliography Bachelor.bib --csl=harvard-right.csl -M lang:de --number-sections

318
harvard-right.csl Normal file
View File

@ -0,0 +1,318 @@
<?xml version="1.0" encoding="utf-8"?>
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only" default-locale="en-GB">
<info>
<title>Cite Them Right 11th edition - Harvard</title>
<id>http://www.zotero.org/styles/harvard-cite-them-right</id>
<link href="http://www.zotero.org/styles/harvard-cite-them-right" rel="self"/>
<link href="http://www.zotero.org/styles/harvard-cite-them-right-10th-edition" rel="template"/>
<link href="http://www.citethemrightonline.com/" rel="documentation"/>
<author>
<name>Patrick O'Brien</name>
</author>
<category citation-format="author-date"/>
<category field="generic-base"/>
<summary>Harvard according to Cite Them Right, 11th edition.</summary>
<updated>2021-09-01T07:43:59+00:00</updated>
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
</info>
<locale xml:lang="en-GB">
<terms>
<term name="editor" form="short">
<single>ed.</single>
<multiple>eds</multiple>
</term>
<term name="editortranslator" form="verb">edited and translated by</term>
<term name="edition" form="short">edn.</term>
</terms>
</locale>
<macro name="editor">
<choose>
<if type="chapter paper-conference" match="any">
<names variable="container-author" delimiter=", " suffix=", ">
<name and="text" initialize-with=". " delimiter=", " sort-separator=", " name-as-sort-order="all"/>
</names>
<choose>
<if variable="container-author" match="none">
<names variable="editor translator" delimiter=", ">
<name and="text" initialize-with="." name-as-sort-order="all"/>
<label form="short" prefix=" (" suffix=")"/>
</names>
</if>
</choose>
</if>
</choose>
</macro>
<macro name="secondary-contributors">
<choose>
<if type="chapter paper-conference" match="none">
<names variable="editor translator" delimiter=". ">
<label form="verb" text-case="capitalize-first" suffix=" "/>
<name and="text" initialize-with="."/>
</names>
</if>
<else-if variable="container-author" match="any">
<names variable="editor translator" delimiter=". ">
<label form="verb" text-case="capitalize-first" suffix=" "/>
<name and="text" initialize-with=". " delimiter=", "/>
</names>
</else-if>
</choose>
</macro>
<macro name="author">
<names variable="author">
<name and="text" delimiter-precedes-last="never" initialize-with="." name-as-sort-order="all"/>
<label form="short" prefix=" (" suffix=")"/>
<et-al font-style="italic"/>
<substitute>
<names variable="editor"/>
<names variable="translator"/>
<choose>
<if type="article-newspaper article-magazine" match="any">
<text variable="container-title" text-case="title" font-style="italic"/>
</if>
<else>
<text macro="title"/>
</else>
</choose>
</substitute>
</names>
</macro>
<macro name="author-short">
<names variable="author">
<name form="short" and="text" delimiter=", " delimiter-precedes-last="never" initialize-with=". "/>
<et-al font-style="italic"/>
<substitute>
<names variable="editor"/>
<names variable="translator"/>
<choose>
<if type="article-newspaper article-magazine" match="any">
<text variable="container-title" text-case="title" font-style="italic"/>
</if>
<else>
<text macro="title"/>
</else>
</choose>
</substitute>
</names>
</macro>
<macro name="access">
<choose>
<if variable="DOI">
<text variable="DOI" prefix="doi:"/>
</if>
<else-if variable="URL">
<text term="available at" suffix=": " text-case="capitalize-first"/>
<text variable="URL"/>
<group prefix=" (" delimiter=": " suffix=")">
<text term="accessed" text-case="capitalize-first"/>
<date form="text" variable="accessed">
<date-part name="day"/>
<date-part name="month"/>
<date-part name="year"/>
</date>
</group>
</else-if>
</choose>
</macro>
<macro name="number-volumes">
<choose>
<if variable="volume" match="none">
<group delimiter=" " prefix="(" suffix=")">
<text variable="number-of-volumes"/>
<label variable="volume" form="short" strip-periods="true"/>
</group>
</if>
</choose>
</macro>
<macro name="title">
<choose>
<if type="bill book legal_case legislation motion_picture report song thesis webpage graphic" match="any">
<group delimiter=". ">
<group delimiter=" ">
<group delimiter=" ">
<text variable="title" font-style="italic"/>
<text variable="medium" prefix="[" suffix="]"/>
</group>
<text macro="number-volumes"/>
</group>
<text macro="edition"/>
</group>
</if>
<else>
<text variable="title" form="long" quotes="true"/>
</else>
</choose>
</macro>
<macro name="publisher">
<choose>
<if type="thesis">
<group delimiter=". ">
<text variable="genre"/>
<text variable="publisher"/>
</group>
</if>
<else-if type="report">
<group delimiter=". ">
<group delimiter=" ">
<text variable="genre"/>
<text variable="number"/>
</group>
<group delimiter=": ">
<text variable="publisher-place"/>
<text variable="publisher"/>
</group>
</group>
</else-if>
<else-if type="article-journal article-newspaper article-magazine" match="none">
<group delimiter=" ">
<group delimiter=", ">
<choose>
<if type="speech" variable="event" match="any">
<text variable="event" font-style="italic"/>
</if>
</choose>
<group delimiter=": ">
<text variable="publisher-place"/>
<text variable="publisher"/>
</group>
</group>
<group prefix="(" suffix=")" delimiter=", ">
<text variable="collection-title"/>
<text variable="collection-number"/>
</group>
</group>
</else-if>
</choose>
</macro>
<macro name="year-date">
<choose>
<if variable="issued">
<date variable="issued">
<date-part name="year"/>
</date>
<text variable="year-suffix"/>
</if>
<else>
<text term="no date"/>
<text variable="year-suffix" prefix=" "/>
</else>
</choose>
</macro>
<macro name="locator">
<choose>
<if type="article-journal">
<text variable="volume"/>
<text variable="issue" prefix="(" suffix=")"/>
</if>
</choose>
</macro>
<macro name="published-date">
<choose>
<if type="article-newspaper article-magazine post-weblog speech" match="any">
<date variable="issued">
<date-part name="day" suffix=" "/>
<date-part name="month" form="long"/>
</date>
</if>
</choose>
</macro>
<macro name="pages">
<choose>
<if type="chapter paper-conference article-journal article article-magazine article-newspaper book review review-book report" match="any">
<group delimiter=" ">
<label variable="page" form="short"/>
<text variable="page"/>
</group>
</if>
</choose>
</macro>
<macro name="container-title">
<choose>
<if variable="container-title">
<group delimiter=". ">
<group delimiter=" ">
<text variable="container-title" font-style="italic"/>
<choose>
<if type="article article-journal" match="any">
<choose>
<if match="none" variable="page volume">
<text value="Preprint" prefix="[" suffix="]"/>
</if>
</choose>
</if>
</choose>
</group>
<text macro="edition"/>
</group>
</if>
</choose>
</macro>
<macro name="edition">
<choose>
<if is-numeric="edition">
<group delimiter=" ">
<number variable="edition" form="ordinal"/>
<text term="edition" form="short" strip-periods="true"/>
</group>
</if>
<else>
<text variable="edition"/>
</else>
</choose>
</macro>
<macro name="container-prefix">
<choose>
<if type="chapter paper-conference" match="any">
<text term="in"/>
</if>
</choose>
</macro>
<citation et-al-min="4" et-al-use-first="1" disambiguate-add-year-suffix="true" disambiguate-add-names="true" disambiguate-add-givenname="true" collapse="year">
<sort>
<key macro="year-date"/>
</sort>
<layout prefix="(" suffix=")" delimiter="; ">
<group delimiter=", ">
<group delimiter=", ">
<text macro="author-short"/>
<text macro="year-date"/>
</group>
<group>
<label variable="locator" form="short" suffix=" "/>
<text variable="locator"/>
</group>
</group>
</layout>
</citation>
<bibliography and="text" et-al-min="4" et-al-use-first="1">
<sort>
<key macro="author"/>
<key macro="year-date"/>
<key variable="title"/>
</sort>
<layout suffix=".">
<group delimiter=". ">
<group delimiter=" ">
<text macro="author"/>
<text macro="year-date" prefix="(" suffix=")"/>
<group delimiter=", ">
<text macro="title"/>
<group delimiter=" ">
<text macro="container-prefix"/>
<text macro="editor"/>
<text macro="container-title"/>
</group>
</group>
</group>
<text macro="secondary-contributors"/>
<text macro="publisher"/>
</group>
<group delimiter=", " prefix=", ">
<text macro="locator"/>
<text macro="published-date"/>
<text macro="pages"/>
</group>
<text macro="access" prefix=". "/>
</layout>
</bibliography>
</style>

361
refract.sty Normal file
View File

@ -0,0 +1,361 @@
%%
%% This is the file fzframes.sty
%% Author: Kathryn Andersen <http://www.katspace.com>
%%
%% This provides a collection of nice frames based on the niceframes
%% package
%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{refract}[2001/06/22
fancy frames for fanzine package
: Kathryn Andersen]
\RequirePackage{niceframe}
\RequirePackage{graphics}
%% Frame with scrolly things
\newcommand{\fzframescroll}[1]{%
\font\border=umranda
\generalframe{\border\char'136}{\border\char'137}{\border\char'140}
{\border\char'145} {\border\char'141}
{\border\char'144}{\border\char'143}{\border\char'142}
{#1}}
%% Frame with flowers
\newcommand{\fzframeflower}[1]{%
\font\border=umranda
\generalframe{\border\char78}{\border\char79}{\border\char84}
{\border\char81} {\border\char85}
{\border\char80}{\border\char83}{\border\char82}
{#1}}
%% Frame with snakes
\newcommand{\fzframesnake}[1]{%
\font\border=umranda
\generalframe{\border\char87}{\border\char87}{\border\char87}
{\border\char89} {\border\char93}
{\border\char91}{\border\char91}{\border\char91}
{#1}}
%% Frame with triangles
\newcommand{\fzframetri}[1]{%
\font\border=umranda
\generalframe{\border\char7}{\border\char6}{\border\char5}
{\reflectbox{\border\char4}} {\border\char4}
{\border\char1}{\border\char2}{\border\char3}
{#1}}
%% Frame with triangles pointing out
\newcommand{\fzframetriout}[1]{%
\font\border=umranda
\generalframe{\border\char3}{\border\char2}{\border\char1}
{\border\char4} {\reflectbox{\border\char4}}
{\border\char5}{\border\char6}{\border\char7}
{#1}}
%% Here follows a collection of frames made of decorative boxes
%% so they are called fzframebx with a letter to differentiate
%% them, A-Z
\newcommand{\fzframebxA}[1]{%
\font\border=umranda
\generalframe{\border\char39}{\border\char37}{\border\char37}
{\border\char39} {\border\char43}
{\border\char41}{\border\char41}{\border\char43}
{#1}}
%
\newcommand{\fzframebxB}[1]{%
\font\border=umranda
\generalframe{\border\char41}{\border\char41}{\border\char39}
{\border\char43} {\border\char39}
{\border\char43}{\border\char37}{\border\char37}
{#1}}
\newcommand{\fzframebxC}[1]{%
\font\border=umranda
\generalframe{\border\char38}{\border\char38}{\border\char36}
{\border\char38} {\border\char36}
{\border\char40}{\border\char40}{\border\char42}
{#1}
}
\newcommand{\fzframebxD}[1]{%
\font\border=umranda
\generalframe{\border\char42}{\border\char40}{\border\char40}
{\border\char36} {\border\char38}
{\border\char36}{\border\char38}{\border\char38}
{#1}
}
\newcommand{\fzframebxE}[1]{%
\font\border=umranda
\generalframe{\border\char44}{\border\char44}{\border\char50}
{\border\char46} {\border\char50}
{\border\char46}{\border\char48}{\border\char48}
{#1}}
\newcommand{\fzframebxF}[1]{%
\font\border=umranda
\generalframe{\border\char51}{\border\char51}{\border\char49}
{\border\char45} {\border\char49}
{\border\char45}{\border\char47}{\border\char47}
{#1}}
%% Here follows a collection of frames made of circles
%% so they are called fzframecir with a letter to differentiate
%% them, A-Z
\newcommand{\fzframecirA}[1]{%
\font\border=umranda
\generalframe{\border\char34}{\border\char34}{\border\char34}
{\border\char34} {\border\char34}
{\border\char34}{\border\char34}{\border\char34}
{#1}}
\newcommand{\fzframecirB}[1]{%
\font\border=umranda
\generalframe{\border\char35}{\border\char35}{\border\char35}
{\border\char35} {\border\char35}
{\border\char35}{\border\char35}{\border\char35}
{#1}}
\newcommand{\fzframecirC}[1]{%
\font\border=umranda
\generalframe{\border\char20}{\border\char25}{\border\char24}
{\border\char22} {\border\char22}
{\border\char24}{\border\char25}{\border\char20}
{#1}}
\newcommand{\fzframecirD}[1]{%
\font\border=umranda
\generalframe{\border\char26}{\border\char30}{\border\char29}
{\border\char27} {\border\char27}
{\border\char29}{\border\char30}{\border\char26}
{#1}}
%% Here follows a collection of frames with lots of lines
%% so they are called fzframelin with a letter to differentiate
%% them, A-Z
%% This bunch, the border has 6 lines, same thickness
\newcommand{\fzframelinA}[1]{%
\font\border=umrandb
\generalframe{\border\char5}{\border\char1}{\border\char4}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char6}{\border\char3}{\border\char7}
{#1}}
\newcommand{\fzframelinB}[1]{%
\font\border=umrandb
\generalframe{\border\char9}{\border\char1}{\border\char8}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char10}{\border\char3}{\border\char11}
{#1}}
\newcommand{\fzframelinC}[1]{%
\font\border=umrandb
\generalframe{\border\char13}{\border\char1}{\border\char12}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char14}{\border\char3}{\border\char15}
{#1}}
\newcommand{\fzframelinD}[1]{%
\font\border=umrandb
\generalframe{\border\char17}{\border\char1}{\border\char16}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char18}{\border\char3}{\border\char19}
{#1}}
\newcommand{\fzframelinE}[1]{%
\font\border=umrandb
\generalframe{\border\char21}{\border\char1}{\border\char20}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char22}{\border\char3}{\border\char23}
{#1}}
\newcommand{\fzframelinF}[1]{%
\font\border=umrandb
\generalframe{\border\char25}{\border\char1}{\border\char24}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char26}{\border\char3}{\border\char27}
{#1}}
\newcommand{\fzframelinG}[1]{%
\font\border=umrandb
\generalframe{\border\char29}{\border\char1}{\border\char28}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char30}{\border\char3}{\border\char31}
{#1}}
\newcommand{\fzframelinH}[1]{%
\font\border=umrandb
\generalframe{\border\char33}{\border\char1}{\border\char32}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char34}{\border\char3}{\border\char35}
{#1}}
\newcommand{\fzframelinI}[1]{%
\font\border=umrandb
\generalframe{\border\char37}{\border\char1}{\border\char36}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char38}{\border\char3}{\border\char39}
{#1}}
\newcommand{\fzframelinJ}[1]{%
\font\border=umrandb
\generalframe{\border\char41}{\border\char1}{\border\char40}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char42}{\border\char3}{\border\char43}
{#1}}
\newcommand{\fzframelinK}[1]{%
\font\border=umrandb
\generalframe{\border\char45}{\border\char1}{\border\char44}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char46}{\border\char3}{\border\char47}
{#1}}
\newcommand{\fzframelinL}[1]{%
\font\border=umrandb
\generalframe{\border\char49}{\border\char1}{\border\char48}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char50}{\border\char3}{\border\char51}
{#1}}
\newcommand{\fzframelinM}[1]{%
\font\border=umrandb
\generalframe{\border\char53}{\border\char1}{\border\char52}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char54}{\border\char3}{\border\char55}
{#1}}
\newcommand{\fzframelinN}[1]{%
\font\border=umrandb
\generalframe{\border\char57}{\border\char1}{\border\char56}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char58}{\border\char3}{\border\char59}
{#1}}
\newcommand{\fzframelinO}[1]{%
\font\border=umrandb
\generalframe{\border\char61}{\border\char1}{\border\char60}
{\border\char2} {\reflectbox{\border\char2}}
{\border\char62}{\border\char3}{\border\char63}
{#1}}
%% Border has 4 lines, same thickness
\newcommand{\fzframelinP}[1]{%
\font\border=umrandb
\generalframe{\border\char69}{\border\char65}{\border\char68}
{\border\char64} {\border\char66}
{\border\char70}{\border\char67}{\border\char71}
{#1}}
\newcommand{\fzframelinQ}[1]{%
\font\border=umrandb
\generalframe{\border\char73}{\border\char65}{\border\char72}
{\border\char64} {\border\char66}
{\border\char74}{\border\char67}{\border\char75}
{#1}}
\newcommand{\fzframelinR}[1]{%
\font\border=umrandb
\generalframe{\border\char77}{\border\char65}{\border\char76}
{\border\char64} {\border\char66}
{\border\char78}{\border\char67}{\border\char79}
{#1}}
\newcommand{\fzframelinS}[1]{%
\font\border=umrandb
\generalframe{\border\char81}{\border\char65}{\border\char80}
{\border\char64} {\border\char66}
{\border\char82}{\border\char67}{\border\char83}
{#1}}
\newcommand{\fzframelinT}[1]{%
\font\border=umrandb
\generalframe{\border\char85}{\border\char65}{\border\char84}
{\border\char64} {\border\char66}
{\border\char86}{\border\char67}{\border\char87}
{#1}}
\newcommand{\fzframelinU}[1]{%
\font\border=umrandb
\generalframe{\border\char89}{\border\char65}{\border\char88}
{\border\char64} {\border\char66}
{\border\char90}{\border\char67}{\border\char91}
{#1}}
\newcommand{\fzframelinV}[1]{%
\font\border=umrandb
\generalframe{\border\char93}{\border\char65}{\border\char92}
{\border\char64} {\border\char66}
{\border\char94}{\border\char67}{\border\char95}
{#1}}
\newcommand{\fzframelinW}[1]{%
\font\border=umrandb
\generalframe{\border\char97}{\border\char65}{\border\char96}
{\border\char64} {\border\char66}
{\border\char98}{\border\char67}{\border\char99}
{#1}}
\newcommand{\fzframelinX}[1]{%
\font\border=umrandb
\generalframe{\border\char101}{\border\char65}{\border\char100}
{\border\char64} {\border\char66}
{\border\char102}{\border\char67}{\border\char103}
{#1}}
%% Border has 5 lines, the middle one thicker
\newcommand{\fzframelinY}[1]{%
\font\border=umrandb
\generalframe{\border\char113}{\border\char105}{\border\char112}
{\border\char106} {\border\char104}
{\border\char114}{\border\char107}{\border\char115}
{#1}}
\newcommand{\fzframelinZ}[1]{%
\font\border=umrandb
\generalframe{\border\char113}{\border\char109}{\border\char112}
{\border\char110} {\border\char108}
{\border\char114}{\border\char111}{\border\char115}
{#1}}
\newcommand{\fzframelinAA}[1]{%
\font\border=umrandb
\generalframe{\border\char117}{\border\char105}{\border\char116}
{\border\char106} {\border\char104}
{\border\char118}{\border\char107}{\border\char119}
{#1}}
\newcommand{\fzframelinAB}[1]{%
\font\border=umrandb
\generalframe{\border\char117}{\border\char109}{\border\char116}
{\border\char110} {\border\char108}
{\border\char118}{\border\char111}{\border\char119}
{#1}}
\newcommand{\fzframelinAC}[1]{%
\font\border=umrandb
\generalframe{\border\char121}{\border\char105}{\border\char120}
{\border\char106} {\border\char104}
{\border\char122}{\border\char107}{\border\char123}
{#1}}
\newcommand{\fzframelinAD}[1]{%
\font\border=umrandb
\generalframe{\border\char121}{\border\char109}{\border\char120}
{\border\char110} {\border\char108}
{\border\char122}{\border\char111}{\border\char123}
{#1}}
%%
%% Sample of dingbats in a font
\RequirePackage{ifthen}
\newcounter{clet}
\newcounter{numchars}
\newcommand{\dingsample}{%
\setcounter{clet}{1}
\setcounter{numchars}{256}
\whiledo{\value{clet}<256}{%
\mbox{
\texttt{ \theclet\ = }\char\value{clet}
}
\addtocounter{clet}{1}
}
}
\endinput