Skip to main content

Crate writ

Crate writ 

Source
Expand description

A hybrid markdown editor: raw text editing with live inline rendering (markers like **, #, and - are hidden when the cursor is elsewhere) plus an inline git diff against HEAD, rendered on winit + wgpu + Vello + Parley.

writ ships as both a desktop application (the writ binary) and a library. The library’s centerpiece is MarkdownView — a headless, render-only markdown renderer you can embed in your own winit/wgpu/Vello app.

§The application

  • Live inline rendering: Markdown syntax is hidden when not editing
  • Syntax highlighting: Code blocks with tree-sitter based highlighting
  • Smart continuation: Shift+Enter continues lists, blockquotes, etc.
  • Inline git diff: Renders the working file’s diff against git HEAD, refreshed live as the file or HEAD changes (an external commit updates the diff too)
// `writ --file notes.md` — the shell reads the path from the CLI and runs the app.
writ::shell::run()?;

§Using writ as a library

MarkdownView turns markdown into a Vello Scene (a CPU display list) with no window, GPU device, editor, or diff machinery — the consumer owns its surface and rasterizes the scene however it likes. It supports streaming: feed content incrementally with MarkdownView::push_str (e.g. tokens from an LLM) and re-render.

use vello::Scene;
use writ::MarkdownView;

let mut view = MarkdownView::new();
view.push_str("# Streaming\n\n");
view.push_str("More text arrives later.\n");

let mut scene = Scene::new();
view.render(&mut scene, 800.0, 600.0, 1.0); // scene is now a display list
// ... hand `scene` to a vello::Renderer to rasterize onto your own surface.

See examples/streaming_markdown.rs for an end-to-end headless render to PNG (via rasterize_scene_to_png). For image support the component stays IO-free: it lists referenced URLs via MarkdownView::image_urls and you push decoded bytes back in with MarkdownView::set_image_bytes.

§Feature flags

Depend on writ with default-features = false to get just the renderer without the app’s editor/git/GitHub/networking stack:

writ = { version = "0.16", default-features = false }
  • (none) — the render-only base: MarkdownView, rasterize_scene_to_png, the diff algorithm, layout, and syntax highlighting. Pulls no winit/tokio/reqwest/ gix/notify.
  • editor — the headless Editor orchestration hub (git diff vs HEAD, GitHub ref validation, file watching). Enables the core module.
  • app (default) — the full desktop application: the winit shell, clipboard, config file, mermaid + math + remote images. Implies editor.
  • Individual toggles: git, github, watch, remote-images, mermaid, math.

Re-exports§

pub use core::Editor;
pub use editor::Direction;
pub use editor::EditorTheme;
pub use image_load::RepaintSignal;
pub use markdown_view::MarkdownView;
pub use raster::rasterize_scene_to_png;

Modules§

buffer
callout
Obsidian-style callouts / admonitions.
chrome
Window chrome for the new shell (see MIGRATION-PLAN.md, Phase 6): an in-window title bar (filename + dirty marker) and a status bar (nesting context + cursor position). Drawn as opaque strips above/below the editor, which is inset between them. CSD (custom window frame) and the async-blocked overlays are deferred.
config
consts
Appearance / frame constants, in one place so the shell (which renders) and the layout tests (which reproduce the frame) share a single source of truth rather than each hardcoding the same numbers. All values are logical px unless noted.
core
Headless editor model — the gpui-free core (see MIGRATION-PLAN.md, Phase 2).
cursor
diff
Inline diff computation for the git HEAD-vs-working view.
doc_layout
Document viewport: per-line Parley layouts stacked by a prefix-sum height model, plus scroll (see MIGRATION-PLAN.md, Phase 3). Replaces gpui’s ListState (which gave virtualization + scroll-to-reveal for free) with hand-rolled math.
editor
fold
Folding: pure geometry over the document’s ATX headings and list items.
git
github
GitHub API client using GraphQL.
highlight
image_cache
Shared, cheaply-cloneable cache of decoded images for standalone-image rendering.
image_load
Standalone-image IO: resolving URLs to local paths, reading/decoding local files, fetching + decoding remote images, and the spawn/blocking entry points that feed decoded images into the shared ImageCache. Kept off the shell so the god-object doesn’t carry the reqwest/decode plumbing.
inline
Inline style extraction for markdown text.
markdown_view
Headless, render-only markdown view: turns markdown text into a Vello Scene (a CPU display list) with no window, GPU device, editor, or diff machinery. It is the reusable core of writ’s renderer, meant to be embedded in another app that owns its own surface and rasterizes the scene however it likes.
marker
Line markers for markdown block-level elements.
math
LaTeX math rendering: turn $…$ / $$…$$ source into a rasterized image via RaTeX (parse → layout → tiny-skia PNG, with the KaTeX fonts embedded), then route it through writ’s existing image pipeline (image_cache::decodeLoadedImage → the standalone- /inline-image draw path). Glyph color is set to the theme foreground at layout time so math is legible on the dark editor; the background is transparent. Rendering runs off the UI thread, cached by a key over (latex, display, size, color).
mermaid
Mermaid diagram rendering: detect a ```mermaid fence, render its source to SVG via mermaid-rs-renderer, and route the SVG through writ’s existing image pipeline (image_cache::decodeLoadedImage → the standalone-image draw path). The diagram is cached under a synthetic mermaid:<hash> key so it renders once per distinct source, not per frame; rendering runs off the UI thread.
outline
The document-map / outline panel: a right-docked list of the document’s ATX headings, the current section highlighted, click a heading to scroll to it.
overlay
Overlay rendering: the GitHub-ref hover popover and the autocomplete dropdown, plus the styled-segment machinery (issue/user/title markdown) they share and the hover hit-testing that finds the ref under the pointer.
parser
paste
Context-aware paste handling for markdown.
raster
Headless rasterization: turn a Vello Scene into a PNG on disk via wgpu, with no window or surface. Shared by the golden-image snapshot harness (crate::shell) and by library consumers/examples so they don’t reimplement the device/renderer/readback dance. On Apple Silicon Fedora (Asahi) set WGPU_BACKEND=vulkan so wgpu picks a working adapter.
render
Per-line styling for the new render path (see MIGRATION-PLAN.md, Phase 3).
segment_map
Display↔buffer segment map (see MIGRATION-PLAN.md, Phase 3b) — the load-bearing invariant of the new render path.
shell
winit + wgpu + Vello application shell — the gpui replacement (see MIGRATION-PLAN.md).
status_bar
table
GFM pipe-table model extraction (headless).
text_engine
Parley text layout + Vello glyph drawing — the core of writ’s render path. Lays out a styled line with browser-grade (Chromium) soft-wrap and hanging indent, and paints its glyphs into a Vello scene. Drives the per-line layout cache and the display↔buffer map.
text_input
A reusable, headless single-line text-input core. No winit, no drawing — pure text/caret/selection state. Adapters (find bar, filter box, goto-line prompt) layer input handling and rendering on top of this.
tokenize
Hand-written syntax-highlight tokenizers for languages that have no publishable tree-sitter grammar crate: Mermaid diagram source and LaTeX math. Each is a small lexical scanner (keyword-match + punctuation/arrow patterns) that emits HighlightSpans using the shared capture categories (see highlight_id), so a Highlighter treats them as ordinary registered languages and they render through the same theme color map as the tree-sitter grammars. Token→category choices follow the consensus of the canonical tree-sitter grammars (monaqa/tree-sitter-mermaid, latex-lsp/tree-sitter-latex) and their Helix/nvim overrides.
validation
GitHub reference validation model and cache.