fix: added factory doctests, caught bugs

This commit is contained in:
əlemi 2023-08-20 08:24:58 +02:00
parent 265b0480b8
commit db0c696cf9

View file

@ -2,10 +2,73 @@
//!
//! a helper trait to produce Operation Sequences, knowing the current
//! state of the buffer
//!
//! ```rust
//! use codemp::buffer::factory::{OperationFactory, SimpleOperationFactory};
//!
//! let mut factory = SimpleOperationFactory::from("");
//! let op = factory.insert("asd", 0);
//! factory.update(op)?;
//! assert_eq!(factory.content(), "asd");
//! # Ok::<(), codemp::ot::OTError>(())
//! ```
//!
//! use [OperationFactory::insert] to add new characters at a specific index
//!
//! ```rust
//! # use codemp::buffer::factory::{OperationFactory, SimpleOperationFactory};
//! # let mut factory = SimpleOperationFactory::from("asd");
//! factory.update(factory.insert(" dsa", 3))?;
//! assert_eq!(factory.content(), "asd dsa");
//! # Ok::<(), codemp::ot::OTError>(())
//! ```
//!
//! use [OperationFactory::delta] to arbitrarily change text at any position
//!
//! ```rust
//! # use codemp::buffer::factory::{OperationFactory, SimpleOperationFactory};
//! # let mut factory = SimpleOperationFactory::from("asd dsa");
//! let op = factory.delta(2, " xxx ", 5).expect("replaced region is equal to origin");
//! factory.update(op)?;
//! assert_eq!(factory.content(), "as xxx sa");
//! # Ok::<(), codemp::ot::OTError>(())
//! ```
//!
//! use [OperationFactory::delete] to remove characters from given index
//!
//! ```rust
//! # use codemp::buffer::factory::{OperationFactory, SimpleOperationFactory};
//! # let mut factory = SimpleOperationFactory::from("as xxx sa");
//! factory.update(factory.delete(2, 5))?;
//! assert_eq!(factory.content(), "assa");
//! # Ok::<(), codemp::ot::OTError>(())
//! ```
//!
//! use [OperationFactory::replace] to completely replace buffer content
//!
//! ```rust
//! # use codemp::buffer::factory::{OperationFactory, SimpleOperationFactory};
//! # let mut factory = SimpleOperationFactory::from("assa");
//! let op = factory.replace("from scratch").expect("replace is equal to origin");
//! factory.update(op)?;
//! assert_eq!(factory.content(), "from scratch");
//! # Ok::<(), codemp::ot::OTError>(())
//! ```
//!
//! use [OperationFactory::cancel] to remove characters at index, but backwards
//!
//! ```rust
//! # use codemp::buffer::factory::{OperationFactory, SimpleOperationFactory};
//! # let mut factory = SimpleOperationFactory::from("from scratch");
//! factory.update(factory.cancel(12, 8))?;
//! assert_eq!(factory.content(), "from");
//! # Ok::<(), codemp::ot::OTError>(())
//! ```
//!
use std::ops::Range;
use operational_transform::{OperationSeq, Operation};
use operational_transform::{OperationSeq, Operation, OTError};
use similar::{TextDiff, ChangeTag};
/// calculate leading no-ops in given opseq
@ -44,7 +107,7 @@ pub trait OperationFactory {
let mut out = OperationSeq::default();
let content = self.content();
let tail_skip = content.len() - end; // TODO len is number of bytes, not chars
let content_slice = &content[start..tail_skip];
let content_slice = &content[start..end];
if content_slice == txt {
// if slice equals given text, no operation should be taken
@ -82,9 +145,9 @@ pub trait OperationFactory {
fn delete(&self, pos: u64, count: u64) -> OperationSeq {
let mut out = OperationSeq::default();
let len = self.content().len() as u64;
out.retain(pos - count);
out.retain(pos);
out.delete(count);
out.retain(len - pos);
out.retain(len - (pos+count));
out
}
@ -92,9 +155,32 @@ pub trait OperationFactory {
fn cancel(&self, pos: u64, count: u64) -> OperationSeq {
let mut out = OperationSeq::default();
let len = self.content().len() as u64;
out.retain(pos);
out.retain(pos - count);
out.delete(count);
out.retain(len - (pos+count));
out.retain(len - pos);
out
}
}
/// a simple example operation factory that just wraps a string
pub struct SimpleOperationFactory(String);
impl SimpleOperationFactory {
/// applies given OperationSeq to underlying string, changing it
pub fn update(&mut self, op: OperationSeq) -> Result<(), OTError> {
self.0 = op.apply(&self.0)?;
Ok(())
}
}
impl From::<&str> for SimpleOperationFactory {
fn from(value: &str) -> Self {
SimpleOperationFactory(value.to_string())
}
}
impl OperationFactory for SimpleOperationFactory {
fn content(&self) -> String {
self.0.clone()
}
}