From 4b5ed06bb722b9e7466d881e46a480155baf46d7 Mon Sep 17 00:00:00 2001 From: zaaarf Date: Wed, 16 Oct 2024 03:11:40 +0200 Subject: [PATCH] chore: renamed TextChange and Event fields Co-authored-by: alemi --- dist/java/src/mp/code/data/TextChange.java | 10 +-- dist/lua/annotations.lua | 4 +- dist/py/src/codemp/codemp.pyi | 96 ++++++++++------------ src/api/change.rs | 33 ++++---- src/api/event.rs | 18 ++-- src/buffer/worker.rs | 12 +-- src/ffi/java/mod.rs | 18 ++-- src/ffi/js/workspace.rs | 6 +- src/ffi/mod.rs | 8 +- src/ffi/python/controllers.rs | 25 +----- src/ffi/python/mod.rs | 28 +++++-- 11 files changed, 124 insertions(+), 134 deletions(-) diff --git a/dist/java/src/mp/code/data/TextChange.java b/dist/java/src/mp/code/data/TextChange.java index bcd72c2..023869f 100644 --- a/dist/java/src/mp/code/data/TextChange.java +++ b/dist/java/src/mp/code/data/TextChange.java @@ -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; } diff --git a/dist/lua/annotations.lua b/dist/lua/annotations.lua index 16b8a4f..df02187 100644 --- a/dist/lua/annotations.lua +++ b/dist/lua/annotations.lua @@ -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 diff --git a/dist/py/src/codemp/codemp.pyi b/dist/py/src/codemp/codemp.pyi index e4cfa2e..5b09cb5 100644 --- a/dist/py/src/codemp/codemp.pyi +++ b/dist/py/src/codemp/codemp.pyi @@ -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: ... diff --git a/src/api/change.rs b/src/api/change.rs index 6270e37..b52cc5c 100644 --- a/src/api/change.rs +++ b/src/api/change.rs @@ -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 { - 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"); diff --git a/src/api/event.rs b/src/api/event.rs index 81df033..8754778 100644 --- a/src/api/event.rs +++ b/src/api/event.rs @@ -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 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 }, } } } diff --git a/src/buffer/worker.rs b/src/buffer/worker.rs index 8b7bc72..21a4746 100644 --- a/src/buffer/worker.rs +++ b/src/buffer/worker.rs @@ -160,8 +160,8 @@ impl BufferWorker { async fn handle_editor_change(&mut self, change: TextChange, tx: &mpsc::Sender) { 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(), }, }, diff --git a/src/ffi/java/mod.rs b/src/ffi/java/mod.rs index 51bd3a5..80ac028 100644 --- a/src/ffi/java/mod.rs +++ b/src/ffi/java/mod.rs @@ -170,9 +170,9 @@ impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::Event { env: &mut jni::JNIEnv<'j>, ) -> Result, 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 { 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, }) } diff --git a/src/ffi/js/workspace.rs b/src/ffi/js/workspace.rs index 70b4c7d..f2e2487 100644 --- a/src/ffi/js/workspace.rs +++ b/src/ffi/js/workspace.rs @@ -19,15 +19,15 @@ pub struct JsEvent { impl From 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, }, diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs index 5c5346d..2fd6fb1 100644 --- a/src/ffi/mod.rs +++ b/src/ffi/mod.rs @@ -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() //! diff --git a/src/ffi/python/controllers.rs b/src/ffi/python/controllers.rs index 9d9d5f3..01b2cc5 100644 --- a/src/ffi/python/controllers.rs +++ b/src/ffi/python/controllers.rs @@ -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(()) diff --git a/src/ffi/python/mod.rs b/src/ffi/python/mod.rs index 75e7695..e620b39 100644 --- a/src/ffi/python/mod.rs +++ b/src/ffi/python/mod.rs @@ -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: ::Err| pyo3::exceptions::PyRuntimeError::new_err(x.to_string()))?; + self.id = value + .parse() + .map_err(|x: ::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 { 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()) }