formulaa 0.1.0

WYSIWYG TUI math editor rendering Unicode/ASCII-art formulas
Documentation
---
name: formulaa-math
description: >
  Read and write formulAA AA math โ€” 2D plain-text formulas (Unicode-first
  ASCII art) that map one-to-one to a math AST and convert losslessly to
  LaTeX. Use when asked to write, edit or interpret formulas in
  formulAA AA form, or to embed re-editable math in plain-text documents.
---

# Reading and writing formulAA AA math

The formulAA AA format looks like the formula itself while converting
mechanically to LaTeX. This document alone should let you write correct
AA.

## Verification commands (always use them when available)

```sh
echo '<AA>' | formulaa --format    # parse and canonicalize (an error means invalid)
echo '<AA>' | formulaa --aa2latex  # convert to LaTeX to confirm the meaning
```

Your AA is correct when `formulaa --format` accepts it and the output matches
your intent. Hand-written input is **lenient**: a lone ASCII letter is
an italic variable (`x+1` โ†’ ๐‘ฅ+1), but a **run of 2+ letters is
upright** (`asiny` โ†’ \operatorname{asiny}, `sin` โ†’ \sin), so write a
product of variables as `a b` (spaced) or `๐‘Ž๐‘` (italic code points).

## Principles

1. A formula is a character grid. **Every subexpression owns a
   rectangle plus a baseline row**; siblings occupy disjoint column
   ranges.
2. Vertical relationships (numerator/denominator, limits, scripts) are
   marked by **structural glyphs** (bars, bands, delimiter columns),
   never by whitespace alone.
3. When unsure, write on one line: `xยฒ+1`-style one-liners are almost
   always safe.

## Structures

### Fractions โ€” the bar `โ”€` (U+2500)

The bar is wider than either half (max width + 2); the bar row is the
baseline.

```plain
 1        a+b
โ”€โ”€โ”€   โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 2      c + d
```

Minus stays ASCII `-` (a different character from the bar).

### Scripts โ€” inline characters when possible

`xยฒ` `aแตข` `eโปโฑ` (available: โฐยนยฒยณโดโตโถโทโธโนโบโปโผโฝโพโฟโฑ /
โ‚€โ‚โ‚‚โ‚ƒโ‚„โ‚…โ‚†โ‚‡โ‚ˆโ‚‰โ‚Šโ‚‹โ‚Œโ‚โ‚Žโ‚โ‚‘โ‚•แตขโฑผโ‚–โ‚—โ‚˜โ‚™โ‚’โ‚šแตฃโ‚›โ‚œแตคแตฅโ‚“). Anything else becomes a 2D block at
the base's **upper/lower right**:

```plain
 ฮฑ+1
๐‘ฅ        โ† x^(ฮฑ+1)     ๐‘ฅ      โ† x_(ฮฑ+1)
                        ฮฑ+1
```

A script at the start of a row needs the explicit base `โฌš`: `โฌšยฒ`.

### Radicals โ€” `โˆš โˆ› โˆœ` plus the overline `โ”Œโ”€โ”€`

```plain
โ”Œโ”€โ”€โ”€โ”€       โ”Œโ”€โ”€โ”€
โˆšx+12       โ”‚ 1
            โ”‚โ”€โ”€โ”€    โ† the stem โ”‚ covers every content row; the bottom is the root glyph
            โˆ› 2
```

Top row: `โ”Œ` (the stem's column) + a `โ”€` run as long as the argument.
One-line content sits directly right of `โˆš`.

### Limits โ€” the band `โ”ˆ` (U+2508)

**Anything sandwiched by `โ”ˆ` without spaces** takes limits above and
below (โˆ‘ and lim use the same notation). One space separates a band
from its neighbors. No limits โ†’ the bare `โˆซ` is fine.

```plain
  โˆž
โ”ˆโ”ˆโˆ‘โ”ˆโ”ˆ aโ‚™      โ”ˆlimโ”ˆ f(x)      โ”ˆargmaxโ”ˆ f(x)   โ† one word, no spaces
 n=1           xโ†’0                xโˆˆS
```

### Delimiters โ€” `( ) [ ] { } โŸจ โŸฉ โŽข โŽฅ โŒˆ โŒ‰ โŒŠ โŒ‹ โ€– โ”† โ”Š` on one line, columns when tall

```plain
โŽ›    1 โŽž    โŽง 1 โŽซ     โ•ฑ    1 โ•ฒ
โŽœ1 + โ”€ โŽŸ    โŽจโ”€โ”€โ”€โŽฌ    โ•ฑ ๐‘ฅ+โ”€โ”€โ”€ โ•ฒ    โŽข๐‘ฅโŽฅ = |x|
โŽ    x โŽ     โŽฉ 2 โŽญ    โ•ฒ    2  โ•ฑ
                      โ•ฒ     โ•ฑ
```

- Parens `โŽ›โŽœโŽ`, brackets `โŽกโŽขโŽฃ`, braces `โŽงโŽชโŽจโŽฉ` (**the vertex โŽจ is
  always the baseline row**); tall angles are **diagonal arms `โ•ฑ โ•ฒ`
  only** (even height, `โŸจ โŸฉ` on one line only). The fold is a vertical
  pair in one column โ€” left: `โ•ฑ` directly above `โ•ฒ` โ€” and the upper
  row of the pair is the baseline.
- Absolute value: left `โŽข` / right `โŽฅ` (bracket extension pieces; a
  column with no corners reads as a bar; `|` is an atom, `โ”‚` is the
  radical stem / segment separator).
- **Middles** (bra-kets, set-builder): full-height `โ”‚` columns split
  segments: `โŸจฯˆโ”‚Hโ”‚ฯˆโŸฉ`, `{๐‘ฅโ”‚๐‘ฅ > 0}` โ†’ \{x \mid x>0\}.
- Mismatched pairs are fine: `(0,1]`.
- Ceil/floor: `โŒˆ โŒ‰ โŒŠ โŒ‹` (tall: bracket pieces with one corner dropped โ€”
  ceil has no foot, floor has no head). Norm: a full-height `โ€–` column
  (tall: the same `โ€–` stacked; a norm directly inside a norm cannot be
  written โ€” use `โŽข โŽฅ` inside).
- **Null delimiters** left `โ”†` U+2506 / right `โ”Š` U+250A ("no wall
  here", `\left.`/`\right.`). `cases` is `โŽง` + a grid + a right `โ”Š`.

### Matrices and grids โ€” the lattice (the same picture everywhere)

Junction glyphs `โ”Œโ”ฌโ” โ”œโ”ผโ”ค โ””โ”ดโ”˜` sit at every separator intersection,
outer border included; a matrix just wraps the grid in a delimiter
pair. Whitespace inside cells is free โ€” markers decide the boundaries:

```plain
โ”Œ   โ”ฌ   โ”      โŽก a   b โŽค     โŽก   โ”ฌ   โŽค     โŽ› a โŽž
  a   b        โŽข   โ”ผ   โŽฅ     โŽข a   b โŽฅ     โ”œ   โ”ค
โ”œ   โ”ผ   โ”ค      โŽฃ c   d โŽฆ     โŽฃ   โ”ด   โŽฆ     โŽ b โŽ 
  c   d        โ† bmatrix      one row       one column (the โ”œโ”ค junctions
โ””   โ”ด   โ”˜       (separator     (โ”ฌโ”ด rows)     bite into the delimiter column)
                rows: spaces + โ”ผ)
```

### Accents โ€” marks directly above/below a one-character base (stackable)

For multi-character bases, a **marked band row** hugs the base:

```plain
โ”ˆโ”ˆหฐโ”ˆโ”ˆ     โ”ˆโ”ˆโ‡พโ”ˆ     โ”ˆ___โ”ˆ
 ๐‘Ž๐‘๐‘       ๐ด๐ต       ๐‘ง+1   โ† \widehat / \vec / \overline
                           (below: โ”ˆยฏยฏยฏโ”ˆ = \underline, โ”ˆหœหœหœโ”ˆ = \utilde;
                            the base stays bare)
```

All marks draw in base-hugging forms: bar above is `_`, hat `หฐ`, tilde
`หท`, check `หฏ`, ring `หณ`, dot `โ€ค` U+2024 (not the atom `.`), vec `โ‡พ`
U+21FE (not the atom `โ†’`), ddot `โ€คโ€ค` (overhanging one column right,
that column's baseline stays blank), underline is `ยฏ` below, utilde `หœ`
below (the tildes swap between AST and drawing).

```plain
โ‡พ       โ‡พ        หฐ
E โ‹… d A          โ‡พ    โ† stacks grow outward: \hat{\vec{a}}
                 ๐‘Ž
```

### Negation โ€” precomposed slashed atoms only

Combining overlays like U+0338 are rejected (explicit error). Write
โ‰  โˆ‰ โŠ„ โ‰ข โ€ฆ directly.

### Spaces

Real spaces are formatting: they survive a parse as formatting, but
carry no meaning. To put a space into the
LaTeX output use the visible atom `โฃ` U+2423 (`\space`; a LaTeX control space).

### Upright text โ€” bare runs, `'โ€ฆ'`, `"โ€ฆ"`

Letter runs like `dx` `asiny` are upright (`\operatorname`);
abbreviations with dots (`i.i.d.`, `w.r.t.`) are one run. A single
letter is roman only when glued to a letter (`d๐‘ฆ`, the differential);
isolate it as `'d'`. `"if x"` โ†’ `\text{if x}` (real spaces allowed,
`\"` `\\` escape). `'` is **always** a quote delimiter โ€” the prime is
the atom `โ€ฒ` U+2032.

### Labelled stretchy arrows โ€” body `โ”€` (`โ•` for โ‡’โ‡) + head `>` `<`

```plain
   f
Aโ”€โ”€โ”€โ”€>B     โ† A \xrightarrow{f} B (labels centered above/below)
```

A head glued to the run makes an arrow; a space makes a fraction bar
plus an atom (`โ”€โ”€โ”€ >`). Double arrows: `โ•โ•>` / `<โ•โ•`.

### overbrace / underbrace โ€” `โ•ญโ”€โ”€โ•ฎ` / `โ•ฐโ”€โ”€โ•ฏ`

```plain
  n
โ•ญโ”€โ”€โ”€โ•ฎ
 a+b + c      โ† \overbrace{a+b}^{n} + \underbrace{c}_{m}
      โ•ฐโ”€โ•ฏ
       m
```

### Function names โ€” upright ASCII

`sin cos tan log ln exp lim det โ€ฆ` are written upright (variables
italicize to `๐‘ฅ`, so they stay distinct). Write `\sin x` as `sin x` or
`sin๐‘ฅ` (`sinx` is not a dictionary word and becomes
`\operatorname{sinx}`).

## Reserved characters (never atoms)

`โ”€ โ”ˆ โ• โ”‚ โˆšโˆ›โˆœ ( ) [ ] โŽ›โŽœโŽโŽžโŽŸโŽ  โŽกโŽขโŽฃโŽคโŽฅโŽฆ { } โŸจ โŸฉ โŽงโŽชโŽจโŽฉโŽซโŽฌโŽญ โ•ฑ โ•ฒ โ”† โ”Š โฌš โ–Œ
โ”Œ โ”ฌ โ” โ”œ โ”ผ โ”ค โ”” โ”ด โ”˜ โ•ญ โ•ฎ โ•ฐ โ•ฏ ยฏ หœ หท _ หฐ หฏ หณ โ€ค โ‡พ ' "`,
math-italic letters, inline script characters. Beyond those, only
characters in the symbol tables are usable (ฮฑ โ‰ค โˆˆ โ†’ โ„ โŠ— โ€ฆ); anything
else โ€” full-width characters, emoji โ€” is a parse error (it would shear
the one-cell grid and has no LaTeX spelling). In ASCII, `^ ~ \` and the
backtick are also unusable โ€” write `\sim`, `\backslash`.

## Multi-line formulas

Stack line blocks with a **lone `โ”ˆ` line** between them:

```plain
๐‘ฆ=(๐‘ฅ+1)ยฒ
โ”ˆ
=๐‘ฅยฒ+2๐‘ฅ+1
```

LaTeX `\\`. There is no alignment.

## Avoiding ambiguity

- Never write an empty script (a `โฌš`-only exponent) โ€” it doesn't exist
  in canonical form.
- Use `โฃ` where the space is part of the formula; a real space is
  formatting (kept, but it means nothing to LaTeX).
- Always band (`โ”ˆ`) the limits of โˆ‘/โˆซ โ€” bare stacking is ambiguous with
  nesting and errors out.
- Never overlap content directly above/below a baseline token (other
  than accent marks) โ€” it errors rather than being dropped.

## Examples

(Real spaces are formatting spacers; the parser keeps them.)

Quadratic formula:

```plain
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€
 -๐‘ยฑโˆš๐‘ยฒ-4๐‘Ž๐‘
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
     2๐‘Ž
```

Gaussian integral:

```plain
 โˆž    -๐‘ฅยฒ   โ”Œโ”€
โ”ˆโˆซโ”ˆโ”ˆ ๐‘’   ๐‘‘๐‘ฅ=โˆšฯ€
 -โˆž
```

Bayes (a one-liner is enough):

```plain
๐‘ƒ(๐ด|๐ต) = ๐‘ƒ(๐ต|๐ด)๐‘ƒ(๐ด)/๐‘ƒ(๐ต)
```

Rotation matrix:

```plain
  โŽก cosฮธ   -sinฮธ โŽค
๐‘…=โŽข      โ”ผ       โŽฅ
  โŽฃ sinฮธ   cosฮธ  โŽฆ
```

## Full specification

See `docs/aa-spec.md` (the format spec) and `docs/adr.md` (decision
records). For any structure you are unsure of, generate a reference
picture first with the `formulAA` TUI or the library
(`formulaa::render::render_root` + `RenderCtx::canonical()`).