diff --git a/README.md b/README.md index ac213c1..6543f55 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,9 @@ Fitten Code AI编程助手 Vim 版本,帮助您在vim中通过AI进行自动 ## Dependencies `Vim` >= 9.0. +`NeoVim` >= 0.8.0. -The support of `NeoVim` is [here](https://github.com/luozhiya/fittencode.nvim) contributed by luozhiya. +The support of `NeoVim` in Lua is [here](https://github.com/luozhiya/fittencode.nvim) contributed by luozhiya. ## Install diff --git a/plugin/fittencode.vim b/plugin/fittencode.vim index b913b8c..ee30571 100644 --- a/plugin/fittencode.vim +++ b/plugin/fittencode.vim @@ -6,14 +6,29 @@ if exists("g:loaded_fittencode") endif let g:loaded_fittencode = 1 +let s:is_nvim = has('nvim') +let s:has_nvim_inline = has('nvim-0.10.0') + let s:hlgroup = 'FittenSuggestion' +let g:nvim_ns_id = s:is_nvim ? nvim_create_namespace(s:hlgroup) : -1 + +function! s:echow(msg) + if !s:is_nvim + echow a:msg + else + echom a:msg + endif +endfunction + function! SetSuggestionStyle() abort if &t_Co == 256 hi def FittenSuggestion guifg=#808080 ctermfg=244 else hi def FittenSuggestion guifg=#808080 ctermfg=8 endif - call prop_type_add(s:hlgroup, {'highlight': s:hlgroup}) + if !s:is_nvim + call prop_type_add(s:hlgroup, {'highlight': s:hlgroup}) + endif endfunction function! Fittenlogin(account, password) @@ -70,7 +85,11 @@ endfunction function! ClearCompletion() unlet! b:fitten_suggestion - call prop_remove({'type': s:hlgroup, 'all': v:true}) + if !s:is_nvim + call prop_remove({'type': s:hlgroup, 'all': v:true}) + else + call nvim_buf_clear_namespace(0, g:nvim_ns_id, 0, -1) + endif endfunction function! ClearCompletionByCursorMoved() @@ -91,13 +110,18 @@ function! CodeCompletion() else let l:col_num = getcurpos()[2] + 1 endif - + + if s:is_nvim && !s:has_nvim_inline && l:col_num - 1 < len(getline(l:line_num)) + call s:echow("Inline extmark is not supported in versions < 0.10.0") + return + endif + let l:prefix = join(getline(1, l:line_num - 1), '\n') if !empty(l:prefix) let l:prefix = l:prefix . '\n' endif let l:prefix = l:prefix . strpart(getline(l:line_num), 0, l:col_num - 1) - + let l:suffix = strpart(getline(l:line_num), l:col_num - 1) if l:line_num < line('$') let l:suffix = l:suffix . '\n' . join(getline(l:line_num + 1, '$'), '\n') @@ -112,7 +136,7 @@ function! CodeCompletion() let l:token = join(readfile($HOME . '/.vimapikey'), "\n") let l:params = '{"inputs": "' . l:escaped_prompt . '", "meta_datas": {"filename": "' . l:filename . '"}}' - + let l:tempfile = tempname() call writefile([l:params], l:tempfile) @@ -124,7 +148,7 @@ function! CodeCompletion() call delete(l:tempfile) if v:shell_error - echow "Request failed" + call s:echow("Request failed") return endif let l:completion_data = json_decode(l:response) @@ -137,7 +161,7 @@ function! CodeCompletion() let l:generated_text = substitute(l:generated_text, '<.endoftext.>', '', 'g') if empty(l:generated_text) - echow "Fitten Code: No More Suggestions" + call s:echow("Fitten Code: No More Suggestions") call timer_start(2000, {-> execute('echo ""')}) return endif @@ -147,6 +171,7 @@ function! CodeCompletion() call remove(l:text, -1) endif + let l:virt_lines = [] let l:is_first_line = v:true for line in text if empty(line) @@ -154,12 +179,31 @@ function! CodeCompletion() endif if l:is_first_line is v:true let l:is_first_line = v:false - call prop_add(line('.'), l:col_num, {'type': s:hlgroup, 'text': line}) + if !s:is_nvim + call prop_add(line('.'), l:col_num, {'type': s:hlgroup, 'text': line}) + else + call nvim_buf_set_extmark(0, g:nvim_ns_id, line('.') - 1, l:col_num - 1, #{ + \ virt_text: [[line, s:hlgroup]], + \ virt_text_pos: s:has_nvim_inline ? 'inline' : 'overlay', + \ hl_mode: 'combine', + \ }) + endif else - call prop_add(line('.'), 0, {'type': s:hlgroup, 'text_align': 'below', 'text': line}) + if !s:is_nvim + call prop_add(line('.'), 0, {'type': s:hlgroup, 'text_align': 'below', 'text': line}) + else + call add(l:virt_lines, [[line, s:hlgroup]]) + endif endif endfor + if s:is_nvim && len(l:virt_lines) > 0 + call nvim_buf_set_extmark(0, g:nvim_ns_id, line('.') - 1, 0, #{ + \ virt_lines: virt_lines, + \ hl_mode: 'combine', + \ }) + endif + let b:fitten_suggestion = l:generated_text endfunction @@ -215,7 +259,7 @@ if !exists('g:fitten_accept_key') endif function! FittenMapping() execute "inoremap" keytrans(g:fitten_trigger) 'call CodeCompletion()' - if g:fitten_accept_key isnot v:none + if !empty(g:fitten_accept_key) execute 'inoremap' keytrans(g:fitten_accept_key) 'call FittenAccept()' endif endfunction