update nvim

This commit is contained in:
kyasuda
2025-09-05 10:32:09 -07:00
parent 22b43c6ddf
commit b8b8d6ef09
16 changed files with 618 additions and 248 deletions

View File

@@ -0,0 +1,94 @@
--- @class CodeCompanion.InlineExtmark
--- @field unique_line_sign_text string Text used for sign when there's only a single line
--- @field first_line_sign_text string Text used for sign on the first line of multi-line section
--- @field last_line_sign_text string Text used for sign on the last line of multi-line section
--- @field extmark vim.api.keyset.set_extmark Extmark options passed to nvim_buf_set_extmark
local M = {}
--- @type CodeCompanion.InlineExtmark
local default_opts = {
unique_line_sign_text = "",
first_line_sign_text = "",
last_line_sign_text = "",
extmark = {
sign_hl_group = "DiagnosticWarn",
sign_text = "",
priority = 1000,
},
}
--- Helper function to set a line extmark with specified sign text
--- @param bufnr number
--- @param ns_id number
--- @param line_num number Line number
--- @param opts vim.api.keyset.set_extmark Extmark options
--- @param sign_type string Key in opts for the sign text to use
local function set_line_extmark(bufnr, ns_id, line_num, opts, sign_type)
vim.api.nvim_buf_set_extmark(
bufnr,
ns_id,
line_num - 1, -- Convert to 0-based index
0,
vim.tbl_deep_extend("force", opts.extmark or {}, {
sign_text = opts[sign_type] or opts.extmark.sign_text,
})
)
end
--- Creates extmarks for inline code annotations
--- @param opts CodeCompanion.InlineExtmark Configuration options for the extmarks
--- @param data CodeCompanion.InlineArgs Data containing context information about the code block
--- @param ns_id number unique namespace id for the extmarks
local function create_extmarks(opts, data, ns_id)
--- @type {bufnr: number, start_line: number, end_line: number}
local context = data.context
-- Handle the case where start and end lines are the same (unique line)
if context.start_line == context.end_line then
set_line_extmark(context.bufnr, ns_id, context.start_line, opts, "unique_line_sign_text")
return
end
-- Set extmark for the first line with special options
set_line_extmark(context.bufnr, ns_id, context.start_line, opts, "first_line_sign_text")
-- Set extmarks for the middle lines with standard options
for i = context.start_line + 1, context.end_line - 1 do
vim.api.nvim_buf_set_extmark(context.bufnr, ns_id, i - 1, 0, opts.extmark)
end
-- Set extmark for the last line with special options
if context.end_line > context.start_line then
set_line_extmark(context.bufnr, ns_id, context.end_line, opts, "last_line_sign_text")
end
end
--- Creates autocmds for CodeCompanionRequest events
--- @param opts CodeCompanion.InlineExtmark Configuration options passed from setup
local function create_autocmds(opts)
vim.api.nvim_create_autocmd({ "User" }, {
pattern = { "CodeCompanionRequest*" },
callback =
--- @param args {buf: number, data : CodeCompanion.InlineArgs, match: string}
function(args)
local data = args.data or {}
local context = data and data.context or {}
if data and data.context then
local ns_id = vim.api.nvim_create_namespace("CodeCompanionInline_" .. data.id)
if args.match:find("StartedInline") then
create_extmarks(opts, data, ns_id)
elseif args.match:find("FinishedInline") then
vim.api.nvim_buf_clear_namespace(context.bufnr, ns_id, 0, -1)
end
end
end,
})
end
--- @param opts? CodeCompanion.InlineExtmark Optional configuration to override defaults
function M.setup(opts)
create_autocmds(vim.tbl_deep_extend("force", default_opts, opts or {}))
end
return M

View File

