Skip to main content

Crate leaf_ffi

Crate leaf_ffi 

Source
Expand description

leaf-ffi — the Swift / C-ABI frontend binding for leaf.

This is the native-Apple analogue of leaf-wasm: it takes leaf-core’s frontend-neutral Doc — the byte-offset caret model and the AST→glyph VisualMap — and exposes it across a C ABI (via UniFFI) in the shape an AppKit/SwiftUI renderer wants. Core stays the single source of truth for the text, the caret math, and the offset⇄position mapping; the Swift side only paints glyphs and forwards key/mouse events back in, exactly as the TUI, gpui, and wasm frontends do.

§The boundary is style runs, not glyphs

Doc::build_visual resolves the document to rows of per-character glyphs, each tagged with a semantic Role and the author’s emphasis. Sending one object per character would make every keystroke O(document) in boundary crossings. Instead LeafDoc::view coalesces each row’s glyphs into maximal runs of identical style and ships those — a handful of records per line. The Swift renderer maps each run’s role to a font/size/weight and its emphasis flags to traits, the native counterpart of the TUI’s to_ratatui and the web’s CSS class.

§Core owns the grid; Swift owns the pixels

Core lays a row out in whole character columns (a terminal-cell measure), and every offset⇄position method speaks that grid. It deliberately does not dictate presentation. So a native renderer is proportional — body text in a real family, headings by size and weight, code in a monospace panel — and never multiplies col × cell_width. It lets NSLayoutManager / Core Text shape each row, places the caret at DocView::caret_ch (a UTF-16 offset, which is exactly what NSAttributedString and NSTextView count in), and hit-tests a click through characterIndex(for:), feeding the resulting row + UTF-16 offset back through LeafDoc::click_ch. Core measures nothing in pixels; Swift positions nothing in the model.

§Threading

A UniFFI object is handed to Swift as a reference-counted handle whose methods take &self, so the Doc lives behind a Mutex. Every call locks, edits or reads, and returns a fresh DocView — one boundary crossing both mutates and repaints, same as the wasm frontend. Drive it from the main thread.

Structs§

Boundary
What a drawn block boundary separates. The FFI mirror of leaf_core::Boundary.
Capabilities
Which formatting controls this document’s format can spell — the toolbar’s enabled state, one flag per button, from LeafDoc::capabilities. Mirrors leaf_core::Capabilities, where the reasoning lives.
DirectiveAttr
One {key=value} attribute of a DirectiveView. A record rather than a tuple because UniFFI has no tuple type; an absent value flattens to "", since a bare attribute is a flag and the distinction from key="" has no consumer on this side.
DirectiveView
A leaf directive (::name{…}) — a standalone block with no body, drawn in DocView::rows as a one-row ⧉ name placeholder. A frontend that knows the host app’s vocabulary reads this and paints the real thing over the rows in [start_row, end_row) — a web view for diaryx’s ::embed{src=…}, say — exactly as a grid-drawing one replaces a TableView’s picture rows. One that doesn’t just paints the placeholder, which is already framed by the directive panel chrome.
DocView
A whole rendered frame: the rows to paint, where the caret sits, and the toolbar state — everything the Swift side needs for one repaint, in one value. Returned by every view-producing method.
FootnoteDefView
A footnote definition and the reference that sends a reader to it — what LeafDoc::footnote_definition_at_caret answers with, and the FFI mirror of leaf_core::FootnoteDef.
FootnoteView
A footnote reference and the note it names — what LeafDoc::footnote_at answers with. The FFI mirror of leaf_core::FootnoteRef.
LandingView
Where a locator lands — what LeafDoc::locate answers with, and the FFI mirror of leaf_core::Landing.
LeafDoc
A live leaf document bound for a native Apple frontend: leaf_core::Doc plus the wrap width the current viewport implies, behind a mutex. Constructed from an in-memory string and driven entirely through method calls — there is no filesystem behind it.
MediaHeight
A per-destination measured height, the way Swift reports one back — the input half of the loop LeafDoc::set_media_rows closes.
MediaSourceView
One <source> alternative of a block media element — a candidate URL plus whichever of the two things HTML picks a <source> by: a media query (<picture>) or a MIME type (<video>/<audio>).
MediaView
One block-level image, video, or audio: which rows core reserved for it and what to build there. The peer of leaf_core::MediaInfo, and the media analogue of DirectiveView — a frontend skips the rows in start_row..end_row and lays its own view over them, rather than painting the 🖼/🎬/🔊 placeholder glyphs core put there for a surface that can’t.
Row
One visual line: its styled runs plus the row-level flags a frontend draws chrome from.
RowCol
A visual position: a row index plus a UTF-16 offset within that row’s text — the coordinate the geometry side (Core Text) draws from. Returned by LeafDoc::pos_for_offset, the bridge from a source offset (what a UITextPosition wraps) to where it sits on screen.
RowRange
The rows a source range covers, both ends inclusive — what a frontend slices out of a frame to draw a block somewhere other than where it sits: a footnote peek, a link peek, a landing flash. Returned by LeafDoc::row_range_for.
Run
One maximal span of same-styled glyphs on a visual row — the unit the Swift renderer turns into a single styled attributed-string run.
TableCellLineView
One visual line of a table cell: its styled runs and the source offsets bounding it. A cell is usually one line, but an in-cell hard break (an inline <br>) splits it into several — each its own line here, so the frontend shapes and caret-maps them independently (the byte↔UTF-16 offset math a cell needs holds within a line, which carries no break). The runs are unwrapped: column width — and any soft wrap within it — is the frontend’s to decide.
TableCellView
One cell of a table’s structural grid: its content as one or more visual lines, the column alignment its text honours, and the source range the whole cell occupies (where a click or the caret lands).
TableRowView
One row of a table’s structural grid; a header row draws bold and is ruled off from the body below it.
TableView
A table described structurally rather than as the monospace box-glyph picture that spells it in DocView::rows. A proportional renderer draws its own grid from this — columns sized to content, real borders — and SKIPS the picture rows in [start_row, end_row). The two describe the same cells at the same source offsets, so the caret lands identically either way. See leaf_core::TableInfo.

Enums§

BlockClass
The block kinds core tells apart — the vocabulary a Boundary is spelled in. The FFI mirror of leaf_core::BlockClass; Other covers every kind core doesn’t separate out, so a frontend’s match stays exhaustive as the list grows.
LeafError
A parse failure constructing a document — the only fallible entry point. Every other method is infallible (it operates on an already-parsed model), so they return a DocView directly.
LineFlow
How the rich view treats a soft break (a bare newline inside a paragraph) — the argument to LeafDoc::set_line_flow. Mirrors leaf_core::LineFlow; Fold is the default (soft breaks reflow into the paragraph, as before).
MarkupMode
How much of the source markup the rich view exposes — the argument to LeafDoc::set_markup_mode. Mirrors leaf_core::MarkupMode; None is the default (the clean surface Diaryx ships, with typed syntax kept literal).
MediaKind
What a block-level media placeholder is, so Swift knows which view to build over the rows core reserved: an NSImageView/UIImageView, or an AVPlayerView with or without a picture to show. The peer of leaf_core::MediaKind.
TableAlignment
A table column’s text alignment — the argument to LeafDoc::table_set_alignment. Mirrors twig’s Alignment.