1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! # Code MultiPlexer - cooperative development
//!
//! `codemp` is an async client library to create cooperation tools for any text editor.
//!
//! It is built as a batteries-included client library managing an authenticated user, multiple
//! workspaces each containing any number of buffers.
//!
//! The [`Client`] is completely managed by the library itself, making its use simple across async
//! contexts and FFI boundaries. All memory is managed by the library itself, which gives out always
//! atomic reference-counted pointers to internally mutable objects. Asynchronous actions are
//! abstracted away by the [`api::Controller`], providing an unopinionated approach with both
//! callback-based and blocking-based APIs.
//!
//! The library also provides ready-to-use bindings in a growing number of other programming languages,
//! to support a potentially infinite number of editors.
//!
//! # Overview
//! The main entrypoint is [`Client::connect`], which establishes an authenticated connection with
//! a supported remote server and returns a [`Client`] handle to interact with it.
//!
//! ```no_run
//! # async {
//! let client = codemp::Client::connect(
//! codemp::api::Config::new(
//! "mail@example.net",
//! "dont-use-this-password"
//! )
//! )
//! .await
//! .expect("failed to connect!");
//! # };
//! ```
//!
//! A [`Client`] can acquire a [`Workspace`] handle by joining an existing one it can access with
//! [`Client::attach_workspace`] or create a new one with [`Client::create_workspace`].
//!
//! ```no_run
//! # async {
//! # let client = codemp::Client::connect(codemp::api::Config::new("", "")).await.unwrap();
//! client.create_workspace("my-workspace").await.expect("failed to create workspace!");
//! let workspace = client.attach_workspace("my-workspace").await.expect("failed to attach!");
//! # };
//! ```
//!
//! A [`Workspace`] handle can be used to acquire a [`cursor::Controller`] to track remote [`api::Cursor`]s
//! and one or more [`buffer::Controller`] to send and receive [`api::TextChange`]s.
//!
//! ```no_run
//! # async {
//! # let client = codemp::Client::connect(codemp::api::Config::new("", "")).await.unwrap();
//! # client.create_workspace("").await.unwrap();
//! # let workspace = client.attach_workspace("").await.unwrap();
//! use codemp::api::controller::{AsyncSender, AsyncReceiver}; // needed to access trait methods
//! let cursor = workspace.cursor();
//! let event = cursor.recv().await.expect("disconnected while waiting for event!");
//! println!("user {} moved on buffer {}", event.user, event.sel.buffer);
//! # };
//! ```
//!
//! Internally, [`buffer::Controller`]s store the buffer state as a [diamond_types] CRDT, guaranteeing
//! eventual consistency. Each [`api::TextChange`] is translated in a network counterpart that is
//! guaranteed to converge.
//!
//! ```no_run
//! # async {
//! # let client = codemp::Client::connect(codemp::api::Config::new("", "")).await.unwrap();
//! # client.create_workspace("").await.unwrap();
//! # let workspace = client.attach_workspace("").await.unwrap();
//! # use codemp::api::controller::{AsyncSender, AsyncReceiver};
//! let buffer = workspace.attach_buffer("/some/file.txt").await.expect("failed to attach");
//! buffer.content(); // force-sync
//! if let Some(mut update) = buffer.try_recv().await.unwrap() {
//! println!(
//! "content: {}, span: {}-{}",
//! update.change.content, update.change.start_idx, update.change.end_idx
//! );
//! buffer.ack(update.version);
//! } // if None, no changes are currently available
//! # };
//! ```
//!
//! ## FFI
//! As mentioned, we provide bindings in various programming languages. To obtain them, you can
//! compile with the appropriate feature flag. Currently, the following are supported:
//! * `lua`
//! * `javascript`
//! * `java` (requires additional build steps to be usable)
//! * `python`
//!
//! For some of these, ready-to-use packages are available in various registries:
//! * [npm (javascript)](https://www.npmjs.com/package/codemp)
//! * [PyPI (python)](https://pypi.org/project/codemp)
//! * [Maven Central (java)](https://central.sonatype.com/artifact/mp.code/codemp)
//! * [LuaRocks (lua)](https://luarocks.org/modules/alemi/codemp)
//!
/// core structs and traits
/// cursor related types and controller
/// buffer related types and controller
/// workspace handle and operations
pub use Workspace;
/// client handle, containing all of the above
pub use Client;
/// crate error types
/// all-in-one imports : `use codemp::prelude::*;`
/// common utils used in this library and re-exposed
/// language-specific ffi "glue"
/// internal network services and interceptors
pub
/// Get the current version of the client