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