mirror of
https://github.com/hexedtech/codemp.git
synced 2024-11-22 15:24:48 +01:00
feat(lua): type annotations
This commit is contained in:
parent
30f692e6e1
commit
e1da62f0c8
2 changed files with 321 additions and 5 deletions
316
dist/lua/annotations.lua
vendored
Normal file
316
dist/lua/annotations.lua
vendored
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
---@meta annotations
|
||||||
|
-- type annotations for codemp native lua library
|
||||||
|
|
||||||
|
-- [[ ASYNC STUFF ]]
|
||||||
|
|
||||||
|
-- TODO lua-language-server doesn't seem to support generic classes
|
||||||
|
-- https://github.com/LuaLS/lua-language-server/issues/1532
|
||||||
|
-- so we need to expand every possible promise type...
|
||||||
|
|
||||||
|
---@class Promise
|
||||||
|
---@field ready boolean true if promise completed
|
||||||
|
|
||||||
|
---@class NilPromise : Promise
|
||||||
|
---@field await fun(self: NilPromise): nil block until promise is ready
|
||||||
|
|
||||||
|
---@class StringArrayPromise : Promise
|
||||||
|
---@field await fun(self: StringArrayPromise): string[] block until promise is ready and return value
|
||||||
|
|
||||||
|
---@class ClientPromise : Promise
|
||||||
|
---@field await fun(self: ClientPromise): Client block until promise is ready and return value
|
||||||
|
|
||||||
|
---@class WorkspacePromise : Promise
|
||||||
|
---@field await fun(self: WorkspacePromise): Workspace block until promise is ready and return value
|
||||||
|
|
||||||
|
---@class WorkspaceEventPromise : Promise
|
||||||
|
---@field await fun(self: WorkspaceEventPromise): WorkspaceEvent block until promise is ready and return value
|
||||||
|
|
||||||
|
---@class BufferControllerPromise : Promise
|
||||||
|
---@field await fun(self: BufferControllerPromise): BufferController block until promise is ready and return value
|
||||||
|
|
||||||
|
---@class CursorPromise : Promise
|
||||||
|
---@field await fun(self: CursorPromise): Cursor block until promise is ready and return value
|
||||||
|
|
||||||
|
---@class MaybeCursorPromise : Promise
|
||||||
|
---@field await fun(self: MaybeCursorPromise): Cursor? block until promise is ready and return value
|
||||||
|
|
||||||
|
---@class TextChangePromise : Promise
|
||||||
|
---@field await fun(self: TextChangePromise): TextChange block until promise is ready and return value
|
||||||
|
|
||||||
|
---@class MaybeTextChangePromise : Promise
|
||||||
|
---@field await fun(self: MaybeTextChangePromise): TextChange? block until promise is ready and return value
|
||||||
|
|
||||||
|
-- [[ END ASYNC STUFF ]]
|
||||||
|
|
||||||
|
|
||||||
|
---@class Client
|
||||||
|
---@field id string uuid of local user
|
||||||
|
---@field username string name of local user
|
||||||
|
---@field active_workspaces string[] array of all currently active workspace names
|
||||||
|
---the effective local client, handling connecting to codemp server
|
||||||
|
local Client = {}
|
||||||
|
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---refresh current user token if possible
|
||||||
|
function Client:refresh() end
|
||||||
|
|
||||||
|
---@param ws string workspace id to connect to
|
||||||
|
---@return WorkspacePromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---join requested workspace if possible and subscribe to event bus
|
||||||
|
function Client:join_workspace(ws) end
|
||||||
|
|
||||||
|
---@param ws string workspace id to create
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---create a new workspace with given id
|
||||||
|
function Client:join_workspace(ws) end
|
||||||
|
|
||||||
|
---@param ws string workspace id to leave
|
||||||
|
---leave workspace with given id, detaching and disconnecting
|
||||||
|
function Client:leave_workspace(ws) end
|
||||||
|
|
||||||
|
---@param ws string workspace id to delete
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---delete workspace with given id
|
||||||
|
function Client:delete_workspace(ws) end
|
||||||
|
|
||||||
|
---@param ws string workspace id to delete
|
||||||
|
---@param user string user name to invite to given workspace
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---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
|
||||||
|
|
||||||
|
---@param ws string workspace id to get
|
||||||
|
---@return Workspace?
|
||||||
|
---get an active workspace by name
|
||||||
|
function Client:get_workspace(ws) end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---@class Workspace
|
||||||
|
---@field name string workspace name
|
||||||
|
---@field cursor CursorController workspace cursor controller
|
||||||
|
---@field active_buffers string[] array of all currently active buffer names
|
||||||
|
---a joined codemp workspace
|
||||||
|
local Workspace = {}
|
||||||
|
|
||||||
|
---@param path string relative path ("name") of new buffer
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---create a new empty buffer
|
||||||
|
function Workspace:create_buffer(path) end
|
||||||
|
|
||||||
|
---@param path string relative path ("name") of buffer to delete
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---delete buffer from workspace
|
||||||
|
function Workspace:delete_buffer(path) end
|
||||||
|
|
||||||
|
---@param path string relative path ("name") of buffer to get
|
||||||
|
---@return BufferController?
|
||||||
|
---get an active buffer controller by name
|
||||||
|
function Workspace:get_buffer(path) end
|
||||||
|
|
||||||
|
---@param path string relative path ("name") of buffer to attach to
|
||||||
|
---@return BufferControllerPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---attach to a remote buffer, synching content and changes and returning its controller
|
||||||
|
function Workspace:attach_buffer(path) end
|
||||||
|
|
||||||
|
---@param path string relative path ("name") of buffer to detach from
|
||||||
|
---@return boolean
|
||||||
|
---detach from an active buffer, closing all streams. returns false if buffer was no longer active
|
||||||
|
function Workspace:detach_buffer(path) end
|
||||||
|
|
||||||
|
---@param filter string only return elements starting with given filter
|
||||||
|
---@return string[]
|
||||||
|
---return the list of available buffers in this workspace, as relative paths from workspace root
|
||||||
|
function Workspace:filetree(filter) end
|
||||||
|
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---force refresh buffer list from workspace
|
||||||
|
function Workspace:fetch_buffers(path) end
|
||||||
|
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---force refresh users list from workspace
|
||||||
|
function Workspace:fetch_users(path) end
|
||||||
|
|
||||||
|
---@class WorkspaceEvent
|
||||||
|
---@field type string
|
||||||
|
---@field value string
|
||||||
|
|
||||||
|
---@return WorkspaceEventPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---get next workspace event
|
||||||
|
function Workspace:event() end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---@class BufferController
|
||||||
|
---handle to a remote buffer, for async send/recv operations
|
||||||
|
local BufferController = {}
|
||||||
|
|
||||||
|
---@class TextChange
|
||||||
|
---@field content string text content of change
|
||||||
|
---@field first integer start index of change
|
||||||
|
---@field last integer end index of change
|
||||||
|
---@field hash integer? optional hash of text buffer after this change, for sync checks
|
||||||
|
---@field apply fun(self: TextChange, other: string): string apply this text change to a string
|
||||||
|
|
||||||
|
---@param first integer change start index
|
||||||
|
---@param last integer change end index
|
||||||
|
---@param content string change content
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---update buffer with a text change; note that to delete content should be empty but not span, while to insert span should be empty but not content (can insert and delete at the same time)
|
||||||
|
function BufferController:send(first, last, content) end
|
||||||
|
|
||||||
|
|
||||||
|
---@return MaybeTextChangePromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---try to receive text changes, returning nil if none is available
|
||||||
|
function BufferController:try_recv() end
|
||||||
|
|
||||||
|
---@return TextChangePromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---block until next text change and return it
|
||||||
|
function BufferController:recv() end
|
||||||
|
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---block until next text change without returning it
|
||||||
|
function BufferController:poll() end
|
||||||
|
|
||||||
|
---@return boolean
|
||||||
|
---stop buffer worker and disconnect, returns false if was already stopped
|
||||||
|
function BufferController:stop() end
|
||||||
|
|
||||||
|
---clears any previously registered buffer callback
|
||||||
|
function BufferController:clear_callback() end
|
||||||
|
|
||||||
|
---@param cb fun(c: BufferController) callback to invoke on each text change from server
|
||||||
|
---register a new callback to be called on remote text changes (replaces any previously registered one)
|
||||||
|
function BufferController:callback(cb) end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---@class CursorController
|
||||||
|
---handle to a workspace's cursor channel, allowing send/recv operations
|
||||||
|
local CursorController = {}
|
||||||
|
|
||||||
|
---@class RowCol
|
||||||
|
---@field row integer row number
|
||||||
|
---@field col integer column number
|
||||||
|
---row and column tuple
|
||||||
|
|
||||||
|
---@class Cursor
|
||||||
|
---@field user string? id of user owning this cursor
|
||||||
|
---@field buffer string relative path ("name") of buffer on which this cursor is
|
||||||
|
---@field start RowCol cursor start position
|
||||||
|
---@field finish RowCol cursor end position
|
||||||
|
---a cursor position
|
||||||
|
|
||||||
|
---@param buffer string buffer relative path ("name") to send this cursor on
|
||||||
|
---@param start_row integer cursor start row
|
||||||
|
---@param start_col integer cursor start col
|
||||||
|
---@param end_row integer cursor end row
|
||||||
|
---@param end_col integer cursor end col
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---update cursor position by sending a cursor event to server
|
||||||
|
function CursorController:send(buffer, start_row, start_col, end_row, end_col) end
|
||||||
|
|
||||||
|
|
||||||
|
---@return MaybeCursorPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---try to receive cursor events, returning nil if none is available
|
||||||
|
function CursorController:try_recv() end
|
||||||
|
|
||||||
|
---@return CursorPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---block until next cursor event and return it
|
||||||
|
function CursorController:recv() end
|
||||||
|
|
||||||
|
---@return NilPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---block until next cursor event without returning it
|
||||||
|
function CursorController:poll() end
|
||||||
|
|
||||||
|
---@return boolean
|
||||||
|
---stop cursor worker and disconnect, returns false if was already stopped
|
||||||
|
function CursorController:stop() end
|
||||||
|
|
||||||
|
---clears any previously registered cursor callback
|
||||||
|
function CursorController:clear_callback() end
|
||||||
|
|
||||||
|
---@param cb fun(c: CursorController) callback to invoke on each cursor event from server
|
||||||
|
---register a new callback to be called on cursor events (replaces any previously registered one)
|
||||||
|
function CursorController:callback(cb) end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---@class Codemp
|
||||||
|
---the codemp shared library
|
||||||
|
local Codemp = {}
|
||||||
|
|
||||||
|
---@param host string server host to connect to
|
||||||
|
---@param username string username used to log in (usually email)
|
||||||
|
---@param password string password used to log in
|
||||||
|
---@return ClientPromise
|
||||||
|
---@async
|
||||||
|
---@nodiscard
|
||||||
|
---connect to codemp server, authenticate and return client
|
||||||
|
function Codemp.connect(host, username, password) end
|
||||||
|
|
||||||
|
---@param data string
|
||||||
|
---@return integer
|
||||||
|
---use xxh3 hash, returns an i64 from any string
|
||||||
|
function Codemp.hash(data) end
|
||||||
|
|
||||||
|
---@class RuntimeDriver
|
||||||
|
---@field stop fun(): boolean stops the runtime thread without deleting the runtime itself, returns false if driver was already stopped
|
||||||
|
|
||||||
|
---@return RuntimeDriver
|
||||||
|
---spawns a background thread and uses it to run the codemp runtime
|
||||||
|
function Codemp.spawn_runtime_driver() end
|
||||||
|
|
||||||
|
---@param printer string | fun(string) log sink used for printing, if string will go to file, otherwise use given function
|
||||||
|
---@param debug boolean? show more verbose debug logs, default false
|
||||||
|
---@return boolean true if logger was setup correctly, false otherwise
|
||||||
|
---setup a global logger for codemp, note that can only be done once
|
||||||
|
function Codemp.logger(printer, debug) end
|
|
@ -77,7 +77,7 @@ macro_rules! a_sync {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runtime_drive_forever(_: &Lua, ():()) -> LuaResult<Driver> {
|
fn spawn_runtime_driver(_: &Lua, ():()) -> LuaResult<Driver> {
|
||||||
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
|
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
|
||||||
std::thread::spawn(move || tokio().block_on(async move {
|
std::thread::spawn(move || tokio().block_on(async move {
|
||||||
tracing::info!(" :: driving runtime...");
|
tracing::info!(" :: driving runtime...");
|
||||||
|
@ -103,6 +103,7 @@ impl LuaUserData for CodempClient {
|
||||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("id", |_, this| Ok(this.user().id.to_string()));
|
fields.add_field_method_get("id", |_, this| Ok(this.user().id.to_string()));
|
||||||
fields.add_field_method_get("username", |_, this| Ok(this.user().name.clone()));
|
fields.add_field_method_get("username", |_, this| Ok(this.user().name.clone()));
|
||||||
|
fields.add_field_method_get("active_workspaces", |_, this| Ok(this.active_workspaces()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
@ -137,7 +138,6 @@ impl LuaUserData for CodempClient {
|
||||||
);
|
);
|
||||||
|
|
||||||
methods.add_method("get_workspace", |_, this, (ws,):(String,)| Ok(this.get_workspace(&ws)));
|
methods.add_method("get_workspace", |_, this, (ws,):(String,)| Ok(this.get_workspace(&ws)));
|
||||||
methods.add_method("active_workspaces", |_, this, ()| Ok(this.active_workspaces()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ impl LuaUserData for CodempWorkspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("id", |_, this| Ok(this.id()));
|
fields.add_field_method_get("name", |_, this| Ok(this.id()));
|
||||||
fields.add_field_method_get("cursor", |_, this| Ok(this.cursor()));
|
fields.add_field_method_get("cursor", |_, this| Ok(this.cursor()));
|
||||||
fields.add_field_method_get("active_buffers", |_, this| Ok(this.buffer_list()));
|
fields.add_field_method_get("active_buffers", |_, this| Ok(this.buffer_list()));
|
||||||
// fields.add_field_method_get("users", |_, this| Ok(this.0.users())); // TODO
|
// fields.add_field_method_get("users", |_, this| Ok(this.0.users())); // TODO
|
||||||
|
@ -334,7 +334,7 @@ impl LuaUserData for CodempTextChange {
|
||||||
|
|
||||||
// define module and exports
|
// define module and exports
|
||||||
#[mlua::lua_module]
|
#[mlua::lua_module]
|
||||||
fn codemp_lua(lua: &Lua) -> LuaResult<LuaTable> {
|
fn codemp_native(lua: &Lua) -> LuaResult<LuaTable> {
|
||||||
let exports = lua.create_table()?;
|
let exports = lua.create_table()?;
|
||||||
|
|
||||||
// entrypoint
|
// entrypoint
|
||||||
|
@ -348,7 +348,7 @@ fn codemp_lua(lua: &Lua) -> LuaResult<LuaTable> {
|
||||||
)?)?;
|
)?)?;
|
||||||
|
|
||||||
// runtime
|
// runtime
|
||||||
exports.set("runtime_drive_forever", lua.create_function(runtime_drive_forever)?)?;
|
exports.set("spawn_runtime_driver", lua.create_function(spawn_runtime_driver)?)?;
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
exports.set("logger", lua.create_function(logger)?)?;
|
exports.set("logger", lua.create_function(logger)?)?;
|
||||||
|
|
Loading…
Reference in a new issue