diff --git a/lua/codemp/utils.lua b/lua/codemp/utils.lua index 85ab275..6e60b09 100644 --- a/lua/codemp/utils.lua +++ b/lua/codemp/utils.lua @@ -16,6 +16,19 @@ local function color(x) return available_colors[ math.fmod(math.abs(native.hash(x)), #available_colors) + 1 ] end +local function async_poller(generator, callback) + local promise = nil + local timer = vim.loop.new_timer() + timer:start(500, 500, function() + if promise == nil then promise = generator() end + if promise.ready then + callback(promise:await()) + promise = nil + end + end) + +end + ---@param first integer ---@param last integer ---@return integer, integer, integer, integer @@ -193,4 +206,5 @@ return { hash = native.hash, available_colors = available_colors, color = color, + poller = async_poller, } diff --git a/lua/codemp/workspace.lua b/lua/codemp/workspace.lua index b6a3913..2091b29 100644 --- a/lua/codemp/workspace.lua +++ b/lua/codemp/workspace.lua @@ -2,6 +2,12 @@ local utils = require('codemp.utils') local buffers = require('codemp.buffers') local session = require('codemp.session') +---@class UserHighlight +---@field ns integer namespace to use for this user +---@field hi string color for user to use +---@field pos [integer, integer] cursor start position of this user + +---@type table local user_hl = {} local function fetch_workspaces_list() @@ -50,32 +56,37 @@ local function register_cursor_handler(ws) while true do local event = controller:try_recv():await() 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 = utils.color(event.user), - } - end - local old_buffer = buffers.users[event.user] - if old_buffer ~= nil then - local old_buffer_id = buffers.map_rev[old_buffer] - if old_buffer_id ~= nil then - vim.api.nvim_buf_clear_namespace(old_buffer_id, user_hl[event.user].ns, 0, -1) + local user = event.user -- do it on separate line so language server understands that it wont be nil + if user ~= nil then + if user_hl[user] == nil then + user_hl[user] = { + ns = vim.api.nvim_create_namespace("codemp-cursor-" .. event.user), + hi = utils.color(event.user), + pos = { 0, 0 }, + } + end + user_hl[user].pos = event.start + local old_buffer = buffers.users[event.user] + if old_buffer ~= nil then + local old_buffer_id = buffers.map_rev[old_buffer] + if old_buffer_id ~= nil then + vim.api.nvim_buf_clear_namespace(old_buffer_id, user_hl[event.user].ns, 0, -1) + end + end + buffers.users[event.user] = event.buffer + local buffer_id = buffers.map_rev[event.buffer] + if buffer_id ~= nil then + utils.multiline_highlight( + buffer_id, + user_hl[event.user].ns, + user_hl[event.user].hi, + event.start, + event.finish + ) + end + if old_buffer ~= event.buffer then + require('codemp.window').update() -- redraw user positions end - end - buffers.users[event.user] = event.buffer - local buffer_id = buffers.map_rev[event.buffer] - if buffer_id ~= nil then - utils.multiline_highlight( - buffer_id, - user_hl[event.user].ns, - user_hl[event.user].hi, - event.start, - event.finish - ) - end - if old_buffer ~= event.buffer then - require('codemp.window').update() -- redraw user positions end end end)) @@ -90,20 +101,29 @@ local function join(workspace) print(" >< joined workspace " .. ws.name) register_cursor_callback(ws) register_cursor_handler(ws) - - -- TODO this is temporary and ad-hoc - -- ws:callback(function (event) - -- if event.type == "leave" then - -- if buffers.users[event.value] ~= nil then - -- vim.schedule(function () - -- vim.api.nvim_buf_clear_namespace(buffers.users[event.value], user_hl[event.value].ns, 0, -1) - -- buffers.users[event.value] = nil - -- user_hl[event.value] = nil - -- end) - -- end - -- end - -- vim.schedule(function() require('codemp.window').update() end) - -- end) + utils.poller( + function() return ws:event() end, + function(event) + if event.type == "leave" then + if buffers.users[event.value] ~= nil then + vim.schedule(function () + local buf_name = buffers.users[event.value] + vim.api.nvim_buf_clear_namespace(buffers.map_rev[buf_name], user_hl[event.value].ns, 0, -1) + buffers.users[event.value] = nil + user_hl[event.value] = nil + end) + end + elseif event.type == "join" then + buffers.users[event.value] = "" + user_hl[event.value] = { + ns = vim.api.nvim_create_namespace("codemp-cursor-" .. event.value), + hi = utils.color(event.value), + pos = { 0, 0 }, + } + end + vim.schedule(function() require('codemp.window').update() end) + end + ) session.workspace = ws require('codemp.window').update()