@@ -17,8 +17,13 @@ local BinaryLifecycle = {
17
17
cursor = nil ,
18
18
max_state_id_retention = 50 ,
19
19
service_message_displayed = false ,
20
+ changed_document_list = {},
21
+ last_state = nil ,
22
+ dust_strings = {},
20
23
}
21
24
25
+ BinaryLifecycle .HARD_SIZE_LIMIT = 10e6
26
+
22
27
local timer = loop .new_timer ()
23
28
timer :start (
24
29
0 ,
@@ -72,33 +77,22 @@ function BinaryLifecycle:greeting_message()
72
77
loop .write (self .stdin , message ) -- fails silently
73
78
end
74
79
80
+ --- @param buffer integer
81
+ --- @param file_name string
82
+ --- @param event_type " text_changed" | " cursor"
75
83
function BinaryLifecycle :on_update (buffer , file_name , event_type )
76
84
if config .ignore_filetypes [vim .bo .ft ] or vim .tbl_contains (config .ignore_filetypes , vim .bo .filetype ) then
77
85
return
78
86
end
79
87
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
99
92
end
100
93
101
- self :send_message (updates )
94
+ self :document_changed (file_path , buffer_text )
95
+ local cursor = api .nvim_win_get_cursor (0 )
102
96
local completion_is_allowed = (buffer_text ~= self .last_text ) and (self .last_path == file_name )
103
97
local context = {
104
98
document_text = buffer_text ,
@@ -242,33 +236,19 @@ function BinaryLifecycle:on_error(err)
242
236
log :error (" Error reading stdout: " .. err )
243
237
end
244
238
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
+
245
244
function BinaryLifecycle :send_message (updates )
246
245
local state_update = {
247
246
kind = " state_update" ,
248
247
newId = tostring (self .current_state_id ),
249
248
updates = updates ,
250
249
}
251
250
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 )
272
252
end
273
253
274
254
function BinaryLifecycle :purge_old_states ()
@@ -306,22 +286,48 @@ function BinaryLifecycle:poll_once()
306
286
local text_split = u .get_text_before_after_cursor (cursor )
307
287
local line_before_cursor = text_split .text_before_cursor
308
288
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
309
292
local status , prefix = pcall (u .get_cursor_prefix , buffer , cursor )
310
293
if not status then
311
294
return
312
295
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
314
302
return
315
303
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
+ )
317
313
318
314
if maybe_completion == nil then
319
315
preview :dispose_inlay ()
320
316
return
321
317
end
322
318
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
+
323
327
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
325
331
return
326
332
end
327
333
@@ -339,11 +345,37 @@ function BinaryLifecycle:poll_once()
339
345
preview :render_with_inlay (buffer , prior_delete , maybe_completion .text , line_after_cursor , line_before_cursor )
340
346
end
341
347
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
+
343
375
self :check_process ()
344
376
local best_completion = {}
345
377
local best_length = 0
346
- local best_state_id = 0
378
+ local best_state_id = - 1
347
379
348
380
for state_id , state in pairs (self .state_map ) do
349
381
local state_prefix = state .prefix
@@ -363,13 +395,6 @@ function BinaryLifecycle:check_state(prefix, line_before_cursor, line_after_curs
363
395
end
364
396
end
365
397
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
-
373
398
return textual .derive_completion (best_completion , params )
374
399
end
375
400
@@ -383,6 +408,65 @@ function BinaryLifecycle:completion_text_length(completion)
383
408
return length
384
409
end
385
410
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
386
470
function BinaryLifecycle :strip_prefix (completion , original_prefix )
387
471
local prefix = original_prefix
388
472
local remaining_response_item = {}
@@ -402,15 +486,14 @@ function BinaryLifecycle:strip_prefix(completion, original_prefix)
402
486
text = text ,
403
487
})
404
488
end
405
- elseif response_item .kind == " del " then
489
+ elseif response_item .kind == " delete " then
406
490
table.insert (remaining_response_item , response_item )
407
491
elseif response_item .kind == " dedent" then
408
492
if # prefix > 0 then
409
493
return nil
410
494
end
411
495
table.insert (remaining_response_item , response_item )
412
496
else
413
- -- barrier/del get added when prefix has been accounted for
414
497
if # prefix == 0 then
415
498
table.insert (remaining_response_item , response_item )
416
499
end
@@ -502,4 +585,19 @@ function BinaryLifecycle:open_popup(message, include_free)
502
585
self .win = win
503
586
end
504
587
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
+
505
603
return BinaryLifecycle
0 commit comments