Skip to content

Commit 84afc0a

Browse files
committed
fix: properly send and apply precise changes
this was really crazy but it seems to work?? can probably be simplified a ton but not rn
1 parent 9ea11d4 commit 84afc0a

2 files changed

Lines changed: 57 additions & 31 deletions

File tree

src/buffers.lua

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,29 @@ local function attach(name, force)
4242
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)
4343
if tick <= ticks[buf] then return end
4444
if id_buffer_map[buf] == nil then return true end -- unregister callback handler
45-
local content = table.concat(
46-
vim.api.nvim_buf_get_text(buf, start_row, start_col, start_row + new_end_row, start_col + new_end_col, {}),
47-
'\n'
48-
)
49-
-- print(string.format("%s %s %s %s -- '%s'", start_row, start_col, start_row + new_end_row, start_col + new_end_col, content))
45+
print(string.format(
46+
"start(row:%s, col:%s) offset:%s end(row:%s, col:%s new(row:%s, col:%s)) len(old:%s, new:%s)",
47+
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
48+
))
49+
local content
50+
if new_byte_len == 0 then
51+
content = ""
52+
else
53+
content = table.concat(
54+
vim.api.nvim_buf_get_text(buf, start_row, start_col, start_row + new_end_row, start_col + new_end_col, {}),
55+
'\n'
56+
)
57+
end
58+
print(string.format("sending: %s %s %s %s -- '%s'", start_row, start_col, start_row + new_end_row, start_col + new_end_col, content))
5059
controller:send(start_offset, start_offset + old_end_byte_len, content)
5160
end,
5261
})
5362

5463
-- hook clientbound callbacks
5564
async.handler(name, controller, function(event)
5665
ticks[buffer] = vim.api.nvim_buf_get_changedtick(buffer)
66+
-- print(" ~~ applying change ~~ " .. event.first .. ".." .. event.last .. "::[" .. event.content .. "]")
67+
utils.buffer.set_content(buffer, event.content, event.first, event.last)
5768
if event.hash ~= nil then
5869
if utils.hash(utils.buffer.get_content(buffer)) ~= event.hash then
5970
-- OUT OF SYNC!
@@ -63,8 +74,6 @@ local function attach(name, force)
6374
return
6475
end
6576
end
66-
-- print(" ~~ applying change ~~ " .. event.first .. ".." .. event.last .. "::" .. event.content)
67-
utils.buffer.set_content(buffer, event.content, event.first, event.last)
6877
end, 20) -- wait 20ms before polling again because it overwhelms libuv?
6978

7079
print(" ++ attached to buffer " .. name)

src/utils.lua

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,5 @@
11
local native = require('codemp.loader').load()
22

3-
local function split_without_trim(str, sep)
4-
local res = vim.fn.split(str, sep)
5-
if str:sub(1,1) == "\n" then
6-
table.insert(res, 1, '')
7-
end
8-
if str:sub(-1) == "\n" then
9-
table.insert(res, '')
10-
end
11-
return res
12-
end
13-
143
local function order_tuples(x) -- TODO send help...
154
if x[1][1] < x[2][1] then
165
return { { x[1][1], x[1][2] }, { x[2][1], x[2][2] } }
@@ -54,31 +43,60 @@ local function buffer_get_content(buf)
5443
return table.concat(lines, '\n')
5544
end
5645

46+
-- TODO this seems to work but i lost my sanity over it. if you want
47+
-- to try and make it better be warned api is madness but i will
48+
-- thank you a lot because this is an ugly mess...
49+
--
50+
-- edge cases to test:
51+
-- - [x] add newline in buffer
52+
-- - [x] append newline to buffer
53+
-- - [x] delete multiline
54+
-- - [x] append at end of buffer
55+
-- - [x] delete at end of buffer
56+
-- - [x] delete line at end of buffer
57+
-- - [x] delete multiline at end of buffer
58+
-- - [x] autocomplete
5759
local function buffer_set_content(buf, content, first, last)
5860
if first == nil and last == nil then
59-
local lines = split_without_trim(content, "\n")
61+
local lines = vim.split(content, "\n", {trimempty=false})
6062
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
6163
else
6264
local first_row, first_col, last_row, last_col
6365
vim.api.nvim_buf_call(buf, function()
6466
first_row = vim.fn.byte2line(first + 1) - 1
6567
if first_row == -2 then
68+
-- print("?? clamping start_row to start")
6669
first_row = vim.fn.line('$') - 1
6770
end
68-
first_col = first - (vim.fn.line2byte(first_row + 1) - 1)
69-
last_row = vim.fn.byte2line(last + 1) - 1
70-
if last_row == -2 then
71-
local sp = vim.split(content, "\n", {trimempty=false})
72-
last_row = first_row + (#sp - 1)
73-
last_col = string.len(sp[#sp])
71+
local first_col_byte = vim.fn.line2byte(first_row + 1) - 1
72+
if first_col_byte == -2 then
73+
-- print("?? clamping start_col to 0")
74+
first_col = 0
7475
else
75-
last_col = last - (vim.fn.line2byte(last_row + 1) - 1)
76+
first_col = first - first_col_byte
77+
end
78+
if first == last then
79+
last_row = first_row
80+
last_col = first_col
81+
else
82+
last_row = vim.fn.byte2line(last + 1) - 1
83+
if last_row == -2 then
84+
print("?? clamping end_row to end")
85+
last_row = vim.fn.line('$') - 1
86+
last_col = last - vim.fn.line2byte(last_row + 1)
87+
else
88+
last_col = last - (vim.fn.line2byte(last_row + 1) - 1)
89+
end
7690
end
7791
end)
78-
vim.api.nvim_buf_set_text(
79-
buf, first_row, first_col, last_row, last_col,
80-
split_without_trim(content, "\n")
81-
)
92+
local content_array
93+
if content == "" then
94+
content_array = {}
95+
else
96+
content_array = vim.split(content, "\n", {trimempty=false})
97+
end
98+
-- 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))
99+
vim.api.nvim_buf_set_text(buf, first_row, first_col, last_row, last_col, content_array)
82100
end
83101
end
84102

@@ -120,7 +138,6 @@ end
120138

121139

122140
return {
123-
split_without_trim = split_without_trim,
124141
order_tuples = order_tuples,
125142
multiline_highlight = multiline_highlight,
126143
cursor = {

0 commit comments

Comments
 (0)