mirror of
https://github.com/hexedtech/codemp.git
synced 2024-12-22 12:54:54 +01:00
chore: split list_workspaces, renamed filetree, refactored fetch_users and fetch_buffers
Co-authored-by: alemi <me@alemi.dev>
This commit is contained in:
parent
6f04c38779
commit
e5fd0ca76a
21 changed files with 239 additions and 183 deletions
21
dist/java/src/mp/code/Client.java
vendored
21
dist/java/src/mp/code/Client.java
vendored
|
@ -91,17 +91,26 @@ public final class Client {
|
|||
invite_to_workspace(this.ptr, workspaceId, user);
|
||||
}
|
||||
|
||||
private static native String[] list_workspaces(long self, boolean owned, boolean invited) throws ConnectionRemoteException;
|
||||
private static native String[] fetch_owned_workspaces(long self) throws ConnectionRemoteException;
|
||||
|
||||
/**
|
||||
* Lists available workspaces according to certain filters.
|
||||
* @param owned if owned workspaces should be included
|
||||
* @param invited if workspaces the user is invited to should be included
|
||||
* Lists workspaces owned by the current user.
|
||||
* @return an array of workspace IDs
|
||||
* @throws ConnectionRemoteException if an error occurs in communicating with the server
|
||||
*/
|
||||
public String[] listWorkspaces(boolean owned, boolean invited) throws ConnectionRemoteException {
|
||||
return list_workspaces(this.ptr, owned, invited);
|
||||
public String[] fetchOwnedWorkspaces() throws ConnectionRemoteException {
|
||||
return fetch_owned_workspaces(this.ptr);
|
||||
}
|
||||
|
||||
private static native String[] fetch_joined_workspaces(long self) throws ConnectionRemoteException;
|
||||
|
||||
/**
|
||||
* Lists workspaces the current user has joined.
|
||||
* @return an array of workspace IDs
|
||||
* @throws ConnectionRemoteException if an error occurs in communicating with the server
|
||||
*/
|
||||
public String[] fetchJoinedWorkspaces() throws ConnectionRemoteException {
|
||||
return fetch_joined_workspaces(this.ptr);
|
||||
}
|
||||
|
||||
private static native String[] active_workspaces(long self);
|
||||
|
|
41
dist/java/src/mp/code/Workspace.java
vendored
41
dist/java/src/mp/code/Workspace.java
vendored
|
@ -1,10 +1,10 @@
|
|||
package mp.code;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import lombok.Getter;
|
||||
import mp.code.data.User;
|
||||
import mp.code.exceptions.ConnectionException;
|
||||
import mp.code.exceptions.ConnectionRemoteException;
|
||||
import mp.code.exceptions.ControllerException;
|
||||
|
@ -57,17 +57,16 @@ public final class Workspace {
|
|||
return Optional.ofNullable(get_buffer(this.ptr, path));
|
||||
}
|
||||
|
||||
private static native String[] filetree(long self, String filter, boolean strict);
|
||||
private static native String[] search_buffers(long self, String filter);
|
||||
|
||||
/**
|
||||
* Gets the file tree for this workspace, optionally filtering it.
|
||||
* @param filter applies an optional filter to the outputs
|
||||
* @param strict whether it should be a strict match (equals) or not (startsWith)
|
||||
* Searches for buffers matching the filter in this workspace.
|
||||
* @param filter the filter to apply
|
||||
* @return an array containing file tree as flat paths
|
||||
*/
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
public String[] filetree(Optional<String> filter, boolean strict) {
|
||||
return filetree(this.ptr, filter.orElse(null), strict);
|
||||
public String[] searchBuffers(Optional<String> filter) {
|
||||
return search_buffers(this.ptr, filter.orElse(null));
|
||||
}
|
||||
|
||||
private static native String[] active_buffers(long self);
|
||||
|
@ -125,37 +124,39 @@ public final class Workspace {
|
|||
return detach_buffer(this.ptr, path);
|
||||
}
|
||||
|
||||
private static native void fetch_buffers(long self) throws ConnectionRemoteException;
|
||||
private static native String[] fetch_buffers(long self) throws ConnectionRemoteException;
|
||||
|
||||
/**
|
||||
* Updates the local list of buffers.
|
||||
* Updates and fetches the local list of buffers.
|
||||
* @return the updated list
|
||||
* @throws ConnectionRemoteException if an error occurs in communicating with the server
|
||||
*/
|
||||
public void fetchBuffers() throws ConnectionRemoteException {
|
||||
fetch_buffers(this.ptr);
|
||||
public String[] fetchBuffers() throws ConnectionRemoteException {
|
||||
return fetch_buffers(this.ptr);
|
||||
}
|
||||
|
||||
private static native void fetch_users(long self) throws ConnectionRemoteException;
|
||||
private static native User[] fetch_users(long self) throws ConnectionRemoteException;
|
||||
|
||||
/**
|
||||
* Updates the local list of users.
|
||||
* Updates and fetches the local list of users.
|
||||
* @return the updated list
|
||||
* @throws ConnectionRemoteException if an error occurs in communicating with the server
|
||||
*/
|
||||
public void fetchUsers() throws ConnectionRemoteException {
|
||||
fetch_buffers(this.ptr);
|
||||
public User[] fetchUsers() throws ConnectionRemoteException {
|
||||
return fetch_users(this.ptr);
|
||||
}
|
||||
|
||||
private static native UUID[] list_buffer_users(long self, String path) throws ConnectionRemoteException;
|
||||
private static native User[] fetch_buffer_users(long self, String path) throws ConnectionRemoteException;
|
||||
|
||||
/**
|
||||
* Lists the user attached to a certain buffer.
|
||||
* Fetches the users attached to a certain buffer.
|
||||
* The user must be attached to the buffer to perform this operation.
|
||||
* @param path the path of the buffer to search
|
||||
* @return an array of user {@link UUID UUIDs}
|
||||
* @return an array of {@link User}s
|
||||
* @throws ConnectionRemoteException if an error occurs in communicating with the server, or the user wasn't attached
|
||||
*/
|
||||
public UUID[] listBufferUsers(String path) throws ConnectionRemoteException {
|
||||
return list_buffer_users(this.ptr, path);
|
||||
public User[] fetchBufferUsers(String path) throws ConnectionRemoteException {
|
||||
return fetch_buffer_users(this.ptr, path);
|
||||
}
|
||||
|
||||
private static native void delete_buffer(long self, String path) throws ConnectionRemoteException;
|
||||
|
|
33
dist/lua/annotations.lua
vendored
33
dist/lua/annotations.lua
vendored
|
@ -158,6 +158,17 @@ function MaybeBufferUpdatePromise:cancel() end
|
|||
---invoke callback asynchronously as soon as promise is ready
|
||||
function MaybeBufferUpdatePromise:and_then(cb) end
|
||||
|
||||
---@class (exact) UserListPromise : Promise
|
||||
local UserListPromise = {}
|
||||
--- block until promise is ready and return value
|
||||
--- @return User[]
|
||||
function UserListPromise:await() end
|
||||
--- cancel promise execution
|
||||
function UserListPromise:cancel() end
|
||||
---@param cb fun(x: User[]) callback to invoke
|
||||
---invoke callback asynchronously as soon as promise is ready
|
||||
function UserListPromise:and_then(cb) end
|
||||
|
||||
-- [[ END ASYNC STUFF ]]
|
||||
|
||||
|
||||
|
@ -212,13 +223,17 @@ function Client:delete_workspace(ws) end
|
|||
---grant user acccess to workspace
|
||||
function Client:invite_to_workspace(ws, user) end
|
||||
|
||||
---@param owned boolean? list owned workspaces, default true
|
||||
---@param invited boolean? list invited workspaces, default true
|
||||
---@return StringArrayPromise
|
||||
---@async
|
||||
---@nodiscard
|
||||
---grant user acccess to workspace
|
||||
function Client:list_workspaces(owned, invited) end
|
||||
---fetch and list owned workspaces
|
||||
function Client:fetch_owned_workspaces() end
|
||||
|
||||
---@return StringArrayPromise
|
||||
---@async
|
||||
---@nodiscard
|
||||
---fetch and list joined workspaces
|
||||
function Client:fetch_joined_workspaces() end
|
||||
|
||||
---@param ws string workspace id to get
|
||||
---@return Workspace?
|
||||
|
@ -281,10 +296,9 @@ function Workspace:attach_buffer(path) end
|
|||
function Workspace:detach_buffer(path) end
|
||||
|
||||
---@param filter? string apply a filter to the return elements
|
||||
---@param strict? boolean whether to strictly match or just check whether it starts with it
|
||||
---@return string[]
|
||||
---return the list of available buffers in this workspace, as relative paths from workspace root
|
||||
function Workspace:filetree(filter, strict) end
|
||||
function Workspace:search_buffers(filter) end
|
||||
|
||||
---@return User[]
|
||||
---return all names of users currently in this workspace
|
||||
|
@ -302,6 +316,13 @@ function Workspace:fetch_buffers(path) end
|
|||
---force refresh users list from workspace
|
||||
function Workspace:fetch_users(path) end
|
||||
|
||||
---@param path string the buffer to look in
|
||||
---@return UserListPromise
|
||||
---@async
|
||||
---@nodiscard
|
||||
---fetch the list of users in the given buffer
|
||||
function Workspace:fetch_buffer_users(path) end
|
||||
|
||||
---@class (exact) WorkspaceEvent
|
||||
---@field type string
|
||||
---@field value string
|
||||
|
|
11
dist/py/src/codemp/codemp.pyi
vendored
11
dist/py/src/codemp/codemp.pyi
vendored
|
@ -51,7 +51,8 @@ class Client:
|
|||
def create_workspace(self, workspace: str) -> Promise[None]: ...
|
||||
def delete_workspace(self, workspace: str) -> Promise[None]: ...
|
||||
def invite_to_workspace(self, workspace: str, username: str) -> Promise[None]: ...
|
||||
def list_workspaces(self, owned: bool, invited: bool) -> Promise[list[str]]: ...
|
||||
def fetch_owned_workspaces(self) -> Promise[list[str]]: ...
|
||||
def fetch_joined_workspaces(self) -> Promise[list[str]]: ...
|
||||
def leave_workspace(self, workspace: str) -> bool: ...
|
||||
def get_workspace(self, id: str) -> Workspace: ...
|
||||
def active_workspaces(self) -> list[str]: ...
|
||||
|
@ -69,16 +70,16 @@ class Workspace:
|
|||
def create_buffer(self, path: str) -> Promise[None]: ...
|
||||
def attach_buffer(self, path: str) -> Promise[BufferController]: ...
|
||||
def detach_buffer(self, path: str) -> bool: ...
|
||||
def fetch_buffers(self) -> Promise[None]: ...
|
||||
def fetch_users(self) -> Promise[None]: ...
|
||||
def list_buffer_users(self, path: str) -> Promise[list[str]]: ...
|
||||
def fetch_buffers(self) -> Promise[list[str]]: ...
|
||||
def fetch_users(self) -> Promise[list[User]]: ...
|
||||
def fetch_buffer_users(self, path: str) -> Promise[list[User]]: ...
|
||||
def delete_buffer(self, path: str) -> Promise[None]: ...
|
||||
def id(self) -> str: ...
|
||||
def cursor(self) -> CursorController: ...
|
||||
def get_buffer(self, path: str) -> Optional[BufferController]: ...
|
||||
def user_list(self) -> list[User]: ...
|
||||
def active_buffers(self) -> list[str]: ...
|
||||
def filetree(self, filter: Optional[str], strict: bool) -> list[str]: ...
|
||||
def search_buffers(self, filter: Optional[str]) -> list[str]: ...
|
||||
def recv(self) -> Promise[Event]: ...
|
||||
def try_recv(self) -> Promise[Optional[Event]]: ...
|
||||
def poll(self) -> Promise[None]: ...
|
||||
|
|
|
@ -19,11 +19,9 @@ pub mod event;
|
|||
/// data structure for remote users
|
||||
pub mod user;
|
||||
|
||||
pub use change::BufferUpdate;
|
||||
pub use change::TextChange;
|
||||
pub use change::{BufferUpdate, TextChange};
|
||||
pub use config::Config;
|
||||
pub use controller::Controller;
|
||||
pub use cursor::Cursor;
|
||||
pub use cursor::Selection;
|
||||
pub use controller::{AsyncReceiver, AsyncSender, Controller};
|
||||
pub use cursor::{Cursor, Selection};
|
||||
pub use event::Event;
|
||||
pub use user::User;
|
||||
|
|
|
@ -170,8 +170,11 @@ impl BufferWorker {
|
|||
|
||||
// in case we have a "replace" span
|
||||
if change.is_delete() {
|
||||
self.branch
|
||||
.delete_without_content(&mut self.oplog, self.agent_id, clip_start..clip_end);
|
||||
self.branch.delete_without_content(
|
||||
&mut self.oplog,
|
||||
self.agent_id,
|
||||
clip_start..clip_end,
|
||||
);
|
||||
}
|
||||
|
||||
if change.is_insert() {
|
||||
|
@ -247,7 +250,9 @@ impl BufferWorker {
|
|||
{
|
||||
tracing::warn!(
|
||||
"Insert span ({}, {}) differs from effective content len ({})",
|
||||
dtop.start(), dtop.end(), dtop.content_as_str().unwrap_or_default().len()
|
||||
dtop.start(),
|
||||
dtop.end(),
|
||||
dtop.content_as_str().unwrap_or_default().len()
|
||||
);
|
||||
}
|
||||
crate::api::BufferUpdate {
|
||||
|
|
|
@ -130,9 +130,18 @@ impl Client {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// List all available workspaces, also filtering between those owned and those invited to.
|
||||
pub async fn list_workspaces(&self, owned: bool, invited: bool) -> RemoteResult<Vec<String>> {
|
||||
let mut workspaces = self
|
||||
/// Fetch the names of all workspaces owned by the current user.
|
||||
pub async fn fetch_owned_workspaces(&self) -> RemoteResult<Vec<String>> {
|
||||
self.fetch_workspaces(true).await
|
||||
}
|
||||
|
||||
/// Fetch the names of all workspaces the current user has joined.
|
||||
pub async fn fetch_joined_workspaces(&self) -> RemoteResult<Vec<String>> {
|
||||
self.fetch_workspaces(false).await
|
||||
}
|
||||
|
||||
async fn fetch_workspaces(&self, owned: bool) -> RemoteResult<Vec<String>> {
|
||||
let workspaces = self
|
||||
.0
|
||||
.session
|
||||
.clone()
|
||||
|
@ -140,20 +149,18 @@ impl Client {
|
|||
.await?
|
||||
.into_inner();
|
||||
|
||||
let mut out = Vec::new();
|
||||
|
||||
if owned {
|
||||
out.append(&mut workspaces.owned)
|
||||
Ok(workspaces.owned)
|
||||
} else {
|
||||
Ok(workspaces.invited)
|
||||
}
|
||||
if invited {
|
||||
out.append(&mut workspaces.invited)
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Join and return a [`Workspace`].
|
||||
pub async fn attach_workspace(&self, workspace: impl AsRef<str>) -> ConnectionResult<Workspace> {
|
||||
pub async fn attach_workspace(
|
||||
&self,
|
||||
workspace: impl AsRef<str>,
|
||||
) -> ConnectionResult<Workspace> {
|
||||
let token = self
|
||||
.0
|
||||
.session
|
||||
|
|
|
@ -2,10 +2,7 @@ use jni::{objects::JObject, JNIEnv};
|
|||
use jni_toolbox::jni;
|
||||
|
||||
use crate::{
|
||||
api::{
|
||||
controller::{AsyncReceiver, AsyncSender},
|
||||
BufferUpdate, TextChange,
|
||||
},
|
||||
api::{AsyncReceiver, AsyncSender, BufferUpdate, TextChange},
|
||||
errors::ControllerError,
|
||||
};
|
||||
|
||||
|
|
|
@ -46,14 +46,16 @@ fn invite_to_workspace(
|
|||
super::tokio().block_on(client.invite_to_workspace(workspace, user))
|
||||
}
|
||||
|
||||
/// List available workspaces.
|
||||
/// List owned workspaces.
|
||||
#[jni(package = "mp.code", class = "Client")]
|
||||
fn list_workspaces(
|
||||
client: &mut Client,
|
||||
owned: bool,
|
||||
invited: bool,
|
||||
) -> Result<Vec<String>, RemoteError> {
|
||||
super::tokio().block_on(client.list_workspaces(owned, invited))
|
||||
fn fetch_owned_workspaces(client: &mut Client) -> Result<Vec<String>, RemoteError> {
|
||||
super::tokio().block_on(client.fetch_owned_workspaces())
|
||||
}
|
||||
|
||||
/// List joined workspaces.
|
||||
#[jni(package = "mp.code", class = "Client")]
|
||||
fn fetch_joined_workspaces(client: &mut Client) -> Result<Vec<String>, RemoteError> {
|
||||
super::tokio().block_on(client.fetch_joined_workspaces())
|
||||
}
|
||||
|
||||
/// List available workspaces.
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
use crate::{
|
||||
api::{
|
||||
controller::{AsyncReceiver, AsyncSender},
|
||||
Cursor, Selection,
|
||||
},
|
||||
api::{AsyncReceiver, AsyncSender, Cursor, Selection},
|
||||
errors::ControllerError,
|
||||
};
|
||||
use jni::{objects::JObject, JNIEnv};
|
||||
|
|
|
@ -25,10 +25,10 @@ fn get_buffer(workspace: &mut Workspace, path: String) -> Option<crate::buffer::
|
|||
workspace.get_buffer(&path)
|
||||
}
|
||||
|
||||
/// Get the filetree.
|
||||
/// Searches for buffers matching the filter.
|
||||
#[jni(package = "mp.code", class = "Workspace")]
|
||||
fn filetree(workspace: &mut Workspace, filter: Option<String>, strict: bool) -> Vec<String> {
|
||||
workspace.filetree(filter.as_deref(), strict)
|
||||
fn search_buffers(workspace: &mut Workspace, filter: Option<String>) -> Vec<String> {
|
||||
workspace.search_buffers(filter.as_deref())
|
||||
}
|
||||
|
||||
/// Gets a list of the active buffers.
|
||||
|
@ -66,23 +66,23 @@ fn detach_buffer(workspace: &mut Workspace, path: String) -> bool {
|
|||
|
||||
/// Update the local buffer list.
|
||||
#[jni(package = "mp.code", class = "Workspace")]
|
||||
fn fetch_buffers(workspace: &mut Workspace) -> Result<(), RemoteError> {
|
||||
fn fetch_buffers(workspace: &mut Workspace) -> Result<Vec<String>, RemoteError> {
|
||||
super::tokio().block_on(workspace.fetch_buffers())
|
||||
}
|
||||
|
||||
/// Update the local user list.
|
||||
#[jni(package = "mp.code", class = "Workspace")]
|
||||
fn fetch_users(workspace: &mut Workspace) -> Result<(), RemoteError> {
|
||||
fn fetch_users(workspace: &mut Workspace) -> Result<Vec<User>, RemoteError> {
|
||||
super::tokio().block_on(workspace.fetch_users())
|
||||
}
|
||||
|
||||
/// List users attached to a buffer.
|
||||
/// Fetch users attached to a buffer.
|
||||
#[jni(package = "mp.code", class = "Workspace")]
|
||||
fn list_buffer_users(
|
||||
fn fetch_buffer_users(
|
||||
workspace: &mut Workspace,
|
||||
path: String,
|
||||
) -> Result<Vec<crate::api::User>, RemoteError> {
|
||||
super::tokio().block_on(workspace.list_buffer_users(&path))
|
||||
super::tokio().block_on(workspace.fetch_buffer_users(&path))
|
||||
}
|
||||
|
||||
/// Delete a buffer.
|
||||
|
|
|
@ -46,14 +46,16 @@ impl Client {
|
|||
Ok(self.delete_workspace(workspace).await?)
|
||||
}
|
||||
|
||||
#[napi(js_name = "listWorkspaces")]
|
||||
/// list available workspaces
|
||||
pub async fn js_list_workspaces(
|
||||
&self,
|
||||
owned: bool,
|
||||
invited: bool,
|
||||
) -> napi::Result<Vec<String>> {
|
||||
Ok(self.list_workspaces(owned, invited).await?)
|
||||
#[napi(js_name = "fetchOwnedWorkspaces")]
|
||||
/// fetch owned workspaces
|
||||
pub async fn js_fetch_owned_workspaces(&self) -> napi::Result<Vec<String>> {
|
||||
Ok(self.fetch_owned_workspaces().await?)
|
||||
}
|
||||
|
||||
#[napi(js_name = "fetchJoinedWorkspaces")]
|
||||
/// fetch joined workspaces
|
||||
pub async fn js_fetch_joined_workspaces(&self) -> napi::Result<Vec<String>> {
|
||||
Ok(self.fetch_joined_workspaces().await?)
|
||||
}
|
||||
|
||||
#[napi(js_name = "inviteToWorkspace")]
|
||||
|
|
|
@ -44,9 +44,9 @@ impl Workspace {
|
|||
}
|
||||
|
||||
/// List all available buffers in this workspace
|
||||
#[napi(js_name = "filetree")]
|
||||
pub fn js_filetree(&self, filter: Option<&str>, strict: bool) -> Vec<String> {
|
||||
self.filetree(filter, strict)
|
||||
#[napi(js_name = "search_buffers")]
|
||||
pub fn js_search_buffers(&self, filter: Option<&str>) -> Vec<String> {
|
||||
self.search_buffers(filter)
|
||||
}
|
||||
|
||||
/// List all user names currently in this workspace
|
||||
|
@ -121,7 +121,7 @@ impl Workspace {
|
|||
})?;
|
||||
self.callback(move |controller: Workspace| {
|
||||
tsfn.call(controller.clone(), ThreadsafeFunctionCallMode::Blocking); //check this with tracing also we could use Ok(event) to get the error
|
||||
// If it blocks the main thread too many time we have to change this
|
||||
// If it blocks the main thread too many time we have to change this
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
@ -137,23 +137,28 @@ impl Workspace {
|
|||
|
||||
/// Re-fetch remote buffer list
|
||||
#[napi(js_name = "fetchBuffers")]
|
||||
pub async fn js_fetch_buffers(&self) -> napi::Result<()> {
|
||||
pub async fn js_fetch_buffers(&self) -> napi::Result<Vec<String>> {
|
||||
Ok(self.fetch_buffers().await?)
|
||||
}
|
||||
/// Re-fetch the list of all users in the workspace.
|
||||
#[napi(js_name = "fetchUsers")]
|
||||
pub async fn js_fetch_users(&self) -> napi::Result<()> {
|
||||
Ok(self.fetch_users().await?)
|
||||
pub async fn js_fetch_users(&self) -> napi::Result<Vec<JsUser>> {
|
||||
Ok(self
|
||||
.fetch_users()
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(JsUser::from)
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// List users attached to a specific buffer
|
||||
#[napi(js_name = "listBufferUsers")]
|
||||
pub async fn js_list_buffer_users(
|
||||
#[napi(js_name = "fetchBufferUsers")]
|
||||
pub async fn js_fetch_buffer_users(
|
||||
&self,
|
||||
path: String,
|
||||
) -> napi::Result<Vec<crate::ffi::js::client::JsUser>> {
|
||||
Ok(self
|
||||
.list_buffer_users(&path)
|
||||
.fetch_buffer_users(&path)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(super::client::JsUser::from)
|
||||
|
|
|
@ -12,8 +12,12 @@ impl LuaUserData for CodempClient {
|
|||
Ok(format!("{:?}", this))
|
||||
});
|
||||
|
||||
methods.add_method("current_user", |_, this, ()| Ok(this.current_user().clone()));
|
||||
methods.add_method("active_workspaces", |_, this, ()| Ok(this.active_workspaces()));
|
||||
methods.add_method("current_user", |_, this, ()| {
|
||||
Ok(this.current_user().clone())
|
||||
});
|
||||
methods.add_method("active_workspaces", |_, this, ()| {
|
||||
Ok(this.active_workspaces())
|
||||
});
|
||||
|
||||
methods.add_method(
|
||||
"refresh",
|
||||
|
@ -39,8 +43,14 @@ impl LuaUserData for CodempClient {
|
|||
a_sync! { this => this.invite_to_workspace(ws, user).await? }
|
||||
);
|
||||
|
||||
methods.add_method("list_workspaces", |_, this, (owned,invited):(Option<bool>,Option<bool>)|
|
||||
a_sync! { this => this.list_workspaces(owned.unwrap_or(true), invited.unwrap_or(true)).await? }
|
||||
methods.add_method(
|
||||
"fetch_owned_workspaces",
|
||||
|_, this, ()| a_sync! { this => this.fetch_owned_workspaces().await? },
|
||||
);
|
||||
|
||||
methods.add_method(
|
||||
"fetch_joined_workspaces",
|
||||
|_, this, ()| a_sync! { this => this.fetch_joined_workspaces().await? },
|
||||
);
|
||||
|
||||
methods.add_method("leave_workspace", |_, this, (ws,): (String,)| {
|
||||
|
|
|
@ -101,6 +101,7 @@ macro_rules! callback_args {
|
|||
callback_args! {
|
||||
Str: String,
|
||||
VecStr: Vec<String>,
|
||||
VecUser: Vec<CodempUser>,
|
||||
Client: CodempClient,
|
||||
CursorController: CodempCursorController,
|
||||
BufferController: CodempBufferController,
|
||||
|
|
|
@ -43,12 +43,15 @@ impl LuaUserData for CodempWorkspace {
|
|||
|_, this, ()| a_sync! { this => this.fetch_users().await? },
|
||||
);
|
||||
|
||||
methods.add_method(
|
||||
"filetree",
|
||||
|_, this, (filter, strict): (Option<String>, Option<bool>)| {
|
||||
Ok(this.filetree(filter.as_deref(), strict.unwrap_or(false)))
|
||||
},
|
||||
);
|
||||
methods.add_method("search_buffers", |_, this, (filter,): (Option<String>,)| {
|
||||
Ok(this.search_buffers(filter.as_deref()))
|
||||
});
|
||||
|
||||
methods.add_method("fetch_buffer_users", |_, this, (path,): (String,)| {
|
||||
a_sync! {
|
||||
this => this.fetch_buffer_users(&path).await?
|
||||
}
|
||||
});
|
||||
|
||||
methods.add_method("id", |_, this, ()| Ok(this.id()));
|
||||
methods.add_method("cursor", |_, this, ()| Ok(this.cursor()));
|
||||
|
|
|
@ -5,26 +5,26 @@
|
|||
//! ```no_run
|
||||
//! # async {
|
||||
//! use codemp::api::controller::{AsyncReceiver, AsyncSender}; // needed for send/recv trait methods
|
||||
//!
|
||||
//!
|
||||
//! // connect first, api.code.mp is managed by hexed.technology
|
||||
//! let client = codemp::Client::connect(codemp::api::Config::new(
|
||||
//! "mail@example.net", "dont-use-this-password"
|
||||
//! )).await?;
|
||||
//!
|
||||
//!
|
||||
//! // create and join a workspace
|
||||
//! client.create_workspace("some-workspace").await?;
|
||||
//! let workspace = client.join_workspace("some-workspace").await?;
|
||||
//!
|
||||
//!
|
||||
//! // create a new buffer in this workspace and attach to it
|
||||
//! workspace.create("/my/file.txt").await?;
|
||||
//! let buffer = workspace.attach("/my/file.txt").await?;
|
||||
//!
|
||||
//!
|
||||
//! // write `hello!` at the beginning of this buffer
|
||||
//! buffer.send(codemp::api::TextChange {
|
||||
//! start: 0, end: 0,
|
||||
//! content: "hello!".to_string(),
|
||||
//! })?;
|
||||
//!
|
||||
//!
|
||||
//! // wait for cursor movements
|
||||
//! loop {
|
||||
//! let event = workspace.cursor().recv().await?;
|
||||
|
@ -42,26 +42,26 @@
|
|||
//!
|
||||
//! ```js
|
||||
//! import * as codemp from 'codemp';
|
||||
//!
|
||||
//!
|
||||
//! // connect first, api.code.mp is managed by hexed.technology
|
||||
//! let client = await codemp.connect({
|
||||
//! username: "mail@example.net", password: "dont-use-this-password"
|
||||
//! });
|
||||
//!
|
||||
//!
|
||||
//! // create and join a workspace
|
||||
//! await client.create_workspace("some-workspace");
|
||||
//! let workspace = await client.join_workspace("some-workspace");
|
||||
//!
|
||||
//!
|
||||
//! // create a new buffer in this workspace and attach to it
|
||||
//! await workspace.create("/my/file.txt");
|
||||
//! let buffer = await workspace.attach("/my/file.txt");
|
||||
//!
|
||||
//!
|
||||
//! // write `hello!` at the beginning of this buffer
|
||||
//! await buffer.send({
|
||||
//! start: 0, end: 0,
|
||||
//! content: "hello!",
|
||||
//! });
|
||||
//!
|
||||
//!
|
||||
//! // wait for cursor movements
|
||||
//! while (true) {
|
||||
//! let event = await workspace.cursor().recv();
|
||||
|
@ -78,26 +78,26 @@
|
|||
//!
|
||||
//! ```py
|
||||
//! 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()
|
||||
//!
|
||||
//!
|
||||
//! # create and join a workspace
|
||||
//! client.create_workspace("some-workspace").wait()
|
||||
//! workspace = client.join_workspace("some-workspace").wait()
|
||||
//!
|
||||
//!
|
||||
//! # create a new buffer in this workspace and attach to it
|
||||
//! workspace.create("/my/file.txt").wait()
|
||||
//! buffer = workspace.attach("/my/file.txt").wait()
|
||||
//!
|
||||
//!
|
||||
//! # write `hello!` at the beginning of this buffer
|
||||
//! buffer.send(
|
||||
//! 0, 0, "hello!"
|
||||
//! ).wait()
|
||||
//!
|
||||
//!
|
||||
//! # wait for cursor movements
|
||||
//! while true:
|
||||
//! event = workspace.cursor().recv().wait()
|
||||
|
@ -124,26 +124,26 @@
|
|||
//!
|
||||
//! ```lua
|
||||
//! CODEMP = require('codemp')
|
||||
//!
|
||||
//!
|
||||
//! -- connect first, api.code.mp is managed by hexed.technology
|
||||
//! local client = CODEMP.connect({
|
||||
//! username = "mail@example.net", password = "dont-use-this-password"
|
||||
//! }):await()
|
||||
//!
|
||||
//!
|
||||
//! -- create and join a workspace
|
||||
//! client:create_workspace("my-workspace"):await()
|
||||
//! local workspace = client:join_workspace("my-workspace"):await()
|
||||
//!
|
||||
//!
|
||||
//! -- create a new buffer in this workspace and attach to it
|
||||
//! workspace:create_buffer("/my/file.txt"):await()
|
||||
//! local buffer = workspace:attach_buffer("/my/file.txt"):await()
|
||||
//!
|
||||
//!
|
||||
//! -- write `hello!` at the beginning of this buffer
|
||||
//! buffer:send({
|
||||
//! start = 0, finish = 0,
|
||||
//! start = 0, finish = 0,
|
||||
//! content = "hello!"
|
||||
//! }):await()
|
||||
//!
|
||||
//!
|
||||
//! -- wait for cursor movements
|
||||
//! while true do
|
||||
//! local event = workspace.cursor:recv():await()
|
||||
|
@ -162,26 +162,26 @@
|
|||
//!
|
||||
//! ```java
|
||||
//! import mp.code.*;
|
||||
//!
|
||||
//!
|
||||
//! // connect first, api.code.mp is managed by hexed.technology
|
||||
//! Client client = Client.connect(
|
||||
//! new data.Config("mail@example.net", "dont-use-this-password")
|
||||
//! );
|
||||
//!
|
||||
//!
|
||||
//! // create and join a workspace
|
||||
//! client.createWorkspace("some-workspace");
|
||||
//! Workspace workspace = client.joinWorkspace("some-workspace");
|
||||
//!
|
||||
//!
|
||||
//! // create a new buffer in this workspace and attach to it
|
||||
//! workspace.createBuffer("/my/file.txt");
|
||||
//! BufferController buffer = workspace.attachToBuffer("/my/file.txt");
|
||||
//!
|
||||
//!
|
||||
//! // write `hello!` at the beginning of this buffer
|
||||
//! buffer.send(new data.TextChange(
|
||||
//! 0, 0, "hello!",
|
||||
//! java.util.OptionalLong.empty() // optional, used for error detection
|
||||
//! ));
|
||||
//!
|
||||
//!
|
||||
//! // wait for cursor movements
|
||||
//! while (true) {
|
||||
//! data.Cursor event = workspace.getCursor().recv();
|
||||
|
|
|
@ -55,16 +55,18 @@ impl Client {
|
|||
a_sync_allow_threads!(py, this.invite_to_workspace(workspace, user).await)
|
||||
}
|
||||
|
||||
#[pyo3(name = "list_workspaces")]
|
||||
fn pylist_workspaces(
|
||||
&self,
|
||||
py: Python<'_>,
|
||||
owned: bool,
|
||||
invited: bool,
|
||||
) -> PyResult<super::Promise> {
|
||||
tracing::info!("attempting to list workspaces");
|
||||
#[pyo3(name = "fetch_owned_workspaces")]
|
||||
fn pyfetch_owned_workspaces(&self, py: Python<'_>) -> PyResult<super::Promise> {
|
||||
tracing::info!("attempting to fetch owned workspaces");
|
||||
let this = self.clone();
|
||||
a_sync_allow_threads!(py, this.list_workspaces(owned, invited).await)
|
||||
a_sync_allow_threads!(py, this.fetch_owned_workspaces().await)
|
||||
}
|
||||
|
||||
#[pyo3(name = "fetch_joined_workspaces")]
|
||||
fn pyfetch_joined_workspaces(&self, py: Python<'_>) -> PyResult<super::Promise> {
|
||||
tracing::info!("attempting to fetch joined workspaces");
|
||||
let this = self.clone();
|
||||
a_sync_allow_threads!(py, this.fetch_joined_workspaces().await)
|
||||
}
|
||||
|
||||
#[pyo3(name = "leave_workspace")]
|
||||
|
|
|
@ -41,11 +41,11 @@ impl Workspace {
|
|||
a_sync_allow_threads!(py, this.fetch_users().await)
|
||||
}
|
||||
|
||||
#[pyo3(name = "list_buffer_users")]
|
||||
fn pylist_buffer_users(&self, py: Python, path: String) -> PyResult<Promise> {
|
||||
#[pyo3(name = "fetch_buffer_users")]
|
||||
fn pyfetch_buffer_users(&self, py: Python, path: String) -> PyResult<Promise> {
|
||||
// crate::Result<Vec<crate::api::User>>
|
||||
let this = self.clone();
|
||||
a_sync_allow_threads!(py, this.list_buffer_users(path.as_str()).await)
|
||||
a_sync_allow_threads!(py, this.fetch_buffer_users(path.as_str()).await)
|
||||
}
|
||||
|
||||
#[pyo3(name = "delete_buffer")]
|
||||
|
@ -74,10 +74,10 @@ impl Workspace {
|
|||
self.active_buffers()
|
||||
}
|
||||
|
||||
#[pyo3(name = "filetree")]
|
||||
#[pyo3(signature = (filter=None, strict=false))]
|
||||
fn pyfiletree(&self, filter: Option<&str>, strict: bool) -> Vec<String> {
|
||||
self.filetree(filter, strict)
|
||||
#[pyo3(name = "search_buffers")]
|
||||
#[pyo3(signature = (filter=None))]
|
||||
fn pysearch_buffers(&self, filter: Option<&str>) -> Vec<String> {
|
||||
self.search_buffers(filter)
|
||||
}
|
||||
|
||||
#[pyo3(name = "user_list")]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//! All-in-one renamed imports with `use codemp::prelude::*`.
|
||||
|
||||
pub use crate::api::{
|
||||
controller::AsyncReceiver as CodempAsyncReceiver, controller::AsyncSender as CodempAsyncSender,
|
||||
AsyncReceiver as CodempAsyncReceiver, AsyncSender as CodempAsyncSender,
|
||||
BufferUpdate as CodempBufferUpdate, Config as CodempConfig, Controller as CodempController,
|
||||
Cursor as CodempCursor, Event as CodempEvent, Selection as CodempSelection,
|
||||
TextChange as CodempTextChange, User as CodempUser,
|
||||
|
|
|
@ -26,7 +26,7 @@ use codemp_proto::{
|
|||
};
|
||||
|
||||
use dashmap::{DashMap, DashSet};
|
||||
use std::{collections::BTreeSet, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{mpsc, mpsc::error::TryRecvError};
|
||||
use tonic::Streaming;
|
||||
use uuid::Uuid;
|
||||
|
@ -201,45 +201,48 @@ impl Workspace {
|
|||
}
|
||||
|
||||
/// Re-fetch the list of available buffers in the workspace.
|
||||
pub async fn fetch_buffers(&self) -> RemoteResult<()> {
|
||||
pub async fn fetch_buffers(&self) -> RemoteResult<Vec<String>> {
|
||||
let mut workspace_client = self.0.services.ws();
|
||||
let buffers = workspace_client
|
||||
let resp = workspace_client
|
||||
.list_buffers(tonic::Request::new(Empty {}))
|
||||
.await?
|
||||
.into_inner()
|
||||
.buffers;
|
||||
.into_inner();
|
||||
|
||||
let mut out = Vec::new();
|
||||
|
||||
self.0.filetree.clear();
|
||||
for b in buffers {
|
||||
self.0.filetree.insert(b.path);
|
||||
for b in resp.buffers {
|
||||
self.0.filetree.insert(b.path.clone());
|
||||
out.push(b.path);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Re-fetch the list of all users in the workspace.
|
||||
pub async fn fetch_users(&self) -> RemoteResult<()> {
|
||||
pub async fn fetch_users(&self) -> RemoteResult<Vec<User>> {
|
||||
let mut workspace_client = self.0.services.ws();
|
||||
let users = BTreeSet::from_iter(
|
||||
workspace_client
|
||||
.list_users(tonic::Request::new(Empty {}))
|
||||
.await?
|
||||
.into_inner()
|
||||
.users
|
||||
.into_iter()
|
||||
.map(User::from),
|
||||
);
|
||||
let users = workspace_client
|
||||
.list_users(tonic::Request::new(Empty {}))
|
||||
.await?
|
||||
.into_inner()
|
||||
.users
|
||||
.into_iter()
|
||||
.map(User::from);
|
||||
|
||||
let mut result = Vec::new();
|
||||
|
||||
self.0.users.clear();
|
||||
for u in users {
|
||||
self.0.users.insert(u.id, u);
|
||||
self.0.users.insert(u.id, u.clone());
|
||||
result.push(u);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Get a list of the [User]s attached to a specific buffer.
|
||||
pub async fn list_buffer_users(&self, path: &str) -> RemoteResult<Vec<User>> {
|
||||
/// Fetch a list of the [User]s attached to a specific buffer.
|
||||
pub async fn fetch_buffer_users(&self, path: &str) -> RemoteResult<Vec<User>> {
|
||||
let mut workspace_client = self.0.services.ws();
|
||||
let buffer_users = workspace_client
|
||||
.list_buffer_users(tonic::Request::new(BufferNode {
|
||||
|
@ -311,20 +314,12 @@ impl Workspace {
|
|||
/// Get the filetree as it is currently cached.
|
||||
/// A filter may be applied, and it may be strict (equality check) or not (starts_with check).
|
||||
// #[cfg_attr(feature = "js", napi)] // https://github.com/napi-rs/napi-rs/issues/1120
|
||||
pub fn filetree(&self, filter: Option<&str>, strict: bool) -> Vec<String> {
|
||||
pub fn search_buffers(&self, filter: Option<&str>) -> Vec<String> {
|
||||
let mut tree = self
|
||||
.0
|
||||
.filetree
|
||||
.iter()
|
||||
.filter(|f| {
|
||||
filter.map_or(true, |flt| {
|
||||
if strict {
|
||||
f.as_str() == flt
|
||||
} else {
|
||||
f.starts_with(flt)
|
||||
}
|
||||
})
|
||||
})
|
||||
.filter(|f| filter.map_or(true, |flt| f.starts_with(flt)))
|
||||
.map(|f| f.clone())
|
||||
.collect::<Vec<String>>();
|
||||
tree.sort();
|
||||
|
|
Loading…
Reference in a new issue