# formulAA
[](https://github.com/ho-oto/formulaa/actions/workflows/ci.yml)
**Math as plain text you can actually edit.** Three pieces:
- a **2D text format** for formulas โ Unicode "ASCII art" with a formal
grammar ([docs/aa-spec.md](docs/aa-spec.md)): every picture has exactly
one reading and parses back to the syntax tree it was rendered from;
- a **WYSIWYG structure editor** in the terminal for writing it;
- **converters** to and from LaTeX, and a formatter.

```sh
$ formulaa gauss.aa # edit it in the terminal; ^W writes and quits
$ cat gauss.aa # the file is just the picture
โ -๐ฅยฒ โโ
โโซโโ ๐ ๐๐ฅ=โฯ
-โ
$ formulaa --aa2latex gauss.aa # the picture converts to LaTeX
\int_{-\infty }^{\infty }e^{-x^{2}}dx=\sqrt{\pi }
โโซโโ ๐ ๐๐ฅ=โฯ
-โ
```
There is no separate source file behind the picture: the AA text is
what gets stored, edited and converted. Put it anywhere plain text goes.
## Why a picture as the source
Terminals, git, Markdown and prompts all work on plain text, but math
fits it badly. LaTeX is machine-readable, but a human has to picture
`\frac{-b\pm\sqrt{b^2-4ac}}{2a}` in their head. ASCII art is readable at
a glance, but no program can interpret it.
Diagram tools take the drawing itself as the source and render it from
there โ [ditaa](https://github.com/stathissideris/ditaa)
(2004), [aafigure](https://pypi.org/project/aafigure/),
[ASCIIToSVG](https://github.com/dhobsd/asciitosvg),
[Markdeep](https://casual-effects.com/markdeep/) (2015),
[svgbob](https://github.com/ivanceras/svgbob),
[GoAT](https://github.com/blampe/goat). formulAA does the same for
math, with LaTeX as the output instead of SVG.
## One picture, one reading
Those tools interpret free-form drawings as best they can. That works
for boxes and arrows, but not for math: `a` above `b` could be a
fraction, a limit, or two unrelated lines, and a wrong guess silently
changes the meaning.
So formulAA does not interpret arbitrary drawings. It defines a format
([docs/aa-spec.md](docs/aa-spec.md)) in which every accepted picture has
exactly one reading; the rules are summarized in [what makes a picture
parseable](#the-core-idea-what-makes-a-picture-parseable) below.
This requires a few **reserved structural glyphs** โ the fraction bar
`โ`, the operator band `โ`, delimiter columns `โ โ โ`, grid junctions
`โผ` โ which never appear as ordinary content and have to line up
correctly. Keeping them aligned by hand would be tedious, so the editor
does it: it edits the syntax tree and redraws the picture. The files
themselves are still plain text โ you can edit them in vim, paste them
into a document, or have a language model write them
([`SKILL.md`](SKILL.md) documents the format for that purpose).
## The editor
`formulaa formula.aa` opens the editor on a file; `^O` saves and `^W`
saves and quits. Full reference: [keys](docs/keys.md) ยท
[commands](docs/commands.md).
- Type naturally: letters become math italics, `//` makes a fraction,
`^`/`_` open scripts, `(` `[` `{` auto-size, and a `\` minibuffer with
Tab completion covers the rest (`\frac`, `\sum`, `\alpha`, `\bbR`,
aliases like `\->` and `\oo`).
- Arrows move *through* structure; `โ`/`โ` enter limits. `Shift+โ/โ`
selects, and a structure key wraps the selection.
Three modes help once a formula grows past one line.
### `^F` โ the free cursor
Arrows move over the picture instead of through the tree; Enter lands
on the nearest edit position.

### `^B` โ block select
`^B` highlights the enclosing structures of the cursor, `โ`/`โ` widen
and narrow the selection, so a whole subexpression can be copied in a
few keys.

### `^G` โ grid edit
Inside a matrix, `^G` gives a cell cursor; `c` and `r` switch to column
and row lanes, where Enter on a gap inserts one and Backspace on a lane
removes it.

## The core idea: what makes a picture parseable
The format is designed around four rules that make parsing
deterministic:
1. **Every subexpression owns a rectangle and a baseline row.** Siblings
sit in disjoint column ranges; vertical structure exists only inside
a rectangle. Parsing is: find the baseline, scan left to right,
recurse into the rectangles that structural glyphs claim.
2. **Structure is drawn with glyphs that can never be atoms.** The bar
`โ`, the band `โ`, delimiter columns `โ โ โ`, the radical `โ` are
banned from ordinary content, so when one appears it always marks
structure. Atoms come from an allow-list of one-cell characters, so
a wide or combining character cannot break the grid.
3. **Extent is spanned, never counted.** A bar is wider than both its
arguments; a band sandwiches its operator. No rule depends on *how
many* spaces separate two things, so shifting something sideways
while hand-editing does not change the reading.
4. **One canonical spelling per tree.** The renderer's output is the
normal form and the parser accepts a superset. What the picture
cannot distinguish, the AST does not represent: accents stack as
flat lists, because the picture cannot tell `\hat{\underline{x}}`
from `\underline{\hat{x}}`.
The result is that a formula is a picture and a syntax tree at the same
time.
## Examples
Taken from the test corpus ([more examples](docs/examples.md)); each
parses back to its exact tree and converts to the LaTeX shown.
The quadratic formula:
```plain
โโโโโโโ
-๐ยฑโ๐ยฒ-4๐๐
๐ฅ=โโโโโโโโโโโโ
2๐
```
```latex
x=\frac{-b\pm \sqrt{b^{2}-4ac}}{2a}
```
CauchyโSchwarz:
```plain
โ ๐ _ โ โ ๐ โ โ ๐ โ
โโโโโโ ๐ขโ๐ฃโโยฒ โค โโโโโโ ๐ขโยฒโ โโโโโโ ๐ฃโยฒโ
โ ๐=1 โ โ ๐=1 โ โ ๐=1 โ
```
```latex
\left(\sum_{k=1}^{n}u_{k}\bar{v}_{k}\right)^{2}\le \left(\sum_{k=1}^{n}u_{k}^{2}\right)\left(\sum_{k=1}^{n}v_{k}^{2}\right)
```
A Vandermonde determinant โ grids carry explicit lattice markers, so
rows and columns stay unambiguous even with empty cells:
```plain
โก 1 ๐ฅโ ๐ฅโยฒ โฏ ๐ฅโโฟโปยน โค
โข โผ โผ โผ โผ โฅ
โข 1 ๐ฅโ ๐ฅโยฒ โฏ ๐ฅโโฟโปยน โฅ
โข โผ โผ โผ โผ โฅ = โโโโโโโโโ (๐ฅโฑผ-๐ฅแตข)
โข โฎ โฎ โฎ โฑ โฎ โฅ 1โค๐<๐โค๐
โข โผ โผ โผ โผ โฅ
โฃ 1 ๐ฅโ ๐ฅโยฒ โฏ ๐ฅโโฟโปยน โฆ
```
## CLI
```sh
formulaa formula.aa # edit a formula file (^O saves, ^W saves and quits,
# ^Y copies the AA; a missing file is created)
formulaa --latex2aa formula.tex # LaTeX โ AA, best effort (KaTeX/MathJax dialect)
formulaa --format formula.aa # normalize hand-written AA to canonical form
```
Everything `--aa2latex` emits reads back to the same tree, and `\latex`
in the editor opens a box to paste LaTeX into (unknown commands are
skipped, never an error).
## Fonts
The format leans on Unicode math symbols โ mathematical alphanumerics
(`๐ฅ`, `๐`, `๐ผ`), big operators, bracket pieces, box drawing โ which most
coding fonts cover only in part.
[JuliaMono](https://juliamono.netlify.app/) has all of them at a
monospace width and is the recommended font for the editor;
[`tools/merge_math_font.py`](tools/merge_math_font.py) ports just those
glyphs into another coding font if you would rather keep yours.
## For AI agents
Language models can read and write the format directly.
[`SKILL.md`](SKILL.md) is a self-contained guide for them, including
the verification loop (`--format` to check the syntax, `--aa2latex` to
confirm the meaning). This makes AA a practical way to embed
re-editable math in documents that humans and agents both maintain.
MIT licensed.