Skip to main content

DocumentSession

Struct DocumentSession 

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

One open prov document: a metadata editor and a body editor over the same file, reconciled on save.

Implementations§

Source§

impl DocumentSession

Source

pub fn open(path: impl Into<PathBuf>) -> Result<Self, SessionError>

Open a prov document from disk, parsing the body in the grammar its extension declares, with no schema.

Source

pub fn open_with_schema( path: impl Into<PathBuf>, schema: Schema, ) -> Result<Self, SessionError>

Open a prov document from disk carrying the workspace schema.

Source

pub fn open_managed( path: impl Into<PathBuf>, schema: Option<Schema>, derived: Vec<String>, ) -> Result<Self, SessionError>

Open a prov document declaring the keys the workspace maintains, so the metadata model draws their rows and declines every edit to them.

derived is Facets::managed_key_namesid, content_hash, and whatever the workspace named as its updated stamp. It is a separate entry point rather than something open_with_schema does for you because declining an edit is a policy, and a repair tool that means to rewrite a stale id is as legitimate a frontend as an editor that must not. This crate hands over the list and lets the frontend decide (see crate::facets); most editors want it, and this is the one line that says so.

The set has to arrive here rather than being applied afterwards: flower takes it before it builds its first row list.

Examples found in repository?
examples/inspect.rs (line 20)
7fn main() {
8    let path = std::path::PathBuf::from(std::env::args().nth(1).expect("a document"));
9    let view = WorkspaceView::discover(&path).expect("discovery");
10    match &view {
11        Some(v) => println!("workspace: {}", v.root_dir().display()),
12        None => println!("workspace: none"),
13    }
14    let facets = view
15        .as_ref()
16        .map(|v| v.facets().clone())
17        .unwrap_or_default();
18    let schema = view.as_ref().map(|v| v.schema_for(&path));
19    let session =
20        DocumentSession::open_managed(&path, schema, facets.managed_key_names()).expect("open");
21
22    println!("\nkeys:");
23    for (key, facet) in facets.classify(session.meta()) {
24        let flags = [
25            facet.structural().then_some("structural"),
26            facet.managed().then_some("managed"),
27        ]
28        .into_iter()
29        .flatten()
30        .collect::<Vec<_>>()
31        .join(",");
32        println!("  {key:<14} {:<9} {flags}", facet.kind());
33    }
34
35    println!("\nlinks:");
36    for link in links_in(session.meta(), &facets) {
37        let landing = match &view {
38            Some(v) => v.resolve(&path, &link),
39            None => resolve_without_workspace(&path, &link),
40        };
41        let mark = if matches!(landing, Destination::Document { exists: true, .. }) {
42            "→"
43        } else {
44            "·"
45        };
46        println!(
47            "  {mark} {:<10} {:<22} {}",
48            link.relation.name,
49            link.display(),
50            landing.describe()
51        );
52    }
53}
Source

pub fn open_with( path: impl Into<PathBuf>, body_format: BodyFormat, schema: Option<Schema>, ) -> Result<Self, SessionError>

Open a prov document from disk, parsing the body as body_format, with an optional workspace schema.

Source

pub fn from_text( path: impl Into<PathBuf>, text: &str, body_format: BodyFormat, schema: Option<Schema>, ) -> Result<Self, SessionError>

Build a session from in-memory text. The path still drives prov’s carrier/format detection (extension for a config doc, content sniffing for a fenced block). schema governs the metadata model when present.

Source

pub fn path(&self) -> &Path

Source

pub fn has_body(&self) -> bool

Whether the document has an editable prose body.

Source

pub fn metadata(&self) -> &Model<ProvBackend>

The metadata editor (its rows are what a metadata pane renders).

Source

pub fn metadata_mut(&mut self) -> &mut Model<ProvBackend>

Source

pub fn meta(&self) -> &Value

The metadata value tree — what crate::links and crate::facets ask their questions of.

The model’s own copy, not a reparse: it is rebuilt on every edit, so this is current and free.

Examples found in repository?
examples/inspect.rs (line 23)
7fn main() {
8    let path = std::path::PathBuf::from(std::env::args().nth(1).expect("a document"));
9    let view = WorkspaceView::discover(&path).expect("discovery");
10    match &view {
11        Some(v) => println!("workspace: {}", v.root_dir().display()),
12        None => println!("workspace: none"),
13    }
14    let facets = view
15        .as_ref()
16        .map(|v| v.facets().clone())
17        .unwrap_or_default();
18    let schema = view.as_ref().map(|v| v.schema_for(&path));
19    let session =
20        DocumentSession::open_managed(&path, schema, facets.managed_key_names()).expect("open");
21
22    println!("\nkeys:");
23    for (key, facet) in facets.classify(session.meta()) {
24        let flags = [
25            facet.structural().then_some("structural"),
26            facet.managed().then_some("managed"),
27        ]
28        .into_iter()
29        .flatten()
30        .collect::<Vec<_>>()
31        .join(",");
32        println!("  {key:<14} {:<9} {flags}", facet.kind());
33    }
34
35    println!("\nlinks:");
36    for link in links_in(session.meta(), &facets) {
37        let landing = match &view {
38            Some(v) => v.resolve(&path, &link),
39            None => resolve_without_workspace(&path, &link),
40        };
41        let mark = if matches!(landing, Destination::Document { exists: true, .. }) {
42            "→"
43        } else {
44            "·"
45        };
46        println!(
47            "  {mark} {:<10} {:<22} {}",
48            link.relation.name,
49            link.display(),
50            landing.describe()
51        );
52    }
53}
Source

pub fn cursor_path(&self) -> Option<Vec<Seg>>

The metadata path the cursor is on, whichever projection the model is showing.

flower has two — a flat row list and a page stack — and asks the question a different way in each. A frontend that wants “the row under the cursor” should not have to know which one it set, least of all a frontend that switches between them; getting it wrong reads as a link that follows the wrong document rather than as an error.

Source

pub fn body(&self) -> &Doc

The body editor.

Source

pub fn body_mut(&mut self) -> &mut Doc

Source

pub fn set_metadata(&mut self, path: &[Seg], value: Value)

Programmatically set the metadata value at path — the flat, by-path edit a UI/FFI issues (vs. driving the selection).

Source

pub fn dirty(&self) -> bool

true if the metadata or the body has unsaved edits.

Source

pub fn reassemble(&mut self) -> Result<String, SessionError>

Reconcile the body edits into the document and return the full reassembled text — exactly the bytes save writes. Does not touch disk.

Source

pub fn save(&mut self) -> Result<(), SessionError>

Write the reassembled document (metadata edits + body edits) to disk.

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, 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> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.