Skip to content

Commit

Permalink
feat: add support for folds
Browse files Browse the repository at this point in the history
* Add support for folds

- Add show_system_prompt option
- Add show_user_selection option
- Add show_folds option

* chore: remove name on plugin

---------

Co-authored-by: Tomas Slusny <ts6234@att.com>
Co-authored-by: Dung Duc Huynh (Kaka) <870029+jellydn@users.noreply.github.com>

chore: add missing name on config
  • Loading branch information
deathbeam authored and jellydn committed Feb 28, 2024
1 parent 601ed82 commit e85f379
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 45 deletions.
7 changes: 4 additions & 3 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ Also make sure to run `:UpdateRemotePlugins` to cleanup the old python commands.
Removed or changed params that you pass to `setup`:

- `show_help` was removed (the help is now always shown as virtual text, and not intrusive)
- `hide_system_prompt` was removed (it is part of `disable_extra_info`)
- `disable_extra_info` was renamed to `show_user_selection`
- `hide_system_prompt` was renamed to `show_system_prompt`
- `proxy` does not work at the moment (waiting for change in plenary.nvim), if you are behind corporate proxy you can look at something like [vpn-slice](https://github.com/dlenski/vpn-slice)
- `language` was removed and is now part of `selection` as `selection.filetype`

Expand Down Expand Up @@ -58,8 +59,8 @@ end, { nargs = '*', range = true })
- [ ] For proxy support, this is needed: https://github.com/nvim-lua/plenary.nvim/pull/559
- [ ] Delete rest of the python code? Or finish rewriting in place then delete
- [ ] Check for curl availability with health check
- [ ] Add folds logic from python, maybe? Not sure if this is even needed
- [x] Add folds logic from python, maybe? Not sure if this is even needed
- [ ] As said in changes part, finish rewriting the authentication request if needed
- [ ] Properly get token file path, atm it only supports Linux (easy fix)
- [x] Properly get token file path, atm it only supports Linux (easy fix)
- [ ] Update README and stuff
- [ ] Add token count support to extra_info, something like this called from lua:
25 changes: 4 additions & 21 deletions lua/CopilotChat/copilot.lua
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,8 @@ local function authenticate(github_token)
return sessionid, token, nil
end

local Copilot = class(function(self, show_extra_info)
local Copilot = class(function(self)
self.github_token = get_cached_token()
self.show_extra_info = show_extra_info or false
self.history = {}
self.token = nil
self.sessionid = nil
Expand Down Expand Up @@ -182,16 +181,6 @@ function Copilot:ask(prompt, opts)
log.debug('Model: ' .. model)
log.debug('Temperature: ' .. temperature)

if self.show_extra_info and on_progress then
on_progress('SYSTEM PROMPT:\n```\n' .. system_prompt .. '```\n')

if selection ~= '' then
on_progress('CODE:\n```' .. filetype .. '\n' .. selection .. '\n```')
end

on_done('')
end

table.insert(self.history, {
content = prompt,
role = 'user',
Expand All @@ -202,14 +191,6 @@ function Copilot:ask(prompt, opts)
self:stop()
end

-- Notify the user about current prompt
if on_progress then
on_progress(prompt)
end
if on_done then
on_done(prompt)
end

if on_start then
on_start()
end
Expand Down Expand Up @@ -262,7 +243,9 @@ function Copilot:ask(prompt, opts)

if not ok then
log.error('Failed parse response: ' .. tostring(err))
on_error(content)
if on_error then
on_error(content)
end
return
end

Expand Down
76 changes: 55 additions & 21 deletions lua/CopilotChat/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,24 @@ local select = require('CopilotChat.select')
local debuginfo = require('CopilotChat.debuginfo')

local M = {}
local plugin_name = 'CopilotChat.nvim'
local state = {
copilot = nil,
chat = nil,
selection = nil,
window = nil,
}

function CopilotChatFoldExpr(lnum, separator)
local line = vim.fn.getline(lnum)
vim.print(line)
if string.match(line, separator .. '$') then
return '>1'
end

return '='
end

local function find_lines_between_separator_at_cursor(bufnr, separator)
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
local cursor = vim.api.nvim_win_get_cursor(0)
Expand Down Expand Up @@ -175,7 +186,7 @@ function M.open(config)
local just_created = false

if not state.chat or not state.chat:valid() then
state.chat = Chat(M.config.name)
state.chat = Chat(plugin_name)
just_created = true

if config.mappings.complete then
Expand All @@ -193,8 +204,8 @@ function M.open(config)
if config.mappings.submit_prompt then
vim.keymap.set('n', config.mappings.submit_prompt, function()
local input, start_line, end_line, line_count =
find_lines_between_separator_at_cursor(state.chat.bufnr, M.config.separator)
if input ~= '' and not vim.startswith(vim.trim(input), '**' .. M.config.name .. ':**') then
find_lines_between_separator_at_cursor(state.chat.bufnr, config.separator)
if input ~= '' and not vim.startswith(vim.trim(input), '**' .. config.name .. ':**') then
-- If we are entering the input at the end, replace it
if line_count == end_line then
vim.api.nvim_buf_set_lines(state.chat.bufnr, start_line, end_line, false, { '' })
Expand Down Expand Up @@ -265,6 +276,15 @@ function M.open(config)
vim.wo[state.window].cursorline = true
vim.wo[state.window].conceallevel = 2
vim.wo[state.window].concealcursor = 'niv'
if config.show_folds then
vim.wo[state.window].foldcolumn = '1'
vim.wo[state.window].foldmethod = 'expr'
vim.wo[state.window].foldexpr = "v:lua.CopilotChatFoldExpr(v:lnum, '"
.. config.separator
.. "')"
else
vim.wo[state.window].foldcolumn = '0'
end

if just_created then
M.reset()
Expand Down Expand Up @@ -327,7 +347,26 @@ function M.ask(prompt, config)
updated_prompt = updated_prompt .. ' ' .. state.selection.prompt_extra
end

local just_started = true
local finish = false
if config.show_system_prompt then
finish = true
append(' **System prompt** ---\n```\n' .. system_prompt .. '```\n')
end
if config.show_user_selection and state.selection and state.selection.lines ~= '' then
finish = true
append(
' **Selection** ---\n```'
.. (state.selection.filetype or '')
.. '\n'
.. state.selection.lines
.. '\n```'
)
end
if finish then
append('\n' .. config.separator .. '\n\n')
end

append(updated_prompt)

return state.copilot:ask(updated_prompt, {
selection = state.selection.lines,
Expand All @@ -336,21 +375,14 @@ function M.ask(prompt, config)
model = config.model,
temperature = config.temperature,
on_start = function()
append('\n\n **' .. config.name .. '** ' .. config.separator .. '\n\n')
state.chat.spinner:start()
append('**' .. M.config.name .. ':** ')
just_started = true
end,
on_done = function()
append('\n\n' .. M.config.separator .. '\n\n')
append('\n\n' .. config.separator .. '\n\n')
show_help()
end,
on_progress = function(token)
-- Add a newline if the token is not a word and we just started (for example code block)
if just_started and not token:match('^%w') then
token = '\n' .. token
end

just_started = false
append(token)
end,
})
Expand All @@ -370,9 +402,11 @@ M.config = {
system_prompt = prompts.COPILOT_INSTRUCTIONS,
model = 'gpt-4',
temperature = 0.1,
debug = false,
clear_chat_on_new_prompt = false,
disable_extra_info = true,
debug = false, -- Enable debug logging
show_user_selection = true, -- Shows user selection in chat
show_system_prompt = false, -- Shows system prompt in chat
show_folds = true, -- Shows folds for sections in chat
clear_chat_on_new_prompt = false, -- Clears chat on every new prompt
name = 'CopilotChat',
separator = '---',
prompts = {
Expand Down Expand Up @@ -422,12 +456,12 @@ M.config = {
-- - mappings: (table?).
function M.setup(config)
M.config = vim.tbl_deep_extend('force', M.config, config or {})
state.copilot = Copilot(not M.config.disable_extra_info)
state.copilot = Copilot()
debuginfo.setup()

local logfile = string.format('%s/%s.log', vim.fn.stdpath('state'), 'CopilotChat.nvim')
local logfile = string.format('%s/%s.log', vim.fn.stdpath('state'), plugin_name)
log.new({
plugin = M.config.name,
plugin = plugin_name,
level = M.config.debug and 'trace' or 'warn',
outfile = logfile,
}, true)
Expand All @@ -444,13 +478,13 @@ function M.setup(config)
nargs = '*',
force = true,
range = true,
desc = prompt.description or ('CopilotChat.nvim ' .. name),
desc = prompt.description or (plugin_name .. ' ' .. name),
})

if prompt.mapping then
vim.keymap.set({ 'n', 'v' }, prompt.mapping, function()
M.ask(prompt.prompt, prompt)
end, { desc = prompt.description or ('CopilotChat.nvim ' .. name) })
end, { desc = prompt.description or (plugin_name .. ' ' .. name) })
end
end

Expand Down

0 comments on commit e85f379

Please sign in to comment.