feat(mapping): plug and expose API (#346)
Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
This commit is contained in:
parent
8a683b053b
commit
2e6a26240e
17
README.md
17
README.md
@ -26,6 +26,11 @@ Install `avante.nvim` using [lazy.nvim](https://github.com/folke/lazy.nvim):
|
||||
opts = {
|
||||
-- add any opts here
|
||||
},
|
||||
keys = { -- See https://github.com/yetone/avante.nvim/wiki#keymaps for more info
|
||||
{ "<leader>aa", function() require("avante.api").ask() end, desc = "avante: ask", mode = { "n", "v" } },
|
||||
{ "<leader>ar", function() require("avante.api").refresh() end, desc = "avante: refresh", mode = "v" },
|
||||
{ "<leader>ae", function() require("avante.api").edit() end, desc = "avante: edit", mode = { "n", "v" } },
|
||||
},
|
||||
dependencies = {
|
||||
"stevearc/dressing.nvim",
|
||||
"nvim-lua/plenary.nvim",
|
||||
@ -94,9 +99,6 @@ _See [config.lua#L9](./lua/avante/config.lua) for the full config_
|
||||
max_tokens = 4096,
|
||||
},
|
||||
mappings = {
|
||||
ask = "<leader>aa",
|
||||
edit = "<leader>ae",
|
||||
refresh = "<leader>ar",
|
||||
--- @class AvanteConflictMappings
|
||||
diff = {
|
||||
ours = "co",
|
||||
@ -113,10 +115,6 @@ _See [config.lua#L9](./lua/avante/config.lua) for the full config_
|
||||
normal = "<CR>",
|
||||
insert = "<C-s>",
|
||||
},
|
||||
toggle = {
|
||||
debug = "<leader>ad",
|
||||
hint = "<leader>ah",
|
||||
},
|
||||
},
|
||||
hints = { enabled = true },
|
||||
windows = {
|
||||
@ -208,6 +206,11 @@ The following key bindings are available for use with `avante.nvim`:
|
||||
| <kbd>[</kbd><kbd>[</kbd> | jump to previous codeblocks (results window) |
|
||||
| <kbd>]</kbd><kbd>]</kbd> | jump to next codeblocks (results windows) |
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> If you are using `lazy.nvim`, then all keymap here will be safely set, meaning if `<leader>aa` is already binded, then avante.nvim won't bind this mapping.
|
||||
> In this case, user will be responsible for setting up their own. See [notes on keymaps](https://github.com/yetone/avante.nvim/wiki#keymaps) for more details.
|
||||
|
||||
## Highlight Groups
|
||||
|
||||
|
||||
|
27
lua/avante/api.lua
Normal file
27
lua/avante/api.lua
Normal file
@ -0,0 +1,27 @@
|
||||
local Utils = require("avante.utils")
|
||||
|
||||
---@class avante.ApiToggle
|
||||
---@operator call(): boolean
|
||||
---@field debug ToggleBind.wrap
|
||||
---@field hint ToggleBind.wrap
|
||||
---
|
||||
---@class avante.Api
|
||||
---@field ask fun(): boolean
|
||||
---@field edit fun(): nil
|
||||
---@field refresh fun(): nil
|
||||
---@field toggle avante.ApiToggle
|
||||
|
||||
return setmetatable({}, {
|
||||
__index = function(t, k)
|
||||
local module = require("avante")
|
||||
---@class AvailableApi: ApiCaller
|
||||
---@field api? boolean
|
||||
local has = module[k]
|
||||
if type(has) ~= "table" or not has.api then
|
||||
Utils.warn(k .. " is not a valid avante's API method", { once = true })
|
||||
return
|
||||
end
|
||||
t[k] = has
|
||||
return t[k]
|
||||
end,
|
||||
}) --[[@as avante.Api]]
|
@ -88,10 +88,7 @@ M.defaults = {
|
||||
},
|
||||
},
|
||||
mappings = {
|
||||
ask = "<leader>aa",
|
||||
edit = "<leader>ae",
|
||||
refresh = "<leader>ar",
|
||||
--- @class AvanteConflictMappings
|
||||
---@class AvanteConflictMappings
|
||||
diff = {
|
||||
ours = "co",
|
||||
theirs = "ct",
|
||||
@ -108,6 +105,10 @@ M.defaults = {
|
||||
normal = "<CR>",
|
||||
insert = "<C-s>",
|
||||
},
|
||||
-- NOTE: The following will be safely set by avante.nvim
|
||||
ask = "<leader>aa",
|
||||
edit = "<leader>ae",
|
||||
refresh = "<leader>ar",
|
||||
toggle = {
|
||||
debug = "<leader>ad",
|
||||
hint = "<leader>ah",
|
||||
|
@ -26,7 +26,7 @@ H.commands = function()
|
||||
end
|
||||
|
||||
cmd("Ask", function()
|
||||
M.toggle()
|
||||
M.ask()
|
||||
end, { desc = "avante: ask AI for code suggestions" })
|
||||
cmd("Close", function()
|
||||
local sidebar, _ = M._get()
|
||||
@ -35,34 +35,53 @@ H.commands = function()
|
||||
end
|
||||
sidebar:close()
|
||||
end, { desc = "avante: close chat window" })
|
||||
cmd("Edit", function()
|
||||
M.edit()
|
||||
end, { desc = "avante: edit selected block" })
|
||||
cmd("Refresh", function()
|
||||
M.refresh()
|
||||
end, { desc = "avante: refresh windows" })
|
||||
end
|
||||
|
||||
H.keymaps = function()
|
||||
vim.keymap.set({ "n", "v" }, Config.mappings.ask, M.toggle, { noremap = true, desc = "avante: Ask" })
|
||||
vim.keymap.set("v", Config.mappings.edit, M.edit, { noremap = true, desc = "avante: Edit" })
|
||||
vim.keymap.set("n", Config.mappings.refresh, M.refresh, { noremap = true, desc = "avante: Refresh" })
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteAsk)", function()
|
||||
M.ask()
|
||||
end, { noremap = true })
|
||||
vim.keymap.set("v", "<Plug>(AvanteEdit)", function()
|
||||
M.edit()
|
||||
end, { noremap = true })
|
||||
vim.keymap.set("n", "<Plug>(AvanteRefresh)", function()
|
||||
M.refresh()
|
||||
end, { noremap = true })
|
||||
--- the following is kinda considered as internal mappings.
|
||||
vim.keymap.set("n", "<Plug>(AvanteToggleDebug)", function()
|
||||
M.toggle.debug()
|
||||
end)
|
||||
vim.keymap.set("n", "<Plug>(AvanteToggleHint)", function()
|
||||
M.toggle.hint()
|
||||
end)
|
||||
|
||||
Utils.toggle_map("n", Config.mappings.toggle.debug, {
|
||||
name = "debug",
|
||||
get = function()
|
||||
return Config.debug
|
||||
Utils.safe_keymap_set({ "n", "v" }, Config.mappings.ask, "<Plug>(AvanteAsk)", { desc = "avante: ask" })
|
||||
Utils.safe_keymap_set("v", Config.mappings.edit, "<Plug>(AvanteEdit)", { desc = "avante: edit" })
|
||||
Utils.safe_keymap_set("n", Config.mappings.refresh, "<Plug>(AvanteRefresh)", { desc = "avante: refresh" })
|
||||
Utils.safe_keymap_set(
|
||||
"n",
|
||||
Config.mappings.toggle.debug,
|
||||
"<Plug>(AvanteToggleDebug)",
|
||||
{ desc = "avante: toggle debug" }
|
||||
)
|
||||
Utils.safe_keymap_set("n", Config.mappings.toggle.hint, "<Plug>(AvanteToggleHint)", { desc = "avante: toggle hint" })
|
||||
end
|
||||
|
||||
---@class ApiCaller
|
||||
---@operator call(...): any
|
||||
|
||||
H.api = function(fun)
|
||||
return setmetatable({ api = true }, {
|
||||
__call = function(...)
|
||||
return fun(...)
|
||||
end,
|
||||
set = function(state)
|
||||
Config.override({ debug = state })
|
||||
end,
|
||||
})
|
||||
Utils.toggle_map("n", Config.mappings.toggle.hint, {
|
||||
name = "hint",
|
||||
get = function()
|
||||
return Config.hints.enabled
|
||||
end,
|
||||
set = function(state)
|
||||
Config.override({ hints = { enabled = state } })
|
||||
end,
|
||||
})
|
||||
}) --[[@as ApiCaller]]
|
||||
end
|
||||
|
||||
H.signs = function()
|
||||
@ -166,26 +185,55 @@ function M._init(id)
|
||||
return M
|
||||
end
|
||||
|
||||
M.toggle = function()
|
||||
local sidebar, _ = M._get()
|
||||
if not sidebar then
|
||||
M._init(api.nvim_get_current_tabpage())
|
||||
M.current.sidebar:open()
|
||||
return true
|
||||
end
|
||||
M.toggle = { api = true }
|
||||
|
||||
return sidebar:toggle()
|
||||
end
|
||||
M.toggle.debug = H.api(Utils.toggle_wrap({
|
||||
name = "debug",
|
||||
get = function()
|
||||
return Config.debug
|
||||
end,
|
||||
set = function(state)
|
||||
Config.override({ debug = state })
|
||||
end,
|
||||
}))
|
||||
|
||||
M.edit = function()
|
||||
M.toggle.hint = H.api(Utils.toggle_wrap({
|
||||
name = "hint",
|
||||
get = function()
|
||||
return Config.hints.enabled
|
||||
end,
|
||||
set = function(state)
|
||||
Config.override({ hints = { enabled = state } })
|
||||
end,
|
||||
}))
|
||||
|
||||
setmetatable(M.toggle, {
|
||||
__index = M.toggle,
|
||||
__call = function()
|
||||
local sidebar, _ = M._get()
|
||||
if not sidebar then
|
||||
M._init(api.nvim_get_current_tabpage())
|
||||
M.current.sidebar:open()
|
||||
return true
|
||||
end
|
||||
|
||||
return sidebar:toggle()
|
||||
end,
|
||||
})
|
||||
|
||||
M.ask = H.api(function()
|
||||
M.toggle()
|
||||
end)
|
||||
|
||||
M.edit = H.api(function()
|
||||
local _, selection = M._get()
|
||||
if not selection then
|
||||
return
|
||||
end
|
||||
selection:create_editing_input()
|
||||
end
|
||||
end)
|
||||
|
||||
M.refresh = function()
|
||||
M.refresh = H.api(function()
|
||||
local sidebar, _ = M._get()
|
||||
if not sidebar then
|
||||
return
|
||||
@ -213,7 +261,7 @@ M.refresh = function()
|
||||
sidebar.code.winid = curwin
|
||||
sidebar.code.bufnr = curbuf
|
||||
sidebar:render()
|
||||
end
|
||||
end)
|
||||
|
||||
---@param opts? avante.Config
|
||||
function M.setup(opts)
|
||||
|
@ -69,23 +69,88 @@ M.shell_run = function(input_cmd)
|
||||
return { stdout = output, code = code }
|
||||
end
|
||||
|
||||
---@see https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/util/toggle.lua
|
||||
---
|
||||
---@alias _ToggleSet fun(state: boolean): nil
|
||||
---@alias _ToggleGet fun(): boolean
|
||||
---
|
||||
---@class ToggleBind
|
||||
---@field name string
|
||||
---@field set _ToggleSet
|
||||
---@field get _ToggleGet
|
||||
---
|
||||
---@class ToggleBind.wrap: ToggleBind
|
||||
---@operator call:boolean
|
||||
|
||||
---@param toggle ToggleBind
|
||||
M.toggle_wrap = function(toggle)
|
||||
return setmetatable(toggle, {
|
||||
__call = function()
|
||||
toggle.set(not toggle.get())
|
||||
local state = toggle.get()
|
||||
if state then
|
||||
M.info("enabled: " .. toggle.name)
|
||||
else
|
||||
M.warn("disabled: " .. toggle.name)
|
||||
end
|
||||
return state
|
||||
end,
|
||||
}) --[[@as ToggleBind.wrap]]
|
||||
end
|
||||
|
||||
---@param lhs string
|
||||
---@param toggle {name: string, set: _ToggleSet, get: _ToggleGet}
|
||||
---@param mode? string | string[]
|
||||
M.toggle_map = function(mode, lhs, toggle)
|
||||
vim.keymap.set(mode or { "n" }, lhs, function()
|
||||
toggle.set(not toggle.get())
|
||||
local state = toggle.get()
|
||||
if state then
|
||||
M.info("enabled: " .. toggle.name, { title = "Avante" })
|
||||
else
|
||||
M.warn("disabled: " .. toggle.name, { title = "Avante" })
|
||||
---@param toggle ToggleBind
|
||||
M.toggle_map = function(lhs, toggle)
|
||||
M.safe_keymap_set("n", lhs, M.toggle_wrap(toggle), { desc = "toggle(avante): " .. toggle.name })
|
||||
end
|
||||
|
||||
-- Wrapper around vim.keymap.set that will
|
||||
-- not create a keymap if a lazy key handler exists.
|
||||
-- It will also set `silent` to true by default.
|
||||
--
|
||||
---@param mode string|string[] Mode short-name, see |nvim_set_keymap()|.
|
||||
--- Can also be list of modes to create mapping on multiple modes.
|
||||
---@param lhs string Left-hand side |{lhs}| of the mapping.
|
||||
---@param rhs string|function Right-hand side |{rhs}| of the mapping, can be a Lua function.
|
||||
---
|
||||
---@param opts? vim.keymap.set.Opts
|
||||
---@see |nvim_set_keymap()|
|
||||
---@see |maparg()|
|
||||
---@see |mapcheck()|
|
||||
---@see |mapset()|
|
||||
M.safe_keymap_set = function(mode, lhs, rhs, opts)
|
||||
---@type boolean
|
||||
local ok
|
||||
---@module "lazy.core.handler"
|
||||
local H
|
||||
|
||||
ok, H = pcall(require, "lazy.core.handler")
|
||||
if not ok then
|
||||
M.warn("lazy.nvim is not available. Avante will use vim.keymap.set", { once = true })
|
||||
vim.keymap.set(mode, lhs, rhs, opts)
|
||||
return
|
||||
end
|
||||
|
||||
local Keys = H.handlers.keys
|
||||
---@cast Keys LazyKeysHandler
|
||||
local modes = type(mode) == "string" and { mode } or mode
|
||||
---@cast modes -string
|
||||
|
||||
---@param m string
|
||||
modes = vim.tbl_filter(function(m)
|
||||
return not (Keys.have and Keys:have(lhs, m))
|
||||
end, modes)
|
||||
|
||||
-- don't create keymap if a lazy keys handler exists
|
||||
if #modes > 0 then
|
||||
opts = opts or {}
|
||||
opts.silent = opts.silent ~= false
|
||||
if opts.remap and not vim.g.vscode then
|
||||
---@diagnostic disable-next-line: no-unknown
|
||||
opts.remap = nil
|
||||
end
|
||||
return state
|
||||
end, { desc = "toggle(avante): " .. toggle.name })
|
||||
vim.keymap.set(mode, lhs, rhs, opts)
|
||||
end
|
||||
end
|
||||
|
||||
---@param str string
|
||||
|
Loading…
x
Reference in New Issue
Block a user