Skip to content

Commit

Permalink
Cleanup auto insert behaviour and add support for insert at end
Browse files Browse the repository at this point in the history
- Cleanup auto insert behaviour and move it to chat.lua
- Add support for moving cursor to end of buffer before entering insert mode in the chat buffer
- Cleanup configuration (move yank register config near the mapping)

Closes #379

Signed-off-by: Tomas Slusny <[email protected]>
  • Loading branch information
deathbeam committed Aug 31, 2024
1 parent 43d033b commit 1c67656
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 55 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,6 @@ Also see [here](/lua/CopilotChat/config.lua):
proxy = nil, -- [protocol://]host[:port] Use this proxy
allow_insecure = false, -- Allow insecure server connections

yank_diff_register = '"', -- Allow overriding the register for yanking diffs

system_prompt = prompts.COPILOT_INSTRUCTIONS, -- System prompt to use
model = 'gpt-4o', -- GPT model to use, 'gpt-3.5-turbo', 'gpt-4', or 'gpt-4o'
temperature = 0.1, -- GPT temperature
Expand All @@ -215,7 +213,8 @@ Also see [here](/lua/CopilotChat/config.lua):
show_folds = true, -- Shows folds for sections in chat
show_help = true, -- Shows help message as virtual lines when waiting for user input
auto_follow_cursor = true, -- Auto-follow cursor in chat
auto_insert_mode = false, -- Automatically enter insert mode when opening window and if auto follow cursor is enabled on new prompt
auto_insert_mode = false, -- Automatically enter insert mode when opening window and on new prompt
insert_at_end = false, -- Move cursor to end of buffer when inserting text
clear_chat_on_new_prompt = false, -- Clears chat on every new prompt
highlight_selection = true, -- Highlight selection in the source buffer when in the chat window

Expand Down Expand Up @@ -306,6 +305,7 @@ Also see [here](/lua/CopilotChat/config.lua):
},
yank_diff = {
normal = 'gy',
register = '"',
},
show_diff = {
normal = 'gd'
Expand Down
18 changes: 17 additions & 1 deletion lua/CopilotChat/chat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ function CopilotChatFoldExpr(lnum, separator)
return '='
end

local Chat = class(function(self, help, on_buf_create)
local Chat = class(function(self, help, auto_insert, on_buf_create)
self.header_ns = vim.api.nvim_create_namespace('copilot-chat-headers')
self.help = help
self.auto_insert = auto_insert
self.on_buf_create = on_buf_create
self.bufnr = nil
self.winnr = nil
Expand Down Expand Up @@ -118,6 +119,10 @@ end
function Chat:append(str)
self:validate()

if self:active() then
utils.return_to_normal_mode()
end

if self.spinner then
self.spinner:start()
end
Expand Down Expand Up @@ -217,18 +222,26 @@ function Chat:close(bufnr)
end

if self:visible() then
if self:active() then
utils.return_to_normal_mode()
end

if self.layout == 'replace' then
self:restore(self.winnr, bufnr)
else
vim.api.nvim_win_close(self.winnr, true)
end

self.winnr = nil
end
end

function Chat:focus()
if self:visible() then
vim.api.nvim_set_current_win(self.winnr)
if self.auto_insert and self:active() then
vim.cmd('startinsert')
end
end
end

Expand Down Expand Up @@ -261,6 +274,9 @@ function Chat:finish(msg)
end

self:show_help(msg, -2)
if self.auto_insert and self:active() then
vim.cmd('startinsert')
end
end

return Chat
9 changes: 4 additions & 5 deletions lua/CopilotChat/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ local select = require('CopilotChat.select')
---@field proxy string?
---@field allow_insecure boolean?
---@field system_prompt string?
---@field yank_diff_register string?
---@field model string?
---@field temperature number?
---@field question_header string?
Expand All @@ -83,8 +82,6 @@ return {
proxy = nil, -- [protocol://]host[:port] Use this proxy
allow_insecure = false, -- Allow insecure server connections

yank_diff_register = '"', -- Allows overriding the register for yanking diffs

system_prompt = prompts.COPILOT_INSTRUCTIONS, -- System prompt to use
model = 'gpt-4o-2024-05-13', -- GPT model to use, 'gpt-3.5-turbo', 'gpt-4', or `gpt-4o-2024-05-13`
temperature = 0.1, -- GPT temperature
Expand All @@ -97,7 +94,8 @@ return {
show_folds = true, -- Shows folds for sections in chat
show_help = true, -- Shows help message as virtual lines when waiting for user input
auto_follow_cursor = true, -- Auto-follow cursor in chat
auto_insert_mode = false, -- Automatically enter insert mode when opening window and if auto follow cursor is enabled on new prompt
auto_insert_mode = false, -- Automatically enter insert mode when opening window and on new prompt
insert_at_end = false, -- Move cursor to end of buffer when inserting text
clear_chat_on_new_prompt = false, -- Clears chat on every new prompt
highlight_selection = true, -- Highlight selection

Expand Down Expand Up @@ -197,7 +195,7 @@ return {
zindex = 1, -- determines if window is on top or below other floating windows
},

-- default mappings (in tables first is normal mode, second is insert mode)
-- default mappings
mappings = {
complete = {
detail = 'Use @<Tab> or /<Tab> for options.',
Expand All @@ -221,6 +219,7 @@ return {
},
yank_diff = {
normal = 'gy',
register = '"',
},
show_diff = {
normal = 'gd',
Expand Down
80 changes: 39 additions & 41 deletions lua/CopilotChat/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ end
--- Open the chat window.
---@param config CopilotChat.config|CopilotChat.config.prompt|nil
---@param source CopilotChat.config.source?
function M.open(config, source, no_insert)
function M.open(config, source)
config = vim.tbl_deep_extend('force', M.config, config or {})
local should_reset = state.config and not utils.table_equals(config.window, state.config.window)
state.config = config
Expand All @@ -316,31 +316,20 @@ function M.open(config, source, no_insert)
winnr = vim.api.nvim_get_current_win(),
})

vim.cmd('stopinsert')
utils.exit_visual_mode()
utils.return_to_normal_mode()

-- Recreate the window if the layout has changed
if should_reset then
M.close()
end

state.chat:open(config)
state.chat:focus()
state.chat:follow()

if
not no_insert
and not state.copilot:running()
and M.config.auto_insert_mode
and state.chat:active()
then
vim.cmd('startinsert')
end
state.chat:focus()
end

--- Close the chat window.
function M.close()
vim.cmd('stopinsert')
state.chat:close(state.source and state.source.bufnr or nil)
end

Expand Down Expand Up @@ -387,10 +376,10 @@ function M.ask(prompt, config, source)
return
end

M.open(config, source, true)
M.open(config, source)

if config.clear_chat_on_new_prompt then
M.stop(true, true)
M.stop(true)
end

state.last_system_prompt = system_prompt
Expand All @@ -412,7 +401,6 @@ function M.ask(prompt, config, source)

append(updated_prompt)
append('\n\n' .. config.answer_header .. config.separator .. '\n\n')
state.chat:follow()

local selected_context = config.context
if string.find(prompt, '@buffers') then
Expand All @@ -428,9 +416,6 @@ function M.ask(prompt, config, source)
append('```\n' .. err .. '\n```')
append('\n\n' .. config.question_header .. config.separator .. '\n\n')
state.chat:finish()
if M.config.auto_follow_cursor and M.config.auto_insert_mode and state.chat:active() then
vim.cmd('startinsert')
end
end)
end

Expand Down Expand Up @@ -466,9 +451,6 @@ function M.ask(prompt, config, source)
if config.callback then
config.callback(response, state.source)
end
if config.auto_follow_cursor and config.auto_insert_mode and state.chat:active() then
vim.cmd('startinsert')
end
end)
end,
on_progress = function(token)
Expand All @@ -483,7 +465,7 @@ end

--- Stop current copilot output and optionally reset the chat ten show the help message.
---@param reset boolean?
function M.stop(reset, no_insert)
function M.stop(reset)
state.response = nil
local stopped = reset and state.copilot:reset() or state.copilot:stop()
local wrap = vim.schedule
Expand All @@ -501,11 +483,6 @@ function M.stop(reset, no_insert)
end
append(M.config.question_header .. M.config.separator .. '\n\n')
state.chat:finish()
state.chat:follow()

if not no_insert and M.config.auto_insert_mode and state.chat:active() then
vim.cmd('startinsert')
end
end)
end

Expand Down Expand Up @@ -589,19 +566,29 @@ end
function M.setup(config)
-- Handle old mapping format and show error
local found_old_format = false
if config and config.mappings then
for name, key in pairs(config.mappings) do
if type(key) == 'string' then
vim.notify(
'config.mappings.'
.. name
.. ": 'mappings' format have changed, please update your configuration, for now revering to default settings. See ':help CopilotChat-configuration' for current format",
vim.log.levels.ERROR
)
found_old_format = true
if config then
if config.mappings then
for name, key in pairs(config.mappings) do
if type(key) == 'string' then
vim.notify(
'config.mappings.'
.. name
.. ": 'mappings' format have changed, please update your configuration, for now revering to default settings. See ':help CopilotChat-configuration' for current format",
vim.log.levels.ERROR
)
found_old_format = true
end
end
end

if config.yank_diff_register then
vim.notify(
'config.yank_diff_register: This option has been removed, please use mappings.yank_diff.register instead',
vim.log.levels.ERROR
)
end
end

if found_old_format then
config.mappings = nil
end
Expand Down Expand Up @@ -722,7 +709,7 @@ function M.setup(config)
state.chat:close(state.source and state.source.bufnr or nil)
state.chat:delete()
end
state.chat = Chat(chat_help, function(bufnr)
state.chat = Chat(chat_help, M.config.auto_insert_mode, function(bufnr)
map_key(M.config.mappings.complete, bufnr, complete)
map_key(M.config.mappings.reset, bufnr, M.reset)
map_key(M.config.mappings.close, bufnr, M.close)
Expand Down Expand Up @@ -775,7 +762,7 @@ function M.setup(config)
local lines = find_lines_between_separator(section_lines, '^```%w*$', true)
if #lines > 0 then
local content = table.concat(lines, '\n')
vim.fn.setreg(M.config.yank_diff_register, content)
vim.fn.setreg(M.config.mappings.yank_diff.register, content)
end
end)

Expand Down Expand Up @@ -841,6 +828,17 @@ function M.setup(config)
end,
})

if M.config.insert_at_end then
vim.api.nvim_create_autocmd({ 'InsertEnter' }, {
buffer = state.chat.bufnr,
callback = function()
vim.cmd('normal! 0')
vim.cmd('normal! G$')
vim.v.char = 'x'
end,
})
end

append(M.config.question_header .. M.config.separator .. '\n\n')
state.chat:finish()
end)
Expand Down
2 changes: 1 addition & 1 deletion lua/CopilotChat/integrations/fzflua.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function M.pick(pick_actions, opts)
return
end

utils.exit_visual_mode()
utils.return_to_normal_mode()
opts = vim.tbl_extend('force', {
prompt = pick_actions.prompt .. '> ',
preview = fzflua.shell.raw_preview_action_cmd(function(items)
Expand Down
2 changes: 1 addition & 1 deletion lua/CopilotChat/integrations/telescope.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function M.pick(pick_actions, opts)
return
end

utils.exit_visual_mode()
utils.return_to_normal_mode()
opts = themes.get_dropdown(opts or {})
pickers
.new(opts, {
Expand Down
9 changes: 6 additions & 3 deletions lua/CopilotChat/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,14 @@ function M.table_equals(a, b)
return true
end

--- Exit visual mode if we are in it
function M.exit_visual_mode()
if vim.fn.mode():lower():find('v') then
--- Return to normal mode
function M.return_to_normal_mode()
local mode = vim.fn.mode():lower()
if mode:find('v') then
-- NOTE: vim.cmd('normal! v') does not work properly when executed from keymap
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<esc>', true, false, true), 'x', false)
elseif mode:find('i') then
vim.cmd('stopinsert')
end
end

Expand Down

0 comments on commit 1c67656

Please sign in to comment.