chore: renamed TextChange and Event fields

Co-authored-by: alemi <me@alemi.dev>
This commit is contained in:
zaaarf 2024-10-16 03:11:40 +02:00
parent 3326217058
commit 4b5ed06bb7
No known key found for this signature in database
GPG key ID: 102E445F4C3F829B
11 changed files with 124 additions and 134 deletions

View file

@ -18,13 +18,13 @@ public class TextChange {
* The starting position of the change.
* If negative, it is clamped to 0.
*/
public final long start;
public final long startIdx;
/**
* The ending position of the change.
* If negative, it is clamped to 0.
*/
public final long end;
public final long endIdx;
/**
* The content of the change.
@ -39,7 +39,7 @@ public class TextChange {
* @return true if this change represents a deletion
*/
public boolean isDelete() {
return this.start < this.end;
return this.startIdx < this.endIdx;
}
/**
@ -66,14 +66,14 @@ public class TextChange {
* @return the mutated string
*/
public String apply(String input) {
long preIndex = Math.min(this.start, input.length());
long preIndex = Math.min(this.startIdx, input.length());
String pre = "";
try {
pre = input.substring(0, (int) preIndex);
} catch(IndexOutOfBoundsException ignored) {}
String post = "";
try {
post = input.substring((int) this.end);
post = input.substring((int) this.endIdx);
} catch(IndexOutOfBoundsException ignored) {}
return pre + this.content + post;
}

View file

@ -361,8 +361,8 @@ local BufferController = {}
---@class TextChange
---@field content string text content of change
---@field start integer start index of change
---@field finish integer end index of change
---@field start_idx integer start index of change
---@field end_idx integer end index of change
local TextChange = {}
---@class (exact) BufferUpdate

View file

@ -39,25 +39,25 @@ class Promise[T]:
It can either be used directly or you can wrap it inside a future python side.
"""
def wait(self) -> T: ...
def is_done(self) -> bool: ...
def wait(self) -> T: ...
def is_done(self) -> bool: ...
class Client:
"""
Handle to the actual client that manages the session. It manages the connection
to a server and joining/creating new workspaces
"""
def attach_workspace(self, workspace: str) -> Promise[Workspace]: ...
def create_workspace(self, workspace: str) -> Promise[None]: ...
def delete_workspace(self, workspace: str) -> Promise[None]: ...
def attach_workspace(self, workspace: str) -> Promise[Workspace]: ...
def create_workspace(self, workspace: str) -> Promise[None]: ...
def delete_workspace(self, workspace: str) -> Promise[None]: ...
def invite_to_workspace(self, workspace: str, username: str) -> Promise[None]: ...
def fetch_owned_workspaces(self) -> Promise[list[str]]: ...
def fetch_joined_workspaces(self) -> Promise[list[str]]: ...
def leave_workspace(self, workspace: str) -> bool: ...
def get_workspace(self, id: str) -> Workspace: ...
def active_workspaces(self) -> list[str]: ...
def current_user(self) -> User: ...
def refresh(self) -> Promise[None]: ...
def fetch_owned_workspaces(self) -> Promise[list[str]]: ...
def fetch_joined_workspaces(self) -> Promise[list[str]]: ...
def leave_workspace(self, workspace: str) -> bool: ...
def get_workspace(self, id: str) -> Workspace: ...
def active_workspaces(self) -> list[str]: ...
def current_user(self) -> User: ...
def refresh(self) -> Promise[None]: ...
class Event:
pass
@ -67,23 +67,23 @@ class Workspace:
Handle to a workspace inside codemp. It manages buffers.
A cursor is tied to the single workspace.
"""
def create_buffer(self, path: str) -> Promise[None]: ...
def attach_buffer(self, path: str) -> Promise[BufferController]: ...
def detach_buffer(self, path: str) -> bool: ...
def fetch_buffers(self) -> Promise[list[str]]: ...
def fetch_users(self) -> Promise[list[User]]: ...
def fetch_buffer_users(self, path: str) -> Promise[list[User]]: ...
def delete_buffer(self, path: str) -> Promise[None]: ...
def id(self) -> str: ...
def cursor(self) -> CursorController: ...
def get_buffer(self, path: str) -> Optional[BufferController]: ...
def user_list(self) -> list[User]: ...
def active_buffers(self) -> list[str]: ...
def create_buffer(self, path: str) -> Promise[None]: ...
def attach_buffer(self, path: str) -> Promise[BufferController]: ...
def detach_buffer(self, path: str) -> bool: ...
def fetch_buffers(self) -> Promise[list[str]]: ...
def fetch_users(self) -> Promise[list[User]]: ...
def fetch_buffer_users(self, path: str) -> Promise[list[User]]: ...
def delete_buffer(self, path: str) -> Promise[None]: ...
def id(self) -> str: ...
def cursor(self) -> CursorController: ...
def get_buffer(self, path: str) -> Optional[BufferController]: ...
def user_list(self) -> list[User]: ...
def active_buffers(self) -> list[str]: ...
def search_buffers(self, filter: Optional[str]) -> list[str]: ...
def recv(self) -> Promise[Event]: ...
def try_recv(self) -> Promise[Optional[Event]]: ...
def poll(self) -> Promise[None]: ...
def clear_callback(self) -> None: ...
def recv(self) -> Promise[Event]: ...
def try_recv(self) -> Promise[Optional[Event]]: ...
def poll(self) -> Promise[None]: ...
def clear_callback(self) -> None: ...
def callback(self, cb: Callable[[Workspace], None]) -> None: ...
class TextChange:
@ -95,10 +95,10 @@ class TextChange:
end: int
content: str
def is_delete(self) -> bool: ...
def is_insert(self) -> bool: ...
def is_empty(self) -> bool: ...
def apply(self, txt: str) -> str: ...
def is_delete(self) -> bool: ...
def is_insert(self) -> bool: ...
def is_empty(self) -> bool: ...
def apply(self, txt: str) -> str: ...
class BufferUpdate:
"""
@ -114,19 +114,16 @@ class BufferController:
Handle to the controller for a specific buffer, which manages the back and forth
of operations to and from other peers.
"""
def path(self) -> str: ...
def content(self) -> Promise[str]: ...
def ack(self, v: list[int]) -> None: ...
def send(self,
start: int,
end: int,
txt: str) -> Promise[None]: ...
def try_recv(self) -> Promise[Optional[TextChange]]: ...
def recv(self) -> Promise[TextChange]: ...
def poll(self) -> Promise[None]: ...
def path(self) -> str: ...
def content(self) -> Promise[str]: ...
def ack(self, v: list[int]) -> None: ...
def send(self, op: TextChange) -> None: ...
def try_recv(self) -> Promise[Optional[TextChange]]: ...
def recv(self) -> Promise[TextChange]: ...
def poll(self) -> Promise[None]: ...
def callback(self,
cb: Callable[[BufferController], None]) -> None: ...
def clear_callback(self) -> None: ...
def clear_callback(self) -> None: ...
@ -151,14 +148,11 @@ class CursorController:
Handle to the controller for a workspace, which manages the back and forth of
cursor movements to and from other peers
"""
def send(self,
path: str,
start: Tuple[int, int],
end: Tuple[int, int]) -> Promise[None]: ...
def try_recv(self) -> Promise[Optional[Cursor]]: ...
def recv(self) -> Promise[Cursor]: ...
def poll(self) -> Promise[None]: ...
def send(self, pos: Selection) -> None: ...
def try_recv(self) -> Promise[Optional[Cursor]]: ...
def recv(self) -> Promise[Cursor]: ...
def poll(self) -> Promise[None]: ...
def callback(self,
cb: Callable[[CursorController], None]) -> None: ...
def clear_callback(self) -> None: ...
def clear_callback(self) -> None: ...

View file

@ -55,10 +55,9 @@ pub struct BufferUpdate {
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub struct TextChange {
/// Range start of text change, as char indexes in buffer previous state.
pub start: u32,
pub start_idx: u32,
/// Range end of text change, as char indexes in buffer previous state.
#[cfg_attr(feature = "serialize", serde(alias = "finish"))] // Lua uses `end` as keyword
pub end: u32,
pub end_idx: u32,
/// New content of text inside span.
pub content: String,
}
@ -66,7 +65,7 @@ pub struct TextChange {
impl TextChange {
/// Returns the [`std::ops::Range`] representing this change's span.
pub fn span(&self) -> std::ops::Range<usize> {
self.start as usize..self.end as usize
self.start_idx as usize..self.end_idx as usize
}
}
@ -76,7 +75,7 @@ impl TextChange {
///
/// Note that this is is **not** mutually exclusive with [TextChange::is_insert].
pub fn is_delete(&self) -> bool {
self.start < self.end
self.start_idx < self.end_idx
}
/// Returns true if this [`TextChange`] adds new text.
@ -93,9 +92,9 @@ impl TextChange {
/// Applies this text change to given text, returning a new string.
pub fn apply(&self, txt: &str) -> String {
let pre_index = std::cmp::min(self.start as usize, txt.len());
let pre_index = std::cmp::min(self.start_idx as usize, txt.len());
let pre = txt.get(..pre_index).unwrap_or("").to_string();
let post = txt.get(self.end as usize..).unwrap_or("").to_string();
let post = txt.get(self.end_idx as usize..).unwrap_or("").to_string();
format!("{}{}{}", pre, self.content, post)
}
}
@ -105,8 +104,8 @@ mod tests {
#[test]
fn textchange_apply_works_for_insertions() {
let change = super::TextChange {
start: 5,
end: 5,
start_idx: 5,
end_idx: 5,
content: " cruel".to_string(),
};
let result = change.apply("hello world!");
@ -116,8 +115,8 @@ mod tests {
#[test]
fn textchange_apply_works_for_deletions() {
let change = super::TextChange {
start: 5,
end: 11,
start_idx: 5,
end_idx: 11,
content: "".to_string(),
};
let result = change.apply("hello cruel world!");
@ -127,8 +126,8 @@ mod tests {
#[test]
fn textchange_apply_works_for_replacements() {
let change = super::TextChange {
start: 5,
end: 11,
start_idx: 5,
end_idx: 11,
content: " not very pleasant".to_string(),
};
let result = change.apply("hello cruel world!");
@ -138,8 +137,8 @@ mod tests {
#[test]
fn textchange_apply_never_panics() {
let change = super::TextChange {
start: 100,
end: 110,
start_idx: 100,
end_idx: 110,
content: "a very long string \n which totally matters".to_string(),
};
let result = change.apply("a short text");
@ -152,8 +151,8 @@ mod tests {
#[test]
fn empty_textchange_doesnt_alter_buffer() {
let change = super::TextChange {
start: 42,
end: 42,
start_idx: 42,
end_idx: 42,
content: "".to_string(),
};
let result = change.apply("some important text");

View file

@ -1,5 +1,7 @@
//! # Event
//! Real time notification of changes in a workspace, to either users or buffers.
#![allow(non_upper_case_globals, non_camel_case_types)] // pyo3 fix your shit
use codemp_proto::workspace::workspace_event::Event as WorkspaceEventInner;
/// Event in a [crate::Workspace].
@ -10,21 +12,21 @@ use codemp_proto::workspace::workspace_event::Event as WorkspaceEventInner;
pub enum Event {
/// Fired when the file tree changes.
/// Contains the modified buffer path (deleted, created or renamed).
FileTreeUpdated(String),
FileTreeUpdated { path: String },
/// Fired when an user joins the current workspace.
UserJoin(String),
UserJoin { name: String },
/// Fired when an user leaves the current workspace.
UserLeave(String),
UserLeave { name: String },
}
impl From<WorkspaceEventInner> for Event {
fn from(event: WorkspaceEventInner) -> Self {
match event {
WorkspaceEventInner::Join(e) => Self::UserJoin(e.user.name),
WorkspaceEventInner::Leave(e) => Self::UserLeave(e.user.name),
WorkspaceEventInner::Create(e) => Self::FileTreeUpdated(e.path),
WorkspaceEventInner::Delete(e) => Self::FileTreeUpdated(e.path),
WorkspaceEventInner::Rename(e) => Self::FileTreeUpdated(e.after),
WorkspaceEventInner::Join(e) => Self::UserJoin { name: e.user.name },
WorkspaceEventInner::Leave(e) => Self::UserLeave { name: e.user.name },
WorkspaceEventInner::Create(e) => Self::FileTreeUpdated { path: e.path },
WorkspaceEventInner::Delete(e) => Self::FileTreeUpdated { path: e.path },
WorkspaceEventInner::Rename(e) => Self::FileTreeUpdated { path: e.after },
}
}
}

View file

@ -160,8 +160,8 @@ impl BufferWorker {
async fn handle_editor_change(&mut self, change: TextChange, tx: &mpsc::Sender<Operation>) {
let last_ver = self.oplog.local_version();
// clip to buffer extents
let clip_start = change.start as usize;
let mut clip_end = change.end as usize;
let clip_start = change.start_idx as usize;
let mut clip_end = change.end_idx as usize;
let b_len = self.branch.len();
if clip_end > b_len {
tracing::warn!("clipping TextChange end span from {clip_end} to {b_len}");
@ -262,8 +262,8 @@ impl BufferWorker {
.map(|x| i64::from_ne_bytes(x.to_ne_bytes()))
.collect(), // TODO this is wasteful
change: crate::api::TextChange {
start: dtop.start() as u32,
end: dtop.start() as u32,
start_idx: dtop.start() as u32,
end_idx: dtop.start() as u32,
content: dtop.content_as_str().unwrap_or_default().to_string(),
},
}
@ -276,8 +276,8 @@ impl BufferWorker {
.map(|x| i64::from_ne_bytes(x.to_ne_bytes()))
.collect(), // TODO this is wasteful
change: crate::api::TextChange {
start: dtop.start() as u32,
end: dtop.end() as u32,
start_idx: dtop.start() as u32,
end_idx: dtop.end() as u32,
content: dtop.content_as_str().unwrap_or_default().to_string(),
},
},

View file

@ -170,9 +170,9 @@ impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::Event {
env: &mut jni::JNIEnv<'j>,
) -> Result<jni::objects::JObject<'j>, jni::errors::Error> {
let (ordinal, arg) = match self {
crate::api::Event::UserJoin(arg) => (0, env.new_string(arg)?),
crate::api::Event::UserLeave(arg) => (1, env.new_string(arg)?),
crate::api::Event::FileTreeUpdated(arg) => (2, env.new_string(arg)?),
crate::api::Event::UserJoin { name: arg } => (0, env.new_string(arg)?),
crate::api::Event::UserLeave { name: arg } => (1, env.new_string(arg)?),
crate::api::Event::FileTreeUpdated { path: arg } => (2, env.new_string(arg)?),
};
let type_class = env.find_class("mp/code/Workspace$Event$Type")?;
@ -242,8 +242,8 @@ impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::TextChange {
class,
"(JJLjava/lang/String;)V",
&[
jni::objects::JValueGen::Long(self.start.into()),
jni::objects::JValueGen::Long(self.end.into()),
jni::objects::JValueGen::Long(self.start_idx.into()),
jni::objects::JValueGen::Long(self.end_idx.into()),
jni::objects::JValueGen::Object(&content),
],
)
@ -438,11 +438,11 @@ impl<'j> jni_toolbox::FromJava<'j> for crate::api::TextChange {
change: Self::From,
) -> Result<Self, jni::errors::Error> {
let start = env
.get_field(&change, "start", "J")?
.get_field(&change, "startIdx", "J")?
.j()?
.clamp(0, u32::MAX.into()) as u32;
let end = env
.get_field(&change, "end", "J")?
.get_field(&change, "endIdx", "J")?
.j()?
.clamp(0, u32::MAX.into()) as u32;
@ -457,8 +457,8 @@ impl<'j> jni_toolbox::FromJava<'j> for crate::api::TextChange {
};
Ok(Self {
start,
end,
start_idx: start,
end_idx: end,
content,
})
}

View file

@ -19,15 +19,15 @@ pub struct JsEvent {
impl From<crate::api::Event> for JsEvent {
fn from(value: crate::api::Event) -> Self {
match value {
crate::api::Event::FileTreeUpdated(value) => Self {
crate::api::Event::FileTreeUpdated { path: value } => Self {
r#type: "filetree".into(),
value,
},
crate::api::Event::UserJoin(value) => Self {
crate::api::Event::UserJoin { name: value } => Self {
r#type: "join".into(),
value,
},
crate::api::Event::UserLeave(value) => Self {
crate::api::Event::UserLeave { name: value } => Self {
r#type: "leave".into(),
value,
},

View file

@ -21,7 +21,7 @@
//!
//! // write `hello!` at the beginning of this buffer
//! buffer.send(codemp::api::TextChange {
//! start: 0, end: 0,
//! start_idx: 0, end_idx: 0,
//! content: "hello!".to_string(),
//! })?;
//!
@ -58,7 +58,7 @@
//!
//! // write `hello!` at the beginning of this buffer
//! await buffer.send({
//! start: 0, end: 0,
//! start_idx: 0, end_idx: 0,
//! content: "hello!",
//! });
//!
@ -94,7 +94,7 @@
//!
//! # write `hello!` at the beginning of this buffer
//! buffer.send(codemp.TextChange(
//! start=0, end=0,
//! start_idx=0, end_idx=0,
//! content="hello!"
//! )).wait()
//!
@ -141,7 +141,7 @@
//!
//! -- write `hello!` at the beginning of this buffer
//! buffer:send({
//! start = 0, finish = 0,
//! start_idx = 0, end_idx = 0,
//! content = "hello!"
//! }):await()
//!

View file

@ -13,22 +13,8 @@ use super::Promise;
#[pymethods]
impl CursorController {
#[pyo3(name = "send")]
fn pysend(
&self,
_py: Python,
path: String,
start: (i32, i32),
end: (i32, i32),
) -> PyResult<()> {
let pos = Selection {
start_row: start.0,
start_col: start.1,
end_row: end.0,
end_col: end.1,
buffer: path,
};
let this = self.clone();
this.send(pos)?;
fn pysend(&self, _py: Python, pos: Selection) -> PyResult<()> {
self.send(pos)?;
Ok(())
}
@ -86,12 +72,7 @@ impl BufferController {
}
#[pyo3(name = "send")]
fn pysend(&self, _py: Python, start: u32, end: u32, txt: String) -> PyResult<()> {
let op = TextChange {
start,
end,
content: txt,
};
fn pysend(&self, _py: Python, op: TextChange) -> PyResult<()> {
let this = self.clone();
this.send(op)?;
Ok(())

View file

@ -10,8 +10,8 @@ use crate::{
};
use pyo3::{
prelude::*,
exceptions::{PyConnectionError, PyRuntimeError, PySystemError},
prelude::*,
types::PyDict,
};
@ -162,7 +162,11 @@ impl User {
#[setter]
fn set_id(&mut self, value: String) -> pyo3::PyResult<()> {
self.id = value.parse().map_err(|x: <uuid::Uuid as std::str::FromStr>::Err| pyo3::exceptions::PyRuntimeError::new_err(x.to_string()))?;
self.id = value
.parse()
.map_err(|x: <uuid::Uuid as std::str::FromStr>::Err| {
pyo3::exceptions::PyRuntimeError::new_err(x.to_string())
})?;
Ok(())
}
@ -220,7 +224,7 @@ impl Selection {
} else {
0
};
let start_col = if let Some(e) = kwds.get_item("start_col")? {
e.extract()?
} else {
@ -245,7 +249,13 @@ impl Selection {
String::default()
};
Ok(Self { start_row, start_col, end_row, end_col, buffer })
Ok(Self {
start_row,
start_col,
end_row,
end_col,
buffer,
})
} else {
Ok(Self::default())
}
@ -269,13 +279,13 @@ impl TextChange {
#[pyo3(signature = (**kwds))]
pub fn py_new(kwds: Option<&Bound<'_, PyDict>>) -> PyResult<Self> {
if let Some(kwds) = kwds {
let start = if let Some(e) = kwds.get_item("start")? {
let start_idx = if let Some(e) = kwds.get_item("start")? {
e.extract()?
} else {
0
};
let end = if let Some(e) = kwds.get_item("end")? {
let end_idx = if let Some(e) = kwds.get_item("end")? {
e.extract()?
} else {
0
@ -287,7 +297,11 @@ impl TextChange {
String::default()
};
Ok(Self { start, end, content })
Ok(Self {
start_idx,
end_idx,
content,
})
} else {
Ok(Self::default())
}