|
| 1 | +local M = {} |
| 2 | + |
| 3 | +---@param tool_call eca.ToolCallRun |
| 4 | +function M.get_preview_lines(tool_call) |
| 5 | + if not tool_call.details then |
| 6 | + local arguments = vim.split(vim.inspect(tool_call.arguments), "\n") |
| 7 | + local messages = {} |
| 8 | + if tool_call.summary then |
| 9 | + table.insert(messages, "Summary: " .. tool_call.summary) |
| 10 | + end |
| 11 | + table.insert(messages, "Tool Name: " .. tool_call.name) |
| 12 | + table.insert(messages, "Tool Type: " .. tool_call.origin) |
| 13 | + table.insert(messages, "Tool Arguments: ") |
| 14 | + for _, v in pairs(arguments) do |
| 15 | + table.insert(messages, v) |
| 16 | + end |
| 17 | + return messages |
| 18 | + end |
| 19 | + local lines = vim.split(tool_call.details.diff, "\n") |
| 20 | + return { tool_call.details.path, unpack(lines) } |
| 21 | +end |
| 22 | + |
| 23 | +---@param lines string[] |
| 24 | +---@return {row: number, col: number, width: number, height: number} |
| 25 | +local function get_position(lines) |
| 26 | + local gheight = math.floor( |
| 27 | + vim.api.nvim_list_uis() and vim.api.nvim_list_uis()[1] and vim.api.nvim_list_uis()[1].height or vim.o.lines |
| 28 | + ) |
| 29 | + local gwidth = math.floor( |
| 30 | + vim.api.nvim_list_uis() and vim.api.nvim_list_uis()[1] and vim.api.nvim_list_uis()[1].width or vim.o.columns |
| 31 | + ) |
| 32 | + local height = #lines > 10 and 35 or #lines |
| 33 | + local width = 0 |
| 34 | + for _, line in ipairs(lines) do |
| 35 | + if #line > width then |
| 36 | + width = #line |
| 37 | + end |
| 38 | + end |
| 39 | + return { |
| 40 | + row = (gheight - height) * 0.5, |
| 41 | + col = (gwidth - width) * 0.5, |
| 42 | + width = math.floor(width * 1.5), |
| 43 | + height = height, |
| 44 | + } |
| 45 | +end |
| 46 | + |
| 47 | +---@param tool_call eca.ToolCallRun |
| 48 | +---@param on_accept function |
| 49 | +---@param on_deny function |
| 50 | +function M.display_preview_lines(tool_call, on_accept, on_deny) |
| 51 | + local lines = M.get_preview_lines(tool_call) |
| 52 | + local buf = vim.api.nvim_create_buf(false, false) |
| 53 | + vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) |
| 54 | + vim.api.nvim_set_option_value("modifiable", false, { buf = buf }) |
| 55 | + local position = get_position(lines) |
| 56 | + local title = tool_call.summary or tool_call.name |
| 57 | + local win = vim.api.nvim_open_win(buf, true, { |
| 58 | + border = "single", |
| 59 | + title = "Approve Tool Call(y/n): " .. title, |
| 60 | + relative = "editor", |
| 61 | + row = position.row, |
| 62 | + col = position.col, |
| 63 | + width = position.width, |
| 64 | + height = position.height, |
| 65 | + }) |
| 66 | + if tool_call.details then |
| 67 | + vim.api.nvim_set_option_value("filetype", "diff", { buf = buf }) |
| 68 | + else |
| 69 | + vim.api.nvim_set_option_value("number", false, { win = win }) |
| 70 | + vim.api.nvim_set_option_value("relativenumber", false, { win = win }) |
| 71 | + end |
| 72 | + |
| 73 | + vim.keymap.set({ "n", "i" }, "y", "", { |
| 74 | + buffer = buf, |
| 75 | + callback = function() |
| 76 | + vim.api.nvim_win_close(win, true) |
| 77 | + vim.api.nvim_buf_delete(buf, { force = true }) |
| 78 | + if on_accept then |
| 79 | + on_accept() |
| 80 | + end |
| 81 | + end, |
| 82 | + }) |
| 83 | + vim.keymap.set({ "n", "i" }, "n", "", { |
| 84 | + buffer = buf, |
| 85 | + callback = function() |
| 86 | + vim.api.nvim_win_close(win, true) |
| 87 | + vim.api.nvim_buf_delete(buf, { force = true }) |
| 88 | + if on_deny then |
| 89 | + on_deny() |
| 90 | + end |
| 91 | + end, |
| 92 | + }) |
| 93 | +end |
| 94 | + |
| 95 | +---@param tool_call eca.ToolCallRun |
| 96 | +---@param on_accept function |
| 97 | +---@param on_deny function |
| 98 | +function M.approve_tool_call(tool_call, on_accept, on_deny) |
| 99 | + M.display_preview_lines(tool_call, on_accept, on_deny) |
| 100 | +end |
| 101 | +return M |
0 commit comments