Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/math_spec/typesetting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def typeset(

blocks = [format_.note(format_.escape(schema.description))] if schema.description else []
if legend:
blocks += [format_.glossary(group.title, group.entries) for group in walk.glossaries(noticed)]
blocks += [format_.section(title, format_.glossary(entries)) for title, entries in walk.glossaries(noticed)]
blocks += [format_.note(text) for text in walk.convention_notes()]
blocks += [format_.note(text) for text in walk.translation_notes(noticed)]
blocks += [format_.note(text) for text in walk.position_notes(noticed)]
Expand Down Expand Up @@ -194,7 +194,7 @@ def typeset_declaration(
Raises:
ValueError: *fmt* names no format.
LanguageError: A model that does not compile; it does not print.
SchemaError: *name* is declared as none of the four, or as two — a
SchemaError: *name* is declared as none of the five, or as two — a
constraint may share a variable's name; or a symbol table entry
names nothing in the model.
"""
Expand Down
14 changes: 3 additions & 11 deletions src/math_spec/typesetting/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,6 @@ class Entry:
meaning: str


@dataclass(frozen=True)
class Glossary:
"""One legend section: its title, and the entries under it."""

title: str
entries: list[Entry]


#: The one notation author prose carries: a name in backticks, set in monospace.
_CODE_SPAN = re.compile(r'`([^`]+)`')

Expand All @@ -169,8 +161,6 @@ class Format(Protocol):
operators: ClassVar[Mapping[OperatorName, str]]
#: The em dash in prose: TeX and Typst read ``---`` as one, Markdown does not.
dash: ClassVar[str]
#: Between the rows of a ``cases`` block.
cases_row: ClassVar[str]

# -- atoms -------------------------------------------------------------

Expand Down Expand Up @@ -255,7 +245,9 @@ def equation(self, line: Line) -> str:

def equations(self, lines: list[Line], *, numbered: bool) -> str: ...

def glossary(self, title: str, entries: list[Entry]) -> str: ...
def glossary(self, entries: list[Entry]) -> str:
"""A legend section's rows; :meth:`section` sets its title, as it does for the equations."""
...

def section(self, title: str, body: str) -> str: ...

Expand Down
7 changes: 3 additions & 4 deletions src/math_spec/typesetting/latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class LatexFormat:
notation: ClassVar[Notation] = 'latex'
#: TeX's own em-dash ligature.
dash: ClassVar[str] = '---'
cases_row: ClassVar[str] = r' \\ '

operators: ClassVar[Mapping[OperatorName, str]] = {name: latex for name, (latex, _) in OPERATOR_SPELLINGS.items()}

Expand Down Expand Up @@ -102,7 +101,7 @@ def set_of(self, members: str, condition: str) -> str:
return rf'\{{ {members} {self.operators["such_that"]} {condition} \}}'

def cases(self, arms: list[tuple[str, str]]) -> str:
rows = self.cases_row.join(f'{value} & {condition}' for value, condition in arms)
rows = r' \\ '.join(f'{value} & {condition}' for value, condition in arms)
return rf'\begin{{cases}} {rows} \end{{cases}}'

def summation(self, domain: str, body: str) -> str:
Expand All @@ -125,9 +124,9 @@ def equations(self, lines: list[Line], *, numbered: bool) -> str:
body = ' \\\\\n'.join(aligned_rows(lines, self, gap=' && '))
return f'\\begin{{{environment}}}\n{body}\n\\end{{{environment}}}'

def glossary(self, title: str, entries: list[Entry]) -> str:
def glossary(self, entries: list[Entry]) -> str:
rows = '\n'.join(rf'\item[{{{self.math(e.symbol)}}}] {e.meaning}' for e in entries)
return f'\\paragraph{{{title}}}\n\\begin{{description}}\n{rows}\n\\end{{description}}'
return f'\\begin{{description}}\n{rows}\n\\end{{description}}'

def section(self, title: str, body: str) -> str:
return f'\\paragraph{{{title}}}\n{body}'
Expand Down
4 changes: 2 additions & 2 deletions src/math_spec/typesetting/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ def equations(self, lines: list[Line], *, numbered: bool) -> str:
return '\n\n'.join(blocks)

@override
def glossary(self, title: str, entries: list[Entry]) -> str:
def glossary(self, entries: list[Entry]) -> str:
rows = '\n'.join(f'| {_cell(self.math(e.symbol))} | {_cell(e.meaning)} |' for e in entries)
return f'#### {title}\n\n| Symbol | Meaning |\n|---|---|\n{rows}'
return f'| Symbol | Meaning |\n|---|---|\n{rows}'

@override
def section(self, title: str, body: str) -> str:
Expand Down
8 changes: 3 additions & 5 deletions src/math_spec/typesetting/typst.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ class TypstFormat:
notation: ClassVar[Notation] = 'typst'
#: Typst applies the same substitution TeX does.
dash: ClassVar[str] = '---'
cases_row: ClassVar[str] = ', '

operators: ClassVar[Mapping[OperatorName, str]] = {name: typst for name, (_, typst) in OPERATOR_SPELLINGS.items()}

Expand Down Expand Up @@ -110,7 +109,7 @@ def set_of(self, members: str, condition: str) -> str:
return f'{{{members} {self.operators["such_that"]} {condition}}}'

def cases(self, arms: list[tuple[str, str]]) -> str:
return 'cases({})'.format(self.cases_row.join(f'{value} & {condition}' for value, condition in arms))
return 'cases({})'.format(', '.join(f'{value} & {condition}' for value, condition in arms))

def summation(self, domain: str, body: str) -> str:
return f'sum_({domain}) {body}'
Expand All @@ -133,9 +132,8 @@ def equations(self, lines: list[Line], *, numbered: bool) -> str:
numbering = '#set math.equation(numbering: "(1)")\n' if numbered else ''
return f'{numbering}$ {body} $'

def glossary(self, title: str, entries: list[Entry]) -> str:
rows = '\n'.join(f'/ {self.math(e.symbol)}: {e.meaning}' for e in entries)
return f'== {title}\n{rows}'
def glossary(self, entries: list[Entry]) -> str:
return '\n'.join(f'/ {self.math(e.symbol)}: {e.meaning}' for e in entries)

def section(self, title: str, body: str) -> str:
return f'== {title}\n{body}'
Expand Down
13 changes: 4 additions & 9 deletions src/math_spec/typesetting/walk.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
TranslatedPredicate,
VariableDefined,
)
from math_spec.typesetting.format import Entry, Glossary, Line, OperatorName
from math_spec.typesetting.format import Entry, Line, OperatorName

if TYPE_CHECKING:
import datetime
Expand Down Expand Up @@ -1018,7 +1018,7 @@ def _sorted(self, dims: frozenset[str]) -> list[str]:

# -- legend ------------------------------------------------------------

def glossaries(self, noticed: Noticed) -> list[Glossary]:
def glossaries(self, noticed: Noticed) -> list[tuple[str, list[Entry]]]:
fmt = self.format
sets = [
self._entry(
Expand All @@ -1041,13 +1041,8 @@ def glossaries(self, noticed: Noticed) -> list[Glossary]:
for e, block in self.schema.expressions.items()
if e in self._defined()
]
groups = (
Glossary('Sets', sets),
Glossary('Parameters', parameters),
Glossary('Variables', variables),
Glossary('Definitions', definitions),
)
return [group for group in groups if group.entries]
groups = (('Sets', sets), ('Parameters', parameters), ('Variables', variables), ('Definitions', definitions))
return [(title, entries) for title, entries in groups if entries]

def _entry(self, symbol: str, what: str, description: str | None) -> Entry:
meaning = f'{what} {self.format.dash} {self.format.escape(description)}' if description else what
Expand Down
Loading