mirror of
https://github.com/hexedtech/codemp.git
synced 2024-12-25 06:14:54 +01:00
feat(python): better struct access
Co-authored-by: alemi <me@alemi.dev>
This commit is contained in:
parent
e1e09cb20e
commit
3326217058
7 changed files with 144 additions and 29 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -703,6 +703,12 @@ version = "2.0.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
|
@ -1269,6 +1275,7 @@ checksum = "3d922163ba1f79c04bc49073ba7b32fd5a8d3b76a87c955921234b8e77333c51"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"indoc",
|
||||
"inventory",
|
||||
"libc",
|
||||
"memoffset",
|
||||
"once_cell",
|
||||
|
|
|
@ -51,7 +51,7 @@ napi = { version = "2.16", features = ["full"], optional = true }
|
|||
napi-derive = { version="2.16", optional = true}
|
||||
|
||||
# glue (python)
|
||||
pyo3 = { version = "0.22", features = ["extension-module"], optional = true}
|
||||
pyo3 = { version = "0.22", features = ["extension-module", "multiple-pymethods"], optional = true}
|
||||
|
||||
# extra
|
||||
async-trait = { version = "0.1", optional = true }
|
||||
|
|
1
dist/java/src/mp/code/data/TextChange.java
vendored
1
dist/java/src/mp/code/data/TextChange.java
vendored
|
@ -13,7 +13,6 @@ import java.util.OptionalLong;
|
|||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@RequiredArgsConstructor
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
public class TextChange {
|
||||
/**
|
||||
* The starting position of the change.
|
||||
|
|
2
dist/py/src/codemp/codemp.pyi
vendored
2
dist/py/src/codemp/codemp.pyi
vendored
|
@ -24,7 +24,7 @@ class Config:
|
|||
port: Optional[int]
|
||||
tls: Optional[bool]
|
||||
|
||||
def __new__(cls, *, username: str, password: str, **kwargs) -> Config: ...
|
||||
def __new__(cls, username: str, password: str, **kwargs) -> Config: ...
|
||||
|
||||
def init() -> Driver: ...
|
||||
def set_logger(logger_cb: Callable[[str], None], debug: bool) -> bool: ...
|
||||
|
|
|
@ -6,11 +6,13 @@ use uuid::Uuid;
|
|||
|
||||
/// Represents a service user
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyo3::pyclass)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct User {
|
||||
/// User unique identifier, should never change.
|
||||
pub id: Uuid,
|
||||
/// User name, can change but should be unique.
|
||||
#[pyo3(get, set)]
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -80,10 +80,9 @@
|
|||
//! import codemp
|
||||
//!
|
||||
//! # connect first, api.code.mp is managed by hexed.technology
|
||||
//! config = codemp.get_default_config()
|
||||
//! config.username = "mail@example.net"
|
||||
//! config.password = "dont-use-this-password"
|
||||
//! client = codemp.connect(config).wait()
|
||||
//! client = codemp.connect(
|
||||
//! codemp.Config('mail@example.net', 'dont-use-this-password')
|
||||
//! ).wait()
|
||||
//!
|
||||
//! # create and join a workspace
|
||||
//! client.create_workspace("some-workspace").wait()
|
||||
|
@ -94,14 +93,16 @@
|
|||
//! buffer = workspace.attach_buffer("/my/file.txt").wait()
|
||||
//!
|
||||
//! # write `hello!` at the beginning of this buffer
|
||||
//! buffer.send(
|
||||
//! 0, 0, "hello!"
|
||||
//! ).wait()
|
||||
//! buffer.send(codemp.TextChange(
|
||||
//! start=0, end=0,
|
||||
//! content="hello!"
|
||||
//! )).wait()
|
||||
//!
|
||||
//! # wait for cursor movements
|
||||
//! while true:
|
||||
//! event = workspace.cursor().recv().wait()
|
||||
//! print(f"user {event.user} moved on buffer {event.buffer}")
|
||||
//!
|
||||
//! ```
|
||||
//!
|
||||
//! ## Lua
|
||||
|
|
|
@ -3,14 +3,14 @@ pub mod controllers;
|
|||
pub mod workspace;
|
||||
|
||||
use crate::{
|
||||
api::{Config, Cursor, TextChange},
|
||||
api::{BufferUpdate, Config, Cursor, Selection, TextChange, User},
|
||||
buffer::Controller as BufferController,
|
||||
cursor::Controller as CursorController,
|
||||
Client, Workspace,
|
||||
};
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::{
|
||||
prelude::*,
|
||||
exceptions::{PyConnectionError, PyRuntimeError, PySystemError},
|
||||
types::PyDict,
|
||||
};
|
||||
|
@ -153,19 +153,28 @@ fn init() -> PyResult<Driver> {
|
|||
Ok(Driver(Some(rt_stop_tx)))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn get_default_config() -> crate::api::Config {
|
||||
let mut conf = crate::api::Config::new("".to_string(), "".to_string());
|
||||
conf.host = Some(conf.host().to_string());
|
||||
conf.port = Some(conf.port());
|
||||
conf.tls = Some(false);
|
||||
conf
|
||||
#[pymethods]
|
||||
impl User {
|
||||
#[getter]
|
||||
fn get_id(&self) -> pyo3::PyResult<String> {
|
||||
Ok(self.id.to_string())
|
||||
}
|
||||
|
||||
#[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()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn __str__(&self) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl Config {
|
||||
#[new]
|
||||
#[pyo3(signature = (*, username, password, **kwds))]
|
||||
#[pyo3(signature = (username, password, **kwds))]
|
||||
pub fn pynew(
|
||||
username: String,
|
||||
password: String,
|
||||
|
@ -176,7 +185,7 @@ impl Config {
|
|||
let port = kwgs.get_item("port")?.and_then(|e| e.extract().ok());
|
||||
let tls = kwgs.get_item("tls")?.and_then(|e| e.extract().ok());
|
||||
|
||||
Ok(Config {
|
||||
Ok(Self {
|
||||
username,
|
||||
password,
|
||||
host,
|
||||
|
@ -184,9 +193,109 @@ impl Config {
|
|||
tls,
|
||||
})
|
||||
} else {
|
||||
Ok(Config::new(username, password))
|
||||
Ok(Self::new(username, password))
|
||||
}
|
||||
}
|
||||
|
||||
fn __str__(&self) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl Cursor {
|
||||
fn __str__(&self) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl Selection {
|
||||
#[new]
|
||||
#[pyo3(signature = (**kwds))]
|
||||
pub fn py_new(kwds: Option<&Bound<'_, PyDict>>) -> PyResult<Self> {
|
||||
if let Some(kwds) = kwds {
|
||||
let start_row = if let Some(e) = kwds.get_item("start_row")? {
|
||||
e.extract()?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let start_col = if let Some(e) = kwds.get_item("start_col")? {
|
||||
e.extract()?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let end_row = if let Some(e) = kwds.get_item("end_row")? {
|
||||
e.extract()?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let end_col = if let Some(e) = kwds.get_item("end_col")? {
|
||||
e.extract()?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let buffer = if let Some(e) = kwds.get_item("buffer")? {
|
||||
e.extract()?
|
||||
} else {
|
||||
String::default()
|
||||
};
|
||||
|
||||
Ok(Self { start_row, start_col, end_row, end_col, buffer })
|
||||
} else {
|
||||
Ok(Self::default())
|
||||
}
|
||||
}
|
||||
|
||||
fn __str__(&self) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl BufferUpdate {
|
||||
fn __str__(&self) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl TextChange {
|
||||
#[new]
|
||||
#[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")? {
|
||||
e.extract()?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let end = if let Some(e) = kwds.get_item("end")? {
|
||||
e.extract()?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let content = if let Some(e) = kwds.get_item("content")? {
|
||||
e.extract()?
|
||||
} else {
|
||||
String::default()
|
||||
};
|
||||
|
||||
Ok(Self { start, end, content })
|
||||
} else {
|
||||
Ok(Self::default())
|
||||
}
|
||||
}
|
||||
|
||||
fn __str__(&self) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
@ -254,27 +363,24 @@ impl From<crate::errors::ControllerError> for PyErr {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoPy<PyObject> for crate::api::User {
|
||||
fn into_py(self, py: Python<'_>) -> PyObject {
|
||||
self.id.to_string().into_py(py)
|
||||
}
|
||||
}
|
||||
|
||||
#[pymodule]
|
||||
fn codemp(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
m.add_function(wrap_pyfunction!(version, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(init, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(get_default_config, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(connect, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(set_logger, m)?)?;
|
||||
m.add_class::<Driver>()?;
|
||||
|
||||
m.add_class::<BufferUpdate>()?;
|
||||
m.add_class::<TextChange>()?;
|
||||
m.add_class::<BufferController>()?;
|
||||
|
||||
m.add_class::<Cursor>()?;
|
||||
m.add_class::<Selection>()?;
|
||||
m.add_class::<CursorController>()?;
|
||||
|
||||
m.add_class::<User>()?;
|
||||
|
||||
m.add_class::<Workspace>()?;
|
||||
m.add_class::<Client>()?;
|
||||
m.add_class::<Config>()?;
|
||||
|
|
Loading…
Reference in a new issue