1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
//! **An undo-redo library.**
//!
//! An implementation of the [command pattern](https://en.wikipedia.org/wiki/Command_pattern),
//! where all edits are done by creating objects that applies the modifications.
//! All objects knows how to undo the changes it applies, and by using the provided data
//! structures it is easy to undo and redo edits made to a target.
//!
//! See the [examples](https://github.com/evenorog/undo/tree/master/examples) for more information.
//!
//! # Features
//!
//! * [`Edit`] provides the base functionality for all edit commands. Multiple edit commands can be merged into a single edit
//! by implementing the [`merge`](Edit::merge) method on the edit. This allows smaller edits to be used to build
//! more complex operations, or smaller incremental changes to be merged into larger changes that can be undone and
//! redone in a single step.
//! * [`Record`] provides basic stack based undo-redo functionality.
//! * [`History`] provides full tree based undo-redo functionality.
//! * Queue and checkpoint functionality is supported for both [`Record`] and [`History`].
//! * The target can be marked as saved to disk and the user will be notified when it changes.
//! * The amount of changes being tracked can be configured by the user so only the `N` most recent changes are stored.
//! * Configurable display formatting using the display structures.
//!
//! # Examples
//!
//! All examples in the documentation uses the `Add`
//! command found [here](https://github.com/evenorog/undo/blob/master/src/add.rs).
//!
//! # Cargo Feature Flags
//!
//! | Name | Default | Enables | Description |
//! |---------|---------|---------|-----------------------------------------------------------------|
//! | std | ✓ | alloc | Enables the standard library. |
//! | alloc | | | Enables the `alloc` crate. |
//! | colored | | | Enables colored output when visualizing the display structures. |
//! | serde | | | Enables serialization and deserialization. |
#![doc(html_root_url = "https://docs.rs/undo")]
#![deny(missing_docs)]
#![forbid(unsafe_code)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(doctest)]
#[doc = include_str!("../README.md")]
pub struct ReadmeDocTest;
#[cfg(feature = "alloc")]
mod add;
#[cfg(feature = "alloc")]
mod entry;
#[cfg(feature = "alloc")]
mod format;
#[cfg(feature = "alloc")]
pub mod history;
#[cfg(feature = "alloc")]
pub mod record;
#[cfg(feature = "alloc")]
mod socket;
#[doc(hidden)]
#[cfg(feature = "alloc")]
pub use add::Add;
#[cfg(feature = "alloc")]
pub use entry::Entry;
#[cfg(feature = "alloc")]
pub use history::History;
#[cfg(feature = "alloc")]
pub use record::Record;
#[cfg(feature = "alloc")]
pub use socket::{Event, Slot};
#[cfg(feature = "alloc")]
use format::Format;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// Base functionality for all edit commands.
pub trait Edit {
/// The target type.
type Target;
/// The output type.
type Output;
/// Applies the edit command on the target.
fn edit(&mut self, target: &mut Self::Target) -> Self::Output;
/// Restores the state of the target as it was before the edit was applied.
fn undo(&mut self, target: &mut Self::Target) -> Self::Output;
/// Reapplies the edit on the target.
///
/// The default implementation uses the [`Edit::edit`] implementation.
fn redo(&mut self, target: &mut Self::Target) -> Self::Output {
self.edit(target)
}
/// Used for manual merging of edits. See [`Merged`] for more information.
fn merge(&mut self, other: Self) -> Merged<Self>
where
Self: Sized,
{
Merged::No(other)
}
}
/// Says if the [`Edit`] command have been merged with another command.
#[derive(Copy, Clone, Debug)]
pub enum Merged<E> {
/// The edits have been merged.
///
/// This means that the `other` edit will not be added to the stack.
Yes,
/// The edits have not been merged.
///
/// We need to return the `other` edit so it can be added to the stack.
No(E),
/// The two edits cancels each other out.
///
/// This means that both edits will be removed from the stack.
Annul,
}
/// A position in a history tree.
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct At {
/// The root branch.
pub root: usize,
/// The index of edit.
pub index: usize,
}
#[cfg(feature = "alloc")]
impl At {
/// Creates a new `At` with the provided root and index.
pub const fn new(root: usize, index: usize) -> At {
At { root, index }
}
const fn no_root(index: usize) -> At {
At::new(0, index)
}
}