Browse Source

lazygit

dev
Gregory Leeman 7 days ago
parent
commit
29af9e0ab9
  1. 299
      plugin/gpt.vim
  2. 37
      python/gpt.py
  3. 9
      vimrc

299
plugin/gpt.vim

@ -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>)

37
python/gpt.py

@ -3,7 +3,7 @@ import vim
import os import os
try: try:
from openai import AzureOpenAI, OpenAI from openai import OpenAI
except ImportError: except ImportError:
print("Error: openai module not found. Please install with Pip and ensure equality of the versions given by :!python3 -V, and :python3 import sys; print(sys.version)") print("Error: openai module not found. Please install with Pip and ensure equality of the versions given by :!python3 -V, and :python3 import sys; print(sys.version)")
raise raise
@ -15,31 +15,16 @@ def safe_vim_eval(expression):
return None return None
def create_client(): def create_client():
api_type = safe_vim_eval('g:gpt_api_type')
api_key = os.getenv('OPENAI_API_KEY') or safe_vim_eval('g:gpt_key') or safe_vim_eval('g:gpt_openai_api_key') api_key = os.getenv('OPENAI_API_KEY') or safe_vim_eval('g:gpt_key') or safe_vim_eval('g:gpt_openai_api_key')
openai_base_url = os.getenv('OPENAI_PROXY') or os.getenv('OPENAI_API_BASE') or safe_vim_eval('g:gpt_openai_base_url') openai_base_url = os.getenv('OPENAI_PROXY') or os.getenv('OPENAI_API_BASE') or safe_vim_eval('g:gpt_openai_base_url')
client = OpenAI(
if api_type == 'azure': base_url=openai_base_url,
azure_endpoint = safe_vim_eval('g:gpt_azure_endpoint') api_key=api_key,
azure_api_version = safe_vim_eval('g:gpt_azure_api_version') )
azure_deployment = safe_vim_eval('g:gpt_azure_deployment')
assert azure_endpoint and azure_api_version and azure_deployment, "azure_endpoint, azure_api_version and azure_deployment not set property, please check your settings in `vimrc` or `enviroment`."
assert api_key, "api_key not set, please configure your `openai_api_key` in your `vimrc` or `enviroment`"
client = AzureOpenAI(
azure_endpoint=azure_endpoint,
azure_deployment=azure_deployment,
api_key=api_key,
api_version=azure_api_version,
)
else:
client = OpenAI(
base_url=openai_base_url,
api_key=api_key,
)
return client return client
def chat_gpt(prompt, persist=0): def chat_gpt(prompt, persist=0)
token_limits = { token_limits = {
"gpt-3.5-turbo": 4097, "gpt-3.5-turbo": 4097,
"gpt-3.5-turbo-16k": 16385, "gpt-3.5-turbo-16k": 16385,
@ -54,6 +39,7 @@ def chat_gpt(prompt, persist=0):
max_tokens = int(vim.eval('g:gpt_max_tokens')) max_tokens = int(vim.eval('g:gpt_max_tokens'))
model = str(vim.eval('g:gpt_model')) model = str(vim.eval('g:gpt_model'))
token_limit = vim.eval('g:gpt_models[g:gpt_model]')
temperature = float(vim.eval('g:gpt_temperature')) temperature = float(vim.eval('g:gpt_temperature'))
lang = str(vim.eval('g:gpt_lang')) lang = str(vim.eval('g:gpt_lang'))
resp = f" And respond in {lang}." if lang != 'None' else "" resp = f" And respond in {lang}." if lang != 'None' else ""
@ -80,7 +66,7 @@ def chat_gpt(prompt, persist=0):
history.reverse() history.reverse()
# Adding messages to history until token limit is reached # Adding messages to history until token limit is reached
token_count = token_limits.get(model, 4097) - max_tokens - len(prompt) - len(str(systemCtx)) token_count = token_limit - max_tokens - len(prompt) - len(str(systemCtx))
for line in history: for line in history:
if line.startswith("USER\n"): if line.startswith("USER\n"):
@ -104,7 +90,7 @@ def chat_gpt(prompt, persist=0):
content += '# GPT' content += '# GPT'
content += '\n\n>>> USER\n' + prompt + '\n\n>>> ASSISTANT\n'.replace("'", "''") content += '\n\n>>> USER\n' + prompt + '\n\n>>> ASSISTANT\n'.replace("'", "''")
vim.command("call DisplayChatGPTResponse('{0}', '', '{1}')".format(content.replace("'", "''"), session_id)) vim.command("call GptDisplay('{0}', '', '{1}')".format(content.replace("'", "''"), session_id))
vim.command("redraw") vim.command("redraw")
messages.append({"role": "user", "content": prompt}) messages.append({"role": "user", "content": prompt})
@ -131,12 +117,11 @@ def chat_gpt(prompt, persist=0):
choice = chunk.choices[0] choice = chunk.choices[0]
finish_reason = choice.finish_reason finish_reason = choice.finish_reason
# Call DisplayChatGPTResponse with the finish_reason or content
if finish_reason: if finish_reason:
vim.command("call DisplayChatGPTResponse('', '{0}', '{1}')".format(finish_reason.replace("'", "''"), chunk_session_id)) vim.command("call GptDisplay('', '{0}', '{1}')".format(finish_reason.replace("'", "''"), chunk_session_id))
elif choice.delta: elif choice.delta:
content = choice.delta.content content = choice.delta.content
vim.command("call DisplayChatGPTResponse('{0}', '', '{1}')".format(content.replace("'", "''"), chunk_session_id)) vim.command("call GptDisplay('{0}', '', '{1}')".format(content.replace("'", "''"), chunk_session_id))
vim.command("redraw") vim.command("redraw")
except Exception as e: except Exception as e:

9
vimrc

@ -153,13 +153,4 @@ set completeopt=noinsert,menuone,noselect
let g:slime_target = "tmux" let g:slime_target = "tmux"
let g:slime_default_config = {"socket_name": get(split($TMUX, ","), 0), "target_pane": ":.2"} let g:slime_default_config = {"socket_name": get(split($TMUX, ","), 0), "target_pane": ":.2"}
let g:gpt_openai_api_key='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' let g:gpt_openai_api_key='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'
let g:gpt_max_tokens=2000
let g:gpt_model='gpt-4o'
let g:gpt_temperature = 0.7
let g:gpt_lang = 'English'
" let g:chat_gpt_split_direction = 'vertical'
" let g:split_ratio=4
vmap <silent> <leader>0 <Plug>(chatgpt-menu)

Loading…
Cancel
Save