2023-09-05 01:30:07 +02:00
|
|
|
//! # MultiPlayer Code Editing lib
|
2023-08-19 21:44:27 +02:00
|
|
|
//!
|
2024-08-07 17:34:46 +02:00
|
|
|
//! ![just a nice pic](https://alemi.dev/img/about-slice-3.jpg)
|
2023-08-20 03:34:48 +02:00
|
|
|
//!
|
2023-11-17 05:58:12 +01:00
|
|
|
//! > the core library of the codemp project, driving all editor plugins
|
2023-08-19 21:44:27 +02:00
|
|
|
//!
|
2023-08-20 09:13:21 +02:00
|
|
|
//! ## structure
|
2024-02-09 01:16:16 +01:00
|
|
|
//! The main entrypoint is the [Client] object, that maintains a connection and can
|
|
|
|
//! be used to join workspaces or attach to buffers. It contains the underlying [Workspace] and
|
2023-09-05 01:31:57 +02:00
|
|
|
//! stores active controllers.
|
2023-08-19 21:44:27 +02:00
|
|
|
//!
|
2023-09-10 03:43:46 +02:00
|
|
|
//! Some actions will return structs implementing the [api::Controller] trait. These can be polled
|
|
|
|
//! for new stream events ([api::Controller::poll]/[api::Controller::recv]), which will be returned in order.
|
|
|
|
//! Blocking and callback variants are also implemented. The [api::Controller] can also be used to send new
|
|
|
|
//! events to the server ([api::Controller::send]).
|
2023-08-20 00:46:55 +02:00
|
|
|
//!
|
2023-11-17 05:47:40 +01:00
|
|
|
//! Each operation on a buffer is represented as an [woot::crdt::Op]. The underlying buffer is a
|
|
|
|
//! [WOOT CRDT](https://inria.hal.science/file/index/docid/71240/filename/RR-5580.pdf),
|
|
|
|
//! but to use this library it's only sufficient to know that all WOOT buffers that have received
|
|
|
|
//! the same operations converge to the same state, and that operations might not get integrated
|
|
|
|
//! immediately but instead deferred until compatible.
|
2023-08-19 21:44:27 +02:00
|
|
|
//!
|
2023-08-20 09:13:21 +02:00
|
|
|
//! ## features
|
2024-02-09 00:39:07 +01:00
|
|
|
//! * `api` : include traits for core interfaces under [api] (default enabled)
|
2024-02-09 01:16:16 +01:00
|
|
|
//! * `woot` : include the underlying CRDT library and re-exports it (default enabled)
|
2024-02-09 00:39:07 +01:00
|
|
|
//! * `proto` : include GRCP protocol definitions under [proto] (default enabled)
|
|
|
|
//! * `client` : include the local [client] implementation (default enabled)
|
2023-08-19 21:44:27 +02:00
|
|
|
//!
|
2023-08-20 09:13:21 +02:00
|
|
|
//! ## examples
|
2024-02-09 01:16:16 +01:00
|
|
|
//! most methods are split between the [Client] itself and the current [Workspace]
|
2023-08-20 09:13:21 +02:00
|
|
|
//!
|
2024-02-09 01:04:24 +01:00
|
|
|
//! ### async
|
2023-08-20 09:13:21 +02:00
|
|
|
//! ```rust,no_run
|
2023-11-17 05:47:40 +01:00
|
|
|
//! use codemp::api::{Controller, TextChange};
|
2023-08-20 09:13:21 +02:00
|
|
|
//!
|
|
|
|
//! # async fn async_example() -> codemp::Result<()> {
|
2024-02-09 01:04:24 +01:00
|
|
|
//! // creating a client session will immediately attempt to connect
|
2024-02-09 01:16:16 +01:00
|
|
|
//! let mut session = codemp::Client::new("http://alemi.dev:50053").await?;
|
2024-02-09 01:04:24 +01:00
|
|
|
//!
|
|
|
|
//! // login first, obtaining a new token granting access to 'some_workspace'
|
|
|
|
//! session.login(
|
|
|
|
//! "username".to_string(),
|
|
|
|
//! "password".to_string(),
|
|
|
|
//! Some("some_workspace".to_string())
|
|
|
|
//! ).await?;
|
2023-08-20 00:46:55 +02:00
|
|
|
//!
|
2024-02-09 01:04:24 +01:00
|
|
|
//! // join a remote workspace, obtaining a workspace handle
|
|
|
|
//! let workspace = session.join_workspace("some_workspace").await?;
|
|
|
|
//!
|
|
|
|
//! workspace.cursor().send( // move cursor
|
|
|
|
//! codemp::proto::cursor::CursorPosition {
|
2023-08-20 09:13:21 +02:00
|
|
|
//! buffer: "test.txt".into(),
|
2024-02-09 01:04:24 +01:00
|
|
|
//! start: codemp::proto::cursor::RowCol { row: 0, col: 0 },
|
|
|
|
//! end: codemp::proto::cursor::RowCol { row: 0, col: 1 },
|
2023-08-20 00:46:55 +02:00
|
|
|
//! }
|
2023-08-20 09:13:21 +02:00
|
|
|
//! )?;
|
2024-02-09 01:04:24 +01:00
|
|
|
//! let op = workspace.cursor().recv().await?; // receive event from server
|
2023-08-20 09:13:21 +02:00
|
|
|
//! println!("received cursor event: {:?}", op);
|
2023-08-20 00:46:55 +02:00
|
|
|
//!
|
2023-08-20 09:13:21 +02:00
|
|
|
//! // attach to a new buffer and execute operations on it
|
2024-02-09 01:04:24 +01:00
|
|
|
//! workspace.create("test.txt").await?; // create new buffer
|
|
|
|
//! let buffer = workspace.attach("test.txt").await?; // attach to it
|
2023-11-17 05:47:40 +01:00
|
|
|
//! let local_change = TextChange { span: 0..0, content: "hello!".into() };
|
|
|
|
//! buffer.send(local_change)?; // insert some text
|
2024-02-09 01:04:24 +01:00
|
|
|
//! let remote_change = buffer.recv().await?; // await remote change
|
2023-08-20 09:13:21 +02:00
|
|
|
//! #
|
|
|
|
//! # Ok(())
|
|
|
|
//! # }
|
2023-08-20 00:46:55 +02:00
|
|
|
//! ```
|
|
|
|
//!
|
2024-02-09 01:16:16 +01:00
|
|
|
//! it's always possible to get a [Workspace] reference using [Client::get_workspace]
|
|
|
|
//!
|
2023-08-20 09:13:21 +02:00
|
|
|
//! ### sync
|
2024-02-09 01:04:24 +01:00
|
|
|
//! if async is not viable, a solution might be keeping a global tokio runtime and blocking on it:
|
2023-08-20 09:13:21 +02:00
|
|
|
//!
|
|
|
|
//! ```rust,no_run
|
|
|
|
//! # use std::sync::Arc;
|
2023-09-03 23:04:08 +02:00
|
|
|
//! # use codemp::api::Controller;
|
2023-08-20 09:13:21 +02:00
|
|
|
//! #
|
|
|
|
//! # fn sync_example() -> codemp::Result<()> {
|
2024-02-09 01:04:24 +01:00
|
|
|
//! let rt = tokio::runtime::Runtime::new().unwrap();
|
|
|
|
//! let mut session = rt.block_on( // using block_on allows calling async code
|
2024-02-09 01:16:16 +01:00
|
|
|
//! codemp::Client::new("http://alemi.dev:50051")
|
2024-02-09 01:04:24 +01:00
|
|
|
//! )?;
|
|
|
|
//!
|
|
|
|
//! rt.block_on(session.login(
|
|
|
|
//! "username".to_string(),
|
|
|
|
//! "password".to_string(),
|
|
|
|
//! Some("some_workspace".to_string())
|
|
|
|
//! ))?;
|
|
|
|
//!
|
|
|
|
//! let workspace = rt.block_on(session.join_workspace("some_workspace"))?;
|
2023-08-20 09:13:21 +02:00
|
|
|
//!
|
|
|
|
//! // attach to buffer and blockingly receive events
|
2024-02-09 01:04:24 +01:00
|
|
|
//! let buffer = rt.block_on(workspace.attach("test.txt"))?; // attach to buffer, must already exist
|
|
|
|
//! while let Ok(op) = rt.block_on(buffer.recv()) { // must pass runtime
|
2023-08-20 09:13:21 +02:00
|
|
|
//! println!("received buffer event: {:?}", op);
|
|
|
|
//! }
|
|
|
|
//! #
|
|
|
|
//! # Ok(())
|
|
|
|
//! # }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! ## references
|
2023-08-20 03:34:48 +02:00
|
|
|
//!
|
|
|
|
//! ![another cool pic coz why not](https://alemi.dev/img/about-slice-2.png)
|
|
|
|
//!
|
|
|
|
//! check [codemp-vscode](https://github.com/codewithotherpeopleandchangenamelater/codemp-vscode)
|
|
|
|
//! or [codemp-nvim](https://github.com/codewithotherpeopleandchangenamelater/codemp-nvim)
|
|
|
|
//! or [codemp-server](https://github.com/codewithotherpeopleandchangenamelater/codemp-server) for
|
2023-08-20 06:51:47 +02:00
|
|
|
//! reference implementations.
|
|
|
|
//!
|
|
|
|
//! keep track of feature completedness with the
|
|
|
|
//! [feature comparison matrix](https://github.com/orgs/codewithotherpeopleandchangenamelater/projects/3)
|
2023-08-20 03:34:48 +02:00
|
|
|
//!
|
2023-08-19 21:44:27 +02:00
|
|
|
|
2023-09-03 23:04:19 +02:00
|
|
|
#![doc(html_no_source)]
|
|
|
|
|
2023-09-03 23:04:08 +02:00
|
|
|
/// public traits exposed to clients
|
|
|
|
pub mod api;
|
|
|
|
|
2023-08-19 21:44:27 +02:00
|
|
|
/// cursor related types and controller
|
2023-04-17 14:56:00 +02:00
|
|
|
pub mod cursor;
|
2023-08-19 21:44:27 +02:00
|
|
|
|
|
|
|
/// buffer operations, factory, controller and types
|
2023-07-30 17:48:55 +02:00
|
|
|
pub mod buffer;
|
2023-08-19 21:44:27 +02:00
|
|
|
|
2024-01-25 03:25:45 +01:00
|
|
|
/// workspace operations
|
2024-01-25 02:13:45 +01:00
|
|
|
pub mod workspace;
|
2024-08-22 00:57:24 +02:00
|
|
|
pub use workspace::Workspace;
|
2024-01-25 02:13:45 +01:00
|
|
|
|
2024-08-22 00:57:24 +02:00
|
|
|
/// codemp client, wrapping all above
|
|
|
|
pub mod client;
|
|
|
|
pub use client::Client;
|
2024-08-10 16:13:16 +02:00
|
|
|
|
2024-08-22 00:57:24 +02:00
|
|
|
/// crate error types and helpers
|
|
|
|
pub mod errors;
|
2024-02-09 01:16:16 +01:00
|
|
|
|
2024-08-22 00:57:24 +02:00
|
|
|
/// all-in-one imports : `use codemp::prelude::*;`
|
|
|
|
pub mod prelude;
|
2024-08-14 17:12:36 +02:00
|
|
|
|
2024-08-22 00:57:24 +02:00
|
|
|
/// common utils used in this library and re-exposed
|
|
|
|
pub mod ext;
|
2024-08-14 17:12:36 +02:00
|
|
|
pub use ext::hash;
|
2024-08-22 00:57:24 +02:00
|
|
|
|
|
|
|
/// language-specific ffi "glue"
|
|
|
|
pub mod ffi;
|