diff options
-rw-r--r-- | meta/3rd/example/config.lua | 18 | ||||
-rw-r--r-- | script/await.lua | 15 | ||||
-rw-r--r-- | script/client.lua | 32 | ||||
-rw-r--r-- | script/core/type-formatting.lua | 3 | ||||
-rw-r--r-- | script/files.lua | 6 | ||||
-rw-r--r-- | script/library.lua | 78 | ||||
-rw-r--r-- | script/plugin.lua | 41 | ||||
-rw-r--r-- | script/provider/provider.lua | 7 | ||||
-rw-r--r-- | script/workspace/workspace.lua | 20 |
9 files changed, 166 insertions, 54 deletions
diff --git a/meta/3rd/example/config.lua b/meta/3rd/example/config.lua index 17b6ab06..7bf8e04a 100644 --- a/meta/3rd/example/config.lua +++ b/meta/3rd/example/config.lua @@ -5,20 +5,20 @@ files = {'thisIsAnExampleFile%.ifItExistsInWorkSpace%.thenTryLoadThisLibrary'} -- lsit of settings to be changed configs = { { - name = 'Lua.runtime.version', - type = 'set', - value = 'LuaJIT', + key = 'Lua.runtime.version', + action = 'set', + value = 'LuaJIT', }, { - name = 'Lua.diagnostics.globals', - type = 'add', - value = 'global1', + key = 'Lua.diagnostics.globals', + action = 'add', + value = 'global1', } } for _, name in ipairs {'global2', 'global3', 'global4'} do configs[#configs+1] = { - name = 'Lua.diagnostics.globals', - type = 'add', - value = name, + key = 'Lua.diagnostics.globals', + action = 'add', + value = name, } end diff --git a/script/await.lua b/script/await.lua index 6815bc1a..81b44679 100644 --- a/script/await.lua +++ b/script/await.lua @@ -10,6 +10,7 @@ m.idMap = {} m.delayQueue = {} m.delayQueueIndex = 1 m.watchList = {} +m.needClose = {} m._enable = true --- 设置错误处理器 @@ -161,6 +162,15 @@ function m.delay() return coroutine.yield() end +--- stop then close +function m.stop() + if not coroutine.isyieldable() then + return + end + m.needClose[#m.needClose+1] = coroutine.running() + coroutine.yield() +end + local function warnStepTime(passed, waker) if passed < 1 then log.warn(('Await step takes [%.3f] sec.'):format(passed)) @@ -180,6 +190,11 @@ end --- 步进 function m.step() + for i = #m.needClose, 1, -1 do + coroutine.close(m.needClose[i]) + m.needClose[i] = nil + end + local resume = m.delayQueue[m.delayQueueIndex] if resume then m.delayQueue[m.delayQueueIndex] = false diff --git a/script/client.lua b/script/client.lua index 14973a64..31093fe7 100644 --- a/script/client.lua +++ b/script/client.lua @@ -47,8 +47,10 @@ local function packMessage(...) return table.concat(strs, '\t') end +---@alias message.type '"Error"'|'"Warning"'|'"Info"'|'"Log"' + ---show message to client ----@param type '"Error"'|'"Warning"'|'"Info"'|'"Log"' +---@param type message.type function m.showMessage(type, ...) local message = packMessage(...) proto.notify('window/showMessage', { @@ -61,7 +63,33 @@ function m.showMessage(type, ...) }) end ----@param type '"Error"'|'"Warning"'|'"Info"'|'"Log"' +---@param type message.type +---@param message string +---@param titles string[] +---@return string action +function m.awaitRequestMessage(type, message, titles) + proto.notify('window/logMessage', { + type = define.MessageType[type] or 3, + message = message, + }) + local actions = {} + for i, title in ipairs(titles) do + actions[i] = { + title = title, + } + end + local item = proto.awaitRequest('window/showMessageRequest', { + type = type, + message = message, + actions = actions, + }) + if not item then + return nil + end + return item.title +end + +---@param type message.type function m.logMessage(type, ...) local message = packMessage(...) proto.notify('window/logMessage', { diff --git a/script/core/type-formatting.lua b/script/core/type-formatting.lua index b01a1999..a225d9d7 100644 --- a/script/core/type-formatting.lua +++ b/script/core/type-formatting.lua @@ -15,6 +15,9 @@ end local function findForward(text, offset, ...) local pos = text:match('^[ \t]*()', offset) + if not pos then + return nil + end for _, symbol in ipairs { ... } do if text:sub(pos, pos + #symbol - 1) == symbol then return pos, symbol diff --git a/script/files.lua b/script/files.lua index c42ed624..1d20a3be 100644 --- a/script/files.lua +++ b/script/files.lua @@ -205,7 +205,13 @@ function m.setText(uri, text, isTrust, instance) end end) end +end +function m.resetText(uri) + local file = m.fileMap[uri] + local originText = file.originText + file.originText = nil + m.setText(uri, originText, file.trusted) end function m.setRawText(uri, text) diff --git a/script/library.lua b/script/library.lua index 628b3bbe..d4be539e 100644 --- a/script/library.lua +++ b/script/library.lua @@ -7,6 +7,7 @@ local lloader = require 'locale-loader' local fsu = require 'fs-utility' local define = require "proto.define" local files = require 'files' +local await = require 'await' local m = {} @@ -246,9 +247,9 @@ local function loadSingle3rdConfig(libraryDir) cfg.name = libraryDir:filename():string() - local pluginPath = libraryDir / 'plugin.lua' - if fs.exists(pluginPath) then - cfg.plugin = pluginPath:string() + local pluginPath = ('${3rd}/%s/plugin.lua'):format('cfg.name') + if fs.exists(fs.path(pluginPath)) then + cfg.plugin = pluginPath end for k, v in pairs(env) do @@ -273,20 +274,81 @@ local function load3rdConfig() return configs end -local function check3rdByWords(configs) - +local function apply3rd(cfg) + local changes = {} + for _, change in ipairs(cfg.configs) do + changes[#changes+1] = change + end + + if cfg.plugin then + changes[#changes+1] = { + key = 'Lua.workspace.library', + action = 'set', + value = cfg.plugin, + } + end +end + +local hasAsked +local function askFor3rd(cfg) + hasAsked = true + -- TODO: translate + local yes = lang.script['启用'] + local no = lang.script.WINDOW_DONT_SHOW_AGAIN + local result = client.awaitRequestMessage('Info' + , lang.script('是否需要将你的工作环境配置为 `{}` ?(这会修改你的工作区设置)', cfg.name) + , {yes, no} + ) + if not result then + return nil + end + client.setConfig { + { + key = 'Lua.workspace.checkThirdParty', + action = 'set', + value = false, + }, + } + if result == yes then + apply3rd(cfg) + end +end + +local function check3rdByWords(text, configs) + await.call(function () + for _, cfg in ipairs(configs) do + if cfg.words then + for _, word in ipairs(cfg.words) do + await.delay() + if text:match(word) then + askFor3rd() + return + end + end + end + end + end) end local thirdConfigs +local hasCheckedUri = {} local function check3rd(uri) + if hasAsked then + return + end + if not config.get 'Lua.workspace.checkThirdParty' then + return + end if thirdConfigs == nil then thirdConfigs = load3rdConfig() or false end if not thirdConfigs then return end - if files.isLua(uri) then - local text = files.getUri(uri) + if not hasCheckedUri[uri] + and files.isLua(uri) then + hasCheckedUri[uri] = true + local text = files.getText(uri) check3rdByWords(text, thirdConfigs) end end @@ -299,7 +361,7 @@ end) files.watch(function (ev, uri) if ev == 'update' then - check3rd(uri) + check3rd(files.asKey(uri)) end end) diff --git a/script/plugin.lua b/script/plugin.lua index af86cea5..15c7c311 100644 --- a/script/plugin.lua +++ b/script/plugin.lua @@ -1,11 +1,8 @@ local config = require 'config' -local fs = require 'bee.filesystem' -local fsu = require 'fs-utility' -local await = require "await" +local util = require 'utility' ---@class plugin local m = {} -m.waitingReady = {} function m.dispatch(event, ...) if not m.interface then @@ -28,49 +25,35 @@ function m.isReady() return m.interface ~= nil end -function m.awaitReady() - if m.isReady() then - return +local function resetFiles() + local files = require 'files' + for uri in files.eachFile() do + files.resetText(uri) end - await.wait(function (waker) - m.waitingReady[#m.waitingReady+1] = waker - end) end function m.init() local ws = require 'workspace' m.interface = {} - local _ <close> = function () - local waiting = m.waitingReady - m.waitingReady = {} - for _, waker in ipairs(waiting) do - waker() - end - end - - if not config.get 'Lua.runtime.plugin' or config.get 'Lua.runtime.plugin' == '' then + local pluginPath = ws.getAbsolutePath(config.get 'Lua.runtime.plugin') + log.info('plugin path:', pluginPath) + if not pluginPath then return end - - local pluginPath = fs.path(config.get 'Lua.runtime.plugin') - if pluginPath:is_relative() then - if not ws.path then - return - end - pluginPath = fs.path(ws.path) / pluginPath - end - local pluginLua = fsu.loadFile(pluginPath) + local pluginLua = util.loadFile(pluginPath) if not pluginLua then return end local env = setmetatable(m.interface, { __index = _ENV }) - local f, err = load(pluginLua, '@'..pluginPath:string(), "t", env) + local f, err = load(pluginLua, '@'..pluginPath, "t", env) if not f then log.error(err) return end xpcall(f, log.error, f) + + resetFiles() end return m diff --git a/script/provider/provider.lua b/script/provider/provider.lua index c3a1113a..ae389b70 100644 --- a/script/provider/provider.lua +++ b/script/provider/provider.lua @@ -40,7 +40,7 @@ end proto.on('initialize', function (params) client.init(params) - workspace.init(params.rootUri) + workspace.initPath(params.rootUri) return { capabilities = cap.getIniter(), serverInfo = { @@ -130,7 +130,6 @@ proto.on('workspace/didChangeWatchedFiles', function (params) if files.isLua(uri) and not files.isOpen(uri) and (not workspace.isIgnored(uri) or files.isLibrary(uri)) then - plugin.awaitReady() files.setText(uri, pub.awaitTask('loadFile', uri), false) else local path = furi.decode(uri) @@ -149,7 +148,6 @@ end) proto.on('workspace/didCreateFiles', function (params) log.debug('workspace/didCreateFiles', util.dump(params)) - plugin.awaitReady() for _, file in ipairs(params.files) do if files.isLua(file.uri) then files.setText(file.uri, pub.awaitTask('loadFile', file.uri), false) @@ -171,7 +169,6 @@ end) proto.on('workspace/didRenameFiles', function (params) log.debug('workspace/didRenameFiles', util.dump(params)) - plugin.awaitReady() for _, file in ipairs(params.files) do local text = files.getOriginText(file.oldUri) if text then @@ -199,7 +196,6 @@ proto.on('textDocument/didOpen', function (params) local text = doc.text log.debug('didOpen', uri) files.open(uri) - plugin.awaitReady() if not files.isOpen(uri) then return end @@ -220,7 +216,6 @@ proto.on('textDocument/didChange', function (params) local doc = params.textDocument local changes = params.contentChanges local uri = doc.uri - plugin.awaitReady() if not files.isLua(uri) and not files.isOpen(uri) then return end diff --git a/script/workspace/workspace.lua b/script/workspace/workspace.lua index 36fc7771..72d7e4bb 100644 --- a/script/workspace/workspace.lua +++ b/script/workspace/workspace.lua @@ -440,6 +440,11 @@ function m.findUrisByRequirePath(path) end function m.normalize(path) + path = path:gsub('$$${(.-)$}', function (key) + if key == '3rd' then + return (ROOT / 'meta' / '3rd'):string() + end + end) if platform.OS == 'Windows' then path = path:gsub('[/\\]+', '\\') :gsub('[/\\]+$', '') @@ -450,6 +455,21 @@ function m.normalize(path) return path end +---@return string +function m.getAbsolutePath(path) + if not path or path == '' then + return nil + end + path = m.normalize(path) + if fs.path(path):is_relative() then + if not m.path then + return nil + end + path = m.normalize(m.path .. '/' .. path) + end + return path +end + function m.getRelativePath(uri) local path = furi.decode(uri) if not m.path then |