summaryrefslogtreecommitdiff
path: root/script/plugin.lua
diff options
context:
space:
mode:
authorfesily <fesil@foxmail.com>2024-01-17 16:14:32 +0800
committerfesily <fesil@foxmail.com>2024-01-17 16:14:32 +0800
commit669ff50e9babebcafcdc3945f803062a927c58d3 (patch)
tree304c81cc1f5cc5eaebb5966b52c7465a48b9a3b9 /script/plugin.lua
parent4432dfea0fe8390be166b832a1ac416c8228296f (diff)
downloadlua-language-server-669ff50e9babebcafcdc3945f803062a927c58d3.zip
support multi plugins
Diffstat (limited to 'script/plugin.lua')
-rw-r--r--script/plugin.lua134
1 files changed, 77 insertions, 57 deletions
diff --git a/script/plugin.lua b/script/plugin.lua
index fc59bbad..1d6b9f86 100644
--- a/script/plugin.lua
+++ b/script/plugin.lua
@@ -18,30 +18,37 @@ function m.showError(scp, err)
client.showMessage('Error', lang.script('PLUGIN_RUNTIME_ERROR', scp:get('pluginPath'), err))
end
+---@alias plugin.event 'OnSetText' | 'OnTransformAst'
+
+---@param event plugin.event
function m.dispatch(event, uri, ...)
local scp = scope.getScope(uri)
- local interface = scp:get('pluginInterface')
- if not interface then
- return false
- end
- local method = interface[event]
- if type(method) ~= 'function' then
+ local interfaces = scp:get('pluginInterfaces')
+ if not interfaces then
return false
end
- local clock = os.clock()
- tracy.ZoneBeginN('plugin dispatch:' .. event)
- local suc, res1, res2 = xpcall(method, log.error, uri, ...)
- tracy.ZoneEnd()
- local passed = os.clock() - clock
- if passed > 0.1 then
- log.warn(('Call plugin event [%s] takes [%.3f] sec'):format(event, passed))
- end
- if suc then
- return true, res1, res2
- else
- m.showError(scp, res1)
+ local failed = 0
+ local res1, res2
+ for i, interface in ipairs(interfaces) do
+ local method = interface[event]
+ if type(method) ~= 'function' then
+ return false
+ end
+ local clock = os.clock()
+ tracy.ZoneBeginN('plugin dispatch:' .. event)
+ local suc
+ suc, res1, res2 = xpcall(method, log.error, uri, ...)
+ tracy.ZoneEnd()
+ local passed = os.clock() - clock
+ if passed > 0.1 then
+ log.warn(('Call plugin event [%s] takes [%.3f] sec'):format(event, passed))
+ end
+ if not suc then
+ m.showError(scp, res1)
+ failed = failed + 1
+ end
end
- return false, res1
+ return failed == 0, res1, res2
end
---@async
@@ -75,53 +82,66 @@ end
local function initPlugin(uri)
await.call(function () ---@async
local scp = scope.getScope(uri)
- local interface = {}
- scp:set('pluginInterface', interface)
-
+ local interfaces = {}
+ scp:set('pluginInterfaces', interfaces)
+
if not scp.uri then
return
end
-
- local pluginPath = ws.getAbsolutePath(scp.uri, config.get(scp.uri, 'Lua.runtime.plugin'))
- log.info('plugin path:', pluginPath)
- if not pluginPath then
- return
+ ---@type string[]|string
+ local pluginConfigPaths = config.get(scp.uri, 'Lua.runtime.plugin')
+ local args = config.get(scp.uri, 'Lua.runtime.pluginArgs')
+ if type(pluginConfigPaths) == 'string' then
+ pluginConfigPaths = {pluginConfigPaths}
end
+ for i, pluginConfigPath in ipairs(pluginConfigPaths) do
+ local myArgs = args
+ for k, v in pairs(args) do
+ if pluginConfigPath:find(k, 1, true) then
+ myArgs = v
+ break
+ end
+ end
+ local pluginPath = ws.getAbsolutePath(scp.uri, pluginConfigPath)
+ log.info('plugin path:', pluginPath)
+ if not pluginPath then
+ return
+ end
- --Adding the plugins path to package.path allows for requires in files
- --to find files relative to itself.
- local oldPath = package.path
- local path = fs.path(pluginPath):parent_path() / '?.lua'
- if not package.path:find(path:string(), 1, true) then
- package.path = package.path .. ';' .. path:string()
- end
+ --Adding the plugins path to package.path allows for requires in files
+ --to find files relative to itself.
+ local oldPath = package.path
+ local path = fs.path(pluginPath):parent_path() / '?.lua'
+ if not package.path:find(path:string(), 1, true) then
+ package.path = package.path .. ';' .. path:string()
+ end
- local pluginLua = util.loadFile(pluginPath)
- if not pluginLua then
- log.warn('plugin not found:', pluginPath)
- package.path = oldPath
- return
- end
+ local pluginLua = util.loadFile(pluginPath)
+ if not pluginLua then
+ log.warn('plugin not found:', pluginPath)
+ package.path = oldPath
+ return
+ end
- scp:set('pluginPath', pluginPath)
+ scp:set('pluginPath', pluginPath)
- local env = setmetatable(interface, { __index = _ENV })
- local f, err = load(pluginLua, '@'..pluginPath, "t", env)
- if not f then
- log.error(err)
- m.showError(scp, err)
- return
- end
- if not client.isVSCode() and not checkTrustLoad(scp) then
- return
- end
- local pluginArgs = config.get(scp.uri, 'Lua.runtime.pluginArgs')
- local suc, err = xpcall(f, log.error, f, uri, pluginArgs)
- if not suc then
- m.showError(scp, err)
- return
+ local interface = setmetatable({}, { __index = _ENV })
+ local f, err = load(pluginLua, '@'..pluginPath, "t", interface)
+ if not f then
+ log.error(err)
+ m.showError(scp, err)
+ return
+ end
+ if not client.isVSCode() and not checkTrustLoad(scp) then
+ return
+ end
+ local suc, err = xpcall(f, log.error, f, uri, myArgs)
+ if not suc then
+ m.showError(scp, err)
+ return
+ end
+ interfaces[#interfaces+1] = interface
end
-
ws.resetFiles(scp)
end)
end