Minor fixes in the lib, finished the python objects wrappers. Started working on plugin.py.

Former-commit-id: 3a5e587b1ba019bb9a263478cd2e08b9b532322e
This commit is contained in:
Camillo Schenone 2023-08-25 14:29:11 +02:00
parent e387b726c8
commit 6fe5effb68
4 changed files with 104 additions and 64 deletions

View file

@ -1 +1 @@
80ba7b16f0b0647e2f1d8520f3a90c51000bbd2c
8114809f135d7ea9f88d0a45a9de8fc93fdbd9ff

View file

@ -9,9 +9,9 @@ import time
# UGLYYYY, find a way to not have global variables laying around.
_tasks = []
_client = CodempClient()
_client = None
_cursor_controller = None
_op_controller = None
_buffer_controller = None
_setting_key = "codemp_buffer"
def store_task(name = None):
@ -23,6 +23,8 @@ def store_task(name = None):
return store_named_task
def plugin_loaded():
global _client
_client = CodempClient()
sublime_asyncio.acquire() # instantiate and start a global event loop.
class CodempClientViewEventListener(sublime_plugin.ViewEventListener):
@ -47,24 +49,24 @@ class CodempClientTextChangeListener(sublime_plugin.TextChangeListener):
return False
def on_text_changed(self, changes):
global _op_controller
if _op_controller:
global _buffer_controller
if _buffer_controller:
for change in changes:
sublime_asyncio.dispatch(apply_changes(change))
async def apply_changes(change):
global _op_controller
global _buffer_controller
text = change.str
skip = change.a.pt
if change.len_utf8 == 0: # we are inserting new text.
tail = len(_op_controller.get_content()) - skip
tail = len(_buffer_controller.get_content()) - skip
else: # we are changing an existing region of text of length len_utf8
tail = len(_op_controller.get_content()) - skip - change.len_utf8
tail = len(_buffer_controller.get_content()) - skip - change.len_utf8
tail_skip = len(_op_controller.get_content()) - tail
tail_skip = len(_buffer_controller.get_content()) - tail
print("[buff change]", skip, text, tail_skip)
await _op_controller.apply(skip, text, tail)
await _buffer_controller.apply(skip, text, tail)
async def make_connection(server_host):
global _client
@ -90,7 +92,7 @@ async def sync_buffer(caller, start, end, txt):
async def share_buffer(buffer):
global _client
global _cursor_controller
global _op_controller
global _buffer_controller
if not _client.ready:
sublime.error_message("No connected client.")
@ -106,8 +108,8 @@ async def share_buffer(buffer):
sublime.error_message("Could not share buffer.")
return
_op_controller = await _client.attach(buffer)
_op_controller.callback(sync_buffer, _client.id)
_buffer_controller = await _client.attach(buffer)
_buffer_controller.callback(sync_buffer, _client.id)
_cursor_controller = await _client.listen()
_cursor_controller.callback(move_cursor, _client.id)
@ -115,7 +117,7 @@ async def share_buffer(buffer):
if not _cursor_controller:
sublime.error_message("Could not subsribe a listener.")
return
if not _op_controller:
if not _buffer_controller:
sublime.error_message("Could not attach to the buffer.")
return
@ -127,7 +129,7 @@ async def share_buffer(buffer):
async def join_buffer(window, buffer):
global _client
global _cursor_controller
global _op_controller
global _buffer_controller
if not _client.ready:
sublime.error_message("No connected client.")
@ -138,8 +140,8 @@ async def join_buffer(window, buffer):
sublime.status_message("[codemp] Joining buffer {}".format(buffer))
print("[codemp] Joining buffer {}".format(buffer))
_op_controller = await _client.attach(buffer)
content = _op_controller.get_content()
_buffer_controller = await _client.attach(buffer)
content = _buffer_controller.get_content()
view.run_command("codemp_replace_view", {"content": content})
_cursor_controller = await _client.listen()
@ -149,7 +151,7 @@ async def join_buffer(window, buffer):
if not _cursor_controller:
sublime.error_message("Could not subsribe a listener.")
return
if not _op_controller:
if not _buffer_controller:
sublime.error_message("Could not attach to the buffer.")
return

View file

@ -4,68 +4,109 @@ import Codemp.bindings.codemp_client as libcodemp
class CodempClient():
def __init__(self):
self.handle = None
self.id = None
self.handle = libcodemp.codemp_init()
self.ready = False
async def connect(self, server_host):
self.handle = await libcodemp.connect(server_host)
self.id = await self.handle.get_id()
async def connect(self, server_host): # -> None
await self.handle.connect(server_host)
self.ready = True
def disconnect(self):
def disconnect(self): # -> None
# disconnect all buffers
# stop all callbacks
self.handle = None
self.id = None
self.ready = False
# some code that tells the server to unsubscribe stuff as well.
async def get_id(self):
if self.ready and not self.id:
self.id = await self.handle.get_id()
return self.id
elif self.ready:
return self.id
else:
raise RuntimeError("Attemp to get id without an established connection.")
async def create(self, path, content=None):
async def create(self, path, content=None): # -> None
if self.ready:
return await self.handle.create(path, content)
else:
raise RuntimeError("Attemp to create a buffer without a connection.")
async def listen(self):
async def join(self, session): # -> CursorController
if self.ready:
return CursorController(await self.handle.listen())
else:
raise RuntimeError("Attempt to listen without a connection.")
return CursorController(await self.handle.join(session))
async def attach(self, path):
async def attach(self, path): # -> BufferController
if self.ready:
return ContentController(await self.handle.attach(path))
else:
raise RuntimeError("Attempt to attach without a connection.")
return BufferController(await self.handle.attach(path))
async def get_cursor(self): # -> CursorController
if self.ready:
return CursorController(await self.handle.get_cursor())
async def get_buffer(self, path): # -> BufferController
if self.ready:
return BufferController(await self.handle.get_buffer())
async def remove_buffer(self, path): # -> None
if self.ready:
await self.handle.disconnect_buffer(path)
class CursorController():
def __init__(self, handle):
self.handle = handle
async def send(self, path, start, end):
await self.handle.send(path, start, end)
def send(self, path, start, end): # -> None
self.handle.send(path, start, end)
def callback(self, coro, id):
def try_recv(self): # -> Optional[CursorEvent]
return self.handle.try_recv()
async def recv(self): # -> CursorEvent
return await self.handle.recv()
async def poll(self): # -> None
# await until new cursor event, then returns
return await self.handle.poll()
def drop_callback(self): # -> None
self.handle.drop_callback()
def callback(self, coro): # -> None
self.handle.callback(coro, id)
class ContentController():
class BufferController():
def __init__(self, handle):
self.handle = handle
def get_content(self):
def get_content(self): # -> String
return self.handle.content()
async def apply(self, skip, text, tail):
return await self.handle.apply(skip, text, tail)
def replace(self, txt): # -> None
# replace the whole buffer.
self.handle.replace(txt)
def insert(self, txt, pos): # -> None
# insert text at buffer position pos
self.handle.insert(txt, pos)
def delta(self, start, txt, end): # -> None
# delta in the region start..end with txt new content
self.handle.delta(start, txt, end)
def delete(self, pos, count): # -> None
# delete starting from pos, count chars.
self.handle.delete(pos, count)
def cancel(self, pos, count): # -> None
# cancel backward `count` elements from pos.
self.handle.cancle(pos, count)
def try_recv(self): # -> Optional[TextChange]
return self.handle.try_recv()
async def recv(self): # -> TextChange
return await self.handle.recv()
async def poll(self): # -> ??
return await self.handle.poll()
def drop_callback(self): # -> None
self.handle.drop_callback()
def callback(self, coro): # -> None
self.handle.callback(coro)
def callback(self, coro, id):
self.handle.callback(coro, id)

View file

@ -53,6 +53,7 @@ impl From::<CodempInstance> for PyClientHandle {
#[pymethods]
impl PyClientHandle {
fn connect<'a>(&'a self, py: Python<'a>, addr: String) ->PyResult<&'a PyAny> {
let rc = self.0.clone();
@ -232,7 +233,7 @@ impl PyCursorController {
}
}
fn send<'a>(&'a self, py: Python<'a>, path: String, start: (i32, i32), end: (i32, i32)) -> PyResult<&'a PyAny> {
fn send<'a>(&'a self, path: String, start: (i32, i32), end: (i32, i32)) -> PyResult<()> {
let rc = self.handle.clone();
let pos = CodempCursorPosition {
buffer: path,
@ -240,12 +241,8 @@ impl PyCursorController {
end: Some(end.into())
};
pyo3_asyncio::tokio::future_into_py(py, async move {
rc.send(pos)
.map_err(PyCodempError::from)?;
Ok(())
})
rc.send(pos).map_err(PyCodempError::from)?;
Ok(())
}
fn try_recv(&self, py: Python<'_>) -> PyResult<PyObject> {