mirror of
https://github.com/hexedtech/codemp.git
synced 2024-11-25 00:24:48 +01:00
chore: update glue code
Co-authored-by: zaaarf <me@zaaarf.foo>
This commit is contained in:
parent
560a634499
commit
6035c448fa
11 changed files with 90 additions and 126 deletions
46
dist/lua/annotations.lua
vendored
46
dist/lua/annotations.lua
vendored
|
@ -135,28 +135,28 @@ function MaybeCursorPromise:cancel() end
|
|||
function MaybeCursorPromise:and_then(cb) end
|
||||
|
||||
|
||||
---@class (exact) DeltaPromise : Promise
|
||||
local DeltaPromise = {}
|
||||
---@class (exact) BufferUpdatePromise : Promise
|
||||
local BufferUpdatePromise = {}
|
||||
--- block until promise is ready and return value
|
||||
--- @return Delta
|
||||
function DeltaPromise:await() end
|
||||
--- @return BufferUpdate
|
||||
function BufferUpdatePromise:await() end
|
||||
--- cancel promise execution
|
||||
function DeltaPromise:cancel() end
|
||||
---@param cb fun(x: Delta) callback to invoke
|
||||
function BufferUpdatePromise:cancel() end
|
||||
---@param cb fun(x: BufferUpdate) callback to invoke
|
||||
---invoke callback asynchronously as soon as promise is ready
|
||||
function DeltaPromise:and_then(cb) end
|
||||
function BufferUpdatePromise:and_then(cb) end
|
||||
|
||||
|
||||
---@class (exact) MaybeDeltaPromise : Promise
|
||||
local MaybeDeltaPromise = {}
|
||||
---@class (exact) MaybeBufferUpdatePromise : Promise
|
||||
local MaybeBufferUpdatePromise = {}
|
||||
--- block until promise is ready and return value
|
||||
--- @return Delta | nil
|
||||
function MaybeDeltaPromise:await() end
|
||||
--- @return BufferUpdate | nil
|
||||
function MaybeBufferUpdatePromise:await() end
|
||||
--- cancel promise execution
|
||||
function MaybeDeltaPromise:cancel() end
|
||||
---@param cb fun(x: Delta | nil) callback to invoke
|
||||
function MaybeBufferUpdatePromise:cancel() end
|
||||
---@param cb fun(x: BufferUpdate | nil) callback to invoke
|
||||
---invoke callback asynchronously as soon as promise is ready
|
||||
function MaybeDeltaPromise:and_then(cb) end
|
||||
function MaybeBufferUpdatePromise:and_then(cb) end
|
||||
|
||||
-- [[ END ASYNC STUFF ]]
|
||||
|
||||
|
@ -322,15 +322,13 @@ local BufferController = {}
|
|||
---@field content string text content of change
|
||||
---@field start integer start index of change
|
||||
---@field finish integer end index of change
|
||||
---@field hash integer? optional hash of text buffer after this change, for sync checks
|
||||
local TextChange = {}
|
||||
|
||||
---@class (exact) Delta
|
||||
---@class (exact) BufferUpdate
|
||||
---@field change TextChange text change for this delta
|
||||
local Delta = {}
|
||||
|
||||
---notify controller that this change has been correctly applied
|
||||
function Delta:ack() end
|
||||
---@field version [integer] CRDT version after this change
|
||||
---@field hash integer? optional hash of text buffer after this change, for sync checks
|
||||
local BufferUpdate = {}
|
||||
|
||||
---@param other string text to apply change to
|
||||
---apply this text change to a string, returning the result
|
||||
|
@ -343,13 +341,13 @@ function TextChange:apply(other) end
|
|||
---update buffer with a text change; note that to delete content should be empty but not span, while to insert span should be empty but not content (can insert and delete at the same time)
|
||||
function BufferController:send(change) end
|
||||
|
||||
---@return MaybeDeltaPromise
|
||||
---@return MaybeBufferUpdatePromise
|
||||
---@async
|
||||
---@nodiscard
|
||||
---try to receive text changes, returning nil if none is available
|
||||
function BufferController:try_recv() end
|
||||
|
||||
---@return DeltaPromise
|
||||
---@return BufferUpdatePromise
|
||||
---@async
|
||||
---@nodiscard
|
||||
---block until next text change and return it
|
||||
|
@ -374,6 +372,10 @@ function BufferController:callback(cb) end
|
|||
---get current content of buffer controller, marking all pending changes as seen
|
||||
function BufferController:content() end
|
||||
|
||||
---@param version [integer] version to ack
|
||||
---notify controller that this version's change has been correctly applied
|
||||
function BufferController:ack(version) end
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
19
dist/py/src/codemp/codemp.pyi
vendored
19
dist/py/src/codemp/codemp.pyi
vendored
|
@ -92,13 +92,13 @@ class TextChange:
|
|||
def is_empty(self) -> bool: ...
|
||||
def apply(self, txt: str) -> str: ...
|
||||
|
||||
class Delta:
|
||||
class BufferUpdate:
|
||||
"""
|
||||
A single editor delta event, wrapping a TextChange and the corresponding ACK channel
|
||||
A single editor delta event, wrapping a TextChange and the new version
|
||||
"""
|
||||
change: TextChange
|
||||
|
||||
def ack(self,) -> str: ...
|
||||
hash: Optional[int]
|
||||
version: list[int]
|
||||
|
||||
|
||||
class BufferController:
|
||||
|
@ -108,6 +108,7 @@ class BufferController:
|
|||
"""
|
||||
def path(self) -> str: ...
|
||||
def content(self) -> Promise[str]: ...
|
||||
def ack(self, v: list[int]) -> None: ...
|
||||
def send(self,
|
||||
start: int,
|
||||
end: int,
|
||||
|
@ -121,14 +122,20 @@ class BufferController:
|
|||
|
||||
|
||||
|
||||
class Cursor:
|
||||
class Selection:
|
||||
"""
|
||||
An Editor agnostic cursor position representation
|
||||
"""
|
||||
start: Tuple[int, int]
|
||||
end: Tuple[int, int]
|
||||
buffer: str
|
||||
user: Optional[str] # can be an empty string
|
||||
|
||||
class Cursor:
|
||||
"""
|
||||
A remote cursor event
|
||||
"""
|
||||
user: str
|
||||
sel: Selection
|
||||
|
||||
|
||||
class CursorController:
|
||||
|
|
|
@ -3,10 +3,8 @@ use jni_toolbox::jni;
|
|||
|
||||
use crate::{
|
||||
api::{
|
||||
controller::{AsyncReceiver, AsyncSender},
|
||||
TextChange,
|
||||
change::BufferUpdate, controller::{AsyncReceiver, AsyncSender}, TextChange
|
||||
},
|
||||
buffer::controller::Delta,
|
||||
errors::ControllerError,
|
||||
};
|
||||
|
||||
|
@ -28,13 +26,13 @@ fn get_content(controller: &mut crate::buffer::Controller) -> Result<String, Con
|
|||
#[jni(package = "mp.code", class = "BufferController")]
|
||||
fn try_recv(
|
||||
controller: &mut crate::buffer::Controller,
|
||||
) -> Result<Option<Delta>, ControllerError> {
|
||||
) -> Result<Option<BufferUpdate>, ControllerError> {
|
||||
super::tokio().block_on(controller.try_recv())
|
||||
}
|
||||
|
||||
/// Block until it receives a [TextChange].
|
||||
#[jni(package = "mp.code", class = "BufferController")]
|
||||
fn recv(controller: &mut crate::buffer::Controller) -> Result<Delta, ControllerError> {
|
||||
fn recv(controller: &mut crate::buffer::Controller) -> Result<BufferUpdate, ControllerError> {
|
||||
super::tokio().block_on(controller.recv())
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,6 @@ into_java_ptr_class!(crate::Client, "mp/code/Client");
|
|||
into_java_ptr_class!(crate::Workspace, "mp/code/Workspace");
|
||||
into_java_ptr_class!(crate::cursor::Controller, "mp/code/CursorController");
|
||||
into_java_ptr_class!(crate::buffer::Controller, "mp/code/BufferController");
|
||||
into_java_ptr_class!(crate::buffer::controller::Delta, "mp/code/data/Delta");
|
||||
|
||||
impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::User {
|
||||
const CLASS: &'static str = "mp/code/data/User";
|
||||
|
@ -202,19 +201,6 @@ impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::TextChange {
|
|||
) -> Result<jni::objects::JObject<'j>, jni::errors::Error> {
|
||||
let content = env.new_string(self.content)?;
|
||||
|
||||
let hash_class = env.find_class("java/util/OptionalLong")?;
|
||||
let hash = if let Some(h) = self.hash {
|
||||
env.call_static_method(
|
||||
hash_class,
|
||||
"of",
|
||||
"(J)Ljava/util/OptionalLong;",
|
||||
&[jni::objects::JValueGen::Long(h)],
|
||||
)
|
||||
} else {
|
||||
env.call_static_method(hash_class, "empty", "()Ljava/util/OptionalLong;", &[])
|
||||
}?
|
||||
.l()?;
|
||||
|
||||
let class = env.find_class(Self::CLASS)?;
|
||||
env.new_object(
|
||||
class,
|
||||
|
@ -223,7 +209,6 @@ impl<'j> jni_toolbox::IntoJavaObject<'j> for crate::api::TextChange {
|
|||
jni::objects::JValueGen::Long(self.start.into()),
|
||||
jni::objects::JValueGen::Long(self.end.into()),
|
||||
jni::objects::JValueGen::Object(&content),
|
||||
jni::objects::JValueGen::Object(&hash),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::api::controller::{AsyncReceiver, AsyncSender};
|
||||
use crate::api::TextChange;
|
||||
use crate::buffer::controller::{Delta, BufferController};
|
||||
use crate::api::change::{TextChange, BufferUpdate};
|
||||
use crate::buffer::controller::BufferController;
|
||||
use napi::threadsafe_function::{
|
||||
ErrorStrategy::Fatal, ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode,
|
||||
};
|
||||
|
@ -53,13 +53,13 @@ impl BufferController {
|
|||
#[napi(js_name = "try_recv")]
|
||||
pub async fn js_try_recv(
|
||||
&self,
|
||||
) -> napi::Result<Option<Delta>> {
|
||||
) -> napi::Result<Option<BufferUpdate>> {
|
||||
Ok(self.try_recv().await?)
|
||||
}
|
||||
|
||||
/// Wait for next buffer event and return it
|
||||
#[napi(js_name = "recv")]
|
||||
pub async fn js_recv(&self) -> napi::Result<Delta> {
|
||||
pub async fn js_recv(&self) -> napi::Result<BufferUpdate> {
|
||||
Ok(self.recv().await?)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,41 +6,6 @@ use napi::threadsafe_function::{
|
|||
};
|
||||
use napi_derive::napi;
|
||||
|
||||
#[napi(object, js_name = "Cursor")]
|
||||
pub struct JsCursor {
|
||||
/// range of text change, as char indexes in buffer previous state
|
||||
pub start_row: i32,
|
||||
pub start_col: i32,
|
||||
pub end_row: i32,
|
||||
pub end_col: i32,
|
||||
pub buffer: String,
|
||||
pub user: Option<String>,
|
||||
}
|
||||
|
||||
impl From<JsCursor> for crate::api::Cursor {
|
||||
fn from(value: JsCursor) -> Self {
|
||||
crate::api::Cursor {
|
||||
start: (value.start_row, value.start_col),
|
||||
end: (value.end_row, value.end_col),
|
||||
buffer: value.buffer,
|
||||
user: value.user,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::api::Cursor> for JsCursor {
|
||||
fn from(value: crate::api::Cursor) -> Self {
|
||||
JsCursor {
|
||||
start_row: value.start.0,
|
||||
start_col: value.start.1,
|
||||
end_row: value.end.0,
|
||||
end_col: value.end.1,
|
||||
buffer: value.buffer,
|
||||
user: value.user.map(|x| x.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
impl CursorController {
|
||||
/// Register a callback to be called on receive.
|
||||
|
@ -74,19 +39,19 @@ impl CursorController {
|
|||
|
||||
/// Send a new cursor event to remote
|
||||
#[napi(js_name = "send")]
|
||||
pub fn js_send(&self, pos: JsCursor) -> napi::Result<()> {
|
||||
Ok(self.send(crate::api::Cursor::from(pos))?)
|
||||
pub fn js_send(&self, sel: crate::api::cursor::Selection) -> napi::Result<()> {
|
||||
Ok(self.send(sel)?)
|
||||
}
|
||||
|
||||
/// Get next cursor event if available without blocking
|
||||
#[napi(js_name = "try_recv")]
|
||||
pub async fn js_try_recv(&self) -> napi::Result<Option<JsCursor>> {
|
||||
Ok(self.try_recv().await?.map(JsCursor::from))
|
||||
pub async fn js_try_recv(&self) -> napi::Result<Option<crate::api::Cursor>> {
|
||||
Ok(self.try_recv().await?.map(crate::api::Cursor::from))
|
||||
}
|
||||
|
||||
/// Block until next
|
||||
#[napi(js_name = "recv")]
|
||||
pub async fn js_recv(&self) -> napi::Result<JsCursor> {
|
||||
pub async fn js_recv(&self) -> napi::Result<crate::api::Cursor> {
|
||||
Ok(self.recv().await?.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::buffer::controller::Delta;
|
||||
use crate::prelude::*;
|
||||
use mlua::prelude::*;
|
||||
use mlua_codemp_patch as mlua;
|
||||
|
@ -22,6 +21,7 @@ impl LuaUserData for CodempBufferController {
|
|||
);
|
||||
methods.add_method("recv", |_, this, ()| a_sync! { this => this.recv().await? });
|
||||
methods.add_method("poll", |_, this, ()| a_sync! { this => this.poll().await? });
|
||||
methods.add_method_mut("ack", |_, this, (version,):(Vec<i64>,)| Ok(this.ack(version)));
|
||||
|
||||
methods.add_method(
|
||||
"content",
|
||||
|
@ -43,7 +43,6 @@ impl LuaUserData for CodempTextChange {
|
|||
fields.add_field_method_get("content", |_, this| Ok(this.content.clone()));
|
||||
fields.add_field_method_get("start", |_, this| Ok(this.start));
|
||||
fields.add_field_method_get("end", |_, this| Ok(this.end));
|
||||
fields.add_field_method_get("hash", |_, this| Ok(this.hash));
|
||||
// add a 'finish' accessor too because in Lua 'end' is reserved
|
||||
fields.add_field_method_get("finish", |_, this| Ok(this.end));
|
||||
}
|
||||
|
@ -56,12 +55,17 @@ impl LuaUserData for CodempTextChange {
|
|||
}
|
||||
}
|
||||
|
||||
impl LuaUserData for Delta {
|
||||
from_lua_serde! { CodempBufferUpdate }
|
||||
impl LuaUserData for CodempBufferUpdate {
|
||||
fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("hash", |_, this| Ok(this.hash));
|
||||
fields.add_field_method_get("version", |_, this| Ok(this.version.clone()));
|
||||
fields.add_field_method_get("change", |_, this| Ok(this.change.clone()));
|
||||
}
|
||||
|
||||
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_method_mut("ack", |_, this, ()| Ok(this.ack()));
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| {
|
||||
Ok(format!("{:?}", this))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ use mlua_codemp_patch as mlua;
|
|||
|
||||
use super::ext::a_sync::a_sync;
|
||||
use super::ext::from_lua_serde;
|
||||
use super::ext::lua_tuple;
|
||||
|
||||
impl LuaUserData for CodempCursorController {
|
||||
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
|
||||
|
@ -12,7 +11,7 @@ impl LuaUserData for CodempCursorController {
|
|||
Ok(format!("{:?}", this))
|
||||
});
|
||||
|
||||
methods.add_method("send", |_, this, (cursor,): (CodempCursor,)| {
|
||||
methods.add_method("send", |_, this, (cursor,): (CodempSelection,)| {
|
||||
Ok(this.send(cursor)?)
|
||||
});
|
||||
methods.add_method(
|
||||
|
@ -33,18 +32,31 @@ impl LuaUserData for CodempCursorController {
|
|||
|
||||
from_lua_serde! { CodempCursor }
|
||||
impl LuaUserData for CodempCursor {
|
||||
fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("user", |_, this| Ok(this.user.clone()));
|
||||
fields.add_field_method_get("sel", |_, this| Ok(this.sel.clone()));
|
||||
}
|
||||
|
||||
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| {
|
||||
Ok(format!("{:?}", this))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
from_lua_serde! { CodempSelection }
|
||||
impl LuaUserData for CodempSelection {
|
||||
fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("user", |_, this| Ok(this.user.clone()));
|
||||
fields.add_field_method_get("buffer", |_, this| Ok(this.buffer.clone()));
|
||||
fields.add_field_method_get("start", |lua, this| lua_tuple(lua, this.start));
|
||||
fields.add_field_method_get("end", |lua, this| lua_tuple(lua, this.end));
|
||||
// add a 'finish' accessor too because in Lua 'end' is reserved
|
||||
fields.add_field_method_get("finish", |lua, this| lua_tuple(lua, this.end));
|
||||
fields.add_field_method_get("start_row", |_, this| Ok(this.start_row));
|
||||
fields.add_field_method_get("start_col", |_, this| Ok(this.start_col));
|
||||
fields.add_field_method_get("end_row", |_, this| Ok(this.end_row));
|
||||
fields.add_field_method_get("end_col", |_, this| Ok(this.end_col));
|
||||
}
|
||||
|
||||
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| {
|
||||
Ok(format!("{:?}", this))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::buffer::controller::Delta;
|
||||
use crate::ext::IgnorableError;
|
||||
use crate::prelude::*;
|
||||
use mlua::prelude::*;
|
||||
|
@ -110,8 +109,10 @@ callback_args! {
|
|||
MaybeEvent: Option<CodempEvent>,
|
||||
Cursor: CodempCursor,
|
||||
MaybeCursor: Option<CodempCursor>,
|
||||
Selection: CodempSelection,
|
||||
MaybeSelection: Option<CodempSelection>,
|
||||
TextChange: CodempTextChange,
|
||||
MaybeTextChange: Option<CodempTextChange>,
|
||||
Delta: Delta,
|
||||
MaybeDelta: Option<Delta>,
|
||||
BufferUpdate: CodempBufferUpdate,
|
||||
MaybeBufferUpdate: Option<CodempBufferUpdate>,
|
||||
}
|
||||
|
|
|
@ -2,19 +2,9 @@ pub mod a_sync;
|
|||
pub mod callback;
|
||||
pub mod log;
|
||||
|
||||
use mlua::prelude::*;
|
||||
use mlua_codemp_patch as mlua;
|
||||
|
||||
pub(crate) use a_sync::tokio;
|
||||
pub(crate) use callback::callback;
|
||||
|
||||
pub(crate) fn lua_tuple<T: IntoLua>(lua: &Lua, (a, b): (T, T)) -> LuaResult<LuaTable> {
|
||||
let table = lua.create_table()?;
|
||||
table.set(1, a)?;
|
||||
table.set(2, b)?;
|
||||
Ok(table)
|
||||
}
|
||||
|
||||
macro_rules! from_lua_serde {
|
||||
($($t:ty)*) => {
|
||||
$(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::api::controller::{AsyncReceiver, AsyncSender};
|
||||
use crate::api::Cursor;
|
||||
use crate::api::cursor::{Cursor, Selection};
|
||||
use crate::api::TextChange;
|
||||
use crate::buffer::Controller as BufferController;
|
||||
use crate::cursor::Controller as CursorController;
|
||||
|
@ -20,11 +20,12 @@ impl CursorController {
|
|||
start: (i32, i32),
|
||||
end: (i32, i32),
|
||||
) -> PyResult<()> {
|
||||
let pos = Cursor {
|
||||
start,
|
||||
end,
|
||||
let pos = Selection {
|
||||
start_row: start.0,
|
||||
start_col: start.1,
|
||||
end_row: end.0,
|
||||
end_col: end.1,
|
||||
buffer: path,
|
||||
user: None,
|
||||
};
|
||||
let this = self.clone();
|
||||
this.send(pos)?;
|
||||
|
@ -90,7 +91,6 @@ impl BufferController {
|
|||
start,
|
||||
end,
|
||||
content: txt,
|
||||
hash: None,
|
||||
};
|
||||
let this = self.clone();
|
||||
this.send(op)?;
|
||||
|
@ -143,21 +143,21 @@ impl BufferController {
|
|||
impl Cursor {
|
||||
#[getter(start)]
|
||||
fn pystart(&self) -> (i32, i32) {
|
||||
self.start
|
||||
(self.sel.start_row, self.sel.start_col)
|
||||
}
|
||||
|
||||
#[getter(end)]
|
||||
fn pyend(&self) -> (i32, i32) {
|
||||
self.end
|
||||
(self.sel.end_row, self.sel.end_col)
|
||||
}
|
||||
|
||||
#[getter(buffer)]
|
||||
fn pybuffer(&self) -> String {
|
||||
self.buffer.clone()
|
||||
self.sel.buffer.clone()
|
||||
}
|
||||
|
||||
#[getter(user)]
|
||||
fn pyuser(&self) -> Option<String> {
|
||||
self.user.clone()
|
||||
Some(self.user.clone())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue