mirror of
https://github.com/hexedtech/codemp-nvim.git
synced 2024-12-23 22:04:52 +01:00
feat: implemented callback api
it works well!!?! when it doesnt crash... but its also pretty clean maybe its our fault? could be worth investigating more lua ffi
This commit is contained in:
parent
36f997b42e
commit
3e9647ab39
4 changed files with 63 additions and 123 deletions
|
@ -1,54 +0,0 @@
|
|||
local state = require('codemp.state')
|
||||
|
||||
local function register_controller_handler(target, controller, handler, delay)
|
||||
local async = vim.loop.new_async(function()
|
||||
while true do
|
||||
local success, event = pcall(controller.try_recv, controller)
|
||||
if success then
|
||||
if event == nil then break end
|
||||
vim.schedule(function()
|
||||
local ok, res = pcall(handler, event)
|
||||
if not ok then
|
||||
print(" !! error running callback handler: " .. res)
|
||||
end
|
||||
end)
|
||||
else
|
||||
print("error receiving: " .. tostring(event))
|
||||
break
|
||||
end
|
||||
end
|
||||
end)
|
||||
-- TODO controller can't be passed to the uvloop new_thread: when sent to the new
|
||||
-- Lua runtime it "loses" its methods defined with mlua, making the userdata object
|
||||
-- completely useless. We can circumvent this by requiring codemp again in the new
|
||||
-- thread and requesting a new reference to the same controller from che global instance
|
||||
-- NOTE variables prefixed with underscore live in another Lua runtime
|
||||
vim.loop.new_thread({}, function(_async, _target, _delay, _ws, _id)
|
||||
local _codemp = require("codemp.loader").load() -- TODO maybe make a native.load() idk
|
||||
local _client = _codemp.get_client(_id)
|
||||
if _client == nil then error("cant find client " .. _id .. " from thread") end
|
||||
local _workspace = _client:get_workspace(_ws)
|
||||
if _workspace == nil then error("cant find workspace " .. _ws .. " from thread") end
|
||||
local _controller = _target ~= nil and _workspace:get_buffer(_target) or _workspace.cursor
|
||||
if _controller == nil then error("cant find controller " .. _target .. " from thread") end
|
||||
if _controller.poll == nil then error("controller has nil poll field???") end
|
||||
while true do
|
||||
local success, _ = pcall(_controller.poll, _controller)
|
||||
if success then
|
||||
_async:send()
|
||||
if _delay ~= nil then vim.loop.sleep(_delay) end
|
||||
else
|
||||
local my_name = "cursor"
|
||||
if _target ~= nil then
|
||||
my_name = "buffer(" .. _target .. ")"
|
||||
end
|
||||
print(" -- stopping " .. my_name .. " controller poller")
|
||||
break
|
||||
end
|
||||
end
|
||||
end, async, target, delay, state.workspace, state.client.id)
|
||||
end
|
||||
|
||||
return {
|
||||
handler = register_controller_handler,
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
local utils = require('codemp.utils')
|
||||
local async = require('codemp.async')
|
||||
local state = require('codemp.state')
|
||||
|
||||
local id_buffer_map = {}
|
||||
|
@ -63,21 +62,32 @@ local function attach(name, current, content)
|
|||
end,
|
||||
})
|
||||
|
||||
-- hook clientbound callbacks
|
||||
async.handler(name, controller, function(event)
|
||||
ticks[buffer] = vim.api.nvim_buf_get_changedtick(buffer)
|
||||
-- print(" ~~ applying change ~~ " .. event.first .. ".." .. event.last .. "::[" .. event.content .. "]")
|
||||
utils.buffer.set_content(buffer, event.content, event.first, event.last)
|
||||
if event.hash ~= nil then
|
||||
if utils.hash(utils.buffer.get_content(buffer)) ~= event.hash then
|
||||
-- OUT OF SYNC!
|
||||
-- TODO this may be destructive! we should probably prompt the user before doing this
|
||||
print(" /!\\ out of sync, resynching...")
|
||||
utils.buffer.set_content(buffer, controller:content())
|
||||
return
|
||||
local async = vim.loop.new_async(vim.schedule_wrap(function ()
|
||||
while true do
|
||||
local success, event = pcall(controller.try_recv, controller)
|
||||
if not success then
|
||||
print("error in buffer async handler: " .. tostring(event))
|
||||
break
|
||||
end
|
||||
if event == nil then break end
|
||||
ticks[buffer] = vim.api.nvim_buf_get_changedtick(buffer)
|
||||
-- print(" ~~ applying change ~~ " .. event.first .. ".." .. event.last .. "::[" .. event.content .. "]")
|
||||
utils.buffer.set_content(buffer, event.content, event.first, event.last)
|
||||
if event.hash ~= nil then
|
||||
if utils.hash(utils.buffer.get_content(buffer)) ~= event.hash then
|
||||
-- OUT OF SYNC!
|
||||
-- TODO this may be destructive! we should probably prompt the user before doing this
|
||||
print(" /!\\ out of sync, resynching...")
|
||||
utils.buffer.set_content(buffer, controller:content())
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end, 20) -- wait 20ms before polling again because it overwhelms libuv?
|
||||
end))
|
||||
controller:callback(function (_controller) async:send() end)
|
||||
vim.schedule(function ()
|
||||
async:send() -- run once to try_recv anything we synched in the meantime
|
||||
end)
|
||||
|
||||
print(" ++ attached to buffer " .. name)
|
||||
return controller
|
||||
|
|
19
src/init.lua
19
src/init.lua
|
@ -25,7 +25,10 @@ end
|
|||
|
||||
local native = require('codemp.loader').load() -- make sure we can load the native library correctly, otherwise no point going forward
|
||||
local state = require('codemp.state')
|
||||
native.runtime_drive_forever() -- spawn thread to drive tokio runtime
|
||||
local rt = native.runtime_drive_forever() -- spawn thread to drive tokio runtime
|
||||
-- native.logger(function (msg)
|
||||
-- vim.schedule(function () print(msg) end)
|
||||
-- end, true)
|
||||
|
||||
vim.api.nvim_create_autocmd(
|
||||
{"ExitPre"},
|
||||
|
@ -40,18 +43,6 @@ vim.api.nvim_create_autocmd(
|
|||
}
|
||||
)
|
||||
|
||||
-- TODO nvim docs say that we should stop all threads before exiting nvim
|
||||
-- but we like to live dangerously (:
|
||||
vim.loop.new_thread({}, function()
|
||||
vim.loop.sleep(1000) -- allow user to setup their own logger options
|
||||
local _codemp = require('codemp.loader').load()
|
||||
_codemp.setup_logger()
|
||||
local logger = _codemp.get_logger()
|
||||
while true do
|
||||
print(logger:recv())
|
||||
end
|
||||
end)
|
||||
|
||||
require('codemp.command')
|
||||
|
||||
return {
|
||||
|
@ -61,5 +52,5 @@ return {
|
|||
workspace = require('codemp.workspace'),
|
||||
window = require('codemp.window'),
|
||||
utils = require('codemp.utils'),
|
||||
async = require('codemp.async'),
|
||||
rt = rt,
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ local native = require('codemp.loader').load()
|
|||
|
||||
local utils = require('codemp.utils')
|
||||
local buffers = require('codemp.buffers')
|
||||
local async = require('codemp.async')
|
||||
local state = require('codemp.state')
|
||||
local window = require('codemp.window')
|
||||
|
||||
|
@ -33,51 +32,45 @@ local function register_cursor_callback(controller)
|
|||
end
|
||||
|
||||
local function register_cursor_handler(controller)
|
||||
async.handler(nil, controller, function(event)
|
||||
if user_hl[event.user] == nil then
|
||||
user_hl[event.user] = {
|
||||
ns = vim.api.nvim_create_namespace("codemp-cursor-" .. event.user),
|
||||
hi = available_colors[ math.random( #available_colors ) ],
|
||||
}
|
||||
local async = vim.loop.new_async(vim.schedule_wrap(function ()
|
||||
while true do
|
||||
local success, event = pcall(controller.try_recv, controller)
|
||||
if not success then
|
||||
print("error in cursor callback: " .. tostring(event))
|
||||
break
|
||||
end
|
||||
if event == nil then break end
|
||||
if user_hl[event.user] == nil then
|
||||
user_hl[event.user] = {
|
||||
ns = vim.api.nvim_create_namespace("codemp-cursor-" .. event.user),
|
||||
hi = available_colors[ math.random( #available_colors ) ],
|
||||
}
|
||||
end
|
||||
user_buffer[event.user] = event.buffer
|
||||
local buffer = buffers.map_rev[event.buffer]
|
||||
if buffer ~= nil then
|
||||
vim.api.nvim_buf_clear_namespace(buffer, user_hl[event.user].ns, 0, -1)
|
||||
utils.multiline_highlight(
|
||||
buffer,
|
||||
user_hl[event.user].ns,
|
||||
user_hl[event.user].hi,
|
||||
event.start,
|
||||
event.finish
|
||||
)
|
||||
end
|
||||
end
|
||||
user_buffer[event.user] = event.buffer
|
||||
local buffer = buffers.map_rev[event.buffer]
|
||||
if buffer ~= nil then
|
||||
vim.api.nvim_buf_clear_namespace(buffer, user_hl[event.user].ns, 0, -1)
|
||||
utils.multiline_highlight(
|
||||
buffer,
|
||||
user_hl[event.user].ns,
|
||||
user_hl[event.user].hi,
|
||||
event.start,
|
||||
event.finish
|
||||
)
|
||||
end
|
||||
end, 20)
|
||||
end))
|
||||
controller:callback(function (_controller) async:send() end)
|
||||
end
|
||||
|
||||
local function join(workspace)
|
||||
local controller = state.client:join_workspace(workspace)
|
||||
register_cursor_callback(controller)
|
||||
register_cursor_handler(controller)
|
||||
|
||||
-- TODO nvim docs say that we should stop all threads before exiting nvim
|
||||
-- but we like to live dangerously (:
|
||||
local refresher = vim.loop.new_async(function () vim.schedule(function() window.update() end) end)
|
||||
vim.loop.new_thread({}, function(_id, _ws, _refresher)
|
||||
local _codemp = require('codemp.loader').load()
|
||||
local _workspace = _codemp.get_client(_id):get_workspace(_ws)
|
||||
while true do
|
||||
local success, res = pcall(_workspace.event, _workspace)
|
||||
if success then
|
||||
print("workspace event!")
|
||||
_refresher:send()
|
||||
else
|
||||
print("error waiting for workspace event: " .. res)
|
||||
break
|
||||
end
|
||||
end
|
||||
end, state.client.id, state.workspace, refresher)
|
||||
local ws = state.client:join_workspace(workspace)
|
||||
register_cursor_callback(ws.cursor)
|
||||
register_cursor_handler(ws.cursor)
|
||||
|
||||
-- ws:callback(function (_ev)
|
||||
-- vim.schedule(function() window.update() end)
|
||||
-- end)
|
||||
window.update()
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue