Skip to content

Commit

Permalink
feat: add status notifications for background tasks
Browse files Browse the repository at this point in the history
Add a new notification system to provide user feedback for background
operations like file scanning, model fetching, and API calls. This improves
the user experience by making it clear when the plugin is performing work.

The changes include:
- New notify module for pub/sub event system
- Integration with spinner UI to show status messages
- Status notifications for file operations, API calls, and embeddings
- Removed redundant logging in favor of user-visible notifications

Signed-off-by: Tomas Slusny <[email protected]>
  • Loading branch information
deathbeam committed Nov 29, 2024
1 parent 98a1391 commit f0d8a71
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 6 deletions.
11 changes: 11 additions & 0 deletions lua/CopilotChat/context.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

local async = require('plenary.async')
local log = require('plenary.log')
local notify = require('CopilotChat.notify')
local utils = require('CopilotChat.utils')
local file_cache = {}
local url_cache = {}
Expand Down Expand Up @@ -311,11 +312,16 @@ end
---@return table<CopilotChat.context.embed>
function M.files(winnr, with_content)
local cwd = utils.win_cwd(winnr)

notify.publish(notify.STATUS, 'Scanning files')

local files = utils.scan_dir(cwd, {
add_dirs = false,
respect_gitignore = true,
})

notify.publish(notify.STATUS, 'Reading files')

local out = {}

-- Read all files if we want content as well
Expand Down Expand Up @@ -373,6 +379,8 @@ function M.file(filename)
return nil
end

notify.publish(notify.STATUS, 'Reading file ' .. filename)

async.util.scheduler()
local ft = utils.filetype(filename)
if not ft then
Expand Down Expand Up @@ -414,6 +422,7 @@ function M.url(url)

local content = url_cache[url]
if not content then
notify.publish(notify.STATUS, 'Fetching ' .. url)
local out = utils.system({ 'lynx', '-dump', url })
if not out or out.code ~= 0 then
return nil
Expand All @@ -434,6 +443,8 @@ end
---@param winnr number
---@return CopilotChat.context.embed?
function M.gitdiff(type, winnr)
notify.publish(notify.STATUS, 'Fetching git diff')

local cwd = utils.win_cwd(winnr)
local cmd = {
'git',
Expand Down
14 changes: 13 additions & 1 deletion lua/CopilotChat/copilot.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
local log = require('plenary.log')
local prompts = require('CopilotChat.prompts')
local tiktoken = require('CopilotChat.tiktoken')
local notify = require('CopilotChat.notify')
local utils = require('CopilotChat.utils')
local class = utils.class
local temp_file = utils.temp_file
Expand Down Expand Up @@ -405,6 +406,8 @@ function Copilot:fetch_models()
return self.models
end

notify.publish(notify.STATUS, 'Fetching models')

local response, err = utils.curl_get(
'https://api.githubcopilot.com/models',
vim.tbl_extend('force', self.request_args, {
Expand Down Expand Up @@ -433,7 +436,6 @@ function Copilot:fetch_models()
end
end

log.info('Models fetched')
log.trace(models)
self.models = out
return out
Expand All @@ -446,6 +448,8 @@ function Copilot:fetch_agents()
return self.agents
end

notify.publish(notify.STATUS, 'Fetching agents')

local response, err = utils.curl_get(
'https://api.githubcopilot.com/agents',
vim.tbl_extend('force', self.request_args, {
Expand Down Expand Up @@ -482,6 +486,8 @@ function Copilot:enable_policy(model)
return
end

notify.publish(notify.STATUS, 'Enabling ' .. model .. ' policy')

local response, err = utils.curl_post(
'https://api.githubcopilot.com/models/' .. model .. '/policy',
vim.tbl_extend('force', self.request_args, {
Expand Down Expand Up @@ -611,6 +617,8 @@ function Copilot:ask(prompt, opts)
return
end

notify.publish(notify.STATUS, '')

local ok, content = pcall(vim.json.decode, line, {
luanil = {
object = true,
Expand Down Expand Up @@ -724,6 +732,8 @@ function Copilot:ask(prompt, opts)
args.stream = stream_func
end

notify.publish(notify.STATUS, 'Thinking')

local response, err = utils.curl_post(url, args)

if self.current_job ~= job_id then
Expand Down Expand Up @@ -867,6 +877,8 @@ function Copilot:embed(inputs)
return {}
end

notify.publish(notify.STATUS, 'Generating embeddings for ' .. #inputs .. ' inputs')

-- Initialize essentials
local model = EMBED_MODEL
local to_process = {}
Expand Down
31 changes: 31 additions & 0 deletions lua/CopilotChat/notify.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
local log = require('plenary.log')

local M = {}

M.STATUS = 'status'

M.listeners = {}

--- Publish an event with a message
---@param event_name string
---@param data any
function M.publish(event_name, data)
if M.listeners[event_name] then
log.debug(event_name .. ':', data)
for _, callback in ipairs(M.listeners[event_name]) do
callback(data)
end
end
end

--- Listen for an event
---@param event_name string
---@param callback fun(data:any)
function M.listen(event_name, callback)
if not M.listeners[event_name] then
M.listeners[event_name] = {}
end
table.insert(M.listeners[event_name], callback)
end

return M
5 changes: 3 additions & 2 deletions lua/CopilotChat/tiktoken.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
local async = require('plenary.async')
local log = require('plenary.log')
local notify = require('CopilotChat.notify')
local utils = require('CopilotChat.utils')
local current_tokenizer = nil
local cache_dir = vim.fn.stdpath('cache')
Expand All @@ -22,7 +22,8 @@ local function load_tiktoken_data(tokenizer)
return cache_path
end

log.info('Downloading tiktoken data from ' .. tiktoken_url)
notify.publish(notify.STATUS, 'Downloading tiktoken data from ' .. tiktoken_url)

utils.curl_get(tiktoken_url, {
output = cache_path,
})
Expand Down
18 changes: 15 additions & 3 deletions lua/CopilotChat/ui/spinner.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local notify = require('CopilotChat.notify')
local utils = require('CopilotChat.utils')
local class = utils.class

Expand All @@ -19,11 +20,17 @@ local spinner_frames = {
---@field bufnr number
---@field timer table
---@field index number
---@field status string?
local Spinner = class(function(self, bufnr)
self.ns = vim.api.nvim_create_namespace('copilot-chat-spinner')
self.bufnr = bufnr
self.timer = nil
self.index = 1
self.status = nil

notify.listen(notify.STATUS, function(status)
self.status = tostring(status)
end)
end)

function Spinner:start()
Expand All @@ -41,6 +48,11 @@ function Spinner:start()
return
end

local frame = spinner_frames[self.index]
if self.status then
frame = self.status .. ' ' .. frame
end

vim.api.nvim_buf_set_extmark(
self.bufnr,
self.ns,
Expand All @@ -50,9 +62,9 @@ function Spinner:start()
id = 1,
hl_mode = 'combine',
priority = 100,
virt_text = vim.tbl_map(function(t)
return { t, 'CopilotChatSpinner' }
end, vim.split(spinner_frames[self.index], '\n')),
virt_text = {
{ frame, 'CopilotChatSpinner' },
},
}
)

Expand Down

0 comments on commit f0d8a71

Please sign in to comment.