mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
add attribute iterator
This commit is contained in:
parent
15c3a821ec
commit
039b4917ed
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
client::{History, RevId, UndoResult},
|
||||
client::{view::View, History, RevId, UndoResult},
|
||||
core::*,
|
||||
errors::{ErrorBuilder, OTError, OTErrorCode::*},
|
||||
};
|
||||
@ -7,8 +7,9 @@ use crate::{
|
||||
pub const RECORD_THRESHOLD: usize = 400; // in milliseconds
|
||||
|
||||
pub struct Document {
|
||||
data: Delta,
|
||||
delta: Delta,
|
||||
history: History,
|
||||
view: View,
|
||||
rev_id_counter: usize,
|
||||
last_edit_time: usize,
|
||||
}
|
||||
@ -17,26 +18,30 @@ impl Document {
|
||||
pub fn new() -> Self {
|
||||
let delta = Delta::new();
|
||||
Document {
|
||||
data: delta,
|
||||
delta,
|
||||
history: History::new(),
|
||||
view: View::new(),
|
||||
rev_id_counter: 1,
|
||||
last_edit_time: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, index: usize, text: &str) -> Result<(), OTError> {
|
||||
if self.data.target_len < index {
|
||||
if self.delta.target_len < index {
|
||||
log::error!(
|
||||
"{} out of bounds. should 0..{}",
|
||||
index,
|
||||
self.data.target_len
|
||||
self.delta.target_len
|
||||
);
|
||||
}
|
||||
let probe = Interval::new(index, index + 1);
|
||||
let mut attributes = self.data.get_attributes(probe);
|
||||
let mut attributes = self.delta.get_attributes(probe);
|
||||
if attributes.is_empty() {
|
||||
attributes = Attributes::Follow;
|
||||
}
|
||||
|
||||
// let delta = self.view.handle_insert(&self.delta, s, interval);
|
||||
|
||||
let mut delta = Delta::new();
|
||||
let insert = Builder::insert(text).attributes(attributes).build();
|
||||
let interval = Interval::new(index, index);
|
||||
@ -86,7 +91,7 @@ impl Document {
|
||||
Some(undo_delta) => {
|
||||
let (new_delta, inverted_delta) = self.invert_change(&undo_delta)?;
|
||||
let result = UndoResult::success(new_delta.target_len as usize);
|
||||
self.data = new_delta;
|
||||
self.delta = new_delta;
|
||||
self.history.add_redo(inverted_delta);
|
||||
|
||||
Ok(result)
|
||||
@ -100,7 +105,7 @@ impl Document {
|
||||
Some(redo_delta) => {
|
||||
let (new_delta, inverted_delta) = self.invert_change(&redo_delta)?;
|
||||
let result = UndoResult::success(new_delta.target_len as usize);
|
||||
self.data = new_delta;
|
||||
self.delta = new_delta;
|
||||
|
||||
self.history.add_undo(inverted_delta);
|
||||
Ok(result)
|
||||
@ -108,26 +113,27 @@ impl Document {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_json(&self) -> String { self.data.to_json() }
|
||||
pub fn to_json(&self) -> String { self.delta.to_json() }
|
||||
|
||||
pub fn to_string(&self) -> String { self.data.apply("").unwrap() }
|
||||
pub fn to_string(&self) -> String { self.delta.apply("").unwrap() }
|
||||
|
||||
pub fn data(&self) -> &Delta { &self.data }
|
||||
pub fn data(&self) -> &Delta { &self.delta }
|
||||
|
||||
pub fn set_data(&mut self, data: Delta) { self.data = data; }
|
||||
pub fn set_data(&mut self, data: Delta) { self.delta = data; }
|
||||
|
||||
fn update_with_op(&mut self, delta: &Delta, interval: Interval) -> Result<(), OTError> {
|
||||
let mut new_delta = Delta::default();
|
||||
let (prefix, interval, suffix) = split_length_with_interval(self.data.target_len, interval);
|
||||
let (prefix, interval, suffix) =
|
||||
split_length_with_interval(self.delta.target_len, interval);
|
||||
|
||||
// prefix
|
||||
if prefix.is_empty() == false && prefix != interval {
|
||||
let intervals = split_interval_with_delta(&self.data, &prefix);
|
||||
intervals.into_iter().for_each(|i| {
|
||||
let attributes = self.data.get_attributes(i);
|
||||
log::trace!("prefix attribute: {:?}, interval: {:?}", attributes, i);
|
||||
new_delta.retain(i.size() as usize, attributes);
|
||||
});
|
||||
DeltaAttributesIter::from_interval(&self.delta, prefix).for_each(
|
||||
|(length, attributes)| {
|
||||
log::debug!("prefix attribute: {:?}, len: {}", attributes, length);
|
||||
new_delta.retain(length, attributes);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
delta.ops.iter().for_each(|op| {
|
||||
@ -136,15 +142,15 @@ impl Document {
|
||||
|
||||
// suffix
|
||||
if suffix.is_empty() == false {
|
||||
let intervals = split_interval_with_delta(&self.data, &suffix);
|
||||
intervals.into_iter().for_each(|i| {
|
||||
let attributes = self.data.get_attributes(i);
|
||||
log::trace!("suffix attribute: {:?}, interval: {:?}", attributes, i);
|
||||
new_delta.retain(i.size() as usize, attributes);
|
||||
});
|
||||
DeltaAttributesIter::from_interval(&self.delta, suffix).for_each(
|
||||
|(length, attributes)| {
|
||||
log::debug!("suffix attribute: {:?}, len: {}", attributes, length);
|
||||
new_delta.retain(length, attributes);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
self.data = self.record_change(&new_delta)?;
|
||||
self.delta = self.record_change(&new_delta)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -154,7 +160,7 @@ impl Document {
|
||||
interval: Interval,
|
||||
) -> Result<(), OTError> {
|
||||
log::debug!("Update document with attributes: {:?}", attributes,);
|
||||
let old_attributes = self.data.get_attributes(interval);
|
||||
let old_attributes = self.delta.get_attributes(interval);
|
||||
log::debug!("combine with old: {:?}", old_attributes);
|
||||
let new_attributes = match &mut attributes {
|
||||
Attributes::Follow => old_attributes,
|
||||
@ -208,8 +214,8 @@ impl Document {
|
||||
// d = b.invert(a)
|
||||
// a = c.compose(d)
|
||||
log::debug!("👉invert change {}", change);
|
||||
let new_delta = self.data.compose(change)?;
|
||||
let inverted_delta = change.invert(&self.data);
|
||||
let new_delta = self.delta.compose(change)?;
|
||||
let inverted_delta = change.invert(&self.delta);
|
||||
// trim(&mut inverted_delta);
|
||||
|
||||
Ok((new_delta, inverted_delta))
|
||||
@ -223,7 +229,7 @@ fn split_length_with_interval(length: usize, interval: Interval) -> (Interval, I
|
||||
(prefix, interval, suffix)
|
||||
}
|
||||
|
||||
fn split_interval_with_delta(delta: &Delta, interval: &Interval) -> Vec<Interval> {
|
||||
fn split_interval_by_delta(delta: &Delta, interval: &Interval) -> Vec<Interval> {
|
||||
let mut start = 0;
|
||||
let mut new_intervals = vec![];
|
||||
delta.ops.iter().for_each(|op| match op {
|
||||
|
@ -1,23 +1,17 @@
|
||||
use crate::{
|
||||
client::{view::insert_ext::*, Document},
|
||||
core::{Attributes, Interval},
|
||||
core::{Attributes, Delta, Interval},
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
pub trait InsertExt {
|
||||
fn apply(document: &Document, s: &str, interval: Interval);
|
||||
fn apply(&self, delta: &Delta, s: &str, interval: Interval) -> Delta;
|
||||
}
|
||||
|
||||
pub trait FormatExt {
|
||||
fn apply(document: &Document, interval: Interval, attributes: Attributes);
|
||||
fn apply(&self, document: &Document, interval: Interval, attributes: Attributes);
|
||||
}
|
||||
|
||||
pub trait DeleteExt {
|
||||
fn apply(document: &Document, interval: Interval);
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref INSERT_EXT: Vec<Box<InsertExt>> = vec![PreserveInlineStyleExt::new(),];
|
||||
static ref FORMAT_EXT: Vec<Box<FormatExt>> = vec![];
|
||||
static ref DELETE_EXT: Vec<Box<DeleteExt>> = vec![];
|
||||
fn apply(&self, document: &Document, interval: Interval);
|
||||
}
|
||||
|
@ -1,14 +1,22 @@
|
||||
use crate::{
|
||||
client::{view::InsertExt, Document},
|
||||
core::Interval,
|
||||
core::{Builder, Delta, Interval},
|
||||
};
|
||||
|
||||
pub struct PreserveInlineStyleExt {}
|
||||
|
||||
impl PreserveInlineStyleExt {
|
||||
pub fn new() -> Self {}
|
||||
pub fn new() -> Self { Self {} }
|
||||
}
|
||||
|
||||
impl InsertExt for PreserveInlineStyleExt {
|
||||
fn apply(document: &Document, s: &str, interval: Interval) { unimplemented!() }
|
||||
fn apply(&self, delta: &Delta, s: &str, interval: Interval) -> Delta {
|
||||
// let mut delta = Delta::default();
|
||||
// let insert = Builder::insert(text).attributes(attributes).build();
|
||||
// let interval = Interval::new(index, index);
|
||||
// delta.add(insert);
|
||||
//
|
||||
// delta
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
mod extension;
|
||||
mod insert_ext;
|
||||
mod view;
|
||||
|
||||
pub use extension::*;
|
||||
|
||||
pub use insert_ext::*;
|
||||
pub use view::*;
|
||||
|
32
rust-lib/flowy-ot/src/client/view/view.rs
Normal file
32
rust-lib/flowy-ot/src/client/view/view.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use crate::{
|
||||
client::view::{InsertExt, PreserveInlineStyleExt},
|
||||
core::{Delta, Interval},
|
||||
};
|
||||
|
||||
type InsertExtension = Box<dyn InsertExt>;
|
||||
|
||||
pub struct View {
|
||||
insert_exts: Vec<InsertExtension>,
|
||||
}
|
||||
|
||||
impl View {
|
||||
pub(crate) fn new() -> Self {
|
||||
let insert_exts = construct_insert_exts();
|
||||
Self { insert_exts }
|
||||
}
|
||||
|
||||
pub(crate) fn handle_insert(&self, delta: &Delta, s: &str, interval: Interval) -> Delta {
|
||||
let mut new_delta = Delta::new();
|
||||
self.insert_exts.iter().for_each(|ext| {
|
||||
new_delta = ext.apply(delta, s, interval);
|
||||
});
|
||||
new_delta
|
||||
}
|
||||
}
|
||||
|
||||
fn construct_insert_exts() -> Vec<InsertExtension> {
|
||||
vec![
|
||||
//
|
||||
Box::new(PreserveInlineStyleExt::new()),
|
||||
]
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::core::{Delta, Interval, Operation};
|
||||
use crate::core::{Attributes, AttributesData, Delta, Interval, Operation};
|
||||
use std::{cmp::min, slice::Iter};
|
||||
|
||||
pub struct Cursor<'a> {
|
||||
@ -77,7 +77,12 @@ pub struct DeltaIter<'a> {
|
||||
}
|
||||
|
||||
impl<'a> DeltaIter<'a> {
|
||||
pub fn new(delta: &'a Delta, interval: Interval) -> Self {
|
||||
pub fn new(delta: &'a Delta) -> Self {
|
||||
let interval = Interval::new(0, usize::MAX);
|
||||
Self::from_interval(delta, interval)
|
||||
}
|
||||
|
||||
pub fn from_interval(delta: &'a Delta, interval: Interval) -> Self {
|
||||
let cursor = Cursor::new(delta, interval);
|
||||
Self { cursor, interval }
|
||||
}
|
||||
@ -87,9 +92,62 @@ impl<'a> DeltaIter<'a> {
|
||||
|
||||
impl<'a> Iterator for DeltaIter<'a> {
|
||||
type Item = Operation;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> { self.cursor.next_op() }
|
||||
}
|
||||
|
||||
pub struct DeltaAttributesIter<'a> {
|
||||
delta_iter: DeltaIter<'a>,
|
||||
interval: Interval,
|
||||
}
|
||||
|
||||
impl<'a> DeltaAttributesIter<'a> {
|
||||
pub fn new(delta: &'a Delta) -> Self {
|
||||
let interval = Interval::new(0, usize::MAX);
|
||||
Self::from_interval(delta, interval)
|
||||
}
|
||||
|
||||
pub fn from_interval(delta: &'a Delta, interval: Interval) -> Self {
|
||||
let delta_iter = DeltaIter::from_interval(delta, interval);
|
||||
Self {
|
||||
delta_iter,
|
||||
interval,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for DeltaAttributesIter<'a> {
|
||||
type Item = (usize, Attributes);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let next_op = self.delta_iter.next();
|
||||
if next_op.is_none() {
|
||||
return None;
|
||||
}
|
||||
let mut length: usize = 0;
|
||||
let mut attributes_data = AttributesData::new();
|
||||
|
||||
match next_op.unwrap() {
|
||||
Operation::Delete(_n) => {},
|
||||
Operation::Retain(retain) => {
|
||||
if let Attributes::Custom(data) = &retain.attributes {
|
||||
log::debug!("extend retain attributes with {} ", &data);
|
||||
attributes_data.extend(Some(data.clone()));
|
||||
}
|
||||
length = retain.n;
|
||||
},
|
||||
Operation::Insert(insert) => {
|
||||
if let Attributes::Custom(data) = &insert.attributes {
|
||||
log::debug!("extend insert attributes with {} ", &data);
|
||||
attributes_data.extend(Some(data.clone()));
|
||||
}
|
||||
length = insert.num_chars();
|
||||
},
|
||||
}
|
||||
|
||||
let attribute: Attributes = attributes_data.into();
|
||||
Some((length, attribute))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
|
@ -573,7 +573,7 @@ fn invert_from_other(
|
||||
end: usize,
|
||||
) {
|
||||
log::debug!("invert op: {} [{}:{}]", operation, start, end);
|
||||
let other_ops = DeltaIter::new(other, Interval::new(start, end)).ops();
|
||||
let other_ops = DeltaIter::from_interval(other, Interval::new(start, end)).ops();
|
||||
other_ops.into_iter().for_each(|other_op| match operation {
|
||||
Operation::Delete(n) => {
|
||||
log::debug!("invert delete: {} by add {}", n, other_op);
|
||||
|
@ -57,7 +57,7 @@ impl OpTester {
|
||||
static INIT: Once = Once::new();
|
||||
INIT.call_once(|| {
|
||||
color_eyre::install().unwrap();
|
||||
std::env::set_var("RUST_LOG", "info");
|
||||
std::env::set_var("RUST_LOG", "debug");
|
||||
env_logger::init();
|
||||
});
|
||||
|
||||
|
@ -14,7 +14,7 @@ fn delta_get_ops_in_interval_1() {
|
||||
delta.add(insert_a.clone());
|
||||
delta.add(insert_b.clone());
|
||||
|
||||
let mut iterator = DeltaIter::new(&delta, Interval::new(0, 4));
|
||||
let mut iterator = DeltaIter::from_interval(&delta, Interval::new(0, 4));
|
||||
assert_eq!(iterator.ops(), delta.ops);
|
||||
}
|
||||
|
||||
@ -32,27 +32,27 @@ fn delta_get_ops_in_interval_2() {
|
||||
delta.add(insert_c.clone());
|
||||
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(0, 2)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(0, 2)).ops(),
|
||||
vec![Builder::insert("12").build()]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(0, 3)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(0, 3)).ops(),
|
||||
vec![insert_a.clone()]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(0, 4)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(0, 4)).ops(),
|
||||
vec![insert_a.clone(), Builder::retain(1).build()]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(0, 6)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(0, 6)).ops(),
|
||||
vec![insert_a.clone(), retain_a.clone()]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(0, 7)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(0, 7)).ops(),
|
||||
vec![insert_a.clone(), retain_a.clone(), insert_b.clone()]
|
||||
);
|
||||
}
|
||||
@ -63,7 +63,7 @@ fn delta_get_ops_in_interval_3() {
|
||||
let insert_a = Builder::insert("123456").build();
|
||||
delta.add(insert_a.clone());
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(3, 5)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(3, 5)).ops(),
|
||||
vec![Builder::insert("45").build()]
|
||||
);
|
||||
}
|
||||
@ -80,20 +80,20 @@ fn delta_get_ops_in_interval_4() {
|
||||
delta.ops.push(insert_c.clone());
|
||||
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(0, 2)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(0, 2)).ops(),
|
||||
vec![insert_a]
|
||||
);
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(2, 4)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(2, 4)).ops(),
|
||||
vec![insert_b]
|
||||
);
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(4, 6)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(4, 6)).ops(),
|
||||
vec![insert_c]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(2, 5)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(2, 5)).ops(),
|
||||
vec![Builder::insert("34").build(), Builder::insert("5").build()]
|
||||
);
|
||||
}
|
||||
@ -106,12 +106,12 @@ fn delta_get_ops_in_interval_5() {
|
||||
delta.ops.push(insert_a.clone());
|
||||
delta.ops.push(insert_b.clone());
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(4, 8)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(4, 8)).ops(),
|
||||
vec![Builder::insert("56").build(), Builder::insert("78").build()]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(8, 9)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(8, 9)).ops(),
|
||||
vec![Builder::insert("9").build()]
|
||||
);
|
||||
}
|
||||
@ -122,7 +122,7 @@ fn delta_get_ops_in_interval_6() {
|
||||
let insert_a = Builder::insert("12345678").build();
|
||||
delta.add(insert_a.clone());
|
||||
assert_eq!(
|
||||
DeltaIter::new(&delta, Interval::new(4, 6)).ops(),
|
||||
DeltaIter::from_interval(&delta, Interval::new(4, 6)).ops(),
|
||||
vec![Builder::insert("56").build()]
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user