Skip to main content

LeafDoc

Struct LeafDoc 

Source
pub struct LeafDoc { /* private fields */ }
Expand description

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.

Implementations§

Source§

impl LeafDoc

Source

pub fn new(source: String, format: String) -> Result<Arc<Self>, LeafError>

Parse source as format ("markdown"/"md", "djot"/"dj", "html", "xml") into a live, untitled document.

Source

pub fn view(&self) -> DocView

Resolve the current document to a renderable frame — the first paint.

Source

pub fn set_width(&self, cols: u32) -> DocView

Set the wrap width (in columns) the viewport implies and repaint. For a fixed-cell frontend (a terminal); a proportional GUI uses [set_unwrapped].

Source

pub fn set_unwrapped(&self) -> DocView

Switch to unwrapped layout — one visual row per block, no column wrapping — and repaint. A proportional GUI calls this once at start-up, then wraps each row at its own pixel width (the caret/hit/selection geometry it derives from the pixel wrap; core still owns the caret model, in byte offsets). Idempotent and cheap to leave in place across edits.

Source

pub fn set_dark_appearance(&self, dark: bool) -> DocView

Tell core whether the host is in a dark appearance, so a <picture>’s prefers-color-scheme <source>s resolve to the right banner. Call it from viewDidChangeEffectiveAppearance (AppKit) or traitCollectionDidChange (UIKit).

Cheap to call repeatedly: resolving at the same appearance yields the same URLs, and a renderer keying its views by src tears nothing down.

Source

pub fn set_media_rows(&self, heights: Vec<MediaHeight>) -> DocView

Report how many visual rows each block media actually needs, measured from the views the renderer laid out, keyed by the media’s src.

Core does no I/O and can’t know how tall a picture or a player is, so this is the only way a placeholder grows past its default single row. The loop is: lay out at the current reservation → measure → call this → repaint if it changed. Handing over the same measurements again is a no-op, so a renderer can report its current state each frame without diffing first.

A frontend that lays media out in its own units and simply reserves the vertical space itself (the way the gpui GUI does with images) never needs to call this at all.

Source

pub fn insert_media( &self, kind: MediaKind, destination: String, alt: String, ) -> DocView

Insert a block-level image, video, or audio at the caret. Any selection becomes the alt / fallback text. See leaf_core::Doc::insert_media for the markup each kind spells.

Source

pub fn insert_thematic_break(&self) -> DocView

Insert a thematic break (---) at the caret — the toolbar’s Horizontal Rule button. See leaf_core::Doc::insert_thematic_break for how it handles a selection, a blank line, and the caret sitting mid-paragraph, mid-list, or inside a quote.

Source

pub fn source(&self) -> String

The current source text — for a save (write to disk / iCloud / a document wrapper) or a source-view display.

Source

pub fn selected_text(&self) -> Option<String>

The selected text, if any — for a clipboard copy/cut.

Source

pub fn mark_saved(&self) -> DocView

Mark the buffer saved after the host persisted LeafDoc::source its own way — clears the dirty flag without touching a filesystem.

Source

pub fn insert(&self, text: String) -> DocView

Source

pub fn paste(&self, text: String) -> DocView

Source

pub fn newline(&self) -> DocView

Source

pub fn indent(&self) -> DocView

Tab away from a table: indent the caret’s line (or the selected lines) one level, nesting a list item under its sibling. The frontend calls this when LeafDoc::cell_tab declined because the caret isn’t in a table.

Source

pub fn outdent(&self) -> DocView

Shift+Tab away from a table: take one indent level back off the caret’s line (or the selected lines), unnesting a list item. The mirror of LeafDoc::indent.

Source

pub fn cell_tab(&self, forward: bool) -> Option<DocView>

Tab (forward) / Shift+Tab hops to the next/previous cell; Tab past the last cell appends a fresh row and enters it.

Source

pub fn cell_return(&self) -> Option<DocView>

Return drops to the cell below in the same column, appending a row at the table’s bottom.

Source

pub fn cell_line_break(&self) -> Option<DocView>

Shift+Return inserts a hard line break within the current cell.

Source

pub fn backspace(&self) -> DocView

Source

pub fn delete_forward(&self) -> DocView

Source

pub fn delete_word_back(&self) -> DocView

Source

pub fn delete_word_forward(&self) -> DocView

Source

pub fn move_left(&self, extend: bool) -> DocView

Source

pub fn move_right(&self, extend: bool) -> DocView

Source

pub fn move_up(&self, extend: bool) -> DocView

Source

pub fn move_down(&self, extend: bool) -> DocView

Source

