mirror of
https://github.com/hexedtech/codemp-nvim.git
synced 2024-11-22 15:34:53 +01:00
feat: lua impl for cursors, tweaks to bindings
This commit is contained in:
parent
480becf588
commit
23b4adafcb
3 changed files with 148 additions and 18 deletions
|
@ -7,7 +7,7 @@ edition = "2021"
|
|||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
codemp = { git = "ssh://git@github.com/codewithotherpeopleandchangenamelater/codemp.git", tag = "v0.4.2", features = ["global", "sync"] }
|
||||
mlua = { version = "0.9.0", features = ["send", "module", "luajit"] }
|
||||
codemp = { git = "ssh://git@github.com/codewithotherpeopleandchangenamelater/codemp.git", tag = "v0.4.4", features = ["global", "sync"] }
|
||||
mlua = { version = "0.9.0", features = ["module", "luajit"] }
|
||||
thiserror = "1.0.47"
|
||||
derive_more = "0.99.17"
|
||||
|
|
111
src/codemp.lua
Normal file
111
src/codemp.lua
Normal file
|
@ -0,0 +1,111 @@
|
|||
local codemp = require("libcodemp_nvim")
|
||||
|
||||
local function register_async_waker(target, cb)
|
||||
local async = vim.loop.new_async(cb)
|
||||
vim.loop.new_thread(function(_async, _target)
|
||||
local _codemp = require("libcodemp_nvim")
|
||||
local _cntrl
|
||||
if _target ~= nil then
|
||||
_cntrl = _codemp.get_buffer(_target)
|
||||
else
|
||||
_cntrl = _codemp.get_cursor()
|
||||
end
|
||||
while true do
|
||||
_cntrl:poll()
|
||||
_async:send()
|
||||
end
|
||||
end, async, target)
|
||||
end
|
||||
|
||||
local function order_tuples(x) -- TODO send help...
|
||||
if x[1][1] < x[2][1] then
|
||||
return { { x[1][1], x[1][2] }, { x[2][1], x[2][2] } }
|
||||
elseif x[1][1] > x[2][1] then
|
||||
return { { x[2][1], x[2][2] }, { x[1][1], x[1][2] } }
|
||||
elseif x[1][2] < x[2][2] then
|
||||
return { { x[1][1], x[1][2] }, { x[2][1], x[2][2] } }
|
||||
else
|
||||
return { { x[2][1], x[2][2] }, { x[1][1], x[1][2] } }
|
||||
end
|
||||
end
|
||||
|
||||
local function cursor_position()
|
||||
local mode = vim.api.nvim_get_mode().mode
|
||||
if mode == "v" or mode == "V" then
|
||||
local _, ls, cs = unpack(vim.fn.getpos('v'))
|
||||
local _, le, ce = unpack(vim.fn.getpos('.'))
|
||||
return order_tuples({ { ls-1, cs-1 }, { le-1, ce } })
|
||||
else
|
||||
local win = vim.api.nvim_get_current_win()
|
||||
local cur = vim.api.nvim_win_get_cursor(win)
|
||||
return order_tuples({ { cur[1]-1, cur[2] }, { cur[1]-1, cur[2]+1 } })
|
||||
end
|
||||
end
|
||||
|
||||
local function multiline_highlight(buf, ns, group, start, fini)
|
||||
for i=start[1],fini[1] do
|
||||
if i == start[1] and i == fini[1] then
|
||||
vim.api.nvim_buf_add_highlight(buf, ns, group, i, start[2], fini[2])
|
||||
elseif i == start[1] then
|
||||
vim.api.nvim_buf_add_highlight(buf, ns, group, i, start[2], -1)
|
||||
elseif i == fini[1] then
|
||||
vim.api.nvim_buf_add_highlight(buf, ns, group, i, 0, fini[2])
|
||||
else
|
||||
vim.api.nvim_buf_add_highlight(buf, ns, group, i, 0, -1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_create_user_command(
|
||||
"Connect",
|
||||
function (args)
|
||||
codemp.connect(#args.args > 0 and args.args or nil)
|
||||
print(" ++ connected")
|
||||
end,
|
||||
{ nargs = "?" }
|
||||
)
|
||||
|
||||
vim.api.nvim_create_user_command(
|
||||
"Join",
|
||||
function (args)
|
||||
local controller = codemp.join(args.args)
|
||||
|
||||
-- hook serverbound callbacks
|
||||
local group = vim.api.nvim_create_augroup("codemp-workspace", { clear = true })
|
||||
vim.api.nvim_create_autocmd({"CursorMoved", "CursorMovedI"}, {
|
||||
group = group,
|
||||
callback = function (_)
|
||||
local cur = cursor_position()
|
||||
controller:send("", cur[1][1], cur[1][2], cur[2][1], cur[2][2])
|
||||
end
|
||||
})
|
||||
|
||||
-- hook clientbound callbacks
|
||||
local ns = vim.api.nvim_create_namespace("codemp-cursors")
|
||||
local buffer = vim.api.nvim_get_current_buf()
|
||||
register_async_waker(nil, function()
|
||||
while true do
|
||||
local event = controller:recv()
|
||||
if event == nil then break end
|
||||
vim.schedule(function()
|
||||
vim.api.nvim_buf_clear_namespace(buffer, ns, 0, -1)
|
||||
multiline_highlight(buffer, ns, "ErrorMsg", event.start, event.finish)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
print(" ++ joined workspace " .. args.args)
|
||||
end,
|
||||
{ nargs = 1 }
|
||||
)
|
||||
|
||||
vim.api.nvim_create_user_command(
|
||||
"Attach",
|
||||
function (args)
|
||||
codemp.connect(#args.args > 0 and args.args or nil)
|
||||
print(" ++ connected")
|
||||
end,
|
||||
{ nargs = 1 }
|
||||
)
|
||||
|
||||
return codemp
|
51
src/lib.rs
51
src/lib.rs
|
@ -16,11 +16,11 @@ impl From::<LuaCodempError> for LuaError {
|
|||
fn cursor_to_table(lua: &Lua, cur: CodempCursorEvent) -> LuaResult<LuaTable> {
|
||||
let pos = cur.position.unwrap_or_default();
|
||||
let start = lua.create_table()?;
|
||||
start.set(0, pos.start().row)?;
|
||||
start.set(1, pos.start().col)?;
|
||||
start.set(1, pos.start().row)?;
|
||||
start.set(2, pos.start().col)?;
|
||||
let end = lua.create_table()?;
|
||||
end.set(0, pos.end().row)?;
|
||||
end.set(1, pos.end().col)?;
|
||||
end.set(1, pos.end().row)?;
|
||||
end.set(2, pos.end().col)?;
|
||||
let out = lua.create_table()?;
|
||||
out.set("user", cur.user)?;
|
||||
out.set("buffer", pos.buffer)?;
|
||||
|
@ -51,7 +51,13 @@ fn connect(_: &Lua, (host,): (Option<String>,)) -> LuaResult<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
fn get_cursor(_: &Lua, _args: ()) -> LuaResult<LuaCursorController> {
|
||||
Ok(
|
||||
CODEMP_INSTANCE.get_cursor()
|
||||
.map_err(LuaCodempError::from)?
|
||||
.into()
|
||||
)
|
||||
}
|
||||
|
||||
/// join a remote workspace and start processing cursor events
|
||||
fn join(_: &Lua, (session,): (String,)) -> LuaResult<LuaCursorController> {
|
||||
|
@ -60,17 +66,24 @@ fn join(_: &Lua, (session,): (String,)) -> LuaResult<LuaCursorController> {
|
|||
Ok(LuaCursorController(controller))
|
||||
}
|
||||
|
||||
#[derive(derive_more::From)]
|
||||
#[derive(Debug, derive_more::From)]
|
||||
struct LuaCursorController(Arc<CodempCursorController>);
|
||||
impl LuaUserData for LuaCursorController {
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_method_mut("send", |_, this, (usr, sr, sc, er, ec):(String, i32, i32, i32, i32)| {
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(format!("{:?}", this)));
|
||||
methods.add_method("send", |_, this, (usr, sr, sc, er, ec):(String, i32, i32, i32, i32)| {
|
||||
Ok(this.0.send(make_cursor(usr, sr, sc, er, ec)).map_err(LuaCodempError::from)?)
|
||||
});
|
||||
methods.add_method_mut("recv", |lua, this, ()| {
|
||||
let event = this.0.blocking_recv(CODEMP_INSTANCE.rt())
|
||||
methods.add_method("recv", |lua, this, ()| {
|
||||
match this.0.try_recv() .map_err(LuaCodempError::from)? {
|
||||
Some(x) => Ok(Some(cursor_to_table(lua, x)?)),
|
||||
None => Ok(None),
|
||||
}
|
||||
});
|
||||
methods.add_method("poll", |_, this, ()| {
|
||||
CODEMP_INSTANCE.rt().block_on(this.0.poll())
|
||||
.map_err(LuaCodempError::from)?;
|
||||
cursor_to_table(lua, event)
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -132,26 +145,27 @@ fn attach(_: &Lua, (path,): (String,)) -> LuaResult<LuaBufferController> {
|
|||
Ok(LuaBufferController(controller))
|
||||
}
|
||||
|
||||
#[derive(derive_more::From)]
|
||||
#[derive(Debug, derive_more::From)]
|
||||
struct LuaBufferController(Arc<CodempBufferController>);
|
||||
impl LuaUserData for LuaBufferController {
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_method_mut("delta", |_, this, (start, txt, end):(usize, String, usize)| {
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(format!("{:?}", this)));
|
||||
methods.add_method("delta", |_, this, (start, txt, end):(usize, String, usize)| {
|
||||
match this.0.delta(start, &txt, end) {
|
||||
Some(op) => Ok(this.0.send(op).map_err(LuaCodempError::from)?),
|
||||
None => Ok(()),
|
||||
}
|
||||
});
|
||||
methods.add_method_mut("replace", |_, this, txt:String| {
|
||||
methods.add_method("replace", |_, this, txt:String| {
|
||||
match this.0.replace(&txt) {
|
||||
Some(op) => Ok(this.0.send(op).map_err(LuaCodempError::from)?),
|
||||
None => Ok(()),
|
||||
}
|
||||
});
|
||||
methods.add_method_mut("insert", |_, this, (txt, pos):(String, u64)| {
|
||||
methods.add_method("insert", |_, this, (txt, pos):(String, u64)| {
|
||||
Ok(this.0.send(this.0.insert(&txt, pos)).map_err(LuaCodempError::from)?)
|
||||
});
|
||||
methods.add_method_mut("recv", |_, this, ()| {
|
||||
methods.add_method("recv", |_, this, ()| {
|
||||
let change = this.0.blocking_recv(CODEMP_INSTANCE.rt())
|
||||
.map_err(LuaCodempError::from)?;
|
||||
Ok(LuaTextChange(change))
|
||||
|
@ -163,7 +177,7 @@ impl LuaUserData for LuaBufferController {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(derive_more::From)]
|
||||
#[derive(Debug, derive_more::From)]
|
||||
struct LuaTextChange(CodempTextChange);
|
||||
impl LuaUserData for LuaTextChange {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
|
@ -171,6 +185,10 @@ impl LuaUserData for LuaTextChange {
|
|||
fields.add_field_method_get("start", |_, this| Ok(this.0.span.start));
|
||||
fields.add_field_method_get("finish", |_, this| Ok(this.0.span.end));
|
||||
}
|
||||
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(format!("{:?}", this)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -182,5 +200,6 @@ fn libcodemp_nvim(lua: &Lua) -> LuaResult<LuaTable> {
|
|||
exports.set("join", lua.create_function(join)?)?;
|
||||
exports.set("create", lua.create_function(create)?)?;
|
||||
exports.set("attach", lua.create_function(attach)?)?;
|
||||
exports.set("get_cursor", lua.create_function(get_cursor)?)?;
|
||||
Ok(exports)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue