summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2021-01-25 19:09:23 +0800
committer最萌小汐 <sumneko@hotmail.com>2021-01-25 19:09:23 +0800
commit7667109acd76492c82b17fbe57666b5db675d7ed (patch)
treec11de10d51f4c3969220044f0a56506e1843a2a8
parent7d6885350af462d400c39a557703890d4ec507f1 (diff)
downloadlua-language-server-7667109acd76492c82b17fbe57666b5db675d7ed.zip
add progress
-rw-r--r--changelog.md1
-rw-r--r--script/progress.lua148
-rw-r--r--script/proto/proto.lua21
-rw-r--r--script/workspace/workspace.lua76
4 files changed, 195 insertions, 51 deletions
diff --git a/changelog.md b/changelog.md
index 4276d5e5..7a000648 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,6 +1,7 @@
# changelog
## 1.12.0
+* `NEW` progress
* `NEW` [#340](https://github.com/sumneko/lua-language-server/pull/340): supports `---@type table<string, number>`
* `FIX` [#355](https://github.com/sumneko/lua-language-server/pull/355)
* `FIX` [#359](https://github.com/sumneko/lua-language-server/issues/359)
diff --git a/script/progress.lua b/script/progress.lua
new file mode 100644
index 00000000..066b5d76
--- /dev/null
+++ b/script/progress.lua
@@ -0,0 +1,148 @@
+local proto = require 'proto.proto'
+local util = require 'utility'
+local timer = require "timer"
+
+local nextToken = util.counter()
+
+local m = {}
+
+m.map = {}
+
+---@class progress
+local mt = {}
+mt.__index = mt
+mt._token = nil
+mt._title = nil
+mt._message = nil
+mt._removed = false
+mt._clock = 0.0
+mt._delay = 1.0
+mt._percentage = nil
+mt._showed = false
+mt._dirty = true
+mt._updated = 0.0
+
+---移除进度条
+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
+
+---设置描述
+---@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:_update()
+ if self._removed then
+ return
+ end
+ if not self._showed then
+ return
+ end
+ if not self._dirty then
+ return
+ end
+ if os.clock() - self._updated < 0.05 then
+ return
+ end
+ self._dirty = false
+ self._updated = os.clock()
+ proto.notify('$/progress', {
+ token = self._token,
+ value = {
+ kind = 'report',
+ cancellable = false,
+ message = self._message,
+ percentage = self._percentage,
+ }
+ })
+ log.info('Report progress:', self._token, self._title, self._message)
+end
+
+function mt:__close()
+ log.info('Close progress:', self._token, self._message)
+ self:remove()
+end
+
+function m.update()
+ local clock = os.clock()
+ ---@param prog progress
+ for token, prog in pairs(m.map) do
+ if prog._removed then
+ goto CONTINUE
+ end
+ if not prog._showed
+ and prog._clock + prog._delay <= clock then
+ prog._showed = true
+ proto.request('window/workDoneProgress/create', {
+ token = token,
+ })
+ proto.notify('$/progress', {
+ token = token,
+ value = {
+ kind = 'begin',
+ title = prog._title,
+ cancellable = false,
+ message = prog._message,
+ percentage = prog._percentage,
+ }
+ })
+ log.info('Create progress:', token, prog._title)
+ goto CONTINUE
+ end
+ prog:_update()
+ ::CONTINUE::
+ end
+end
+
+---创建一个进度条
+---@param title string # 标题
+---@param delay number # 至少经过这么久之后才会显示出来
+function m.create(title, delay)
+ local prog = setmetatable({
+ _token = nextToken(),
+ _title = title,
+ _clock = os.clock(),
+ _delay = delay,
+ }, mt)
+
+ m.map[prog._token] = prog
+
+ return prog
+end
+
+timer.loop(0.1, m.update)
+
+return m
diff --git a/script/proto/proto.lua b/script/proto/proto.lua
index 944268c2..fe0277ef 100644
--- a/script/proto/proto.lua
+++ b/script/proto/proto.lua
@@ -68,7 +68,7 @@ function m.notify(name, params)
end
function m.awaitRequest(name, params)
- local id = reqCounter()
+ local id = reqCounter()
local buf = jsonrpc.encode {
id = id,
method = name,
@@ -85,6 +85,25 @@ function m.awaitRequest(name, params)
return result
end
+function m.request(name, params, callback)
+ local id = reqCounter()
+ local buf = jsonrpc.encode {
+ id = id,
+ method = name,
+ params = params,
+ }
+ --log.debug('Request', name, #buf)
+ io.stdout:write(buf)
+ m.waiting[id] = function (result, error)
+ if error then
+ log.warn(('Response of [%s] error [%d]: %s'):format(name, error.code, error.message))
+ end
+ if callback then
+ callback(result)
+ end
+ end
+end
+
function m.doMethod(proto)
local method, optional = m.getMethodName(proto)
local abil = m.ability[method]
diff --git a/script/workspace/workspace.lua b/script/workspace/workspace.lua
index ca490886..06bb900d 100644
--- a/script/workspace/workspace.lua
+++ b/script/workspace/workspace.lua
@@ -10,6 +10,8 @@ local proto = require 'proto.proto'
local lang = require 'language'
local library = require 'library'
local sp = require 'bee.subprocess'
+local timer = require 'timer'
+local progress = require 'progress'
local m = {}
m.type = 'workspace'
@@ -170,11 +172,11 @@ function m.isIgnored(uri)
return ignore(path)
end
-local function loadFileFactory(root, progress, isLibrary)
+local function loadFileFactory(root, progressData, isLibrary)
return function (path)
local uri = furi.encode(path)
if files.isLua(uri) then
- if not isLibrary and progress.preload >= config.config.workspace.maxPreload then
+ if not isLibrary and progressData.preload >= config.config.workspace.maxPreload then
if not m.hasHitMaxPreload then
m.hasHitMaxPreload = true
proto.notify('window/showMessage', {
@@ -185,11 +187,13 @@ local function loadFileFactory(root, progress, isLibrary)
return
end
if not isLibrary then
- progress.preload = progress.preload + 1
+ progressData.preload = progressData.preload + 1
end
- progress.max = progress.max + 1
+ progressData.max = progressData.max + 1
+ progressData:update()
pub.task('loadFile', uri, function (text)
- progress.read = progress.read + 1
+ progressData.read = progressData.read + 1
+ progressData:update()
if text then
log.info(('Preload file at: %s , size = %.3f KB'):format(uri, #text / 1000.0))
if isLibrary then
@@ -203,9 +207,11 @@ local function loadFileFactory(root, progress, isLibrary)
end)
end
if files.isDll(uri) then
- progress.max = progress.max + 1
+ progressData.max = progressData.max + 1
+ progressData:update()
pub.task('loadFile', uri, function (content)
- progress.read = progress.read + 1
+ progressData.read = progressData.read + 1
+ progressData:update()
if content then
log.info(('Preload file at: %s , size = %.3f KB'):format(uri, #content / 1000.0))
if isLibrary then
@@ -218,41 +224,6 @@ local function loadFileFactory(root, progress, isLibrary)
end
end
-local function testProgress()
- local client = require 'provider.client'
- proto.notify('$/progress', {
- token = client.info.workDoneToken,
- value = {
- kind = 'begin',
- title = '测试标题',
- cancellable = false,
- message = '测试描述',
- percentage = 0,
- }
- })
- for i = 1, 100 do
- await.sleep(0.1)
- log.info('sleep', i)
- proto.notify('$/progress', {
- token = client.info.workDoneToken,
- value = {
- kind = 'report',
- cancellable = false,
- message = '测试描述',
- percentage = i,
- }
- })
- end
- await.sleep(0.1)
- proto.notify('$/progress', {
- token = client.info.workDoneToken,
- value = {
- kind = 'end',
- message = '测试描述',
- }
- })
-end
-
--- 预读工作区内所有文件
function m.awaitPreload()
local diagnostic = require 'provider.diagnostic'
@@ -262,13 +233,18 @@ function m.awaitPreload()
m.libraryMatchers = nil
m.nativeMatcher = nil
m.cache = {}
- local progress = {
+ local progressBar <close> = progress.create('正在加载文件', 0)
+ local progressData = {
max = 0,
read = 0,
preload = 0,
+ update = function (self)
+ progressBar:setMessage(('%d/%d'):format(self.read, self.max))
+ progressBar:setPercentage(self.read / self.max * 100)
+ end
}
log.info('Preload start.')
- local nativeLoader = loadFileFactory(m.path, progress)
+ local nativeLoader = loadFileFactory(m.path, progressData)
local native = m.getNativeMatcher()
local librarys = m.getLibraryMatchers()
if native then
@@ -276,21 +252,21 @@ function m.awaitPreload()
native:scan(m.path, nativeLoader)
end
for _, library in ipairs(librarys) do
- local libraryLoader = loadFileFactory(library.path, progress, true)
+ local libraryLoader = loadFileFactory(library.path, progressData, true)
log.info('Scan library at:', library.path)
library.matcher:scan(library.path, libraryLoader)
end
- log.info(('Found %d files.'):format(progress.max))
+ log.info(('Found %d files.'):format(progressData.max))
while true do
- log.info(('Loaded %d/%d files'):format(progress.read, progress.max))
- if progress.read >= progress.max then
+ log.info(('Loaded %d/%d files'):format(progressData.read, progressData.max))
+ progressData:update()
+ if progressData.read >= progressData.max then
break
end
await.sleep(0.1)
end
-
- --testProgress()
+ progressBar:remove()
log.info('Preload finish.')