Lint & format
This commit is contained in:
parent
9da05c6ff6
commit
48f301d8ab
9 changed files with 54 additions and 57 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"reconcile",
|
"reconcile",
|
||||||
"sync_server",
|
"sync_server",
|
||||||
"sync_lib"
|
"sync_lib"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -14,9 +14,9 @@ license = "MIT"
|
||||||
repository = "https://github.com/schmelczer/vault-link"
|
repository = "https://github.com/schmelczer/vault-link"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
serde = { version = "1.0.219", default-features = false, features = ["derive"] }
|
serde = { version = "1.0.219", default-features = false, features = ["derive"] }
|
||||||
thiserror = { version = "1.0.66", default-features = false }
|
thiserror = { version = "1.0.66", default-features = false }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
@ -58,6 +58,7 @@ unnested_or_patterns = "warn"
|
||||||
unused_self = "warn"
|
unused_self = "warn"
|
||||||
verbose_file_reads = "warn"
|
verbose_file_reads = "warn"
|
||||||
|
|
||||||
|
large_stack_arrays = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/13774
|
||||||
cast_possible_truncation = { level = "allow", priority = 1 }
|
cast_possible_truncation = { level = "allow", priority = 1 }
|
||||||
doc_link_with_quotes = { level = "allow", priority = 1 }
|
doc_link_with_quotes = { level = "allow", priority = 1 }
|
||||||
cast_sign_loss = { level = "allow", priority = 1 }
|
cast_sign_loss = { level = "allow", priority = 1 }
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ use crate::{
|
||||||
/// Diff `old`, between indices `old_range` and `new` between indices
|
/// Diff `old`, between indices `old_range` and `new` between indices
|
||||||
/// `new_range`.
|
/// `new_range`.
|
||||||
///
|
///
|
||||||
/// The returned RawOperations all have a token count of 1.
|
/// The returned `RawOperations` all have a token count of 1.
|
||||||
pub fn diff<T>(old: &[Token<T>], new: &[Token<T>]) -> Vec<RawOperation<T>>
|
pub fn diff<T>(old: &[Token<T>], new: &[Token<T>]) -> Vec<RawOperation<T>>
|
||||||
where
|
where
|
||||||
T: PartialEq + Clone + std::fmt::Debug,
|
T: PartialEq + Clone + std::fmt::Debug,
|
||||||
|
|
@ -245,7 +245,7 @@ fn conquer<T>(
|
||||||
old[old_range.start..old_range.start + common_prefix_len]
|
old[old_range.start..old_range.start + common_prefix_len]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|token| RawOperation::Equal(vec![token.clone()])),
|
.map(|token| RawOperation::Equal(vec![token.clone()])),
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
old_range.start += common_prefix_len;
|
old_range.start += common_prefix_len;
|
||||||
new_range.start += common_prefix_len;
|
new_range.start += common_prefix_len;
|
||||||
|
|
@ -266,13 +266,13 @@ fn conquer<T>(
|
||||||
old[old_range.start..old_range.start + old_range.len()]
|
old[old_range.start..old_range.start + old_range.len()]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|token| RawOperation::Delete(vec![token.clone()])),
|
.map(|token| RawOperation::Delete(vec![token.clone()])),
|
||||||
)
|
);
|
||||||
} else if old_range.is_empty() {
|
} else if old_range.is_empty() {
|
||||||
result.extend(
|
result.extend(
|
||||||
new[new_range.start..new_range.start + new_range.len()]
|
new[new_range.start..new_range.start + new_range.len()]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|token| RawOperation::Insert(vec![token.clone()])),
|
.map(|token| RawOperation::Insert(vec![token.clone()])),
|
||||||
)
|
);
|
||||||
} else if let Some((x_start, y_start)) =
|
} else if let Some((x_start, y_start)) =
|
||||||
find_middle_snake(old, old_range.clone(), new, new_range.clone(), vf, vb)
|
find_middle_snake(old, old_range.clone(), new, new_range.clone(), vf, vb)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -30,18 +30,18 @@ where
|
||||||
|
|
||||||
pub fn is_left_joinable(&self) -> bool {
|
pub fn is_left_joinable(&self) -> bool {
|
||||||
let first_token = self.tokens().first();
|
let first_token = self.tokens().first();
|
||||||
first_token.map_or(true, |t| t.get_is_left_joinable())
|
first_token.is_none_or(super::super::tokenizer::token::Token::get_is_left_joinable)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_right_joinable(&self) -> bool {
|
pub fn is_right_joinable(&self) -> bool {
|
||||||
let last_token = self.tokens().last();
|
let last_token = self.tokens().last();
|
||||||
last_token.map_or(true, |t| t.get_is_right_joinable())
|
last_token.is_none_or(super::super::tokenizer::token::Token::get_is_right_joinable)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extends the operation with another operation when it returns Some
|
/// Extends the operation with another operation. Only operations of the
|
||||||
/// operation. Only operations of the same type as self can be used to
|
/// same type as self can be used to extend self, otherwise the function
|
||||||
/// extend self. If the operations are of different types, returns None.
|
/// will panic.
|
||||||
pub fn extend(self, other: RawOperation<T>) -> Option<RawOperation<T>> {
|
pub fn extend(self, other: RawOperation<T>) -> RawOperation<T> {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
std::mem::discriminant(&self) == std::mem::discriminant(&other),
|
std::mem::discriminant(&self) == std::mem::discriminant(&other),
|
||||||
"Cannot extend operations of different types. This should have been handled before \
|
"Cannot extend operations of different types. This should have been handled before \
|
||||||
|
|
@ -49,15 +49,15 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(RawOperation::Insert(tokens1), RawOperation::Insert(tokens2)) => Some(
|
(RawOperation::Insert(tokens1), RawOperation::Insert(tokens2)) => {
|
||||||
RawOperation::Insert(tokens1.into_iter().chain(tokens2).collect()),
|
RawOperation::Insert(tokens1.into_iter().chain(tokens2).collect())
|
||||||
),
|
}
|
||||||
(RawOperation::Delete(tokens1), RawOperation::Delete(tokens2)) => Some(
|
(RawOperation::Delete(tokens1), RawOperation::Delete(tokens2)) => {
|
||||||
RawOperation::Delete(tokens1.into_iter().chain(tokens2).collect()),
|
RawOperation::Delete(tokens1.into_iter().chain(tokens2).collect())
|
||||||
),
|
}
|
||||||
(RawOperation::Equal(tokens1), RawOperation::Equal(tokens2)) => Some(
|
(RawOperation::Equal(tokens1), RawOperation::Equal(tokens2)) => {
|
||||||
RawOperation::Equal(tokens1.into_iter().chain(tokens2).collect()),
|
RawOperation::Equal(tokens1.into_iter().chain(tokens2).collect())
|
||||||
),
|
}
|
||||||
_ => unreachable!("Only operations of the same type can be extended"),
|
_ => unreachable!("Only operations of the same type can be extended"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,6 @@ use std::borrow::Cow;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::merge_context::MergeContext;
|
|
||||||
use crate::operation_transformation::Operation;
|
|
||||||
|
|
||||||
// CursorPosition represents the position of an identifiable cursor in a text
|
// CursorPosition represents the position of an identifiable cursor in a text
|
||||||
// document based on its (UTF-8) character index.
|
// document based on its (UTF-8) character index.
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
|
@ -16,6 +13,7 @@ pub struct CursorPosition {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CursorPosition {
|
impl CursorPosition {
|
||||||
|
#[must_use]
|
||||||
pub fn with_index(self, index: usize) -> Self {
|
pub fn with_index(self, index: usize) -> Self {
|
||||||
CursorPosition {
|
CursorPosition {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ use core::iter;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{ordered_operation::OrderedOperation, CursorPosition, Operation, TextWithCursors};
|
use super::{CursorPosition, Operation, TextWithCursors, ordered_operation::OrderedOperation};
|
||||||
use crate::{
|
use crate::{
|
||||||
diffs::{myers::diff, raw_operation::RawOperation},
|
diffs::{myers::diff, raw_operation::RawOperation},
|
||||||
operation_transformation::{merge_context::MergeContext, operation},
|
operation_transformation::merge_context::MergeContext,
|
||||||
tokenizer::{word_tokenizer::word_tokenizer, Tokenizer},
|
tokenizer::{Tokenizer, word_tokenizer::word_tokenizer},
|
||||||
utils::{merge_iters::MergeSorted as _, side::Side, string_builder::StringBuilder},
|
utils::{merge_iters::MergeSorted as _, side::Side, string_builder::StringBuilder},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -84,7 +84,7 @@ where
|
||||||
.flat_map(|next| match next {
|
.flat_map(|next| match next {
|
||||||
RawOperation::Insert(..) => match maybe_previous_insert.take() {
|
RawOperation::Insert(..) => match maybe_previous_insert.take() {
|
||||||
Some(prev) if prev.is_right_joinable() && next.is_left_joinable() => {
|
Some(prev) if prev.is_right_joinable() && next.is_left_joinable() => {
|
||||||
maybe_previous_insert = prev.extend(next);
|
maybe_previous_insert = Some(prev.extend(next));
|
||||||
Box::new(iter::empty()) as Box<dyn Iterator<Item = RawOperation<T>>>
|
Box::new(iter::empty()) as Box<dyn Iterator<Item = RawOperation<T>>>
|
||||||
}
|
}
|
||||||
prev => {
|
prev => {
|
||||||
|
|
@ -94,7 +94,7 @@ where
|
||||||
},
|
},
|
||||||
RawOperation::Delete(..) => match maybe_previous_delete.take() {
|
RawOperation::Delete(..) => match maybe_previous_delete.take() {
|
||||||
Some(prev) if prev.is_right_joinable() && next.is_left_joinable() => {
|
Some(prev) if prev.is_right_joinable() && next.is_left_joinable() => {
|
||||||
maybe_previous_delete = prev.extend(next);
|
maybe_previous_delete = Some(prev.extend(next));
|
||||||
Box::new(iter::empty()) as Box<dyn Iterator<Item = RawOperation<T>>>
|
Box::new(iter::empty()) as Box<dyn Iterator<Item = RawOperation<T>>>
|
||||||
}
|
}
|
||||||
prev => {
|
prev => {
|
||||||
|
|
@ -133,7 +133,7 @@ where
|
||||||
let mut new_index = 0; // this is the start index of the operation on the new text
|
let mut new_index = 0; // this is the start index of the operation on the new text
|
||||||
let mut order = 0; // this is the start index of the operation on the original text
|
let mut order = 0; // this is the start index of the operation on the original text
|
||||||
|
|
||||||
raw_operations.into_iter().flat_map(move |raw_operation| {
|
raw_operations.into_iter().filter_map(move |raw_operation| {
|
||||||
let length = raw_operation.original_text_length();
|
let length = raw_operation.original_text_length();
|
||||||
|
|
||||||
match raw_operation {
|
match raw_operation {
|
||||||
|
|
@ -261,8 +261,8 @@ where
|
||||||
&mut left_merge_context,
|
&mut left_merge_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(ref op @ Operation::Insert { .. })
|
if let Some(ref op @ (Operation::Insert { .. } | Operation::Equal { .. })) =
|
||||||
| Some(ref op @ Operation::Equal { .. }) = result
|
result
|
||||||
{
|
{
|
||||||
while let Some(mut cursor) =
|
while let Some(mut cursor) =
|
||||||
left_cursors.next_if(|cursor| cursor.char_index <= original_end + 1)
|
left_cursors.next_if(|cursor| cursor.char_index <= original_end + 1)
|
||||||
|
|
@ -284,8 +284,8 @@ where
|
||||||
&mut right_merge_context,
|
&mut right_merge_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(ref op @ Operation::Insert { .. })
|
if let Some(ref op @ (Operation::Insert { .. } | Operation::Equal { .. })) =
|
||||||
| Some(ref op @ Operation::Equal { .. }) = result
|
result
|
||||||
{
|
{
|
||||||
while let Some(mut cursor) = right_cursors
|
while let Some(mut cursor) = right_cursors
|
||||||
.next_if(|cursor| cursor.char_index <= original_end + 1)
|
.next_if(|cursor| cursor.char_index <= original_end + 1)
|
||||||
|
|
@ -310,8 +310,7 @@ where
|
||||||
let last_index = merged_operations
|
let last_index = merged_operations
|
||||||
.iter()
|
.iter()
|
||||||
.last()
|
.last()
|
||||||
.map(|op| op.operation.end_index())
|
.map_or(0, |op| op.operation.end_index());
|
||||||
.unwrap_or(0);
|
|
||||||
|
|
||||||
for cursor in left_cursors.chain(right_cursors) {
|
for cursor in left_cursors.chain(right_cursors) {
|
||||||
merged_cursors.push(cursor.with_index(last_index));
|
merged_cursors.push(cursor.with_index(last_index));
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,7 @@ where
|
||||||
/// and updating the context. This implements a comples FSM that handles
|
/// and updating the context. This implements a comples FSM that handles
|
||||||
/// the merging of operations in a way that is consistent with the text.
|
/// the merging of operations in a way that is consistent with the text.
|
||||||
/// The contexts are updated in-place.
|
/// The contexts are updated in-place.
|
||||||
|
#[allow(clippy::too_many_lines)]
|
||||||
pub fn merge_operations_with_context(
|
pub fn merge_operations_with_context(
|
||||||
self,
|
self,
|
||||||
affecting_context: &mut MergeContext<T>,
|
affecting_context: &mut MergeContext<T>,
|
||||||
|
|
@ -298,7 +299,7 @@ where
|
||||||
|
|
||||||
(
|
(
|
||||||
operation @ Operation::Delete { .. },
|
operation @ Operation::Delete { .. },
|
||||||
None | Some(Operation::Insert { .. }) | Some(Operation::Equal { .. }),
|
None | Some(Operation::Insert { .. } | Operation::Equal { .. }),
|
||||||
) => {
|
) => {
|
||||||
produced_context.consume_and_replace_last_operation(Some(operation.clone()));
|
produced_context.consume_and_replace_last_operation(Some(operation.clone()));
|
||||||
Some(operation)
|
Some(operation)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ pub fn word_tokenizer(text: &str) -> Vec<Token<String>> {
|
||||||
let mut result: Vec<Token<String>> = Vec::new();
|
let mut result: Vec<Token<String>> = Vec::new();
|
||||||
|
|
||||||
let mut previous_boundary_index = 0;
|
let mut previous_boundary_index = 0;
|
||||||
let mut previous_char_is_whitespace = text.chars().next().map_or(true, |c| c.is_whitespace());
|
let mut previous_char_is_whitespace = text.chars().next().is_none_or(char::is_whitespace);
|
||||||
|
|
||||||
for (i, c) in text.char_indices() {
|
for (i, c) in text.char_indices() {
|
||||||
let is_current_char_whitespace = c.is_whitespace();
|
let is_current_char_whitespace = c.is_whitespace();
|
||||||
|
|
@ -31,8 +31,8 @@ pub fn word_tokenizer(text: &str) -> Vec<Token<String>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..result.len() - 1 {
|
for i in 0..result.len() - 1 {
|
||||||
if result[i].original().chars().all(|c| c.is_whitespace()) {
|
if result[i].original().chars().all(char::is_whitespace) {
|
||||||
result[i].normalised = result[i].normalised().to_owned() + result[i + 1].original()
|
result[i].normalised = result[i].normalised().to_owned() + result[i + 1].original();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,9 @@ impl ExampleDocument {
|
||||||
result.insert(
|
result.insert(
|
||||||
result
|
result
|
||||||
.char_indices()
|
.char_indices()
|
||||||
.skip(cursor.char_index + i)
|
.nth(cursor.char_index + i)
|
||||||
.next()
|
.map_or_else(|| result.len(), |(byte_index, _)| byte_index), /* find the utf8 char index of the insert
|
||||||
.map(|(byte_index, _)| byte_index)
|
* in byte index */
|
||||||
.unwrap_or_else(|| result.len()), /* find the utf8 char index of the insert
|
|
||||||
* in byte index */
|
|
||||||
'|',
|
'|',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,46 +8,46 @@ use serde::Deserialize;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_document_one_way_without_cursors() {
|
fn test_document_one_way_without_cursors() {
|
||||||
get_all_documents().iter().for_each(|doc| {
|
for doc in &get_all_documents() {
|
||||||
doc.assert_eq_without_cursors(&reconcile(
|
doc.assert_eq_without_cursors(&reconcile(
|
||||||
&doc.parent(),
|
&doc.parent(),
|
||||||
&doc.left().text,
|
&doc.left().text,
|
||||||
&doc.right().text,
|
&doc.right().text,
|
||||||
))
|
));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_document_one_way_with_cursors() {
|
fn test_document_one_way_with_cursors() {
|
||||||
get_all_documents().iter().for_each(|doc| {
|
for doc in &get_all_documents() {
|
||||||
doc.assert_eq(&reconcile_with_cursors(
|
doc.assert_eq(&reconcile_with_cursors(
|
||||||
&doc.parent(),
|
&doc.parent(),
|
||||||
doc.left(),
|
doc.left(),
|
||||||
doc.right(),
|
doc.right(),
|
||||||
))
|
));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_document_inverse_way_without_cursors() {
|
fn test_document_inverse_way_without_cursors() {
|
||||||
get_all_documents().iter().for_each(|doc| {
|
for doc in &get_all_documents() {
|
||||||
doc.assert_eq_without_cursors(&reconcile(
|
doc.assert_eq_without_cursors(&reconcile(
|
||||||
&doc.parent(),
|
&doc.parent(),
|
||||||
&doc.right().text,
|
&doc.right().text,
|
||||||
&doc.left().text,
|
&doc.left().text,
|
||||||
));
|
));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_document_inverse_way_with_cursors() {
|
fn test_document_inverse_way_with_cursors() {
|
||||||
get_all_documents().iter().for_each(|doc| {
|
for doc in &get_all_documents() {
|
||||||
doc.assert_eq(&reconcile_with_cursors(
|
doc.assert_eq(&reconcile_with_cursors(
|
||||||
&doc.parent(),
|
&doc.parent(),
|
||||||
doc.right(),
|
doc.right(),
|
||||||
doc.left(),
|
doc.left(),
|
||||||
))
|
));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_all_documents() -> Vec<ExampleDocument> {
|
fn get_all_documents() -> Vec<ExampleDocument> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue