feat: transform patht

This commit is contained in:
Vincent Chan 2022-08-22 11:10:06 +08:00
parent c61b4d0865
commit 0def48d0ca
5 changed files with 75 additions and 6 deletions

View File

@ -207,10 +207,10 @@ Path transformPath(Path preInsertPath, Path b, [int delta = 1]) {
Operation transformOperation(Operation a, Operation b) {
if (a is InsertOperation) {
final newPath = transformPath(a.path, b.path);
final newPath = transformPath(a.path, b.path, a.nodes.length);
return b.copyWithPath(newPath);
} else if (a is DeleteOperation) {
final newPath = transformPath(a.path, b.path, -1);
final newPath = transformPath(a.path, b.path, -1 * a.nodes.length);
return b.copyWithPath(newPath);
}
// TODO: transform update and textedit

View File

@ -124,6 +124,15 @@ impl DocumentTree {
return;
}
let children_length = parent.children(&self.arena).fold(0, |counter, _| counter + 1);
if index == children_length {
for id in insert_children {
parent.append(*id, &mut self.arena);
}
return;
}
let node_to_insert = self.child_at_index_of_path(parent, index).unwrap();
for id in insert_children {

View File

@ -10,6 +10,14 @@ pub enum DocumentOperation {
}
impl DocumentOperation {
pub fn path(&self) -> &Position {
match self {
DocumentOperation::Insert(insert) => &insert.path,
DocumentOperation::Update(update) => &update.path,
DocumentOperation::Delete(delete) => &delete.path,
DocumentOperation::TextEdit(text_edit) => &text_edit.path,
}
}
pub fn invert(&self) -> DocumentOperation {
match self {
DocumentOperation::Insert(insert_operation) => DocumentOperation::Delete(DeleteOperation {
@ -32,8 +40,40 @@ impl DocumentOperation {
}),
}
}
pub fn transform(_a: &DocumentOperation, b: &DocumentOperation) -> DocumentOperation {
b.clone()
pub fn clone_with_new_path(&self, path: Position) -> DocumentOperation {
match self {
DocumentOperation::Insert(insert) => DocumentOperation::Insert(InsertOperation {
path,
nodes: insert.nodes.clone(),
}),
DocumentOperation::Update(update) => DocumentOperation::Update(UpdateOperation {
path,
attributes: update.attributes.clone(),
old_attributes: update.old_attributes.clone(),
}),
DocumentOperation::Delete(delete) => DocumentOperation::Delete(DeleteOperation {
path,
nodes: delete.nodes.clone(),
}),
DocumentOperation::TextEdit(text_edit) => DocumentOperation::TextEdit(TextEditOperation {
path,
delta: text_edit.delta.clone(),
inverted: text_edit.inverted.clone(),
}),
}
}
pub fn transform(a: &DocumentOperation, b: &DocumentOperation) -> DocumentOperation {
match a {
DocumentOperation::Insert(insert_op) => {
let new_path = Position::transform(a.path(), b.path(), insert_op.nodes.len() as i64);
b.clone_with_new_path(new_path)
}
DocumentOperation::Delete(delete_op) => {
let new_path = Position::transform(a.path(), b.path(), delete_op.nodes.len() as i64);
b.clone_with_new_path(new_path)
}
_ => b.clone(),
}
}
}

View File

@ -12,7 +12,7 @@ impl Position {
impl Position {
// delta is default to be 1
pub fn transform(pre_insert_path: &Position, b: &Position, delta: usize) -> Position {
pub fn transform(pre_insert_path: &Position, b: &Position, delta: i64) -> Position {
if pre_insert_path.len() > b.len() {
return b.clone();
}
@ -30,7 +30,7 @@ impl Position {
let prev_insert_last: usize = *pre_insert_path.0.last().unwrap();
let b_at_index = b.0[pre_insert_path.0.len() - 1];
if prev_insert_last <= b_at_index {
prefix.push(b_at_index + delta);
prefix.push(((b_at_index as i64) + delta) as usize);
} else {
prefix.push(b_at_index);
}

View File

@ -34,3 +34,23 @@ fn test_documents() {
document.apply(transaction);
assert!(document.node_at_path(&vec![0].into()).is_none());
}
#[test]
fn test_transform_paths() {
let mut document = DocumentTree::new();
let transaction = {
let mut tb = TransactionBuilder::new(&document);
tb.insert_nodes(&vec![0].into(), &vec![NodeData::new("text")]);
tb.insert_nodes(&vec![1].into(), &vec![NodeData::new("text")]);
tb.insert_nodes(&vec![2].into(), &vec![NodeData::new("text")]);
tb.finalize()
};
document.apply(transaction);
let transaction = {
let mut tb = TransactionBuilder::new(&document);
tb.insert_nodes(&vec![1].into(), &vec![NodeData::new("text")]);
tb.finalize()
};
document.apply(transaction);
}