@@ -8,6 +8,9 @@ let g:loaded_fittencode = 1
88let g: accept_just_now = 0
99
1010let s: hlgroup = ' FittenSuggestion'
11+ let s: virtual_text_line = 0
12+ let s: virtual_text_start_col = 0
13+ let s: virtual_text_updated = 0
1114function ! SetSuggestionStyle () abort
1215 if &t_Co == 256
1316 hi FittenSuggestion guifg= #808080 ctermfg= 244
@@ -76,23 +79,34 @@ function! CheckLoginStatus()
7679 endif
7780endfunction
7881
79- function ! ClearCompletion ()
80- if exists (' b:fitten_suggestion' )
81- unlet ! b: fitten_suggestion
82- call prop_remove ({' type' : s: hlgroup , ' all' : v: true })
82+ function ! ClearCompletion (clear_state= 1 )
83+ call prop_remove ({' type' : s: hlgroup , ' all' : v: true })
84+ if a: clear_state == 1
85+ if exists (' b:fitten_suggestion' )
86+ unlet ! b: fitten_suggestion
87+ endif
88+ if exists (' s:job' ) && job_status (s: job ) == ' run'
89+ call job_stop (s: job )
90+ unlet ! s: job
91+ endif
92+ let s: virtual_text_line = 0
93+ let s: virtual_text_start_col = 0
8394 endif
8495endfunction
8596
8697function ! ClearCompletionByCursorMoved ()
8798 if exists (' g:accept_just_now' ) && g: accept_just_now == 2
8899 let g: accept_just_now = 1
89100 endif
90- if exists (' b:fitten_suggestion' )
91- call ClearCompletion ()
101+ if exists (' b:fitten_suggestion' ) && ! s: virtual_text_updated
102+ call ClearCompletion (0 )
92103 endif
93104endfunction
94105
95106function ! CodeCompletion ()
107+ if exists (' b:fitten_suggestion' ) && s: virtual_text_line == line (' .' )
108+ return
109+ endif
96110 call ClearCompletion ()
97111
98112 let l: filename = substitute (expand (' %' ), ' \\' , ' /' , ' g' )
@@ -128,15 +142,24 @@ function! CodeCompletion()
128142 let l: server_addr = ' https://fc.fittenlab.cn/codeapi/completion/generate_one_stage/'
129143
130144 let l: cmd = ' curl -s -X POST -H "Content-Type: application/json" -d @' . l: tempfile . ' "' . l: server_addr . l: token . ' ?ide=vim&v=0.2.1"'
131- let l: response = system (l: cmd )
145+ " let l:response = system(l:cmd)
146+
147+ let result = []
148+ let s: job = job_start (l: cmd , {
149+ \ ' out_mode' : ' raw' ,
150+ \ ' out_cb' : { channel, data - > add (result, data) },
151+ \ ' exit_cb' : { job, status - > s: OnExit (result, status, tempfile, col_num) }
152+ \ })
132153
133- call delete ( l: tempfile )
154+ endfunction
134155
135- if v: shell_error
136- echow " Request failed"
156+ fu s: OnExit (out, status, tempfile, col_num) abort
157+ call delete (a: tempfile )
158+ if a: status != 0
137159 return
138160 endif
139- let l: completion_data = json_decode (l: response )
161+
162+ let l: completion_data = json_decode (join (a: out , " \n " ))
140163
141164 if ! has_key (l: completion_data , ' generated_text' )
142165 return
@@ -164,13 +187,67 @@ function! CodeCompletion()
164187 endif
165188 if l: is_first_line is v: true
166189 let l: is_first_line = v: false
167- call prop_add (line (' .' ), l : col_num , {' type' : s: hlgroup , ' text' : line })
190+ call prop_add (line (' .' ), a : col_num , {' type' : s: hlgroup , ' text' : line })
168191 else
169192 call prop_add (line (' .' ), 0 , {' type' : s: hlgroup , ' text_align' : ' below' , ' text' : line })
170193 endif
171194 endfor
172195
173196 let b: fitten_suggestion = l: generated_text
197+ let s: virtual_text_updated = 0
198+ let s: virtual_text_line = line (' .' )
199+ let s: virtual_text_start_col = a: col_num
200+ endf
201+
202+ function ! s: UpdateVirtualTextOnInput () abort
203+ if ! exists (' b:fitten_suggestion' )
204+ \ || s: virtual_text_line != line (' .' )
205+ return 0
206+ endif
207+ if s: virtual_text_start_col > getcurpos ()[2 ]
208+ call ClearCompletion ()
209+ return 0
210+ endif
211+ let l: cur_col = getcurpos ()[2 ]
212+ let l: line_content = getline (' .' )
213+ let l: input_content = strpart (l: line_content , s: virtual_text_start_col - 1 , l: cur_col - s: virtual_text_start_col )
214+ let l: input_len = len (l: input_content )
215+
216+ if l: input_len == 0
217+ return 0
218+ endif
219+ let l: virtual_prefix = strpart (b: fitten_suggestion , 0 , l: input_len )
220+ if l: virtual_prefix !=? l: input_content
221+ call ClearCompletion ()
222+ return 0
223+ endif
224+ let l: remaining_text = strpart (b: fitten_suggestion , l: input_len )
225+ if empty (l: remaining_text )
226+ call ClearCompletion ()
227+ return 1
228+ endif
229+ call ClearCompletion (0 )
230+ let l: text_lines = split (l: remaining_text , " \n " , 1 )
231+ if empty (l: text_lines [-1 ])
232+ call remove (l: text_lines , -1 )
233+ endif
234+ let l: text_lines = map (l: text_lines , ' substitute(v:val, "\t", repeat(" ", &ts), "g")' )
235+ let l: is_first_line = v: true
236+ for line in l: text_lines
237+ if empty (line )
238+ let line = " "
239+ endif
240+ if l: is_first_line
241+ let l: is_first_line = v: false
242+ call prop_add (line (' .' ), l: cur_col , {' type' : s: hlgroup , ' text' : line })
243+ else
244+ call prop_add (line (' .' ), 0 , {' type' : s: hlgroup , ' text_align' : ' below' , ' text' : line })
245+ endif
246+ endfor
247+ let b: fitten_suggestion = l: remaining_text
248+ let s: virtual_text_updated = 1
249+ let s: virtual_text_start_col = l: cur_col
250+ return 1
174251endfunction
175252
176253function ! CodeAutoCompletion ()
@@ -270,4 +347,5 @@ augroup fittencode
270347 autocmd VimEnter * call FittenMapping ()
271348 set updatetime = 1500
272349 autocmd CursorHoldI * if g: fitten_auto_completion == 1 | call CodeAutoCompletion () | endif
350+ autocmd TextChangedI * call s: UpdateVirtualTextOnInput ()
273351augroup END
0 commit comments