feat(experimental): slash commands (#162)
* feat(experimental): slash commands Signed-off-by: Aaron Pham <contact@aarnphm.xyz> * fix(jump): add binding jumping between codeblock Signed-off-by: Aaron Pham <contact@aarnphm.xyz> * chore: add docs Signed-off-by: Aaron Pham <contact@aarnphm.xyz> --------- Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
This commit is contained in:
parent
1245508063
commit
1cbf7e106c
@ -214,6 +214,7 @@ The following key bindings are available for use with `avante.nvim`:
|
|||||||
- [x] Chat with current file
|
- [x] Chat with current file
|
||||||
- [x] Apply diff patch
|
- [x] Apply diff patch
|
||||||
- [x] Chat with the selected block
|
- [x] Chat with the selected block
|
||||||
|
- [x] Slash commands
|
||||||
- [ ] Edit the selected block
|
- [ ] Edit the selected block
|
||||||
- [ ] Smart Tab (Cursor Flow)
|
- [ ] Smart Tab (Cursor Flow)
|
||||||
- [ ] Chat with project
|
- [ ] Chat with project
|
||||||
|
@ -505,6 +505,53 @@ function Sidebar:on_mount()
|
|||||||
---@type AvanteCodeblock[]
|
---@type AvanteCodeblock[]
|
||||||
local codeblocks = {}
|
local codeblocks = {}
|
||||||
|
|
||||||
|
---@param direction "next" | "prev"
|
||||||
|
local function jump_to_codeblock(direction)
|
||||||
|
local cursor_line = api.nvim_win_get_cursor(self.result.winid)[1]
|
||||||
|
---@type AvanteCodeblock
|
||||||
|
local target_block
|
||||||
|
|
||||||
|
if direction == "next" then
|
||||||
|
for _, block in ipairs(codeblocks) do
|
||||||
|
if block.start_line > cursor_line then
|
||||||
|
target_block = block
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not target_block and #codeblocks > 0 then
|
||||||
|
target_block = codeblocks[1]
|
||||||
|
end
|
||||||
|
elseif direction == "prev" then
|
||||||
|
for i = #codeblocks, 1, -1 do
|
||||||
|
if codeblocks[i].end_line < cursor_line then
|
||||||
|
target_block = codeblocks[i]
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not target_block and #codeblocks > 0 then
|
||||||
|
target_block = codeblocks[#codeblocks]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if target_block then
|
||||||
|
api.nvim_win_set_cursor(self.result.winid, { target_block.start_line + 1, 0 })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function bind_jump_keys()
|
||||||
|
vim.keymap.set("n", Config.mappings.jump.next, function()
|
||||||
|
jump_to_codeblock("next")
|
||||||
|
end, { buffer = self.result.bufnr, noremap = true, silent = true })
|
||||||
|
vim.keymap.set("n", Config.mappings.jump.prev, function()
|
||||||
|
jump_to_codeblock("prev")
|
||||||
|
end, { buffer = self.result.bufnr, noremap = true, silent = true })
|
||||||
|
end
|
||||||
|
|
||||||
|
local function unbind_jump_keys()
|
||||||
|
pcall(vim.keymap.del, "n", "]c", { buffer = self.result.bufnr })
|
||||||
|
pcall(vim.keymap.del, "n", "[c", { buffer = self.result.bufnr })
|
||||||
|
end
|
||||||
|
|
||||||
api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, {
|
api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, {
|
||||||
buffer = self.result.bufnr,
|
buffer = self.result.bufnr,
|
||||||
callback = function(ev)
|
callback = function(ev)
|
||||||
@ -524,6 +571,7 @@ function Sidebar:on_mount()
|
|||||||
buffer = self.result.bufnr,
|
buffer = self.result.bufnr,
|
||||||
callback = function(ev)
|
callback = function(ev)
|
||||||
codeblocks = parse_codeblocks(ev.buf)
|
codeblocks = parse_codeblocks(ev.buf)
|
||||||
|
bind_jump_keys()
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -534,6 +582,14 @@ function Sidebar:on_mount()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
codeblocks = parse_codeblocks(self.result.bufnr)
|
codeblocks = parse_codeblocks(self.result.bufnr)
|
||||||
|
bind_jump_keys()
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
api.nvim_create_autocmd("BufLeave", {
|
||||||
|
buffer = self.result.bufnr,
|
||||||
|
callback = function()
|
||||||
|
unbind_jump_keys()
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1063,17 +1119,9 @@ function Sidebar:create_input()
|
|||||||
|
|
||||||
local chat_history = load_chat_history(self)
|
local chat_history = load_chat_history(self)
|
||||||
|
|
||||||
|
---@param request string
|
||||||
local function handle_submit(request)
|
local function handle_submit(request)
|
||||||
---@type string
|
local model = Config.has_provider(Config.provider) and Config.get_provider(Config.provider).model or "default"
|
||||||
local model
|
|
||||||
|
|
||||||
local builtins_provider_config = Config[Config.provider]
|
|
||||||
if builtins_provider_config ~= nil then
|
|
||||||
model = builtins_provider_config.model
|
|
||||||
else
|
|
||||||
local vendor_provider_config = Config.vendors[Config.provider]
|
|
||||||
model = vendor_provider_config and vendor_provider_config.model or "default"
|
|
||||||
end
|
|
||||||
|
|
||||||
local timestamp = get_timestamp()
|
local timestamp = get_timestamp()
|
||||||
|
|
||||||
@ -1094,6 +1142,56 @@ function Sidebar:create_input()
|
|||||||
prepend_line_number(self.code.selection.content, self.code.selection.range.start.line)
|
prepend_line_number(self.code.selection.content, self.code.selection.range.start.line)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if request:sub(1, 1) == "/" then
|
||||||
|
local command, args = request:match("^/(%S+)%s*(.*)")
|
||||||
|
if command == "help" then
|
||||||
|
local help_text = [[
|
||||||
|
Available commands:
|
||||||
|
/clear - Clear chat history
|
||||||
|
/help - Show this help message
|
||||||
|
/lines <start>-<end> <question> - Ask a question about specific lines
|
||||||
|
]]
|
||||||
|
self:update_content(help_text, { focus = false, scroll = false })
|
||||||
|
return
|
||||||
|
elseif command == "lines" then
|
||||||
|
---@diagnostic disable-next-line: no-unknown
|
||||||
|
local start_line, end_line, question = args:match("(%d+)-(%d+)%s+(.*)")
|
||||||
|
---@cast question string
|
||||||
|
|
||||||
|
if selected_code_content_with_line_numbers ~= nil then
|
||||||
|
Utils.warn("/lines is mutually exclusive with visual selection on blocks.", { once = true, title = "Avante" })
|
||||||
|
request = question
|
||||||
|
else
|
||||||
|
if start_line and end_line and question then
|
||||||
|
---@cast start_line integer
|
||||||
|
start_line = tonumber(start_line)
|
||||||
|
---@cast end_line integer
|
||||||
|
end_line = tonumber(end_line)
|
||||||
|
selected_code_content_with_line_numbers = prepend_line_number(
|
||||||
|
table.concat(api.nvim_buf_get_lines(self.code.bufnr, start_line - 1, end_line, false), "\n"),
|
||||||
|
start_line
|
||||||
|
)
|
||||||
|
request = question
|
||||||
|
else
|
||||||
|
self:update_content(
|
||||||
|
"Invalid format. Use: /lines <start>-<end> <question>",
|
||||||
|
{ focus = false, scroll = false }
|
||||||
|
)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif command == "clear" then
|
||||||
|
chat_history = {}
|
||||||
|
save_chat_history(self, chat_history)
|
||||||
|
self:update_content("Chat history cleared", { focus = false, scroll = false })
|
||||||
|
return
|
||||||
|
else
|
||||||
|
-- Unknown command
|
||||||
|
self:update_content("Unknown command: " .. command, { focus = false, scroll = false })
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local full_response = ""
|
local full_response = ""
|
||||||
|
|
||||||
local filetype = api.nvim_get_option_value("filetype", { buf = self.code.bufnr })
|
local filetype = api.nvim_get_option_value("filetype", { buf = self.code.bufnr })
|
||||||
@ -1101,7 +1199,7 @@ function Sidebar:create_input()
|
|||||||
---@type AvanteChunkParser
|
---@type AvanteChunkParser
|
||||||
local on_chunk = function(chunk)
|
local on_chunk = function(chunk)
|
||||||
full_response = full_response .. chunk
|
full_response = full_response .. chunk
|
||||||
self:update_content(content_prefix .. full_response, { stream = false, scroll = true })
|
self:update_content(chunk, { stream = true, scroll = true })
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
vim.cmd("redraw")
|
vim.cmd("redraw")
|
||||||
end)
|
end)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user