@@ -0,0 +1,126 @@
local notify = require("notify")
local spinner_frames = { "", "", "", "", "", "", "", "", "", "" }
local spinner_len = #spinner_frames -- cache spinner length
local M = {}
local timeout = 2999
-- Helper function to safely call notify
local function safe_notify(msg, level, opts)
local ok, res = pcall(notify, msg, level, opts)
return ok, res
end
function M:init()
local group = vim.api.nvim_create_augroup("CodeCompanionFidgetHooks", {})
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "CodeCompanionRequestStarted",
group = group,
callback = function(request)
local handle = M:create_progress_handle(request)
M:store_progress_handle(request.data.id, handle)
end,
})
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "CodeCompanionRequestFinished",
group = group,
callback = function(request)
local handle = M:pop_progress_handle(request.data.id)
if handle then
M:report_exit_status(handle, request)
handle:finish()
end
end,
})
end
M.handles = {}
function M:store_progress_handle(id, handle)
M.handles[id] = handle
end
function M:pop_progress_handle(id)
local handle = M.handles[id]
M.handles[id] = nil
return handle
end
function M:create_progress_handle(request)
local title = " Requesting assistance"
.. " ("
.. request.data.strategy
.. ") from "
.. request.data.adapter.formatted_name
.. " using "
.. request.data.adapter.model
local idx = 1
local start_time = os.time()
local notification_id =
notify(spinner_frames[idx] .. " In progress (" .. "0s" .. ")...", "info", { title = title, timeout = false })
local handle = { notification_id = notification_id, title = title, finished = false }
local timer = vim.loop.new_timer()
timer:start(
0,
100,
vim.schedule_wrap(function()
if handle.finished then
return
end -- stop updating if finished
idx = idx % spinner_len + 1
local elapsed = os.difftime(os.time(), start_time)
local opts = { replace = handle.notification_id, title = title, timeout = false }
local ok, new_id = safe_notify(spinner_frames[idx] .. " In progress (" .. elapsed .. "s)...", "info", opts)
if ok then
handle.notification_id = new_id
else
handle.notification_id = notify(
spinner_frames[idx] .. " In progress (" .. elapsed .. "s)...",
"info",
{ title = title, timeout = false }
)
end
end)
)
handle.timer = timer
handle.finish = function()
handle.finished = true -- mark as finished to abort future updates
if handle.timer then
handle.timer:stop()
handle.timer:close()
handle.timer = nil
end
end
return handle
end
function M:report_exit_status(handle, request)
local title = handle.title
or (
" Requesting assistance"
.. " ("
.. request.data.strategy
.. ") from "
.. request.data.adapter.formatted_name
.. " using "
.. request.data.adapter.model
)
local function report(msg, level)
local opts = { replace = handle.notification_id, title = title, timeout = timeout }
local ok = safe_notify(msg, level, opts)
if not ok then
notify(msg, level, { title = title, timeout = timeout })
end
end
if request.data.status == "success" then
report("Completed", "info")
elseif request.data.status == "error" then
report(" Error", "error")
else
report("󰜺 Cancelled", "warn")
end
end
return M

View File

@@ -0,0 +1,73 @@
-- lua/plugins/codecompanion/fidget-spinner.lua
local progress = require("fidget.progress")
local M = {}
function M:init()
local group = vim.api.nvim_create_augroup("CodeCompanionFidgetHooks", {})
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "CodeCompanionRequestStarted",
group = group,
callback = function(request)
local handle = M:create_progress_handle(request)
M:store_progress_handle(request.data.id, handle)
end,
})
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "CodeCompanionRequestFinished",
group = group,
callback = function(request)
local handle = M:pop_progress_handle(request.data.id)
if handle then
M:report_exit_status(handle, request)
handle:finish()
end
end,
})
end
M.handles = {}
function M:store_progress_handle(id, handle)
M.handles[id] = handle
end
function M:pop_progress_handle(id)
local handle = M.handles[id]
M.handles[id] = nil
return handle
end
function M:create_progress_handle(request)
return progress.handle.create({
title = " Requesting assistance (" .. request.data.strategy .. ")",
message = "In progress...",
lsp_client = {
name = M:llm_role_title(request.data.adapter),
},
})
end
function M:llm_role_title(adapter)
local parts = {}
table.insert(parts, adapter.formatted_name)
if adapter.model and adapter.model ~= "" then
table.insert(parts, "(" .. adapter.model .. ")")
end
return table.concat(parts, " ")
end
function M:report_exit_status(handle, request)
if request.data.status == "success" then
handle.message = "Completed"
elseif request.data.status == "error" then
handle.message = " Error"
else
handle.message = "󰜺 Cancelled"
end
end
return M