ratex-gpui
A structural, MathQuill-style math editor for GPUI, built on the RaTeX typesetting engine. RaTeX is the engine (parse → layout → rasterize); this crate is the editor + display layer for gpui.
Two halves, usable independently:
- Static rendering (the
rendermodule) — turn a LaTeX string into agpui::RenderImage, or a PNG / self-contained SVG for export. - An interactive structural editor —
MathEditor, a gpui view that edits a formula two-dimensionally (a fraction is a real stacked box, the caret moves into a numerator), Casio-Natural-Display / MathQuill style — not by editing raw LaTeX text. It serializes back to LaTeX on demand.
The editing core is GUI-free (editor::{model, cursor, geometry, input, latex}) —
the gpui glue (editor::view) is layered on top.
📖 Full reference: every public item, with signatures, parameter tables, return contracts, edge cases, and cost notes, lives in API.md.
Features
Section titled “Features”- 2-D structural editing — fractions, roots (incl. nth-roots with an editable degree), super/subscripts, big operators with limits (∫ ∑ ∏ lim), and matrices (add/remove rows + columns)
- Delimiters that wrap a selection or insert an empty pair:
()[]{}||‖‖⟨⟩⌊⌋⌈⌉ \commandautocomplete (~100 commands: Greek, relations, operators, arrows, set/logic) plus a click-to-insert palette- Mouse + keyboard — click-to-place caret, drag / double / triple-click selection, arrow navigation that flows out of the formula at its edges
- Undo / redo, per-formula alignment, selection wrapping (into a fraction, root, or delimiter)
- LaTeX in, LaTeX out — seed from a string, serialize back with
to_latex() - Export — crisp
RenderImage, PNG, or self-contained SVG (KaTeX glyph paths embedded) - Host-themed — all chrome colors come from a host-supplied
MathTheme
Coverage: rendering ≈ KaTeX (RaTeX’s parser is a KaTeX port, ~660 commands), so
anything KaTeX renders, this renders. The 2-D editor models a practical subset —
constructs outside it (accents, math fonts, multi-line environments, …) still render
perfectly but degrade if opened in the structural editor (the wrapper is dropped on
commit); edit those as raw LaTeX instead. Details in API.md under parse_latex.
Adding the dependency
Section titled “Adding the dependency”# Full crate (default `editor` feature: MathEditor + the editing modules):ratex-gpui = { version = "0.1" }
# Render-only build — LaTeX → image / PNG / SVG plus the parse/serialize core,# without the gpui view + editing machinery:ratex-gpui = { version = "0.1", default-features = false }Quick start
Section titled “Quick start”Render a formula to an image
Section titled “Render a formula to an image”use gpui::{img, px};use ratex_gpui::render;
let r = render::render_latex( r"\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}", 22.0, // font size (px/em) window.scale_factor(), // device-pixel ratio theme.text_color, // tint);match r { Some(r) => img(r.image).w(px(r.width)).h(px(r.height)).into_any_element(), None => /* parse/layout failed — fall back to the raw source */ todo!(),};Rendering is pure CPU (no Window/GPU), so it’s safe to run off the main thread and
cache — render once per formula, keyed by the LaTeX.
Host the interactive editor
Section titled “Host the interactive editor”MathEditor is a normal gpui view. Create it, focus it, place it in your tree, and
listen for MathNav events:
use ratex_gpui::{MathAlign, MathEditor, MathNav, MathTheme};
let editor = cx.new(|cx| { MathEditor::from_latex(r"x^2 + 1", 22.0, true, MathAlign::Center, my_theme(), cx)});window.focus(&editor.read(cx).focus_handle(), cx);
cx.subscribe(&editor, |this, editor, ev: &MathNav, cx| match ev { // Arrowing past an edge (or Esc) — commit and take focus back. MathNav::Exit { after } => { let latex = editor.read(cx).to_latex(); // splice `latex` back into your document, move your text caret out } // Right-click while editing — show your copy-LaTeX / export menu. MathNav::ContextMenu { position } => { /* … */ }});Hosting notes
Section titled “Hosting notes”The crate is a leaf: it edits one formula and tells you (via MathNav) when to take
focus back. When hosting:
- Drop your key context while the editor is focused — it lives inside your element, so your own keybindings would otherwise swallow arrows/typing before they reach it.
- Commit on
MathNav::Exit, on focus-loss (click-away), or when the user opens another formula: readto_latex()(+align()) and splice it back. - On
MathNav::ContextMenu, show your menu at the given window position;set_align(…)re-justifies live if you offer alignment there.
This is exactly how its host application (Zorite) drives it for both display $$…$$
blocks and inline $…$ formulas.
Built on RaTeX
Section titled “Built on RaTeX”Typesetting comes from the RaTeX crates —
ratex-parser (parse), ratex-layout (box layout), ratex-render (raster, KaTeX fonts
embedded), and ratex-svg (vector export). This crate adds the editing model + cursor +
hit-testing and the gpui view/render adapters on top. gpui is a git-only dependency
(tracking Zed), so this isn’t published to crates.io yet.
License
Section titled “License”GPL-3.0-or-later.