diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2021-01-25 19:09:23 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2021-01-25 19:09:23 +0800 |
commit | 7667109acd76492c82b17fbe57666b5db675d7ed (patch) | |
tree | c11de10d51f4c3969220044f0a56506e1843a2a8 | |
parent | 7d6885350af462d400c39a557703890d4ec507f1 (diff) | |
download | lua-language-server-7667109acd76492c82b17fbe57666b5db675d7ed.zip |
add progress
-rw-r--r-- | changelog.md | 1 | ||||
-rw-r--r-- | script/progress.lua | 148 | ||||
-rw-r--r-- | script/proto/proto.lua | 21 | ||||
-rw-r--r-- | script/workspace/workspace.lua | 76 |
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.') |