pub fn move_word_left(&self, extend: bool) -> DocView

Source

pub fn move_word_right(&self, extend: bool) -> DocView

Source

pub fn move_home(&self, extend: bool) -> DocView

Source

pub fn move_end(&self, extend: bool) -> DocView

Source

pub fn move_doc_start(&self, extend: bool) -> DocView

Source

pub fn move_doc_end(&self, extend: bool) -> DocView

Source

pub fn select_all(&self) -> DocView

Source

pub fn click(&self, row: u32, col: u32, extend: bool) -> DocView

Place the caret from a click, in core’s column grid: row indexes the visual Rows and col is the glyph column within it. Core clamps both to real caret stops. Prefer LeafDoc::click_ch from a proportional renderer.

Source

pub fn click_ch(&self, row: u32, ch: u32, extend: bool) -> DocView

Place the caret from a click whose horizontal position is a UTF-16 offset into the visual row’s text — what characterIndex(for:) hands back. Converted to core’s display column before clicking, so a proportional renderer never reasons about column widths itself.

Source

pub fn select_word_ch(&self, row: u32, ch: u32) -> DocView

Select the word under a click (row, ch) — the double-click gesture.

Source

pub fn select_block_ch(&self, row: u32, ch: u32) -> DocView

Select the whole logical text block under a click (row, ch) — the triple-click gesture. Grabs the entire block even where it soft-wraps.

Source

pub fn set_selection( &self, anchor_row: u32, anchor_ch: u32, focus_row: u32, focus_ch: u32, ) -> DocView

Mirror a native selection into the model: [anchor, focus] given as row + UTF-16 offset pairs. Each is resolved to a source offset the way a click is, then set as the selection’s fixed and moving ends. A collapsed range (anchor == focus) just places the caret.

Source

pub fn selection_html(&self) -> Option<String>

The current selection rendered to HTML by twig — the rich flavor a copy writes alongside the plain LeafDoc::selected_text. None when nothing is selected.

Source

pub fn paste_rich(&self, html: Option<String>, text: String) -> DocView

Paste, preferring the clipboard’s rich (text/html) flavor: twig parses html into the document’s own markup and inserts it. Falls back to the plain text when there’s no HTML or it doesn’t parse.

Source

pub fn toggle_bold(&self) -> DocView

Source

pub fn toggle_italic(&self) -> DocView

Source

pub fn toggle_code(&self) -> DocView

Source

pub fn toggle_mark(&self) -> DocView

Source

pub fn toggle_underline(&self) -> DocView

Source

pub fn toggle_strike(&self) -> DocView

Source

pub fn set_paragraph(&self) -> DocView

Source

pub fn set_heading(&self, level: u32) -> DocView

Toggle the current block to a heading of level (1–6); toggling the active level off returns it to a paragraph, per core.

Source

pub fn toggle_blockquote(&self) -> DocView

Source

pub fn toggle_list(&self, ordered: bool) -> DocView

Source

pub fn toggle_task_checked(&self) -> DocView

Tick or untick the task item at the caret. See leaf_core::Doc::toggle_task_checked.

Source

pub fn toggle_task_at(&self, offset: u64) -> DocView

Tick or untick the task item covering offset — a tap on a rendered checkbox, which must not drag the caret across the document to get there.

Source

pub fn toggle_task_item(&self) -> DocView

Give the list item at the caret a checkbox, or take its checkbox away.

Source

pub fn task_checked_at_caret(&self) -> Option<bool>

Whether the item at the caret has a box and which way it faces — None for a plain list item or no item at all. Drives a toolbar’s checked state.

Source

pub fn capabilities(&self) -> Capabilities

Which of the formatting commands above this document’s format can actually spell — one flag per control, for building the toolbar.

Read once when a document opens: the answer depends only on the format, so it cannot change under an edit. Every command refuses on its own regardless — the model is the authority, not the toolbar — so a frontend that ignores this stays correct, it just offers buttons whose only effect is a line in the status bar.

Don’t collapse it to one flag. An HTML document takes ⌘B, ⌘I and inline code (its marks are a tag pair) while refusing every heading, list, quote and link, and Markdown refuses the highlight djot spells — so a toolbar driven by Self::authorable alone would be wrong in both directions.

Source

pub fn authorable(&self) -> bool

Whether this document’s format offers any door in — false only for a wholly parse-only one (XML), where an app may as well open the file read-only and hide the formatting section outright. For anything finer, including whether to dim an individual button, use Self::capabilities.

Source

pub fn caret_in_table(&self) -> bool

Whether the caret is inside a table — for enabling the table controls. Pair it with Capabilities::table: the caret is genuinely inside an HTML <table>, and the grid controls still cannot edit one.

Source

pub fn table_insert_row(&self, below: bool) -> DocView

Insert an empty row below (below) or above the caret’s row.

Source

pub fn table_delete_row(&self) -> DocView

Delete the caret’s row (not the header or the last body row).

Source

pub fn table_insert_column(&self, right: bool) -> DocView

Insert an empty column right (right) or left of the caret’s column.

Source

pub fn table_delete_column(&self) -> DocView

Delete the caret’s column (unless it is the only one).

Source

pub fn table_set_alignment(&self, alignment: TableAlignment) -> DocView

Set the caret’s column to alignment.

Source

pub fn table_move_row(&self, down: bool) -> DocView

Move the caret’s row one place down (down) or up.

Source

pub fn table_move_column(&self, right: bool) -> DocView

Move the caret’s column one place right (right) or left.

The destination of the link under the caret, if the caret is inside one — so a frontend can open it (⌘-click / “Open Link”) or show it. None when the caret isn’t on a link.

The destination of the link at byte offset offlink_destination_at_caret for a place the caret isn’t.

What a frontend drawing part of the document outside the document asks: a footnote’s text in a popover has link runs in it, and this is how those runs learn where they point, since a Run carries how a span looks and not what it means.

Source

pub fn locate(&self, id: String) -> Option<LandingView>

Where the locator id lands in this document — the #v2 half of a chapter.dj#v2, resolved to the block it names. None when nothing here answers to it, which is a host’s cue to open the document at its top rather than refuse to go.

The query that gives a link finer granularity than the file. It reads an explicit {#v1}, a djot heading’s minted id, or (for Markdown, which mints none) a heading’s own words slugged — see leaf_core::Doc::locate.

Asked of any document, not only the open one: a host peeking at a citation builds a LeafDoc over the other file’s bytes and asks this, which is what lets a hover show the verse instead of the filename.

Source

pub fn insert_footnote(&self) -> DocView

Write a footnote at the caret — the toolbar’s Footnote button. Both the [^1] and the definition it needs go in as one edit (one undo takes both back), the label is the lowest number the document has free, and the caret is left in the empty note ready to type it. Gate the button on Capabilities::footnote; see leaf_core::Doc::insert_footnote.

Source

pub fn footnote_at_caret(&self) -> Option<FootnoteView>

The footnote reference under the caret, resolved to the note it names — so a frontend can show the note when a reader activates a [1], instead of the nothing a reference click used to do. None when the caret isn’t on a reference; see FootnoteView for the reference that resolved to no definition.

Source

pub fn footnote_at(&self, off: u32) -> Option<FootnoteView>

The footnote reference at byte offset off, resolved to the note it names — footnote_at_caret for a place the caret isn’t.

This is what a hover asks: a pointer resting on a [1] wants the note’s text in a popover, and moving the caret to find out would yank the reader out of wherever they were typing.

Source

pub fn footnote_definition_at_caret(&self) -> Option<FootnoteDefView>

The footnote definition the caret stands in, and where the reference that names it is — the return leg of footnote_at_caret, so following a footnote is a round trip rather than a fall.

None when the caret isn’t in a definition, which is also how a frontend tells the two directions apart: the reference query answers up top, this one answers down in the notes, and never both at once.

Source

pub fn undo(&self) -> DocView

Source

pub fn redo(&self) -> DocView

Source

pub fn toggle_view(&self) -> DocView

Switch between the rendered WYSIWYG surface and the raw source.

Source

pub fn markup_mode(&self) -> MarkupMode

The current markup-exposure preference (see MarkupMode).

Source

pub fn set_markup_mode(&self, mode: MarkupMode) -> DocView

Set the markup-exposure preference. Returns a fresh view so a frontend can repaint — and under Full it must, because the returned view is the first one showing the caret’s line raw. Diaryx leaves it at the None default.

Source

pub fn line_flow(&self) -> LineFlow

The current soft-break flow preference (see LineFlow).

Source

pub fn set_line_flow(&self, mode: LineFlow) -> DocView

Set the soft-break flow preference. Returns a fresh view so a frontend can repaint: like the markup-exposure preference this one changes rendering immediately, laying preserved soft breaks out as their own rows.

Source§

impl LeafDoc

Source

pub fn caret_offset(&self) -> u32

The caret’s source offset (the selection’s moving end).

Source

pub fn anchor_offset(&self) -> u32

The selection’s fixed end (equals the caret when there’s no selection).

Source

pub fn doc_end_offset(&self) -> u32

The last caret stop in the document — UITextInput.endOfDocument.

Source

pub fn snap_offset(&self, off: u32) -> u32

Snap an arbitrary offset to the nearest valid caret stop.

Source

pub fn pos_for_offset(&self, off: u32) -> RowCol

Where a source offset sits on screen: its visual (row, ch).

Source

pub fn row_range_for(&self, start: u32, end: u32) -> RowRange

The rows a source range covers, inclusive — for drawing a block away from where it sits (a footnote peek, a link peek, a landing flash).

Ask this rather than mapping start and end - 1 through Self::pos_for_offset. That pair reads correctly and is wrong: a block’s last byte is often hidden — a note or a paragraph ending in a link ends inside the link’s destination — and pos_for_offset snaps a hidden offset forward to the next visible glyph, which for a trailing one is on the next block’s row. A peek slicing that span drew the block after it too. pos_for_offset’s snap is right for a caret and wrong for a span; this is the question spans should be asking.

Source

pub fn offset_for_pos(&self, row: u32, ch: u32) -> u32

The source offset at visual (row, ch) — the inverse of Self::pos_for_offset, for hit-testing a point to a position.

Source

pub fn step_offset(&self, off: u32, delta: i32) -> u32

Move off by delta caret stops (negative = left) — position(from:offset:).

Source

pub fn distance_offset(&self, from: u32, to: u32) -> i32

The count of caret stops between two offsets (signed) — offset(from:to:).

Source

pub fn vertical_offset(&self, off: u32, down: bool) -> Option<u32>

The offset one navigable row up/down from off, keeping its column — position(from:in: .up/.down). None at the top/bottom edge.

Source

pub fn text_in_range(&self, from: u32, to: u32) -> String

The visible text between two offsets — text(in:). In the WYSIWYG view this is not the raw source slice: a hidden inline-mark delimiter (**, `, _) contributes nothing, matching what distance_offset/step_offset already count in this same offset space — while a genuine block boundary the range spans (a paragraph gap, a table rule, …) contributes one inserted '\n' that distance_offset/step_offset do not count (a block boundary costs caret motion zero stops there, by design — see the_caret_skips_the_gap_between_two_paragraphs in leaf-core’s doc.rs). So the relationship is text_in_range(a, b).chars().count() >= distance_offset(a, b), not strict equality: the two agree exactly when (a, b) spans no block boundary, and text_in_range is never shorter, only ever as long or longer, when it does. That inequality is still what UITextInput‘s own word/line tokenizer needs (see leaf_core::wysiwyg::VisualMap::visible_text for why): it only reads this string to find a boundary and converts the result back to a position via position(from:offset:), which walks stops — the inserted character is never hit as one, it only keeps the tokenizer from reading two paragraphs’ last/first words as a single run of letters. The source view has nothing hidden to begin with, so there this is still exactly the raw slice.

Source

pub fn set_selection_offsets(&self, anchor: u32, focus: u32) -> DocView

Set the selection to [anchor, focus] by source offsets — the setter behind UITextInput.selectedTextRange and handle dragging.

Source

pub fn replace_range(&self, from: u32, to: u32, text: String) -> DocView

Replace the source range [from, to] with textreplace(_:withText:).

Trait Implementations§

Source§

impl<UT> LiftRef<UT> for LeafDoc

Source§

impl<UT> LowerError<UT> for LeafDoc

Source§

fn lower_error(obj: Self) -> RustBuffer

Lower this value for scaffolding function return Read more
Source§

impl<UT> LowerReturn<UT> for LeafDoc

Source§

type ReturnType = <Arc<LeafDoc> as LowerReturn<UniFfiTag>>::ReturnType

The type that should be returned by scaffolding functions for this type. Read more
Source§

fn lower_return(obj: Self) -> Result<Self::ReturnType, RustCallError>

Lower the return value from an scaffolding call Read more
Source§

fn handle_failed_lift( error: LiftArgsError, ) -> Result<Self::ReturnType, RustCallError>

Lower the return value for failed argument lifts Read more
Source§

impl<UT> TypeId<UT> for LeafDoc

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, UT> HandleAlloc<UT> for T
where T: Send + Sync,

Source§

fn new_handle(value: Arc<T>) -> Handle

Create a new handle for an Arc value Read more
Source§

unsafe fn clone_handle(handle: Handle) -> Handle

Clone a handle Read more
Source§

unsafe fn consume_handle(handle: Handle) -> Arc<T>

Consume a handle, getting back the initial Arc<> Read more
Source§

unsafe fn get_arc(handle: Handle) -> Arc<Self>

Get a clone of the Arc<> using a “borrowed” handle. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.