Skip to content

Add unicode math shorthand for $...$ regions in labels - #89

Merged
Psy-Fer merged 1 commit into
Psy-Fer:devfrom
gabo515:feat/math-lookup
Jun 12, 2026
Merged

Add unicode math shorthand for $...$ regions in labels#89
Psy-Fer merged 1 commit into
Psy-Fer:devfrom
gabo515:feat/math-lookup

Conversation

@gabo515

@gabo515 gabo515 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

This is the unicode shorthand half of #88, split out per the review discussion there — the typst math layer and typst backend stay parked on the other branch for later.

Any label (title, axis labels, TextPlot markdown bodies) may embed $...$ math written in LaTeX-ish syntax. Math regions are lowered to inline Unicode by every backend, including the terminal:

Input Output
$\sigma^2$ σ²
$x_i$ xᵢ
$a \leq b \cdot c$ a ≤ b · c
$\frac{a+b}{c}$ (a+b)/c
$\sqrt{x^2+y^2}$ √(x²+y²)
$\sum_{i=1}^{n} x_i$ ∑ᵢ₌₁ⁿ xᵢ

Zero dependencies, no feature flag, always on. No Cargo.toml changes at all.

Design notes

  • Inline only, by design. Fractions and radicals lower to a/b and √(…), never stacked 2-D layout — the output is plain text that flows anywhere a label can go (rotated y-axis titles, terminal character grids, markdown bodies).
  • All-or-nothing super/subscripts. x^{2n} → x²ⁿ, but if any character in the group lacks a Unicode form (q, most capitals), the whole group falls back to a clean x^(2q) — never a half-substituted mix.
  • Never leaks source. The lowering never emits a stray \ or $. Literal dollars are written \$; an unclosed $ is left untouched as ordinary text.
  • One module, four call sites. src/render/math.rs holds detection (contains_math), segmentation, the command table, and to_unicode. The SVG, raster (PNG/PDF), and terminal Text arms lower at draw time; markdown TextSpans are lowered once after markup parsing, so **bold** $\sigma^2$ works in TextPlot bodies.

Supported syntax

Greek letters (incl. \varepsilon/\varphi variants), operators/relations/arrows (\pm \times \cdot \leq \neq \approx \in \partial \nabla \infty \to \degree …), \frac{a}{b}, \sqrt{x} / \sqrt[3]{x} (→ ³√x), and ^/_ scripts with {...} groups or braceless \command operands (x^\alphax^(α)).

Testing

  • 21 unit tests in render::math — substitution, fallbacks, escaped/unclosed dollars, nested chains (quadratic formula end-to-end), no-leak guarantees.
  • tests/math_lookup.rs — per-backend integration: terminal, SVG, markdown TextPlot body, escaped-dollar literal.
  • 7 smoke tests across plot types (scatter/line/bar) and label slots (title, x/y labels, rotated y-label).
  • scripts/terminal_plots.sh — math labels entry for visual terminal inspection.
  • cargo ci-test (99 suites), cargo ci-clippy, and the full smoke suite (190 checks) all pass.

Docs

  • New reference page Reference → Math in Labels with the substitution table, supported-syntax list, CLI usage, and generated example SVGs (examples/math.rs, committed under docs/src/assets/math/).
  • Crate-level docs section in lib.rs; CHANGELOG entry.

🤖 Generated with Claude Code

Any label (title, axis labels, TextPlot markdown bodies) may embed
$...$ math written in LaTeX-ish syntax. Math regions are lowered to
inline Unicode by every backend, including the terminal:

  $\sigma^2$            ->  σ²
  $\frac{a+b}{c}$       ->  (a+b)/c
  $\sqrt{x^2+y^2}$      ->  √(x²+y²)
  $\sum_{i=1}^{n} x_i$  ->  ∑ᵢ₌₁ⁿ xᵢ

Zero dependencies, no feature flag, deliberately inline-only (no 2-D
layout). Super/subscript substitution is all-or-nothing: if any char in
the group lacks a Unicode form the whole group falls back to a clean
x^(2q), never a half-substituted mix. The lowering never emits a stray
backslash or dollar; literal dollars are written \$.

- src/render/math.rs: detection, command table, to_unicode + 21 unit tests
- backends: SVG, raster (PNG/PDF), terminal Text arms lower math inline
- render: markdown TextSpans lowered after markup parsing
- tests/math_lookup.rs: per-backend integration tests
- smoke_tests.sh: 7 checks across plot types and label slots
- terminal_plots.sh: math labels entry
- docs: Reference -> Math in Labels + generated example SVGs
@gabo515
gabo515 force-pushed the feat/math-lookup branch from bcd562f to d9e8790 Compare June 11, 2026 19:11
@Psy-Fer

Psy-Fer commented Jun 12, 2026

Copy link
Copy Markdown
Owner

This is great.
Few little things I'll change but after I merge it.

Thanks
James

@Psy-Fer
Psy-Fer merged commit eff0462 into Psy-Fer:dev Jun 12, 2026
2 checks passed
gabo515 added a commit to gabo515/kuva that referenced this pull request Aug 31, 2026
Rebased onto the krilla-era dev: the zero-dep lookup tier already merged
via Psy-Fer#89 and evolved there, so this commit now adds only the typst work.

- feature `math`: links the Typst compiler as a library and typesets any
  label containing $...$ into an SVG fragment (SVG backend) or pixmap
  (PNG), embedded at the label position with color injection and
  per-label ID namespacing. Compile failure falls back to the lookup
  tier with a one-time warning per distinct label.
- PDF: math fragments flow through the krilla pipeline unchanged
  (SvgBackend -> usvg -> krilla-svg draw_svg) — the xlink:href->href
  rewrite is exactly what usvg needs; no pdf.rs changes required.
- feature `typst` (zero deps, now in `full`): TypstBackend emits a
  CETZ-based .typ document for external `typst compile`; $...$ regions
  pass through as native Typst math.
- bundles NewCM Math (~0.75 MB gzip) instead of the 15 MB typst-assets;
  fonts module gains newcm_math() behind the `math` gate.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants