From 75743dffaad75638bf88b0cd1d762fd8793e551b Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Tue, 27 Jan 2026 13:35:06 +0100 Subject: [PATCH 1/4] llama.vim : add inst support for classic vim (wip) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit add instruction support for classic vim. This differs a little from the neovim version but it works well enough this far. After selecting a code block and entring an instruction command the will be a information ghost test specifying the number of tokens being generated, and after the generation is completed there will be a note saying: ``` 16 ✅ Ready! Press to accept. ``` Note sure if this is the optimal way but I've started using this and will iterate and improve as I go. --- autoload/llama.vim | 69 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/autoload/llama.vim b/autoload/llama.vim index 8dfac80..fbc7864 100644 --- a/autoload/llama.vim +++ b/autoload/llama.vim @@ -296,12 +296,25 @@ function! llama#init() let s:hlgroup_hint = 'llama_hl_fim_hint' let s:hlgroup_info = 'llama_hl_fim_info' + let s:hlgroup_inst = 'llama_hl_inst_src' + let s:hlgroup_inst_info = 'llama_hl_inst_info' + if empty(prop_type_get(s:hlgroup_hint)) call prop_type_add(s:hlgroup_hint, {'highlight': s:hlgroup_hint}) endif if empty(prop_type_get(s:hlgroup_info)) call prop_type_add(s:hlgroup_info, {'highlight': s:hlgroup_info}) endif + if empty(prop_type_get(s:hlgroup_inst)) + call prop_type_add(s:hlgroup_inst, {'highlight': s:hlgroup_inst}) + endif + + if !hlexists(s:hlgroup_inst_info) + highlight link llama_hl_inst_info Comment + endif + if empty(prop_type_get(s:hlgroup_inst_info)) + call prop_type_add(s:hlgroup_inst_info, {'highlight': s:hlgroup_inst_info}) + endif endif if g:llama_config.enable_at_startup @@ -1439,7 +1452,12 @@ function! llama#inst(l0, l1) \ 'hl_group': 'llama_hl_inst_src' \ }) elseif s:ghost_text_vim - " TODO: implement classic Vim support + let l:prop_id = prop_add(l:l0, 1, { + \ 'type': 'llama_hl_inst_src', + \ 'end_lnum': l:l1, + \ 'end_col': len(getline(l:l1)) + 1 + \ }) + let l:req.extmark = l:prop_id endif " Initialize virtual text with processing status @@ -1587,7 +1605,43 @@ function! s:inst_update(id, status) \ }) endif elseif s:ghost_text_vim - " TODO: implement classic Vim support + if l:req.extmark_virt != -1 + call prop_remove({ + \ 'type': 'llama_hl_inst_info', + \ 'id': l:req.extmark_virt, + \ 'bufnr': l:req.bufnr + \ }) + endif + + let l:text = '' + + if a:status == 'proc' + let l:text = ' ⏳ Processing... (' . g:llama_config.model_inst . ')' + + elseif a:status == 'gen' + let l:preview = substitute(l:req.result, '.*\n\s*', '', '') + " Truncate if too long so it fits on screen + if len(l:preview) > 40 + let l:preview = l:preview[:37] . '...' + endif + let l:text = printf(' ⏳ Generating (%d tokens): %s', l:req.n_gen, l:preview) + + elseif a:status == 'ready' + let l:text = ' ✅ Ready! Press to accept.' + endif + + let l:prop_id = 9000 + a:id + + call prop_add(l:req.range[1], 0, { + \ 'type': 'llama_hl_inst_info', + \ 'id': l:prop_id, + \ 'bufnr': l:req.bufnr, + \ 'text': l:text, + \ 'text_align': 'after', + \ 'text_padding_left': 2 + \ }) + + let l:req.extmark_virt = l:prop_id endif endfunction @@ -1682,7 +1736,16 @@ function! s:inst_remove(id) endif call jobstop(l:req.job) elseif s:ghost_text_vim - " TODO: implement classic Vim support + call prop_remove({ + \ 'type': 'llama_hl_inst_src', + \ 'bufnr': l:req.bufnr + \ }) + + call prop_remove({ + \ 'type': 'llama_hl_inst_info', + \ 'bufnr': l:req.bufnr + \ }) + call job_stop(l:req.job) endif From 5394a0925cd35a7131319e02e8453c808fb36550 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Wed, 28 Jan 2026 14:15:58 +0100 Subject: [PATCH 2/4] llama.vim : fix undo issue after accepting a completion --- autoload/llama.vim | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/autoload/llama.vim b/autoload/llama.vim index fbc7864..b95c186 100644 --- a/autoload/llama.vim +++ b/autoload/llama.vim @@ -1779,6 +1779,17 @@ function! llama#inst_accept() call llama#inst_update_pos(l:req) if l:line >= l:req.range[0] && l:line <= l:req.range[1] + if s:ghost_text_vim + call prop_remove({ + \ 'type': 'llama_hl_inst_src', + \ 'bufnr': l:req.bufnr + \ }) + call prop_remove({ + \ 'type': 'llama_hl_inst_info', + \ 'bufnr': l:req.bufnr + \ }) + endif + call s:inst_callback(l:req.bufnr, l:req.range[0], l:req.range[1], l:req.result) call s:inst_remove(l:req.id) return From ea1353963905d768c060a2ae6b62cec53e6d7485 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Sat, 31 Jan 2026 04:49:34 +0100 Subject: [PATCH 3/4] remove duplicate text prop removals and change order of operations This commit removes the duplicate prop_remove calls that are currently in the llama#inst_accept function. These calls are also done in the s:inst_remove function. The order of operations is also changed so that the inst_remove is called before inst_callback. The reason for this is that in inst_callback deletebufline is called the text properties are attached to the lines that are being deleted. Later when vim restores (undo) the classic vim will restore the deleted lines including the text properties. So the text properties will come back unless they are removed before this. By calling inst_remove first we are explicitly removing the text properties first. --- autoload/llama.vim | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/autoload/llama.vim b/autoload/llama.vim index b95c186..58ff061 100644 --- a/autoload/llama.vim +++ b/autoload/llama.vim @@ -1779,19 +1779,8 @@ function! llama#inst_accept() call llama#inst_update_pos(l:req) if l:line >= l:req.range[0] && l:line <= l:req.range[1] - if s:ghost_text_vim - call prop_remove({ - \ 'type': 'llama_hl_inst_src', - \ 'bufnr': l:req.bufnr - \ }) - call prop_remove({ - \ 'type': 'llama_hl_inst_info', - \ 'bufnr': l:req.bufnr - \ }) - endif - - call s:inst_callback(l:req.bufnr, l:req.range[0], l:req.range[1], l:req.result) call s:inst_remove(l:req.id) + call s:inst_callback(l:req.bufnr, l:req.range[0], l:req.range[1], l:req.result) return endif endif From 32d3842e55bb3aaa8fd4ce79502c4df2cb15666d Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Sat, 31 Jan 2026 12:01:10 +0200 Subject: [PATCH 4/4] cont : minor indentation fixes --- autoload/llama.vim | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/autoload/llama.vim b/autoload/llama.vim index 58ff061..e623507 100644 --- a/autoload/llama.vim +++ b/autoload/llama.vim @@ -1453,10 +1453,10 @@ function! llama#inst(l0, l1) \ }) elseif s:ghost_text_vim let l:prop_id = prop_add(l:l0, 1, { - \ 'type': 'llama_hl_inst_src', - \ 'end_lnum': l:l1, - \ 'end_col': len(getline(l:l1)) + 1 - \ }) + \ 'type': 'llama_hl_inst_src', + \ 'end_lnum': l:l1, + \ 'end_col': len(getline(l:l1)) + 1 + \ }) let l:req.extmark = l:prop_id endif @@ -1617,7 +1617,6 @@ function! s:inst_update(id, status) if a:status == 'proc' let l:text = ' ⏳ Processing... (' . g:llama_config.model_inst . ')' - elseif a:status == 'gen' let l:preview = substitute(l:req.result, '.*\n\s*', '', '') " Truncate if too long so it fits on screen @@ -1625,7 +1624,6 @@ function! s:inst_update(id, status) let l:preview = l:preview[:37] . '...' endif let l:text = printf(' ⏳ Generating (%d tokens): %s', l:req.n_gen, l:preview) - elseif a:status == 'ready' let l:text = ' ✅ Ready! Press to accept.' endif