Skip to content

Commit 776c885

Browse files
committed
llama.vim : async
1 parent 44846e7 commit 776c885

File tree

1 file changed

+101
-73
lines changed

1 file changed

+101
-73
lines changed

examples/llama.vim

+101-73
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
" sample config:
22
"
3-
" - Ctrl+F - trigger FIM completion
3+
" - Ctrl+F - trigger FIM completion manually
44
"
55
" run this once to initialise the plugin:
66
"
@@ -31,46 +31,30 @@ function! llama#init()
3131

3232
let s:line_cur = ''
3333

34+
let s:line_cur_prefix = ''
35+
let s:line_cur_suffix = ''
36+
3437
let s:pos_dx = 0
3538
let s:content = []
3639
let s:can_accept = v:false
3740

3841
let s:timer_fim = -1
39-
let s:t_fim_last = reltime()
42+
let s:t_fim_last = reltime()
43+
let s:t_fim_start = reltime()
44+
45+
let s:current_job = v:null
4046

4147
augroup llama
4248
autocmd!
4349
autocmd InsertEnter * inoremap <buffer> <silent> <C-F> <C-O>:call llama#fim(v:false)<CR>
50+
autocmd InsertLeave * call llama#fim_cancel()
4451
augroup END
4552

4653
silent! call llama#fim_cancel()
4754
endfunction
4855

49-
" setup accept/cancel events
50-
function! llama#on_hint(id_timer)
51-
inoremap <buffer> <Tab> <C-O>:call llama#fim_accept()<CR>
52-
inoremap <buffer> <Esc> <C-O>:call llama#fim_cancel()<CR><Esc>
53-
54-
augroup llama_insert
55-
autocmd!
56-
autocmd CursorMovedI * call llama#fim_cancel()
57-
augroup END
58-
endfunction
59-
60-
function! llama#fim_auto()
61-
if reltimefloat(reltime(s:t_fim_last)) < 0.50
62-
if s:timer_fim != -1
63-
call timer_stop(s:timer_fim)
64-
let s:timer_fim = -1
65-
endif
66-
endif
67-
68-
let s:t_fim_last = reltime()
69-
let s:timer_fim = timer_start(500, {-> llama#fim(v:true)})
70-
endfunction
71-
7256
function! llama#fim(is_auto) abort
73-
let l:t_start = reltime()
57+
let s:t_fim_start = reltime()
7458

7559
let s:content = []
7660
let s:can_accept = v:false
@@ -86,16 +70,16 @@ function! llama#fim(is_auto) abort
8670

8771
let s:pos_x0 = s:pos_x == len(s:line_cur) ? s:pos_x : s:pos_x - 1
8872

89-
let l:line_cur_prefix = strpart(s:line_cur, 0, s:pos_x0)
90-
let l:line_cur_suffix = strpart(s:line_cur, s:pos_x0)
73+
let s:line_cur_prefix = strpart(s:line_cur, 0, s:pos_x0)
74+
let s:line_cur_suffix = strpart(s:line_cur, s:pos_x0)
9175

9276
let l:prefix = ""
9377
\ . join(l:lines_prefix, "\n")
9478
\ . "\n"
95-
\ . l:line_cur_prefix
79+
\ . s:line_cur_prefix
9680

9781
let l:suffix = ""
98-
\ . l:line_cur_suffix
82+
\ . s:line_cur_suffix
9983
\ . "\n"
10084
\ . join(l:lines_suffix, "\n")
10185
\ . "\n"
@@ -116,12 +100,80 @@ function! llama#fim(is_auto) abort
116100
\ 'samplers': ["top_k", "infill"]
117101
\ })
118102

119-
" request completion from the server
120103
let l:curl_command = printf(
121104
\ "curl --silent --no-buffer --request POST --url %s --header \"Content-Type: application/json\" --data %s",
122105
\ g:llama_config.endpoint, shellescape(l:request)
123106
\ )
124107

108+
" send the request asynchronously
109+
let s:current_job = jobstart(l:curl_command, {
110+
\ 'on_stdout': function('s:fim_on_stdout'),
111+
\ 'on_exit': function('s:fim_on_exit'),
112+
\ 'stdout_buffered': v:true,
113+
\ 'is_auto': a:is_auto
114+
\ })
115+
endfunction
116+
117+
function! llama#fim_accept()
118+
" insert the suggestion at the cursor location
119+
if s:can_accept && len(s:content) > 0
120+
call setline(s:pos_y, s:line_cur[:(s:pos_x0 - 1)] . s:content[0])
121+
if len(s:content) > 1
122+
call append(s:pos_y, s:content[1:-1])
123+
endif
124+
125+
" move the cursor to the end of the accepted text
126+
call cursor(s:pos_y + len(s:content) - 1, s:pos_x + s:pos_dx)
127+
endif
128+
129+
call llama#fim_cancel()
130+
endfunction
131+
132+
function! llama#fim_cancel()
133+
if s:current_job != v:null
134+
call jobstop(s:current_job)
135+
endif
136+
137+
" clear the virtual text
138+
let l:bufnr = bufnr('%')
139+
140+
let l:id_vt_fim = nvim_create_namespace('vt_fim')
141+
let l:id_vt_info = nvim_create_namespace('vt_info')
142+
143+
call nvim_buf_clear_namespace(l:bufnr, l:id_vt_fim, 0, -1)
144+
call nvim_buf_clear_namespace(l:bufnr, l:id_vt_info, 0, -1)
145+
146+
silent! iunmap <buffer> <Tab>
147+
silent! iunmap <buffer> <Esc>
148+
149+
augroup llama_insert
150+
autocmd!
151+
if g:llama_config.auto_fim
152+
autocmd CursorMovedI * call s:fim_auto()
153+
endif
154+
augroup END
155+
endfunction
156+
157+
function! s:fim_auto()
158+
if s:current_job != v:null
159+
call jobstop(s:current_job)
160+
endif
161+
162+
if reltimefloat(reltime(s:t_fim_last)) < 0.001*250
163+
if s:timer_fim != -1
164+
call timer_stop(s:timer_fim)
165+
let s:timer_fim = -1
166+
endif
167+
endif
168+
169+
let s:t_fim_last = reltime()
170+
let s:timer_fim = timer_start(250, {-> llama#fim(v:true)})
171+
endfunction
172+
173+
174+
function! s:fim_on_stdout(job_id, data, event) dict
175+
let l:raw = join(a:data, "\n")
176+
125177
let s:can_accept = v:true
126178
let l:has_info = v:false
127179

@@ -133,17 +185,15 @@ function! llama#fim(is_auto) abort
133185
let l:t_gen_ms = 1.0
134186
let l:s_gen = 0
135187

136-
" TODO: async this
137-
let l:raw = system(l:curl_command)
138188
if s:can_accept && v:shell_error
139-
if !a:is_auto
189+
if !self.is_auto
140190
call add(s:content, "<| curl error: is the server on? |>")
141191
endif
142192
let s:can_accept = v:false
143193
endif
144194

145195
if s:can_accept && l:raw == ""
146-
if !a:is_auto
196+
if !self.is_auto
147197
call add(s:content, "<| empty response: is the server on? |>")
148198
endif
149199
let s:can_accept = v:false
@@ -178,7 +228,7 @@ function! llama#fim(is_auto) abort
178228
endif
179229

180230
if len(s:content) == 0
181-
if !a:is_auto
231+
if !self.is_auto
182232
call add(s:content, "<| nothing to suggest |>")
183233
endif
184234
let s:can_accept = v:false
@@ -189,7 +239,7 @@ function! llama#fim(is_auto) abort
189239
endif
190240

191241
let s:pos_dx = len(s:content[-1])
192-
let s:content[-1] .= l:line_cur_suffix
242+
let s:content[-1] .= s:line_cur_suffix
193243

194244
call llama#fim_cancel()
195245

@@ -202,13 +252,13 @@ function! llama#fim(is_auto) abort
202252
" construct the info message:
203253
if l:has_info
204254
" prefix the info string with whitespace in order to offset it to the right of the fim overlay
205-
let l:prefix = repeat(' ', len(s:content[0]) - len(l:line_cur_suffix) + 3)
255+
let l:prefix = repeat(' ', len(s:content[0]) - len(s:line_cur_suffix) + 3)
206256

207257
let l:info = printf("%s | prompt: %d (%.2f ms, %.2f t/s) | predict: %d (%.2f ms, %.2f t/s) | total: %f.2 ms",
208258
\ l:prefix,
209259
\ l:n_prompt, l:t_prompt_ms, l:s_prompt,
210260
\ l:n_gen, l:t_gen_ms, l:s_gen,
211-
\ 1000.0 * reltimefloat(reltime(l:t_start))
261+
\ 1000.0 * reltimefloat(reltime(s:t_fim_start))
212262
\ )
213263

214264
call nvim_buf_set_extmark(l:bufnr, l:id_vt_info, s:pos_y - 1, s:pos_x - 1, {
@@ -227,42 +277,20 @@ function! llama#fim(is_auto) abort
227277
\ 'virt_text_win_col': virtcol('.')
228278
\ })
229279

230-
" need to async this call because the <C-O> in insert mode causes the cursor to move when at the end of the line
231-
call timer_start(0, 'llama#on_hint')
232-
endfunction
233-
234-
function! llama#fim_accept()
235-
" insert the suggestion at the cursor location
236-
if s:can_accept && len(s:content) > 0
237-
call setline(s:pos_y, s:line_cur[:(s:pos_x0 - 1)] . s:content[0])
238-
if len(s:content) > 1
239-
call append(s:pos_y, s:content[1:-1])
240-
endif
241-
242-
" move the cursor to the end of the accepted text
243-
call cursor(s:pos_y + len(s:content) - 1, s:pos_x + s:pos_dx)
244-
endif
245-
246-
call llama#fim_cancel()
247-
endfunction
248-
249-
function! llama#fim_cancel()
250-
" clear the virtual text
251-
let l:bufnr = bufnr('%')
252-
253-
let l:id_vt_fim = nvim_create_namespace('vt_fim')
254-
let l:id_vt_info = nvim_create_namespace('vt_info')
255-
256-
call nvim_buf_clear_namespace(l:bufnr, l:id_vt_fim, 0, -1)
257-
call nvim_buf_clear_namespace(l:bufnr, l:id_vt_info, 0, -1)
258-
259-
silent! iunmap <buffer> <Tab>
260-
silent! iunmap <buffer> <Esc>
280+
" setup accept/cancel events
281+
inoremap <buffer> <Tab> <C-O>:call llama#fim_accept()<CR>
282+
inoremap <buffer> <Esc> <C-O>:call llama#fim_cancel()<CR><Esc>
261283
262284
augroup llama_insert
263285
autocmd!
264-
if g:llama_config.auto_fim
265-
autocmd CursorMovedI * call llama#fim_auto()
266-
endif
286+
autocmd CursorMovedI * call llama#fim_cancel()
267287
augroup END
268288
endfunction
289+
290+
function! s:fim_on_exit(job_id, exit_code, event) dict
291+
if a:exit_code != 0
292+
echom "Job failed with exit code: " . a:exit_code
293+
endif
294+
295+
let s:current_job = v:null
296+
endfunction

0 commit comments

Comments
 (0)