This project is not being actively maintained by me at the moment. If you are interested in it, you might consider Michael Hayes's fork: https://github.com/s6mike/argmap
This repository contains some tools for working with argument maps written in
a relatively simple YAML
format, described below. For
example, the map above was generated from this YAML
:
"Brunellus is irrational":
r1:
"Brunellus is a donkey.":
"All donkeys are irrational.":
o1:
"Brunellus studied in Paris.":
"-Most who study in Paris are rational.":
The map above is also a hyper-link: click on it to open an version of the map in Mindmup's Argument Visualization Mode.
Place argmap2mup
, argmap2tikz
, and mup2argmap
somewhere in your path.
Place pandoc-argmap.lua
in the filters
folder inside your pandoc data
directory, e.g., $HOME/.pandoc/filters/pandoc-argmap.lua
.
argmap2mup
, argmap2tikz
, and mup2argmap
require
penlight (for command line option
parsing), , lyaml (for parsing YAML
),
and json (for encoding JSON
). You can
install these with:
$ luarocks install penlight
$ luarocks install lyaml
$ luarocks install json
argmap2mup
and mup2argmap
also depend on the command line utility
gdrive
for Google Drive integration.
Follow the link for installation instructions.
Converting the tikz
code generated by argmap2tikz
to PDF requires several
TeX
packages, some of which you may need to install if they are not already
available on your system.
pandoc-argmap.lua
depends on pandoc
, and on
argmap2lua
and argmap2tikz
. It also depends on
pdf2svg
for conversion
to svg, and ImageMagick's convert
for
conversion to png.
There are some example files in the examples folder in the repository. Here are some things to try:
$ cat example.yml | argmap2mup > example.mup
: generate a MindMup map from
example.yml. Import that map into MindMup to work with.
$ argmap2mup -u example-2.yml
: generate a MindMup map and upload it to your
Google Drive. You can then go to Google Drive and open the map in MindMup to
work with it.
Create an argument map on
Mindmup and
download it as a MindMup file (File → Download As → MindMup). Now convert it
to YAML
:
mup2argmap download.mup > download.yml
Next, try generating a PDF image from example.yml
:
$ cat example.yml | argmap2tikz -s > example.tex
$ lualatex example
Finally, try generating an HTML document from a markdown document containing an embedded argument map:
$ pandoc example.md -o example.html --lua-filter pandoc-argmap.lua
The goal here is to describe a spec for argument maps that is relatively easy for humans to read and write. The spec we use is much less ambitious than other specs that I know of, like Argdown and the Argument Interchange Format.
For our purposes, an argument map consists of claims and reasons: each claim can be supported by zero or more reasons; each reason consists of zero or more claims.
We represent each claim as a key-value pair:
- the key is the content of the claim;
- the value is a (possibly empty) list of reasons.
So here is how we represent the claim that Brunellus is irrational unsupported by any reasons:
"Brunellus is irrational": {}
We also represent each reason as a key-value pair:
- the key is an identifier;
- the value is a (possibly empty) list of claims.
For example, here is a reason that consists of two claims:
reason1:
"Brunellus is a donkey.": {}
"All donkeys are irrational.": {}
There are two kinds of reasons: supporting reasons and reasons against (i.e., objections). We use the identifier to represent this difference:
- a reason whose key begins with an
o
or-
is an objection; - all other reasons are supporting reasons.
So that takes us back to our original example:
"Brunellus is irrational":
r1:
"Brunellus is a donkey.": {}
"All donkeys are irrational.": {}
o1:
"Brunellus studied in Paris.": {}
"-Most who study in Paris are rational.": {}
Note the '-
' before "Most who study..". Claims are either explicit or
implicit. We use the key to represent this:
- a claim whose key begins with a
-
is implicit; - all other claims are explicit.
We also include a way to attach a single note to each claim, and a way to label reasons and specify their relative strength.
Note that the reasons for a given claim cannot share the same identifier. Something like this will lead to unpredictable behavior:
"Brunellus is irrational":
reason: {}
reason: {}
The resulting map will only display a single reason, and which one it will choose in unpredictable.
Instead, you need to ensure that the keys are distinct:
"Brunellus is irrational.":
reason1: {}
reason2: {}
Reasons for distinct claims can have the same identifier. So this is okay:
"Brunellus is a donkey.":
reason1: {}
"All donkeys are irrational.":
reason1: {}
The same holds for claims: each of the claims that make up a given reason must have distinct keys. So don't write something like this:
"Brunellus is irrational":
r1:
"Brunellus is a donkey.": {}
"Brunellus is a donkey.": {}
Since the key is the content of the claim, this restriction makes sense: you would not want to represent the same premise twice as part of a single reason. But, of course, the same premise can occur as part of two distinct reasons:
"Brunellus is irrational":
r1:
"Brunellus is a donkey.": {}
"All donkeys are irrational.": {}
r2:
"Brunellus is a donkey.": {}
"Most donkeys I've met have been irrational.": {}
Note that every claim is represented as key-value pair, where the value is a list of reasons. If there are no reasons offered for or against a claim, that means that the value is an empty list. You can represent this empty list explicitly if you like:
"Brunellus is a donkey.": {}
Or you can leave it implicit, omitting the '{}
'. But you still must put
the colon (':
') after the claim:
"Brunellus is a donkey.":
In practice, the implicit empty list notation is preferred, because it means you don't have to delete the braces before adding reasons in support of a claim.
YAML
allows just about any string to be a key, but you do have to be careful
about quotes and line-wrapping. If your key has no special characters, like
':
', you get away with omitting the quotes:
Brunellus is a donkey.:
Multiline keys are also possible, but the format is a bit complicated (1, 2)
?
"Brunellus is a donkey who wanted a longer tail, and he went to Paris
to study, but he couldn't remember the city's name."
:
r1:
?
"The wikipedia says that Brunellus is a donkey who wanted a longer
tail, and he went to Paris to study, but he couldn't remember the
city's name."
:
?
"The wikipedia is a reliable source for information about donkeys
in medieval literature."
:
Each claim key is processed by pandoc
. This means that you should be able to
get away with using simple markdown inside the claim keys.
"Brunellus is *probably* 90% H~2~O":
Keep in mind that MindMup offers very limited support for formatted text. So,
for MindMup maps, formatting will be converted to pandoc
's "plain" output:
Brunellus is _probably_ 90% H₂O
For TikZ
maps, formatting will be converted to latex:
Brunellus is \emph{probably} 90\% H\textsubscript{2}O
(Currently, notes are only supported for MindMup input and output, and do not appear in TikZ output.)
You can attach one note to any claim (if you attach more than one note, only one of them will be processed). A note is represented by a key-value pair, where the key is the string "note" and the value is the content of the note. To attach a note to a claim, add it to the list of reasons:
Brunellus is irrational:
r1:
Brunellus is a donkey.:
note: |
Brunellus means "brown one" in Latin, and was the name of a stock
character in medieval logic texts.
All donkeys are irrational.:
note: |
Although donkeys *are* notoriously stubborn, it seems a bit much to
suppose that irrationality is the defining feature of a donkey.
Notes are also processed by pandoc
, allowing the use of simple markdown.
You can attach a label or strength to any reason. A label is a key-value pair, where the key is the string "label" and the value is the content of the label. A strength is a key-value pair, where the key is "strength" and the value is a number between 1 (weak) and 5 (strong). Labels and strengths are added to the list of a reason's claims:
Brunellus is irrational:
r1:
Brunellus is a donkey.:
All donkeys are irrational.:
label: argumentum ad asinum
strength: 4
o1:
Brunellus studied in Paris.:
-Most who study in Paris are rational.:
label: argumentum ad parisiensis
strength: 2
argmap2mup
is a pipe for converting YAML
maps to JSON
encoded MindMup
maps. It takes as its input the first cli argument that is not an option, or,
if there is no such argument, STDIN.
$ cat example.yml | argmap2mup | jq
{
⋮
"ideas": {
"1": {
"attr": {},
"title": "Brunellus is irrational",
⋮
}
(Here I've used jq
to pretty-print the
JSON
output.)
The following options are available:
-u, --upload
: Upload to Google Drive.
If this option is selected, then, instead of dumping the map to STDOUT, it is uploaded to Google Drive, and its Google Drive ID is returned.
$ argmap2mup -u example.yml
1e4HAl1iHPKBiKZ_BI_yBw7rXYbuvMsC2
If you have connected your MindMup account to Google Drive, you can use this Google Drive ID to construct a URL that allows you to open the file directly in MindMup. The format for the URL is:
https://drive.mindmup.com/map/ID
-g ID, --gdrive_id ID
: Update the file with ID on Google Drive.
By default, argmap2mup
creates a new file on your Google Drive every time
you run it. If you have already uploaded a map, and would prefer to update
that map rather than create a new one, use this option to specify its Google
Drive ID. If you don't know its Google Drive ID, use gdrive list
to find it.
This command implies --upload
:
$ cat example.yml | argmap2mup -g 1e4HAl1iHPKBiKZ_BI_yBw7rXYbuvMsC2
1e4HAl1iHPKBiKZ_BI_yBw7rXYbuvMsC2
-f ID, --folder ID
: upload to Google Drive folder with ID
For example, I prefer to upload all of my automatically generated maps to a
folder called argmaps
.
p, --public
: Mark the uploaded file as shareable.
By default, files uploaded to Google Drive are private and unshared. Use this
flag to mark them as shareable instead. This option also implies --upload
.
-n, --name
: Specify a name for your map.
This name is used to set the title attribute within the map itself. It is also used as the name of the file on Google Drive. If this option is omitted, and so no name is specified, the conclusion of the argument will be used as the name. No sanity checks are performed on this: no doubt you can break things by specifying weird things as the name.
-h, --help
: Display a brief synopsis of these options.
mup2argmap
is a pipe for converting MindMup maps into the argmap YAML
format. It takes as its input the first cli argument that is not an option,
or, if there is no such argument, STDIN.
cat example.mup | mup2argmap
mup2argmap example.mup
The following options are available:
-g ID, --gdrive_id ID
: read the file with the specified Google Drive ID.
This option takes precedence any files specified on the command line or anything piped to STDIN.
-e, --embed
: wrap output in a pandoc markdown code block with attributes,
suitable for embedding.
-h, --help
: Display a brief synopsis of these options.
argmap2tikz
is a pipe for converting YAML
maps to TikZ pictures, suitable
for embedding in LaTeX
. It takes as its input the first cli argument that is
not an option, or, if there is no such argument, STDIN.
$ cat example.yml | argmap2tikz
\begin{tikzpicture}
⋮
{
c1/"Brunellus is irrational
"[claim]
--[opposingedge]
r2/"" [opposing] // [ tree layout ] {
⋮
\end{tikzpicture}
Note that it uses TikZ's graph
support, and TikZ's graph
support only
works with lualatex
. So you need to use lualatex
instead of pdflatex
or
xelatex
to convert the tikz
code to PDF.
Also note that the resulting tikz
code requires some settings in your
preamble. For the required settings, see the --includes
option below.
The following options are available:
-s, --standalone
: generate a standalone LaTeX file.
$ argmap2tikz -s example.yml
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{graphs,graphdrawing}
⋮
\begin{document}
\begin{tikzpicture}
⋮
\end{tikzpicture}
\end{document}
This standalone LaTeX file is suitable for generating a PDF image of the map, which can then be used as is or converted into other formats using other tools, e.g.,
$ argmap2tikz -s example.yml > example.tex
$ lualatex example
$ convert example.pdf example.png
-i, --includes
: dump lines suitable for including in a LaTeX
preamble
-t, --template
: dump lines suitable for including in a LaTeX
preamble in a
pandoc
template.
If you want to use the tikz
code inside your own LaTeX
file, include the
output of --includes
in your preamble:
$ argmap2tikz -i
\usepackage{tikz}
\usetikzlibrary{graphs,graphdrawing}
⋮
\usepackage{varwidth}
\newcommand{\argmapmaxnodewidth}{15em}
If you want to use the tikz
code with pandoc
, include the output of
--template
in a custom pandoc LaTeX
template, and set the metadata
variable argmaps
to true
, either in your document's YAML
metadata block,
or using the --metadata
option.
$ argmap2tikz -t
$if(argmaps)$
\usepackage{tikz}
\usetikzlibrary{graphs,graphdrawing}
⋮
\usepackage{varwidth}
\newcommand{\argmapmaxnodewidth}{15em}
$endif$
-h, --help
: Display a brief synopsis of these options.
pandoc-argmap.lua
is a pandoc lua
filter for converting YAML
argument
maps embedded in a pandoc document, using argmap2mup
and argmap2tikz
.
I put a line like this at the top of my personal copy of pandoc-argmap.lua
:
local gdriveFolder = "11w-foIj3p_FWSUROEX0VJg1KsslhJR0m"
This tells pandoc to upload all the maps it generates to a specific folder on my Google Drive.
Embedded argument maps are represented as code blocks with the class argmap
.
```{.argmap}
"Brunellus is irrational":
r1:
"Brunellus is a donkey.":
"All donkeys are irrational.":
o1:
"Brunellus studied in Paris.":
"-Most who study in Paris are rational.":
```
A name and Google Drive ID can also be specified as attributes of the code block:
``` {.argmap name="A Donkey Argument" gid="1X6uD8KyrSawW2qSqhmPaNtuSy-6eEK6g"}
"Brunellus is irrational":
r1:
"Brunellus is a donkey.":
"All donkeys are irrational.":
o1:
"Brunellus studied in Paris.":
"-Most who study in Paris are rational.":
```
To process a file containing argument maps, use the --lua-filter
option with
pandoc
:
$ pandoc example.md -o example.html --lua-filter pandoc-argmap.lua
If you want to generate a PDF file using LaTeX
, you will also need to use
the --pdf-engine=lualatex
option, and use a custom template with the
--template
:
$ pandoc example.md -o example.pdf --lua-filter pandoc-argmap.lua --pdf-engine lualatex --template example-template.latex
If you prefer, you could use the --include-in-header
option instead of a
custom template:
$ argmap2tikz -i > header.tex
$ pandoc example.md -o example.pdf --lua-filter pandoc-argmap.lua --pdf-engine lualatex --include-in-header header.tex
With one exception, pandoc-argmap.lua
replaces each embedded YAML
map with
a TikZ generated image of the map, generates a MindMup map and uploads it
to Google Drive, and links the image to the MindMup url.
Here is the exception: if your output format is markdown
and the map has the
attribute "tidy" set to "true",
```{.argmap tidy=true}
"Brunellus is irrational":
```
then the filter will generate and upload a MindMup map to Google Drive, but it
will not use TikZ to generate any images. In addition, if a gid
attribute
will be added to the code block, pointing to the map on Google Drive. That
makes this a useful way to associate the map in your markdown file with a
specific map on your Google Drive, so that future conversions will update that
map, rather than cluttering your Google Drive by generating a new map every
time.
If the output format is latex, the filter directly embeds the tikzpicture code
into the latex file as raw latex. This is why, if you want to use pandoc
to
directly produce a PDF using one of its latex engines, you will need to
specify --pdf-engine lualatex
and use a custom template or the
--include-in-header
option.
$ pandoc example.md -o example.pdf --lua-filter pandoc-argmap.lua --template
custom.latex --pdf-engine lualatex
If the output format is html5, the filter generates individual pdf files for
each map, and then uses pdf2svg
to convert them to svg, which it embeds
directly into the html file.
For all other formats, it uploads the mindmup file to Google Drive and
generates individual pdf files for each map, and then converts them to png
using ImageMagick's convert
command. It replaces the code block with a
paragraph containing the generated image, linked to the mindmup file.
- add sane syntax checking: right now, if you mess up the syntax of your map, everything breaks.
- improve the tikz styling of maps.
- support for labels in tikz output
- support for strength in tikz output
- support for notes in tikz output
- the green and red "umbrellas" should only be as wide as the claim boxes immediately beneath them.
- the green and red edges should be curved.
- support for other formats?
- import/export rationale?
- DOT output? (See AIF's DOT format?)
- merge the three pipes into a single
argmap
command, using cli options to select input and output formats - mup2argmap should support fetching mup files from Google Drive and offer embeddable output (i.e., code block with both name and gid attributes)