Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow progress notification without real lsp #683

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 86 additions & 10 deletions lua/noice/lsp/progress.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,92 @@ local M = {}
M._progress = {}
M._running = false

---@param data {client_id: integer, params: lsp.ProgressParams}
---@alias WorkDoneProgressKind 'begin'|'report'|'end'

---@class lsp.ProgressParams
---@field token integer|string provided by the client or server
---@field value MsgInfo the progress data

---@class MsgInfo
---@field id string? unique id associated with the message
---@field kind WorkDoneProgressKind? process message with respect to the kind
---@field title string? brief desc for the progress operation
---@field message string? more detailed associated progress message
---@field percentage integer? progress percentage to display [0, 100]

---@param name string the fake lsp client name
---@param msg MsgInfo? lsp progress params.value
---@return string?
function M.progress_msg(name, msg)
-- id == {name}.{token} == {name}.{time}.{rand}

local msg_token
if msg and msg.id then
if not (string.sub(msg.id, 1, #name) == name) then
return -- invalid msg.id
end
msg_token = string.sub(msg.id, #name + 2)
else
msg_token = os.time() .. "." .. math.random(1e8)
end

local msg_value = vim.tbl_deep_extend("force", {
id = name .. "." .. msg_token,
kind = "begin",
}, msg or {})

M.progress({
client_id = nil,
params = {
token = msg_token,
value = msg_value,
},
})

return msg_value.id
end

---@param id string
function M.progress_msg_end(id)
local message = M._progress[id]
if not message then
return
end

local msg = message.opts.progress
M.progress_msg(msg.client, {
id = id,
kind = "end",
title = msg.title,
message = msg.message,
percentage = msg.percentage,
})
end

---@param data {client_id: integer?, params: lsp.ProgressParams}
function M.progress(data)
local client_id = data.client_id
local params = data.params or data.result -- TODO: Remove data.result after nvim 0.10 release
local id = client_id .. "." .. params.token
local params = data.params or data.result -- TODO: Remove data.result after nvim 0.10 release
local id, client

-- real/fake lsp client by client_id
if client_id then
id = client_id .. "." .. params.token
else
id = params.value.id or ""

local x = string.find(id, ".", 1, true)
client = { name = string.sub(id, 1, x and x - 1) }
end

local message = M._progress[id]
if not message then
local client = vim.lsp.get_client_by_id(client_id)
-- should not happen, but it does for some reason
if not client then
return
if client_id then
client = vim.lsp.get_client_by_id(client_id)
-- should not happen, but it does for some reason
if not client then
return
end
end
message = Message("lsp", "progress")
message.opts.progress = {
Expand Down Expand Up @@ -63,9 +137,11 @@ end
function M._update()
if not vim.tbl_isempty(M._progress) then
for id, message in pairs(M._progress) do
local client = vim.lsp.get_client_by_id(message.opts.progress.client_id)
if not client then
M.close(id)
if message.opts.progress.client_id then
local client = vim.lsp.get_client_by_id(message.opts.progress.client_id)
if not client then
M.close(id)
end
end
if message.opts.progress.kind == "end" then
Manager.add(Format.format(message, Config.options.lsp.progress.format_done))
Expand Down