math_spec.typesetting.format
The seam between what a model says and how a format spells it.
One walk, many formats — the split relational/sinks/ makes at the other end
of the pipeline. :mod:math_spec.typesetting.walk decides where a bracket is needed,
which dimension a reduction binds and where a mask belongs; a :class:Format
decides only that a sum is \sum_{…} or sum_(…).
Two rules make the split hold:
- Everything a walk emits is bare math. No
$, no environment; a format wraps it with :meth:Format.mathto embed it in prose, so the walk never knows which mode it is in. - A format spells; it never decides. No method takes an AST node or a schema. If a format had to look at the model, the question belongs in the walk.
LATEX_OPERATORS = {name: latex for name, (latex, _) in OPERATOR_SPELLINGS.items()}
module-attribute
#
OPERATOR_NAMES = frozenset(OPERATOR_SPELLINGS)
module-attribute
#
OPERATOR_SPELLINGS = {'cdot': ('\\cdot', 'dot'), 'plus': ('+', '+'), 'minus': ('-', '-'), 'equal': ('=', '='), 'le': ('\\le', '<='), 'ge': ('\\ge', '>='), 'lt': ('<', '<'), 'gt': ('>', '>'), 'ne': ('\\neq', '!='), 'in': ('\\in', 'in'), 'and': ('\\wedge', 'and'), 'or': ('\\vee', 'or'), 'not': ('\\neg', 'not'), 'true': ('\\top', 'top'), 'false': ('\\bot', 'bot'), 'forall': ('\\forall\\,', 'forall'), 'such_that': ('\\,:\\,', 'colon'), 'infinity': ('\\infty', 'infinity'), 'minus_infinity': ('-\\infty', '-infinity'), 'cyclic_minus': ('\\ominus', 'minus.o'), 'cyclic_plus': ('\\oplus', 'plus.o'), 'edge_minus': ('\\boxminus', 'minus.square'), 'edge_plus': ('\\boxplus', 'plus.square'), 'times': ('\\times', 'times'), 'maps_to': ('\\to', 'arrow.r'), 'reals': ('\\mathbb{R}', 'RR'), 'integers': ('\\mathbb{Z}', 'ZZ'), 'binary_set': ('\\{0, 1\\}', '{0, 1}'), 'sos_set': ('\\mathrm{SOS}', 'upright("SOS")'), 'position': ('\\mathrm{pos}', 'upright("pos")'), 'minimize': ('\\min', 'min'), 'maximize': ('\\max', 'max')}
module-attribute
#
TYPST_OPERATORS = {name: typst for name, (_, typst) in OPERATOR_SPELLINGS.items()}
module-attribute
#
Entry(symbol, name, detail='', description='')
dataclass
#
One legend row: a symbol, the name it stands for, and what it is.
description = ''
class-attribute
instance-attribute
#
detail = ''
class-attribute
instance-attribute
#
name
instance-attribute
#
symbol
instance-attribute
#
meaning(dash)
#
Everything opposite the symbol, as one string.
What the row says is the walk's answer, not a spelling, so the three formats differ only in the table cell they put it in — and in how they spell the dash between a name and its description, which is the one piece of punctuation here that is not the same in all three.
Source code in src/math_spec/typesetting/format.py
Format
#
Bases: Protocol
How one output format spells what a walk emits.
dash
class-attribute
#
notation
class-attribute
#
operators
class-attribute
#
suffix
class-attribute
#
apply(function, argument)
#
cardinality(inner)
#
How many members a set has: |T|.
A fence rather than an entry in :data:OPERATOR_NAMES, which is a
vocabulary of infix spellings — tests/typesetting/test_typeset.py
compiles every one of them between two operands.
Source code in src/math_spec/typesetting/format.py
document(blocks, *, standalone)
#
Source code in src/math_spec/typesetting/format.py
equations(lines, *, numbered)
#
Source code in src/math_spec/typesetting/format.py
escape(prose)
#
Author prose, made safe for this format's text mode.
Every other atom escapes as it wraps, so what passes through here is
what arrives already being prose — a description:. Not
:meth:prose, which is words inside math, and not :meth:note,
which is handed generated markup too.
Source code in src/math_spec/typesetting/format.py
fraction(numerator, denominator)
#
Source code in src/math_spec/typesetting/format.py
glossary(title, entries)
#
Source code in src/math_spec/typesetting/format.py
greek(name)
#
A name that is a Greek letter, set as the letter.
The walk decides which names those are; a format only spells one. Lower-case names only — every one of them has a letter in both notations, which the capitals do not.
Source code in src/math_spec/typesetting/format.py
italic(name)
#
joined(parts, operator)
#
math(expression)
#
mono(text)
#
note(text)
#
parenthesise(inner)
#
Source code in src/math_spec/typesetting/format.py
prose(text)
#
script(letter)
#
section(title, body)
#
Source code in src/math_spec/typesetting/format.py
subscript(base, indices)
#
Source code in src/math_spec/typesetting/format.py
summation(domain, body)
#
Source code in src/math_spec/typesetting/format.py
superscript(base, tail)
#
Source code in src/math_spec/typesetting/format.py
Glossary(title, entries)
dataclass
#
Line(label, left, right, condition='')
dataclass
#
One typeset line of the model, split where a format may align it.
left and right are the two sides of a relation — right carries
the relation symbol, so a format aligns on the boundary between them
without having to parse anything back out.