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. Mirrorsleaf_core::Capabilities, where the reasoning lives. - Directive
Attr - One
{key=value}attribute of aDirectiveView. 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 fromkey=""has no consumer on this side. - Directive
View - A leaf directive (
::name{…}) — a standalone block with no body, drawn inDocView::rowsas a one-row⧉ nameplaceholder. 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 aTableView’s picture rows. One that doesn’t just paints the placeholder, which is already framed by the directive panel chrome. - DocView
- A 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.
- Drop
Target View - Where a dragged block would land — what
LeafDoc::drop_target_atanswers with, and the FFI mirror ofleaf_core::DropTarget. A drop is aimed at a row and lands at a boundary, and a host needs both halves: theoffsetto handLeafDoc::move_block, and therowto draw the indicator above —rows.len()for a drop below everything. - Footnote
DefView - A footnote definition and the reference that sends a reader to it — what
LeafDoc::footnote_definition_at_caretanswers with, and the FFI mirror ofleaf_core::FootnoteDef. - Footnote
View - A footnote reference and the note it names — what
LeafDoc::footnote_atanswers with. The FFI mirror ofleaf_core::FootnoteRef. - Heading
View - The heading a place sits under — what
LeafDoc::heading_atanswers with, and the FFI mirror ofleaf_core::Heading. - Highlight
- A host-painted range of the source — an annotation’s footprint, a search
hit. The FFI shape of
leaf_core::Highlight; seeLeafDoc::set_highlights. - Landing
View - Where a locator lands — what
LeafDoc::locateanswers with, and the FFI mirror ofleaf_core::Landing. - LeafDoc
- A live leaf document bound for a native Apple frontend:
leaf_core::Docplus 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. - Math
Height - A per-formula measured height, the way a renderer that reserves rows
(rather than laying pictures out in its own units) reports one back — the
input half of the loop
LeafDoc::set_math_rowscloses. The Swift views lay a formula out in points and never need this. - Math
Picture - A typeset formula: a standalone SVG document and where its baseline is.
The peer of
leaf_math::MathPicture; seetypeset_math. - Math
View - One formula standing as a picture: what to typeset and where its picture
goes. The peer of
leaf_core::MathInfo. Two shapes: - Media
Height - A per-destination measured height, the way Swift reports one back — the input
half of the loop
LeafDoc::set_media_rowscloses. - Media
Source View - 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>). - Media
View - 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 ofDirectiveView— a frontend skips the rows instart_row..end_rowand 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 aUITextPositionwraps) 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.
- Selection
Quote - A selection cited out of the source — the text, a little of what
surrounded it, and the byte range it came from. The FFI shape of
leaf_core::Quote; seeLeafDoc::selection_quote. - Table
Cell Line View - 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. - Table
Cell View - 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).
- Table
RowView - One row of a table’s structural grid; a header row draws bold and is ruled off from the body below it.
- Table
View - 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. Seeleaf_core::TableInfo. - Text
Counts - How much writing there is — over the whole document, or over the
selection. The FFI shape of
leaf_core::TextCounts; seeLeafDoc::countsfor what is counted and what isn’t.
Enums§
- Align
- How a block’s lines are set across the measure — the closed vocabulary
LeafDoc::set_alignmentwrites andLeafDoc::alignment_at_caretreports. - Block
Class - The block kinds core tells apart — the vocabulary a
Boundaryis spelled in. The FFI mirror ofleaf_core::BlockClass;Othercovers every kind core doesn’t separate out, so a frontend’smatchstays exhaustive as the list grows. - Font
Face - The face a run is set in: one of CSS’s four generics, or the family the author named.
- Font
Family - The face a run is set in — CSS’s generic families, less
fantasyandsystem-ui, neither of which an author asks for. WhatLeafDoc::set_font_familywrites. - Font
Size - How large a run is set: a
SizeSteprelative to the text around it, or the point size the author asked for. WhatLeafDoc::set_font_sizewrites andLeafDoc::font_size_at_caretanswers. - Leaf
Error - 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
DocViewdirectly. - Line
Flow - How the rich view treats a soft break (a bare newline inside a paragraph) —
the argument to
LeafDoc::set_line_flow. Mirrorsleaf_core::LineFlow;Foldis the default (soft breaks reflow into the paragraph, as before). - Line
Height - How far apart a block’s lines are set: a
LineSpacingfrom the menu’s three, or the ratio the author asked for.FontSize’s peer one property along, and with no unit at all — a line height is a multiple. - Line
Spacing - How far apart a block’s lines are set, as a multiple of the theme’s own line
height — the vocabulary
LeafDoc::set_line_spacingwrites. - Mark
Color - The colour of a highlight — the closed palette
LeafDoc::set_mark_colorwrites andDocView::mark_colorreports. - Markup
Mode - How much of the source markup the rich view exposes — the argument to
LeafDoc::set_markup_mode. Mirrorsleaf_core::MarkupMode;Noneis the default (the clean surface Diaryx ships, with typed syntax kept literal). - Media
Kind - What a block-level media placeholder is, so Swift knows which view to build
over the rows core reserved: an
NSImageView/UIImageView, or anAVPlayerViewwith or without a picture to show. The peer ofleaf_core::MediaKind. - Size
Step - How large a run is set relative to the text around it — CSS’s
<absolute-size>keywords withmediumremoved, becausemediumis absence. WhatLeafDoc::set_font_sizewrites. - Table
Alignment - A table column’s text alignment — the argument to
LeafDoc::table_set_alignment. Mirrors twig’sAlignment. - Text
Color - A run’s foreground colour: one of the seven
MarkColornames, or the RGB triple the author asked for.
Functions§
- typeset_
math - Typeset
tex— the text between a formula’s delimiters, as aMathViewhands it over — to a picture.displayis the view’sdisplay;sizeis the font size in points the formula is set at (an inline formula takes the run’s, a block the body’s);r,g,b,aare the ink, as bytes. A theme change is a re-render with a new colour.