diff --git a/src/buffers.lua b/src/buffers.lua index 10f4699..5fa8e48 100644 --- a/src/buffers.lua +++ b/src/buffers.lua @@ -6,16 +6,21 @@ local buffer_id_map = {} local user_buffer_name = {} local ticks = {} +---@param name string local function create(name) state.workspace:create_buffer(name):await() print(" ++ created buffer '" .. name .. "' on " .. state.workspace.name) end +---@param name string local function delete(name) state.workspace:delete_buffer(name):await() print(" -- deleted buffer " .. name) end +---@param name string +---@param current boolean +---@param content string local function attach(name, current, content) local buffer = nil if current ~= nil then @@ -92,6 +97,7 @@ local function attach(name, current, content) return controller end +---@param name string local function detach(name) local buffer = buffer_id_map[name] id_buffer_map[buffer] = nil diff --git a/src/utils.lua b/src/utils.lua index a2d3cb1..9ac8059 100644 --- a/src/utils.lua +++ b/src/utils.lua @@ -10,10 +10,14 @@ local available_colors = { -- TODO these are definitely not portable! "CmpItemKindInterface", } +---@param x string +---@return string local function color(x) return available_colors[ math.fmod(math.abs(native.hash(x)), #available_colors) + 1 ] end +---@param x [ [integer, integer], [integer, integer] ] +---@return [ [integer, integer], [integer, integer] ] 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] } } @@ -26,6 +30,73 @@ local function order_tuples(x) -- TODO send help... end end +---@param first integer +---@param last integer +---@return integer, integer, integer, integer +local function offset_to_rowcol(first, last) + local start_row, start_col, end_row, end_col + + -- TODO this seems to work but i lost my sanity over it. if you want + -- to try and make it better be warned api is madness but i will + -- thank you a lot because this is an ugly mess... + -- + -- edge cases to test: + -- - [x] add newline in buffer + -- - [x] append newline to buffer + -- - [x] delete multiline + -- - [x] append at end of buffer + -- - [x] delete at end of buffer + -- - [x] delete line at end of buffer + -- - [x] delete multiline at end of buffer + -- - [x] autocomplete + -- - [ ] delete whole buffer + -- - [ ] enter insert in newline with `o` + + start_row = vim.fn.byte2line(first + 1) - 1 + if start_row == -2 then + -- print("?? clamping start_row to start") + start_row = vim.fn.line('$') - 1 + end + local first_col_byte = vim.fn.line2byte(start_row + 1) - 1 + if first_col_byte == -2 then + -- print("?? clamping start_col to 0") + start_col = 0 + else + start_col = first - first_col_byte + end + if first == last then + end_row = start_row + end_col = start_col + else + end_row = vim.fn.byte2line(last + 1) - 1 + if end_row == -2 then + print("?? clamping end_row to end") + end_row = vim.fn.line('$') - 1 + end_col = last - vim.fn.line2byte(end_row + 1) + else + end_col = last - (vim.fn.line2byte(end_row + 1) - 1) + end + end + + -- TODO this is an older approach, which covers less edge cases + -- but i didnt bother documenting/testing it yet properly + + ----send help it works but why is lost knowledge + --start_row = vim.fn.byte2line(first + 1) - 1 + --if start_row < 0 then start_row = 0 end + --local start_row_byte = vim.fn.line2byte(start_row + 1) - 1 + --if start_row_byte < 0 then start_row_byte = 0 end + --start_col = first - start_row_byte + --end_row = vim.fn.byte2line(last + 1) - 1 + --if end_row < 0 then end_row = 0 end + --local end_row_byte = vim.fn.line2byte(end_row + 1) - 1 + --if end_row_byte < 0 then end_row_byte = 0 end + --end_col = last - end_row_byte + + return start_row, start_col, end_row, end_col +end + +---@return [ [integer, integer], [integer, integer] ] local function cursor_position() local mode = vim.api.nvim_get_mode().mode if mode == "v" then @@ -49,6 +120,8 @@ local function cursor_position() end end +---@param buf integer? +---@return string local function buffer_get_content(buf) if buf == nil then buf = vim.api.nvim_get_current_buf() @@ -57,53 +130,27 @@ local function buffer_get_content(buf) return table.concat(lines, '\n') end --- TODO this seems to work but i lost my sanity over it. if you want --- to try and make it better be warned api is madness but i will --- thank you a lot because this is an ugly mess... --- --- edge cases to test: --- - [x] add newline in buffer --- - [x] append newline to buffer --- - [x] delete multiline --- - [x] append at end of buffer --- - [x] delete at end of buffer --- - [x] delete line at end of buffer --- - [x] delete multiline at end of buffer --- - [x] autocomplete --- - [ ] delete whole buffer --- - [ ] enter insert in newline with `o` +---@param buf integer +---@param content string +---@param first integer? +---@param last integer? +---set content of a buffer using byte indexes +---if first and last are both nil, set whole buffer content +---if first is nil, it defaults to 0 +---if last is nil, it will calculate and use the last byte in the buffer local function buffer_set_content(buf, content, first, last) if first == nil and last == nil then local lines = vim.split(content, "\n", {trimempty=false}) vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) else + if first == nil then first = 0 end + if last == nil then + local line_count = vim.api.nvim_buf_line_count(buf) + last = vim.api.nvim_buf_get_offset(buf, line_count + 1) + end local first_row, first_col, last_row, last_col vim.api.nvim_buf_call(buf, function() - first_row = vim.fn.byte2line(first + 1) - 1 - if first_row == -2 then - -- print("?? clamping start_row to start") - first_row = vim.fn.line('$') - 1 - end - local first_col_byte = vim.fn.line2byte(first_row + 1) - 1 - if first_col_byte == -2 then - -- print("?? clamping start_col to 0") - first_col = 0 - else - first_col = first - first_col_byte - end - if first == last then - last_row = first_row - last_col = first_col - else - last_row = vim.fn.byte2line(last + 1) - 1 - if last_row == -2 then - print("?? clamping end_row to end") - last_row = vim.fn.line('$') - 1 - last_col = last - vim.fn.line2byte(last_row + 1) - else - last_col = last - (vim.fn.line2byte(last_row + 1) - 1) - end - end + first_row, first_col, last_row, last_col = offset_to_rowcol(first or 0, last or 0) end) local content_array if content == "" then @@ -116,26 +163,11 @@ local function buffer_set_content(buf, content, first, last) end end -local function buffer_replace_content(buffer, first, last, content) - -- TODO send help it works but why is lost knowledge - local start_row = vim.fn.byte2line(first + 1) - 1 - if start_row < 0 then start_row = 0 end - local start_row_byte = vim.fn.line2byte(start_row + 1) - 1 - if start_row_byte < 0 then start_row_byte = 0 end - local end_row = vim.fn.byte2line(last + 1) - 1 - if end_row < 0 then end_row = 0 end - local end_row_byte = vim.fn.line2byte(end_row + 1) - 1 - if end_row_byte < 0 then end_row_byte = 0 end - vim.api.nvim_buf_set_text( - buffer, - start_row, - first - start_row_byte, - end_row, - last - end_row_byte, - vim.fn.split(content, '\n', true) - ) -end - +---@param buf integer buffer to highlight onto +---@param ns integer namespace for highlight +---@param group string highlight group +---@param start RowCol +---@param fini RowCol local function multiline_highlight(buf, ns, group, start, fini) for i=start.row,fini.row do if i == start.row and i == fini.row then @@ -162,7 +194,6 @@ return { buffer = { get_content = buffer_get_content, set_content = buffer_set_content, - replace_content = buffer_replace_content, }, hash = native.hash, available_colors = available_colors, diff --git a/src/window.lua b/src/window.lua index 407a678..1780332 100644 --- a/src/window.lua +++ b/src/window.lua @@ -2,9 +2,15 @@ local state = require('codemp.state') local utils = require('codemp.utils') local buffers = require('codemp.buffers') -local buffer_id +---@type integer? +local buffer_id = nil + +---@type integer? local prev_window = nil + +---@type integer? local window_id = nil + local ns = vim.api.nvim_create_namespace("codemp-window") vim.api.nvim_create_autocmd({"WinLeave"}, { @@ -15,6 +21,7 @@ vim.api.nvim_create_autocmd({"WinLeave"}, { end }) +---@type table local row_to_buffer = {} local function update_window() @@ -109,6 +116,7 @@ local function init_window() end local function open_window() + if buffer_id == nil then error("no active codemp buffer, reinitialize the window") end window_id = vim.api.nvim_open_win(buffer_id, true, { win = 0, split = 'left', diff --git a/src/workspace.lua b/src/workspace.lua index 4af65b7..da5a554 100644 --- a/src/workspace.lua +++ b/src/workspace.lua @@ -4,8 +4,8 @@ local state = require('codemp.state') local window = require('codemp.window') local user_hl = {} -local tree_buf = nil +---@param controller CursorController local function register_cursor_callback(controller) vim.api.nvim_create_autocmd({"CursorMoved", "CursorMovedI", "ModeChanged"}, { group = vim.api.nvim_create_augroup("codemp-workspace-" .. state.workspace, { clear = true }), @@ -13,12 +13,13 @@ local function register_cursor_callback(controller) local cur = utils.cursor.position() local buf = vim.api.nvim_get_current_buf() if buffers.map[buf] ~= nil then - controller:send(buffers.map[buf], cur[1][1], cur[1][2], cur[2][1], cur[2][2]) + local _ = controller:send(buffers.map[buf], cur[1][1], cur[1][2], cur[2][1], cur[2][2]) -- no need to await here end end }) end +---@param controller CursorController local function register_cursor_handler(controller) local async = vim.loop.new_async(vim.schedule_wrap(function () while true do @@ -56,6 +57,9 @@ local function register_cursor_handler(controller) controller:callback(function (_controller) async:send() end) end +---@param workspace string workspace name to join +---@return Workspace +---join a workspace and register event handlers local function join(workspace) local ws = state.client:join_workspace(workspace):await() register_cursor_callback(ws.cursor) @@ -84,30 +88,8 @@ local function leave() print(" -- left workspace") end -local function open_buffer_tree() - local tree = state.workspace:filetree() - if tree_buf == nil then - tree_buf = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_name(tree_buf, "codemp::" .. state.workspace) - vim.api.nvim_set_option_value('buftype', 'nofile', { buf = tree_buf }) - end - vim.api.nvim_set_option_value('modifiable', true, { buf = tree_buf }) - utils.buffer.set_content(tree_buf, "codemp::" .. state.workspace .. "\n\n- " .. vim.fn.join(tree, "\n- ")) - vim.api.nvim_set_option_value('modifiable', false, { buf = tree_buf }) - vim.api.nvim_open_win(tree_buf, true, { - win = 0, - split = 'left', - width = 20, - }) - vim.api.nvim_set_option_value('relativenumber', false, {}) - vim.api.nvim_set_option_value('number', false, {}) - vim.api.nvim_set_option_value('cursorlineopt', 'line', {}) -end - return { join = join, leave = leave, map = user_hl, - open_buffer_tree = open_buffer_tree, - buffer_tree = tree_buf, }