3 changed files with 179 additions and 166 deletions
@ -1,185 +1,222 @@ |
|||||
" ChatGPT Vim Plugin |
" gpt.vim |
||||
|
|
||||
if !has('python3') |
if !has('python3') |
||||
echo "Python 3 support is required for ChatGPT plugin" |
echo "Python 3 support is required for ChatGPT plugin" |
||||
finish |
finish |
||||
endif |
endif |
||||
|
|
||||
if !exists("g:gpt_max_tokens") |
if !exists("g:gpt_openai_api_key") |
||||
let g:gpt_max_tokens = 2000 |
echo "g:gpt_openai_api_key is not set. Please set it to your OpenAI API key." |
||||
|
finish |
||||
endif |
endif |
||||
|
|
||||
if !exists("g:gpt_temperature") |
if !exists("g:gpt_max_tokens") |
||||
let g:gpt_temperature = 0.7 |
let g:gpt_max_tokens = 2000 |
||||
endif |
endif |
||||
|
|
||||
if !exists("g:gpt_model") |
if !exists("g:gpt_temperature") |
||||
let g:gpt_model = 'gpt-4o' |
let g:gpt_temperature = 0.7 |
||||
endif |
endif |
||||
|
|
||||
if !exists("g:gpt_lang") |
if !exists("g:gpt_lang") |
||||
let g:gpt_lang = 'English' |
let g:gpt_lang = 'English' |
||||
endif |
endif |
||||
|
|
||||
if !exists("g:gpt_split_direction") |
if !exists("g:gpt_split_direction") |
||||
let g:gpt_split_direction = 'horizontal' |
let g:gpt_split_direction = 'horizontal' |
||||
endif |
endif |
||||
|
|
||||
if !exists("g:gpt_split_ratio") |
if !exists("g:gpt_split_ratio") |
||||
let g:gpt_split_ratio = 3 |
let g:gpt_split_ratio = 3 |
||||
endif |
endif |
||||
|
|
||||
if !exists("g:gpt_persona") |
if !exists("g:gpt_persona") |
||||
let g:gpt_persona = 'default' |
let g:gpt_persona = 'default' |
||||
endif |
endif |
||||
|
|
||||
let g:gpt_templates = { |
let g:gpt_personas = { |
||||
\ 'Rewrite': 'Rewrite this more idiomatically', |
\ "default": '', |
||||
\ 'Review': 'Review this code', |
\ "bob": 'You are a helpful expert programmer we are working together to solve complex coding challenges, and I need your help. Please make sure to wrap all code blocks in ``` annotate the programming language you are using.', |
||||
\ 'Document': 'Return documentation following language pattern conventions', |
|
||||
\ 'Explain': 'Explain how this works', |
|
||||
\ 'Test': 'Write a test', |
|
||||
\ 'Fix': 'Fix this error', |
|
||||
\} |
\} |
||||
|
|
||||
let g:gpt_keys = keys(g:gpt_templates) |
if !exists("g:gpt_model") |
||||
|
let g:gpt_model = 'gpt-4o' |
||||
|
endif |
||||
|
|
||||
let g:gpt_personas = { |
let g:gpt_models = { |
||||
\ "default": '', |
\ "gpt-3.5-turbo": 4097, |
||||
\ "bob": 'You are a helpful expert programmer we are working together to solve complex coding challenges, and I need your help. Please make sure to wrap all code blocks in ``` annotate the programming language you are using.', |
\ "gpt-3.5-turbo-16k": 16385, |
||||
|
\ "gpt-3.5-turbo-1106": 16385, |
||||
|
\ "gpt-4": 8192, |
||||
|
\ "gpt-4-turbo": 128000, |
||||
|
\ "gpt-4-turbo-preview": 128000, |
||||
|
\ "gpt-4-32k": 32768, |
||||
|
\ "gpt-4o": 128000, |
||||
|
\ "gpt-4o-mini": 128000, |
||||
\} |
\} |
||||
|
|
||||
function! DisplayChatGPTResponse(response, finish_reason, chat_gpt_session_id) " {{{ |
function! GptInfo() " {{{ |
||||
let response = a:response |
echo 'model: ' . g:gpt_model |
||||
let finish_reason = a:finish_reason |
echo 'max_tokens: ' . string(g:gpt_max_tokens) |
||||
|
echo 'temperature: ' . string(g:gpt_temperature) |
||||
let chat_gpt_session_id = a:chat_gpt_session_id |
echo 'persona: ' . g:gpt_persona |
||||
|
echo 'language: ' . g:gpt_lang |
||||
if !bufexists(chat_gpt_session_id) |
echo 'split_direction: ' . g:gpt_split_direction |
||||
if g:gpt_split_direction ==# 'vertical' |
echo 'split_ratio: ' . string(g:gpt_split_ratio) |
||||
silent execute winwidth(0)/g:gpt_split_ratio.'vnew '. chat_gpt_session_id |
echo 'personas: ' . join(keys(g:gpt_personas), ', ') |
||||
else |
echo 'models: ' . join(keys(g:gpt_models), ', ') |
||||
silent execute winheight(0)/g:gpt_split_ratio.'new '. chat_gpt_session_id |
endfunction |
||||
endif |
|
||||
call setbufvar(chat_gpt_session_id, '&buftype', 'nofile') |
" }}} |
||||
call setbufvar(chat_gpt_session_id, '&bufhidden', 'hide') |
|
||||
call setbufvar(chat_gpt_session_id, '&swapfile', 0) |
function! GptDisplay(response, finish_reason, chat_gpt_session_id) " {{{ |
||||
setlocal modifiable |
let response = a:response |
||||
setlocal wrap |
let finish_reason = a:finish_reason |
||||
setlocal linebreak |
|
||||
call setbufvar(chat_gpt_session_id, '&ft', 'markdown') |
let chat_gpt_session_id = a:chat_gpt_session_id |
||||
call setbufvar(chat_gpt_session_id, '&syntax', 'markdown') |
|
||||
endif |
if !bufexists(chat_gpt_session_id) |
||||
|
if g:gpt_split_direction ==# 'vertical' |
||||
if bufwinnr(chat_gpt_session_id) == -1 |
silent execute winwidth(0)/g:gpt_split_ratio.'vnew '. chat_gpt_session_id |
||||
if g:gpt_split_direction ==# 'vertical' |
else |
||||
execute winwidth(0)/g:gpt_split_ratio.'vsplit ' . chat_gpt_session_id |
silent execute winheight(0)/g:gpt_split_ratio.'new '. chat_gpt_session_id |
||||
else |
endif |
||||
execute winheight(0)/g:gpt_split_ratio.'split ' . chat_gpt_session_id |
call setbufvar(chat_gpt_session_id, '&buftype', 'nofile') |
||||
endif |
call setbufvar(chat_gpt_session_id, '&bufhidden', 'hide') |
||||
endif |
call setbufvar(chat_gpt_session_id, '&swapfile', 0) |
||||
|
setlocal modifiable |
||||
let last_lines = getbufline(chat_gpt_session_id, '$') |
setlocal wrap |
||||
let last_line = empty(last_lines) ? '' : last_lines[-1] |
setlocal linebreak |
||||
|
call setbufvar(chat_gpt_session_id, '&ft', 'markdown') |
||||
let new_lines = substitute(last_line . response, '\n', '\r\n\r', 'g') |
call setbufvar(chat_gpt_session_id, '&syntax', 'markdown') |
||||
let lines = split(new_lines, '\n') |
endif |
||||
|
|
||||
let clean_lines = [] |
if bufwinnr(chat_gpt_session_id) == -1 |
||||
for line in lines |
if g:gpt_split_direction ==# 'vertical' |
||||
call add(clean_lines, substitute(line, '\r', '', 'g')) |
execute winwidth(0)/g:gpt_split_ratio.'vsplit ' . chat_gpt_session_id |
||||
endfor |
else |
||||
|
execute winheight(0)/g:gpt_split_ratio.'split ' . chat_gpt_session_id |
||||
call setbufline(chat_gpt_session_id, '$', clean_lines) |
endif |
||||
|
endif |
||||
execute bufwinnr(chat_gpt_session_id) . 'wincmd w' |
|
||||
|
let last_lines = getbufline(chat_gpt_session_id, '$') |
||||
|
let last_line = empty(last_lines) ? '' : last_lines[-1] |
||||
|
|
||||
|
let new_lines = substitute(last_line . response, '\n', '\r\n\r', 'g') |
||||
|
let lines = split(new_lines, '\n') |
||||
|
|
||||
|
let clean_lines = [] |
||||
|
for line in lines |
||||
|
call add(clean_lines, substitute(line, '\r', '', 'g')) |
||||
|
endfor |
||||
|
|
||||
|
call setbufline(chat_gpt_session_id, '$', clean_lines) |
||||
|
|
||||
|
execute bufwinnr(chat_gpt_session_id) . 'wincmd w' |
||||
" Move the viewport to the bottom of the buffer |
" Move the viewport to the bottom of the buffer |
||||
normal! G |
normal! G |
||||
call cursor('$', 1) |
call cursor('$', 1) |
||||
|
|
||||
if finish_reason != '' |
if finish_reason != '' |
||||
wincmd p |
wincmd p |
||||
endif |
endif |
||||
endfunction |
endfunction |
||||
|
|
||||
" }}} |
" }}} |
||||
|
|
||||
function! ChatGPT(prompt, persist) abort " {{{ |
function! Gpt(prompt, persist) abort " {{{ |
||||
" echo 'prompt: ' . a:prompt |
" echo 'prompt: ' . a:prompt |
||||
" echo 'persist: ' . a:persist |
" echo 'persist: ' . a:persist |
||||
|
silent py3file ~/.vim/python/gpt.py |
||||
silent py3file ~/.vim/python/gpt.py |
|
||||
endfunction |
endfunction |
||||
|
|
||||
" }}} |
" }}} |
||||
|
|
||||
function! SendToChatGPT(prompt, bang) abort " {{{ |
function! GptSend(prompt, bang) abort " {{{ |
||||
|
|
||||
let persist = (a:bang ==# '!') ? 1 : 0 |
let persist = (a:bang ==# '!') ? 1 : 0 |
||||
|
|
||||
let save_cursor = getcurpos() |
let save_cursor = getcurpos() |
||||
let [current_line, current_col] = getcurpos()[1:2] |
let [current_line, current_col] = getcurpos()[1:2] |
||||
let save_reg = @@ |
let save_reg = @@ |
||||
let save_regtype = getregtype('@') |
let save_regtype = getregtype('@') |
||||
|
|
||||
let [line_start, col_start] = getpos("'<")[1:2] |
let [line_start, col_start] = getpos("'<")[1:2] |
||||
let [line_end, col_end] = getpos("'>")[1:2] |
let [line_end, col_end] = getpos("'>")[1:2] |
||||
|
|
||||
if (col_end - col_start > 0 || line_end - line_start > 0) && |
if (col_end - col_start > 0 || line_end - line_start > 0) && |
||||
\ (current_line == line_start && current_col == col_start || |
\ (current_line == line_start && current_col == col_start || |
||||
\ current_line == line_end && current_col == col_end) |
\ current_line == line_end && current_col == col_end) |
||||
|
|
||||
let current_line_start = line_start |
let current_line_start = line_start |
||||
let current_line_end = line_end |
let current_line_end = line_end |
||||
|
|
||||
if current_line_start == line_start && current_line_end == line_end |
|
||||
execute 'normal! ' . line_start . 'G' . col_start . '|v' . line_end . 'G' . col_end . '|y' |
|
||||
let snippet = "\n" . '```' . &syntax . "\n" . @@ . "\n" . '```' |
|
||||
else |
|
||||
let snippet = '' |
|
||||
endif |
|
||||
else |
|
||||
let snippet = '' |
|
||||
endif |
|
||||
|
|
||||
if has_key(g:gpt_templates, a:prompt) |
|
||||
let prompt = g:gpt_templates[a:prompt] |
|
||||
else |
|
||||
let prompt = a:prompt |
|
||||
endif |
|
||||
|
|
||||
let prompt = prompt . snippet |
if current_line_start == line_start && current_line_end == line_end |
||||
|
execute 'normal! ' . line_start . 'G' . col_start . '|v' . line_end . 'G' . col_end . '|y' |
||||
|
let snippet = "\n" . '```' . &syntax . "\n" . @@ . "\n" . '```' |
||||
|
else |
||||
|
let snippet = '' |
||||
|
endif |
||||
|
else |
||||
|
let snippet = '' |
||||
|
endif |
||||
|
|
||||
call ChatGPT(prompt, persist) |
let prompt = a:prompt . snippet |
||||
|
|
||||
let @@ = save_reg |
call Gpt(prompt, persist) |
||||
call setreg('@', save_reg, save_regtype) |
|
||||
|
let @@ = save_reg |
||||
|
call setreg('@', save_reg, save_regtype) |
||||
|
|
||||
|
let curpos = getcurpos() |
||||
|
call setpos("'<", curpos) |
||||
|
call setpos("'>", curpos) |
||||
|
call setpos('.', save_cursor) |
||||
|
|
||||
let curpos = getcurpos() |
|
||||
call setpos("'<", curpos) |
|
||||
call setpos("'>", curpos) |
|
||||
call setpos('.', save_cursor) |
|
||||
endfunction |
endfunction |
||||
|
|
||||
" }}} |
" }}} |
||||
|
|
||||
command! -range -bang -nargs=1 Gpt call SendToChatGPT(<q-args>, '<bang>') |
function! GptPersona(persona=0) " {{{ |
||||
|
if a:persona == 0 |
||||
for i in range(len(g:gpt_keys)) |
echo 'Personas: ' . join(keys(g:gpt_personas), ', ') |
||||
execute "command! -range -bang -nargs=0 " . g:gpt_keys[i] . " call SendToChatGPT('" . g:gpt_keys[i] . "', '<bang>')" |
return |
||||
endfor |
endif |
||||
|
|
||||
function! SetPersona(persona) " {{{ |
let personas = keys(g:gpt_personas) |
||||
let personas = keys(g:gpt_personas) |
|
||||
if index(personas, a:persona) != -1 |
if index(personas, a:persona) != -1 |
||||
echo 'Persona set to: ' . a:persona |
echo 'Persona set to: ' . a:persona |
||||
let g:gpt_persona = a:persona |
let g:gpt_persona = a:persona |
||||
else |
else |
||||
let g:gpt_persona = 'default' |
let g:gpt_persona = 'default' |
||||
echo a:persona . ' is not a valid persona. Defaulting to: ' . g:gpt_persona |
echo a:persona . ' is not a valid persona. Defaulting to: ' . g:gpt_persona |
||||
end |
end |
||||
|
|
||||
|
endfunction |
||||
|
|
||||
|
" }}} |
||||
|
|
||||
|
function! GptModel(model=0) " {{{ |
||||
|
if a:model == 0 |
||||
|
echo 'Models: ' . join(keys(g:gpt_models), ', ') |
||||
|
return |
||||
|
endif |
||||
|
|
||||
|
let models = keys(g:gpt_models) |
||||
|
|
||||
|
if index(models, a:model) != -1 |
||||
|
echo 'model set to: ' . a:model |
||||
|
let g:gpt_model = a:model |
||||
|
else |
||||
|
let g:gpt_model = 'gpt-4o' |
||||
|
echo a:model . ' is not a valid model. Defaulting to: ' . g:gpt_model |
||||
|
end |
||||
endfunction |
endfunction |
||||
|
|
||||
" }}} |
" }}} |
||||
|
|
||||
command! -nargs=1 Persona call SetPersona(<q-args>) |
command! -nargs=0 GptInfo call GptInfo() |
||||
|
command! -nargs=1 -range -bang Gpt call GptSend(<q-args>, '<bang>') |
||||
|
command! -nargs=? GptPersona call GptPersona(<q-args>) |
||||
|
command! -nargs=? GptModel call GptModel(<q-args>) |
||||
|
Loading…
Reference in new issue