nixos/lua-lsp/script/progress.lua

183 lines
4 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local proto = require 'proto.proto'
local util = require 'utility'
local timer = require "timer"
local config = require 'config'
local time = require 'bee.time'
local nextToken = util.counter()
local m = {}
m.map = {}
---@class progress
---@field _uri uri
---@field _token integer
local mt = {}
mt.__index = mt
mt._title = nil
mt._message = nil
mt._removed = false
mt._clock = 0.0
mt._delay = 0.0
mt._percentage = 0.0
mt._showed = false
mt._dirty = true
mt._updated = 0.0
mt._onCancel = nil
---移除进度条
function mt:remove()
if self._removed then
return
end
self._removed = true
local token = self._token
m.map[token] = nil
if self._showed then
self._showed = false
proto.notify('$/progress', {
token = token,
value = {
kind = 'end',
}
})
--log.info('Remove progress:', token, self._title)
end
end
function mt:isRemoved()
return self._removed == true
end
---设置描述
---@param message string # 描述
function mt:setMessage(message)
if self._message == message then
return
end
self._message = message
self._dirty = true
self:update()
end
---设置百分比
---@param per number # 百分比1-100
function mt:setPercentage(per)
if self._percentage == per then
return
end
self._percentage = math.floor(per)
self._dirty = true
self:update()
end
---取消事件
function mt:onCancel(callback)
self._onCancel = callback
self:update()
end
function mt:update()
if self._removed then
return
end
if not self._dirty then
return
end
if not self._showed
and self._clock + self._delay <= time.time() then
self._updated = time.time()
self._dirty = false
if not config.get(self._uri, 'Lua.window.progressBar') then
return
end
proto.request('window/workDoneProgress/create', {
token = self._token,
})
proto.notify('$/progress', {
token = self._token,
value = {
kind = 'begin',
title = self._title,
cancellable = self._onCancel ~= nil,
message = self._message,
percentage = self._percentage,
}
})
self._showed = true
--log.info('Create progress:', self._token, self._title)
return
end
if not self._showed then
return
end
if not config.get(self._uri, 'Lua.window.progressBar') then
self:remove()
return
end
if time.time() - self._updated < 50 then
return
end
self._dirty = false
self._updated = time.time()
proto.notify('$/progress', {
token = self._token,
value = {
kind = 'report',
message = self._message,
percentage = self._percentage,
}
})
--log.info('Report progress:', self._token, self._title, self._message, self._percentage)
end
function mt:__close()
--log.info('Close progress:', self._token, self._title, self._message)
self:remove()
end
function m.update()
---@param prog progress
for _, prog in pairs(m.map) do
if prog:isRemoved() then
goto CONTINUE
end
prog:update()
::CONTINUE::
end
end
---创建一个进度条
---@param uri? uri
---@param title string # 标题
---@param delay number # 至少经过这么久之后才会显示出来
function m.create(uri, title, delay)
local token = nextToken()
local prog = setmetatable({
_token = token,
_title = title,
_clock = time.time(),
_delay = delay * 1000,
_uri = uri,
}, mt)
m.map[token] = prog
return prog
end
---取消一个进度条
function m.cancel(token)
local prog = m.map[token]
if not prog then
return
end
xpcall(prog._onCancel, log.error, prog)
prog:remove()
end
timer.loop(0.1, m.update)
return m