diff --git a/src/buffers.lua b/src/buffers.lua index b4880d6..fcc62c1 100644 --- a/src/buffers.lua +++ b/src/buffers.lua @@ -42,11 +42,20 @@ local function attach(name, force) on_bytes = function(_, buf, tick, start_row, start_col, start_offset, old_end_row, old_end_col, old_end_byte_len, new_end_row, new_end_col, new_byte_len) if tick <= ticks[buf] then return end if id_buffer_map[buf] == nil then return true end -- unregister callback handler - local content = table.concat( - vim.api.nvim_buf_get_text(buf, start_row, start_col, start_row + new_end_row, start_col + new_end_col, {}), - '\n' - ) - -- print(string.format("%s %s %s %s -- '%s'", start_row, start_col, start_row + new_end_row, start_col + new_end_col, content)) + print(string.format( + "start(row:%s, col:%s) offset:%s end(row:%s, col:%s new(row:%s, col:%s)) len(old:%s, new:%s)", + start_row, start_col, start_offset, old_end_row, old_end_col, new_end_row, new_end_col, old_end_byte_len, new_byte_len + )) + local content + if new_byte_len == 0 then + content = "" + else + content = table.concat( + vim.api.nvim_buf_get_text(buf, start_row, start_col, start_row + new_end_row, start_col + new_end_col, {}), + '\n' + ) + end + print(string.format("sending: %s %s %s %s -- '%s'", start_row, start_col, start_row + new_end_row, start_col + new_end_col, content)) controller:send(start_offset, start_offset + old_end_byte_len, content) end, }) @@ -54,6 +63,8 @@ local function attach(name, force) -- 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! @@ -63,8 +74,6 @@ local function attach(name, force) return end end - -- print(" ~~ applying change ~~ " .. event.first .. ".." .. event.last .. "::" .. event.content) - utils.buffer.set_content(buffer, event.content, event.first, event.last) end, 20) -- wait 20ms before polling again because it overwhelms libuv? print(" ++ attached to buffer " .. name) diff --git a/src/utils.lua b/src/utils.lua index 43df36f..0254f52 100644 --- a/src/utils.lua +++ b/src/utils.lua @@ -1,16 +1,5 @@ local native = require('codemp.loader').load() -local function split_without_trim(str, sep) - local res = vim.fn.split(str, sep) - if str:sub(1,1) == "\n" then - table.insert(res, 1, '') - end - if str:sub(-1) == "\n" then - table.insert(res, '') - end - return res -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] } } @@ -54,31 +43,60 @@ 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 local function buffer_set_content(buf, content, first, last) if first == nil and last == nil then - local lines = split_without_trim(content, "\n") + local lines = vim.split(content, "\n", {trimempty=false}) vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) else 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 - first_col = first - (vim.fn.line2byte(first_row + 1) - 1) - last_row = vim.fn.byte2line(last + 1) - 1 - if last_row == -2 then - local sp = vim.split(content, "\n", {trimempty=false}) - last_row = first_row + (#sp - 1) - last_col = string.len(sp[#sp]) + 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 - last_col = last - (vim.fn.line2byte(last_row + 1) - 1) + 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 end) - vim.api.nvim_buf_set_text( - buf, first_row, first_col, last_row, last_col, - split_without_trim(content, "\n") - ) + local content_array + if content == "" then + content_array = {} + else + content_array = vim.split(content, "\n", {trimempty=false}) + end + -- print(string.format("set [%s..%s::'%s'] -> start(row:%s col:%s) end(row:%s, col:%s)", first, last, content, first_row, first_col, last_row, last_col)) + vim.api.nvim_buf_set_text(buf, first_row, first_col, last_row, last_col, content_array) end end @@ -120,7 +138,6 @@ end return { - split_without_trim = split_without_trim, order_tuples = order_tuples, multiline_highlight = multiline_highlight, cursor = {