nixos/lua-lsp/script/progress.lua

183 lines
4 KiB
Lua
Raw Normal View History

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