Skip to main content

Edit

Enum Edit 

Source
pub enum Edit {
    Property {
        path: Vec<usize>,
        name: String,
        value: Option<Literal>,
    },
    Insert {
        parent: Vec<usize>,
        index: usize,
        text: String,
    },
    Argument {
        path: Vec<usize>,
        value: Literal,
    },
    Move {
        from: Vec<usize>,
        to: Vec<usize>,
        index: usize,
    },
    Remove {
        path: Vec<usize>,
    },
    Many(Vec<Edit>),
    Replace {
        path: Vec<usize>,
        text: String,
    },
}
Expand description

One reversible change to a form.

Applied with Form::apply, which hands back the edit that undoes it. See there for why an inverse is always knowable.

Variants§

§

Property

Set a property, or take it away with None.

Fields

§path: Vec<usize>

The node.

§name: String

The property.

§value: Option<Literal>

What to set it to, or None to remove it — which is what returning a property to its default means, since a default is not written.

§

Insert

Put a node, written as form-file text, among a parent’s children.

The text is a whole node with its own formatting, which is what makes this the inverse of a removal and what a paste from the clipboard is.

Fields

§parent: Vec<usize>

The parent’s path; empty for the form itself.

§index: usize

Where among its children.

§text: String

The node.

§

Argument

Set a node’s positional argument — the "Hello" in label "Hello".

Only ever replaces one. A node written without an argument does not grow one this way: an argument has to come before every property, and there is no shape of edit that puts something at the front of a line without rewriting the line. Setting the matching property is what an editor does instead, and means the same thing to the engine.

Fields

§path: Vec<usize>

The node.

§value: Literal

What to put there.

§

Move

Take a node out and put it back under another parent.

Reordering among siblings and reparenting are the same edit: both take a node out and put it back somewhere, and doing it as one keeps it to one step on an undo stack.

A node that changes depth is re-indented — every line of it, so the children come along — because a file whose nesting and whose indentation disagree is a file somebody has to fix by hand. Moving it back re-indents it back, so an undo is still byte-for-byte.

Fields

§from: Vec<usize>

The node now.

§to: Vec<usize>

The parent it goes under; empty for the form itself.

§index: usize

Where among that parent’s children.

§

Remove

Take a node, and everything under it, out.

Fields

§path: Vec<usize>

The node.

§

Many(Vec<Edit>)

Several edits as one.

Applied in order and undone in reverse, which is what makes a drag that moved and resized a single step on an undo stack rather than four. If any of them fails the ones already applied are put back, so a compound edit either happens or does not.

§

Replace

Swap a node for another, written as form-file text.

The exact inverse of anything that cannot be undone by putting a value back — taking a property away is the case: a property re-added by name lands at the end of the line rather than where it was, so the values would come back right and the line would not. Restoring the node’s own text restores its order too.

Fields

§path: Vec<usize>

The node.

§text: String

What to put there.

Implementations§

Source§

impl Edit

Source

pub fn number(path: &[usize], name: &str, value: Option<i64>) -> Self

Sets or clears a whole-number property.

The common one by a long way: every rectangle a drag writes is four of these.

let mut form = Form::parse(r#"form "F" version=1 width=99 height=99 { label "Hi" x=0 y=0 w=9 h=9 }"#)?;

form.apply(Edit::number(&[0], "x", Some(24)))?;
assert_eq!(form.property(&[0], "x").as_deref(), Some("24"));

// `None` takes it out of the file, which is what a default is.
form.apply(Edit::number(&[0], "x", None))?;
assert_eq!(form.property(&[0], "x"), None);
Source

pub fn property(path: &[usize], name: &str, value: Option<Literal>) -> Self

The path is child indices from the form node down, and the empty path is the form itself — its size, its kind, its theme.

let mut form = Form::parse(r#"form "F" version=1 width=320 height=240 { label "Hi" x=0 y=0 w=9 h=9 }"#)?;

form.apply(Edit::property(&[], "width", Some(Literal::Int(640))))?;
assert_eq!(form.size(), denise::Size::new(640, 240));

Sets or clears a property.

Source

pub fn argument(path: &[usize], text: impl Into<String>) -> Self

A label "Heading" keeps its text there rather than in a text= property, and so does the form’s own title.

let mut form = Form::parse(r#"form "F" version=1 width=99 height=99 { label "Hi" x=0 y=0 w=9 h=9 }"#)?;

form.apply(Edit::argument(&[0], "Hello"))?;
assert_eq!(form.argument(&[0]).as_deref(), Some("Hello"));

// The form's title is its argument too.
form.apply(Edit::argument(&[], "Greeting"))?;
assert_eq!(form.title(), "Greeting");

Sets a node’s positional argument to a string.

Source

pub fn move_to(from: &[usize], to: &[usize], index: usize) -> Self

index is the position after the node has been taken out, which is the part that is easy to get wrong: removing [1] moves [3] to [2].

let mut form = Form::parse(
    "form \"F\" version=1 width=99 height=99 {\n    label \"a\" x=0 y=0 w=9 h=9\n    panel name=box x=0 y=9 w=9 h=9\n}\n",
)?;

// The label into the panel, which grows the braces it did not have.
form.apply(Edit::move_to(&[0], &[1], 0))?;
assert!(form.text().contains("panel name=box x=0 y=9 w=9 h=9 {"), "{}", form.text());

Moves a node under another parent, or to another place among its siblings.

Source

pub fn remove(path: &[usize]) -> Self

Its children go with it, and so does the comment written above it — the node’s leading trivia is part of the node, which is what makes undoing a removal put the comment back.

let source = "form \"F\" version=1 width=99 height=99 {\n    // why\n    label \"a\" x=0 y=0 w=9 h=9\n}\n";
let mut form = Form::parse(source)?;

let undo = form.apply(Edit::remove(&[0]))?;
assert!(!form.text().contains("why"));

form.apply(undo)?;
assert_eq!(form.text(), source, "the comment came back with the node");

Removes a node.

Trait Implementations§

Source§

impl Clone for Edit

Source§

fn clone(&self) -> Edit

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Edit

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Edit

Source§

fn eq(&self, other: &Edit) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Edit

Auto Trait Implementations§

§

impl Freeze for Edit

§

impl RefUnwindSafe for Edit

§

impl Send for Edit

§

impl Sync for Edit

§

impl Unpin for Edit

§

impl UnsafeUnpin for Edit

§

impl UnwindSafe for Edit

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> AsAny for T
where T: Any,

Source§

fn as_any(&self) -> &(dyn Any + 'static)

Borrows as dyn Any.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Mutably borrows as dyn Any.
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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.