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
impl DocumentSession
Sourcepub fn open(path: impl Into<PathBuf>) -> Result<Self, SessionError>
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.
Sourcepub fn open_with_schema(
path: impl Into<PathBuf>,
schema: Schema,
) -> Result<Self, SessionError>
pub fn open_with_schema( path: impl Into<PathBuf>, schema: Schema, ) -> Result<Self, SessionError>
Open a prov document from disk carrying the workspace schema.
Sourcepub fn open_managed(
path: impl Into<PathBuf>,
schema: Option<Schema>,
derived: Vec<String>,
) -> Result<Self, SessionError>
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_names — id,
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?
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}Sourcepub fn open_with(
path: impl Into<PathBuf>,
body_format: BodyFormat,
schema: Option<Schema>,
) -> Result<Self, SessionError>
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.
Sourcepub fn from_text(
path: impl Into<PathBuf>,
text: &str,
body_format: BodyFormat,
schema: Option<Schema>,
) -> Result<Self, SessionError>
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.
pub fn path(&self) -> &Path
Sourcepub fn metadata(&self) -> &Model<ProvBackend>
pub fn metadata(&self) -> &Model<ProvBackend>
The metadata editor (its rows are what a metadata pane renders).
pub fn metadata_mut(&mut self) -> &mut Model<ProvBackend>
Sourcepub fn meta(&self) -> &Value
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?
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}Sourcepub fn cursor_path(&self) -> Option<Vec<Seg>>
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.
pub fn body_mut(&mut self) -> &mut Doc
Sourcepub fn set_metadata(&mut self, path: &[Seg], value: Value)
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).
Sourcepub fn reassemble(&mut self) -> Result<String, SessionError>
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.
Sourcepub fn save(&mut self) -> Result<(), SessionError>
pub fn save(&mut self) -> Result<(), SessionError>
Write the reassembled document (metadata edits + body edits) to disk.