Remove a few index uses

This commit is contained in:
Andras Schmelczer 2025-06-21 10:50:35 +01:00
commit 351caf74b5
No known key found for this signature in database
GPG key ID: FC8F2C3D3D1A718C
2 changed files with 85 additions and 49 deletions

View file

@ -1,14 +1,14 @@
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{CursorPosition, Operation, TextWithCursors, ordered_operation::OrderedOperation}; use super::{ordered_operation::OrderedOperation, CursorPosition, Operation, TextWithCursors};
use crate::{ use crate::{
diffs::{myers::diff, raw_operation::RawOperation}, diffs::{myers::diff, raw_operation::RawOperation},
operation_transformation::{ operation_transformation::{
merge_context::MergeContext, merge_context::MergeContext,
utils::{cook_operations::cook_operations, elongate_operations::elongate_operations}, utils::{cook_operations::cook_operations, elongate_operations::elongate_operations},
}, },
tokenizer::{Tokenizer, word_tokenizer::word_tokenizer}, tokenizer::{word_tokenizer::word_tokenizer, Tokenizer},
utils::{side::Side, string_builder::StringBuilder}, utils::{side::Side, string_builder::StringBuilder},
}; };
@ -82,18 +82,6 @@ where
operations: Vec<OrderedOperation<T>>, operations: Vec<OrderedOperation<T>>,
mut cursors: Vec<CursorPosition>, mut cursors: Vec<CursorPosition>,
) -> Self { ) -> Self {
operations
.iter()
.zip(operations.iter().skip(1))
.for_each(|(previous, next)| {
debug_assert!(
previous.operation.start_index() <= next.operation.start_index(),
"{} must not come before {} yet it does",
previous.operation,
next.operation
);
});
cursors.sort_by_key(|cursor| cursor.char_index); cursors.sort_by_key(|cursor| cursor.char_index);
Self { Self {
@ -126,6 +114,10 @@ where
let mut maybe_left_op = left_iter.next(); let mut maybe_left_op = left_iter.next();
let mut maybe_right_op = right_iter.next(); let mut maybe_right_op = right_iter.next();
let mut seen_left_length: usize = 0;
let mut seen_right_length: usize = 0;
let mut merged_length: usize = 0;
loop { loop {
let (side, OrderedOperation { operation, order }) = let (side, OrderedOperation { operation, order }) =
match (maybe_left_op.clone(), maybe_right_op.clone()) { match (maybe_left_op.clone(), maybe_right_op.clone()) {
@ -142,58 +134,96 @@ where
(None, None) => break, (None, None) => break,
}; };
if side == Side::Left { let is_advancing_operation = matches!(
maybe_left_op = left_iter.next(); operation,
} else { Operation::Insert { .. } | Operation::Equal { .. }
maybe_right_op = right_iter.next(); );
} println!(" {operation:?}");
let original_start = operation.start_index() as i64;
let original_end = operation.end_index();
let original_length = operation.len() as i64; let original_length = operation.len() as i64;
let result = match side { let result = match side {
Side::Left => operation.merge_operations_with_context(
&mut right_merge_context,
&mut left_merge_context,
),
Side::Right => operation.merge_operations_with_context(
&mut left_merge_context,
&mut right_merge_context,
),
};
if let Some(ref op @ (Operation::Insert { .. } | Operation::Equal { .. })) = result {
let shift =
op.start_index() as i64 - original_start + op.len() as i64 - original_length;
match side {
Side::Left => { Side::Left => {
while let Some(cursor) = let are_equal = matches!(operation, Operation::Equal { .. })
left_cursors.next_if(|cursor| cursor.char_index <= original_end + 1) && maybe_right_op
.as_ref()
.map(|op| {
matches!(op.operation, Operation::Equal { .. })
&& op.operation.eq(&operation)
})
.unwrap_or_default();
let result = operation.merge_operations_with_context(
&mut right_merge_context,
&mut left_merge_context,
);
if let Some(ref op @ (Operation::Insert { .. } | Operation::Equal { .. })) =
result
{ {
let shift = op.start_index() as i64 - seen_left_length as i64
+ op.len() as i64
- original_length;
while let Some(cursor) = left_cursors.next_if(|cursor| {
cursor.char_index <= seen_left_length + original_length as usize
}) {
merged_cursors.push(cursor.with_index( merged_cursors.push(cursor.with_index(
(op.start_index() as i64).max(cursor.char_index as i64 + shift) (op.start_index() as i64).max(cursor.char_index as i64 + shift)
as usize, as usize,
)); ));
} }
} }
if is_advancing_operation {
seen_left_length += original_length as usize;
}
maybe_left_op = left_iter.next();
if are_equal {
None
} else {
result
}
}
Side::Right => { Side::Right => {
while let Some(cursor) = let result = operation.merge_operations_with_context(
right_cursors.next_if(|cursor| cursor.char_index <= original_end + 1) &mut left_merge_context,
&mut right_merge_context,
);
if let Some(ref op @ (Operation::Insert { .. } | Operation::Equal { .. })) =
result
{ {
println!("merged_length {merged_length}, idx {}", op.start_index());
let shift = op.start_index() as i64 - seen_right_length as i64
+ op.len() as i64
- original_length;
while let Some(cursor) = right_cursors.next_if(|cursor| {
cursor.char_index <= seen_right_length + original_length as usize
}) {
merged_cursors.push(cursor.with_index( merged_cursors.push(cursor.with_index(
(op.start_index() as i64).max(cursor.char_index as i64 + shift) (op.start_index() as i64).max(cursor.char_index as i64 + shift)
as usize, as usize,
)); ));
} }
} }
}
if is_advancing_operation {
seen_right_length += original_length as usize;
} }
merged_operations.extend(result.into_iter().map(|op| OrderedOperation { maybe_right_op = right_iter.next();
order,
operation: op, result
})); }
};
if let Some(operation) = result {
merged_length += operation.len() as usize;
merged_operations.push(OrderedOperation { order, operation });
}
} }
let last_index = merged_operations let last_index = merged_operations

View file

@ -24,6 +24,12 @@ left: long small
right: long with big and small right: long with big and small
expected: long small expected: long small
---
parent: long run of text where one barely has no changes but has cursors
left: long| run of tex|t where one barely has no |changes but has |cursors
right: long run one barely has no changes cursors
expected: long| run| one barely has no |changes |cursors
--- ---
parent: long text where the cursor has to be clamped after delete parent: long text where the cursor has to be clamped after delete
left: long text where the cursor has to be clamped after delete| left: long text where the cursor has to be clamped after delete|