Skip to content

Commit 32e54fa

Browse files
authored
Merge pull request #109 from supermaven-inc/rust-binary
Support newest version of binary
2 parents 40bde48 + a828927 commit 32e54fa

File tree

5 files changed

+425
-82
lines changed

5 files changed

+425
-82
lines changed

lua/supermaven-nvim/binary/binary_fetcher.lua

+6-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ end
4646
function BinaryFetcher:discover_binary_url()
4747
local platform = self:platform()
4848
local arch = self:get_arch()
49-
local url = "https://supermaven.com/api/download-path?platform=" .. platform .. "&arch=" .. arch .. "&editor=neovim"
49+
local url = "https://supermaven.com/api/download-path-v2?platform="
50+
.. platform
51+
.. "&arch="
52+
.. arch
53+
.. "&editor=neovim"
5054
local response = ""
5155
if platform == "windows" then
5256
response = vim.fn.system({
@@ -141,7 +145,7 @@ function BinaryFetcher:local_binary_parent_path()
141145
else
142146
dir = home_dir .. "/.supermaven"
143147
end
144-
return dir .. "/binary/v15/" .. self:platform() .. "-" .. self:get_arch()
148+
return dir .. "/binary/v20/" .. self:platform() .. "-" .. self:get_arch()
145149
end
146150

147151
return BinaryFetcher

lua/supermaven-nvim/binary/binary_handler.lua

+152-54
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@ local BinaryLifecycle = {
1717
cursor = nil,
1818
max_state_id_retention = 50,
1919
service_message_displayed = false,
20+
changed_document_list = {},
21+
last_state = nil,
22+
dust_strings = {},
2023
}
2124

25+
BinaryLifecycle.HARD_SIZE_LIMIT = 10e6
26+
2227
local timer = loop.new_timer()
2328
timer:start(
2429
0,
@@ -72,33 +77,22 @@ function BinaryLifecycle:greeting_message()
7277
loop.write(self.stdin, message) -- fails silently
7378
end
7479

80+
---@param buffer integer
81+
---@param file_name string
82+
---@param event_type "text_changed" | "cursor"
7583
function BinaryLifecycle:on_update(buffer, file_name, event_type)
7684
if config.ignore_filetypes[vim.bo.ft] or vim.tbl_contains(config.ignore_filetypes, vim.bo.filetype) then
7785
return
7886
end
7987
local buffer_text = u.get_text(buffer)
80-
local updates = {
81-
{
82-
kind = "file_update",
83-
path = file_name,
84-
content = buffer_text,
85-
},
86-
}
87-
local cursor = api.nvim_win_get_cursor(0)
88-
if cursor ~= nil then
89-
local prefix = self:save_state_id(buffer, cursor, file_name)
90-
if prefix == nil then
91-
return
92-
end
93-
local offset = #prefix
94-
updates[#updates + 1] = {
95-
kind = "cursor_update",
96-
path = file_name,
97-
offset = offset,
98-
}
88+
local file_path = vim.api.nvim_buf_get_name(buffer)
89+
if #buffer_text > self.HARD_SIZE_LIMIT then
90+
log:warn("File is too large to send to server. Skipping...")
91+
return
9992
end
10093

101-
self:send_message(updates)
94+
self:document_changed(file_path, buffer_text)
95+
local cursor = api.nvim_win_get_cursor(0)
10296
local completion_is_allowed = (buffer_text ~= self.last_text) and (self.last_path == file_name)
10397
local context = {
10498
document_text = buffer_text,
@@ -242,33 +236,19 @@ function BinaryLifecycle:on_error(err)
242236
log:error("Error reading stdout: " .. err)
243237
end
244238

239+
function BinaryLifecycle:send_json(msg)
240+
local message = vim.json.encode(msg) .. "\n"
241+
loop.write(self.stdin, message) -- fails silently
242+
end
243+
245244
function BinaryLifecycle:send_message(updates)
246245
local state_update = {
247246
kind = "state_update",
248247
newId = tostring(self.current_state_id),
249248
updates = updates,
250249
}
251250

252-
local message = vim.json.encode(state_update) .. "\n"
253-
loop.write(self.stdin, message) -- fails silently
254-
end
255-
256-
function BinaryLifecycle:save_state_id(buffer, cursor, file_name)
257-
self.current_state_id = self.current_state_id + 1
258-
self:purge_old_states()
259-
260-
local status, prefix = pcall(u.get_cursor_prefix, buffer, cursor)
261-
if not status then
262-
return nil
263-
end
264-
265-
self.state_map[self.current_state_id] = {
266-
prefix = prefix,
267-
completion = {},
268-
has_ended = false,
269-
}
270-
271-
return prefix
251+
self:send_json(state_update)
272252
end
273253

274254
function BinaryLifecycle:purge_old_states()
@@ -306,22 +286,48 @@ function BinaryLifecycle:poll_once()
306286
local text_split = u.get_text_before_after_cursor(cursor)
307287
local line_before_cursor = text_split.text_before_cursor
308288
local line_after_cursor = text_split.text_after_cursor
289+
if line_before_cursor == nil or line_after_cursor == nil then
290+
return
291+
end
309292
local status, prefix = pcall(u.get_cursor_prefix, buffer, cursor)
310293
if not status then
311294
return
312295
end
313-
if line_before_cursor == nil or line_after_cursor == nil then
296+
local get_following_line = function(index)
297+
return u.safe_get_line(buffer, cursor[1] + index) or ""
298+
end
299+
local cached_chain_info = nil -- TODO
300+
local query_state_id = self:submit_query(buffer, prefix)
301+
if query_state_id == nil then
314302
return
315303
end
316-
local maybe_completion = self:check_state(prefix, line_before_cursor, line_after_cursor)
304+
local maybe_completion = self:check_state(
305+
prefix,
306+
line_before_cursor,
307+
line_after_cursor,
308+
false,
309+
get_following_line,
310+
query_state_id,
311+
cached_chain_info
312+
)
317313

318314
if maybe_completion == nil then
319315
preview:dispose_inlay()
320316
return
321317
end
322318

319+
if maybe_completion.kind == "jump" then
320+
return
321+
elseif maybe_completion.kind == "delete" then
322+
return
323+
elseif maybe_completion.kind == "skip" then
324+
return
325+
end
326+
323327
self.wants_polling = maybe_completion.is_incomplete
324-
if #maybe_completion.dedent > 0 and not u.ends_with(line_before_cursor, maybe_completion.dedent) then
328+
if maybe_completion.dedent == nil or
329+
(#maybe_completion.dedent > 0 and not u.ends_with(line_before_cursor, maybe_completion.dedent))
330+
then
325331
return
326332
end
327333

@@ -339,11 +345,37 @@ function BinaryLifecycle:poll_once()
339345
preview:render_with_inlay(buffer, prior_delete, maybe_completion.text, line_after_cursor, line_before_cursor)
340346
end
341347

342-
function BinaryLifecycle:check_state(prefix, line_before_cursor, line_after_cursor)
348+
---@param prefix string
349+
---@param line_before_cursor string
350+
---@param line_after_cursor string
351+
---@param can_retry boolean
352+
---@param get_following_line fun(line: string): string
353+
---@param query_state_id integer
354+
---@param cached_chain_info ChainInfo | nil
355+
---@return AnyCompletion | nil
356+
function BinaryLifecycle:check_state(
357+
prefix,
358+
line_before_cursor,
359+
line_after_cursor,
360+
can_retry,
361+
get_following_line,
362+
query_state_id,
363+
cached_chain_info
364+
)
365+
local params = {
366+
line_before_cursor = line_before_cursor,
367+
line_after_cursor = line_after_cursor,
368+
get_following_line = get_following_line,
369+
dust_strings = self.dust_strings,
370+
can_show_partial_line = true,
371+
can_retry = can_retry,
372+
source_state_id = query_state_id,
373+
}
374+
343375
self:check_process()
344376
local best_completion = {}
345377
local best_length = 0
346-
local best_state_id = 0
378+
local best_state_id = -1
347379

348380
for state_id, state in pairs(self.state_map) do
349381
local state_prefix = state.prefix
@@ -363,13 +395,6 @@ function BinaryLifecycle:check_state(prefix, line_before_cursor, line_after_curs
363395
end
364396
end
365397

366-
local params = {
367-
line_before_cursor = line_before_cursor,
368-
line_after_cursor = line_after_cursor,
369-
dust_strings = self.dust_strings,
370-
can_show_partial_line = true,
371-
}
372-
373398
return textual.derive_completion(best_completion, params)
374399
end
375400

@@ -383,6 +408,65 @@ function BinaryLifecycle:completion_text_length(completion)
383408
return length
384409
end
385410

411+
---@param bufnr integer
412+
---@param prefix string
413+
---@return integer | nil
414+
function BinaryLifecycle:submit_query(bufnr, prefix)
415+
self:purge_old_states()
416+
local buffer_text = u.get_text(bufnr)
417+
local offset = #prefix
418+
local document_state = {
419+
kind = "file_update",
420+
path = vim.api.nvim_buf_get_name(bufnr),
421+
content = buffer_text,
422+
}
423+
local cursor_state = {
424+
kind = "cursor_update",
425+
path = vim.api.nvim_buf_get_name(bufnr),
426+
offset = offset,
427+
}
428+
if self.last_state ~= nil then
429+
if #self.changed_document_list == 0 then
430+
if self.last_state.cursor.path == cursor_state.path and self.last_state.cursor.offset == cursor_state.offset then
431+
if
432+
self.last_state.document.path == document_state.path
433+
and self.last_state.document.content == document_state.content
434+
then
435+
return self.current_state_id
436+
end
437+
end
438+
end
439+
end
440+
441+
local updates = {
442+
cursor_state,
443+
}
444+
self:document_changed(document_state.path, buffer_text)
445+
for _, document_value in pairs(self.changed_document_list) do
446+
updates[#updates + 1] = {
447+
kind = "file_update",
448+
path = document_value.path,
449+
content = document_value.content,
450+
}
451+
end
452+
self.changed_document_list = {}
453+
self.current_state_id = self.current_state_id + 1
454+
self:send_message(updates)
455+
self.state_map[self.current_state_id] = {
456+
prefix = prefix,
457+
completion = {},
458+
has_ended = false,
459+
}
460+
self.last_state = {
461+
cursor = cursor_state,
462+
document = document_state,
463+
}
464+
return self.current_state_id
465+
end
466+
467+
---@param completion ResponseItem[]
468+
---@param original_prefix string
469+
---@return ResponseItem[] | nil
386470
function BinaryLifecycle:strip_prefix(completion, original_prefix)
387471
local prefix = original_prefix
388472
local remaining_response_item = {}
@@ -402,15 +486,14 @@ function BinaryLifecycle:strip_prefix(completion, original_prefix)
402486
text = text,
403487
})
404488
end
405-
elseif response_item.kind == "del" then
489+
elseif response_item.kind == "delete" then
406490
table.insert(remaining_response_item, response_item)
407491
elseif response_item.kind == "dedent" then
408492
if #prefix > 0 then
409493
return nil
410494
end
411495
table.insert(remaining_response_item, response_item)
412496
else
413-
-- barrier/del get added when prefix has been accounted for
414497
if #prefix == 0 then
415498
table.insert(remaining_response_item, response_item)
416499
end
@@ -502,4 +585,19 @@ function BinaryLifecycle:open_popup(message, include_free)
502585
self.win = win
503586
end
504587

588+
---@param full_path string
589+
---@param buffer_text string
590+
function BinaryLifecycle:document_changed(full_path, buffer_text)
591+
self.changed_document_list[full_path] = {
592+
path = full_path,
593+
content = buffer_text,
594+
cursor = api.nvim_win_get_cursor(0),
595+
}
596+
local outgoing_message = {
597+
kind = "inform_file_changed",
598+
path = full_path,
599+
}
600+
self:send_json(outgoing_message)
601+
end
602+
505603
return BinaryLifecycle

0 commit comments

Comments
 (0)