mirror of
https://github.com/hexedtech/codemp.git
synced 2024-11-22 23:34:49 +01:00
feat: moved TextChange into api, added from diff
This commit is contained in:
parent
5208ff65c0
commit
2ccb5c936b
6 changed files with 66 additions and 19 deletions
56
src/api/change.rs
Normal file
56
src/api/change.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
//! # TextChange
|
||||||
|
//! this represent a range in the previous state of the string and a new content which should be
|
||||||
|
//! replaced to it, allowing to represent any combination of deletions, insertions or replacements
|
||||||
|
//!
|
||||||
|
//! bulk and widespread operations will result in a TextChange effectively sending the whole new
|
||||||
|
//! buffer, but small changes are efficient and easy to create or apply
|
||||||
|
//!
|
||||||
|
//! ### examples
|
||||||
|
//! to insert 'a' after 4th character we should send a
|
||||||
|
//! `TextChange { span: 4..4, content: "a".into() }`
|
||||||
|
//!
|
||||||
|
//! to delete a the fourth character we should send a
|
||||||
|
//! `TextChange { span: 3..4, content: "".into() }`
|
||||||
|
//!
|
||||||
|
|
||||||
|
/// an editor-friendly representation of a text change in a buffer
|
||||||
|
/// span refers to previous text content
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct TextChange {
|
||||||
|
/// range of text change, as char indexes in buffer previous state
|
||||||
|
pub span: std::ops::Range<usize>,
|
||||||
|
/// new content of text inside span
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextChange {
|
||||||
|
/// create a new TextChange from the difference of given strings
|
||||||
|
pub fn from_diff(before: &str, after: &str) -> TextChange {
|
||||||
|
let diff = similar::TextDiff::from_chars(before, after);
|
||||||
|
let mut start = 0;
|
||||||
|
let mut end = 0;
|
||||||
|
let mut from_beginning = true;
|
||||||
|
for op in diff.ops() {
|
||||||
|
match op {
|
||||||
|
similar::DiffOp::Equal { .. } => {
|
||||||
|
if from_beginning {
|
||||||
|
start += 1
|
||||||
|
} else {
|
||||||
|
end += 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
end = 0;
|
||||||
|
from_beginning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let end_before = before.len() - end;
|
||||||
|
let end_after = after.len() - end;
|
||||||
|
|
||||||
|
TextChange {
|
||||||
|
span: start..end_before,
|
||||||
|
content: after[start..end_after].to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,4 +7,8 @@
|
||||||
/// a generic async provider for bidirectional communication
|
/// a generic async provider for bidirectional communication
|
||||||
pub mod controller;
|
pub mod controller;
|
||||||
|
|
||||||
|
/// a generic representation of a text change
|
||||||
|
pub mod change;
|
||||||
|
|
||||||
pub use controller::Controller;
|
pub use controller::Controller;
|
||||||
|
pub use change::TextChange;
|
||||||
|
|
|
@ -11,7 +11,7 @@ use tonic::async_trait;
|
||||||
use crate::errors::IgnorableError;
|
use crate::errors::IgnorableError;
|
||||||
use crate::{api::Controller, Error};
|
use crate::{api::Controller, Error};
|
||||||
|
|
||||||
use super::TextChange;
|
use crate::api::TextChange;
|
||||||
|
|
||||||
/// the buffer controller implementation
|
/// the buffer controller implementation
|
||||||
///
|
///
|
||||||
|
|
|
@ -12,18 +12,3 @@ pub mod controller;
|
||||||
pub(crate) mod worker;
|
pub(crate) mod worker;
|
||||||
|
|
||||||
pub use controller::BufferController as Controller;
|
pub use controller::BufferController as Controller;
|
||||||
|
|
||||||
|
|
||||||
/// an editor-friendly representation of a text change in a buffer
|
|
||||||
///
|
|
||||||
/// TODO move in proto
|
|
||||||
#[derive(Clone, Debug, Default)]
|
|
||||||
pub struct TextChange {
|
|
||||||
/// range of text change, as byte indexes in buffer
|
|
||||||
pub span: std::ops::Range<usize>,
|
|
||||||
/// content of text change, as string
|
|
||||||
pub content: String,
|
|
||||||
/// content after this text change
|
|
||||||
/// note that this field will probably be dropped, don't rely on it
|
|
||||||
pub after: String
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,8 +12,8 @@ use crate::errors::IgnorableError;
|
||||||
use crate::proto::{OperationRequest, RawOp};
|
use crate::proto::{OperationRequest, RawOp};
|
||||||
use crate::proto::buffer_client::BufferClient;
|
use crate::proto::buffer_client::BufferClient;
|
||||||
use crate::api::controller::ControllerWorker;
|
use crate::api::controller::ControllerWorker;
|
||||||
|
use crate::api::TextChange;
|
||||||
|
|
||||||
use super::TextChange;
|
|
||||||
use super::controller::BufferController;
|
use super::controller::BufferController;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,16 @@ pub use crate::{
|
||||||
pub use crate::ot::OperationSeq as CodempOperationSeq;
|
pub use crate::ot::OperationSeq as CodempOperationSeq;
|
||||||
|
|
||||||
#[cfg(feature = "api")]
|
#[cfg(feature = "api")]
|
||||||
pub use crate::api::Controller as CodempController;
|
pub use crate::api::{
|
||||||
|
Controller as CodempController,
|
||||||
|
TextChange as CodempTextChange,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
client::Client as CodempClient,
|
client::Client as CodempClient,
|
||||||
cursor::Controller as CodempCursorController,
|
cursor::Controller as CodempCursorController,
|
||||||
buffer::Controller as CodempBufferController,
|
buffer::Controller as CodempBufferController,
|
||||||
buffer::TextChange as CodempTextChange,
|
|
||||||
Instance as CodempInstance,
|
Instance as CodempInstance,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue