pub struct ProvBackend { /* private fields */ }Expand description
A backend over a single prov document, editing its embedded metadata.
Implementations§
Source§impl ProvBackend
impl ProvBackend
Sourcepub fn open(
path: impl Into<PathBuf>,
text: impl Into<String>,
) -> Result<Self, BackendError>
pub fn open( path: impl Into<PathBuf>, text: impl Into<String>, ) -> Result<Self, BackendError>
Open a prov document from its full text, with no schema. Errors if prov
cannot parse it.
Sourcepub fn open_with_schema(
path: impl Into<PathBuf>,
text: impl Into<String>,
schema: Schema,
) -> Result<Self, BackendError>
pub fn open_with_schema( path: impl Into<PathBuf>, text: impl Into<String>, schema: Schema, ) -> Result<Self, BackendError>
Open a prov document carrying the workspace schema — the prov-aware path,
so the flower model validates controlled fields and offers pickers.
Sourcepub fn body(&self) -> Result<String, BackendError>
pub fn body(&self) -> Result<String, BackendError>
The prose body outside the metadata block — the region a leaf editor
would own. Empty for a whole-file config document.
Sourcepub fn has_body(&self) -> Result<bool, BackendError>
pub fn has_body(&self) -> Result<bool, BackendError>
Whether the document has an editable prose body (a fenced carrier). A whole-file config document has none — its body cannot be replaced.
Sourcepub fn set_candidates(&mut self, candidates: HashMap<String, Vec<Choice>>)
pub fn set_candidates(&mut self, candidates: HashMap<String, Vec<Choice>>)
Tell the backend what a picker on each relation’s field should
offer — the injection Backend::candidates exists for.
A reference field’s candidates are other documents, and this backend is
one document with a path: it can say which relation a path is, from the
schema it is already carrying, and nothing about what else exists. So the
list arrives from whoever has a workspace —
WorkspaceView::candidates_map builds one, and
WorkspaceView::open_document hands it over at open.
§What it costs, and when it is paid
Enumerating a workspace’s documents is a walk. It is paid once, when the map is built, and never again: this is a lookup by relation name against an owned map, so the picker opens in constant time however many times it is opened. A census per open, never per keystroke. The staleness that buys is the staleness a per-document check already has — a document created in another window is not on the list until this one is reopened — and it is the right trade for a key pressed on a keystroke.
Keyed by relation rather than by path so that contents, contents[4]
and the append position contents[len] are one entry: the schema rule at
each of those names the same relation, and a list of link targets does
not change because the index did.
Replaces the whole map; an empty one puts the backend back where it started.
Sourcepub fn relation_at(&self, path: &[Seg]) -> Option<&str>
pub fn relation_at(&self, path: &[Seg]) -> Option<&str>
The relation a metadata path is a reference for, according to the
schema this backend carries — None for a path that is not a reference
field, and for a backend with no schema.
A reified vocabulary answers None here, and that is the point. A
key that is both a declared field with a vocabulary and a relation gets
two rules from schema_from_config, the field’s first; a schema
resolves first-match-wins, so the rule at that path is the
Enum and flower answers the picker
from the vocabulary’s own terms without asking a backend at all. Reading
the same rule here is what keeps the two from disagreeing — there is no
second precedence rule written down anywhere.
Sourcepub fn set_body(&mut self, body: &str) -> Result<(), BackendError>
pub fn set_body(&mut self, body: &str) -> Result<(), BackendError>
Replace the prose body, leaving the metadata block untouched — the write
path for edits a leaf editor makes to body.
Uses fig’s Embed::replace_body (the same lossless primitive prov edits
through). A frontend that wants fixity/updated restamping routes this
through prov’s write path instead; here it demonstrates that the metadata
and body regions edit independently over one document.
Trait Implementations§
Source§impl Backend for ProvBackend
impl Backend for ProvBackend
Source§fn candidates(&self, path: &[Seg]) -> Result<Option<Vec<Choice>>, BackendError>
fn candidates(&self, path: &[Seg]) -> Result<Option<Vec<Choice>>, BackendError>
The documents a picker on this reference field should offer — whatever
set_candidates was given for the relation the
schema says path is.
None for anything that is not a reference field, for a relation the map
has no entry for, and always for a backend outside a workspace. A
controlled vocabulary never reaches here: flower asks its own schema
first — see relation_at.
Source§fn item_key(
&self,
seq_path: &[Seg],
index: usize,
) -> Result<Option<String>, BackendError>
fn item_key( &self, seq_path: &[Seg], index: usize, ) -> Result<Option<String>, BackendError>
What an item of a relation’s list is, across a reorder: the document it points at.
A path addresses a sequence item by position, so a reorder re-points
every path after the item that moved — a page opened on contents[1]
goes on showing contents[1], which is now a different document. A
link’s target survives that, and survives a relabel with it:
[The Vault](/README.md) and [Home](/README.md) are one edge with a
different word on it, and the word is the part a reader edits. So a
reorder moves the page with the item, and retitling the item does not
move it at all.
Link::addressed_target, so the
#locator is stripped: a.md#one and a.md#two are one identity, and
the first of them wins — which is Backend::item_key’s documented
behaviour for a repeated key rather than a loss. Two items pointing into
the same document are two ways of saying where to look, and a page that
lands on the first has landed in the right document.
None for a list that is not a relation’s, for an item that is not a
scalar, and for an empty target. flower’s own fallback — a mapping item’s
title, a scalar’s own text — is the better answer for those, and it is
what it uses when this declines.
Source§fn apply(&mut self, op: EditOp) -> Result<(), BackendError>
fn apply(&mut self, op: EditOp) -> Result<(), BackendError>
Err, the document is unchanged.Source§fn to_value(&self) -> Result<Value, BackendError>
fn to_value(&self) -> Result<Value, BackendError>
Source§fn source(&self) -> Result<String, BackendError>
fn source(&self) -> Result<String, BackendError>
Source§fn schema(&self) -> Option<Schema>
fn schema(&self) -> Option<Schema>
None so existing backends are unaffected.Source§fn leading_comment(&self, path: &[Seg]) -> Result<Option<String>, BackendError>
fn leading_comment(&self, path: &[Seg]) -> Result<Option<String>, BackendError>
path, lines
joined by \n with markers and indentation stripped. None when there is
no block — and, by default, always: a backend that never reads comments
renders every page exactly as it did before this method existed, so the
comment surface is opt-in for an implementor and never a blank column
for a document that has none. Read moreSource§fn trailing_comment(&self, path: &[Seg]) -> Result<Option<String>, BackendError>
fn trailing_comment(&self, path: &[Seg]) -> Result<Option<String>, BackendError>
path, marker stripped. None
when there is none, and by default always — see
leading_comment.