Skip to content

Commit 669ff50

Browse files
committed
support multi plugins
1 parent 4432dfe commit 669ff50

File tree

2 files changed

+79
-59
lines changed

2 files changed

+79
-59
lines changed

script/config/template.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ local template = {
223223
'||', '&&', '!', '!=',
224224
'continue',
225225
}),
226-
['Lua.runtime.plugin'] = Type.String,
227-
['Lua.runtime.pluginArgs'] = Type.Array(Type.String),
226+
['Lua.runtime.plugin'] = Type.Or(Type.String, Type.Array(Type.String)) ,
227+
['Lua.runtime.pluginArgs'] = Type.Or(Type.Array(Type.String), Type.Hash(Type.String, Type.String)),
228228
['Lua.runtime.fileEncoding'] = Type.String >> 'utf8' << {
229229
'utf8',
230230
'ansi',

script/plugin.lua

Lines changed: 77 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,37 @@ function m.showError(scp, err)
1818
client.showMessage('Error', lang.script('PLUGIN_RUNTIME_ERROR', scp:get('pluginPath'), err))
1919
end
2020

21+
---@alias plugin.event 'OnSetText' | 'OnTransformAst'
22+
23+
---@param event plugin.event
2124
function m.dispatch(event, uri, ...)
2225
local scp = scope.getScope(uri)
23-
local interface = scp:get('pluginInterface')
24-
if not interface then
25-
return false
26-
end
27-
local method = interface[event]
28-
if type(method) ~= 'function' then
26+
local interfaces = scp:get('pluginInterfaces')
27+
if not interfaces then
2928
return false
3029
end
31-
local clock = os.clock()
32-
tracy.ZoneBeginN('plugin dispatch:' .. event)
33-
local suc, res1, res2 = xpcall(method, log.error, uri, ...)
34-
tracy.ZoneEnd()
35-
local passed = os.clock() - clock
36-
if passed > 0.1 then
37-
log.warn(('Call plugin event [%s] takes [%.3f] sec'):format(event, passed))
38-
end
39-
if suc then
40-
return true, res1, res2
41-
else
42-
m.showError(scp, res1)
30+
local failed = 0
31+
local res1, res2
32+
for i, interface in ipairs(interfaces) do
33+
local method = interface[event]
34+
if type(method) ~= 'function' then
35+
return false
36+
end
37+
local clock = os.clock()
38+
tracy.ZoneBeginN('plugin dispatch:' .. event)
39+
local suc
40+
suc, res1, res2 = xpcall(method, log.error, uri, ...)
41+
tracy.ZoneEnd()
42+
local passed = os.clock() - clock
43+
if passed > 0.1 then
44+
log.warn(('Call plugin event [%s] takes [%.3f] sec'):format(event, passed))
45+
end
46+
if not suc then
47+
m.showError(scp, res1)
48+
failed = failed + 1
49+
end
4350
end
44-
return false, res1
51+
return failed == 0, res1, res2
4552
end
4653

4754
---@async
@@ -75,53 +82,66 @@ end
7582
local function initPlugin(uri)
7683
await.call(function () ---@async
7784
local scp = scope.getScope(uri)
78-
local interface = {}
79-
scp:set('pluginInterface', interface)
80-
85+
local interfaces = {}
86+
scp:set('pluginInterfaces', interfaces)
87+
8188
if not scp.uri then
8289
return
8390
end
84-
85-
local pluginPath = ws.getAbsolutePath(scp.uri, config.get(scp.uri, 'Lua.runtime.plugin'))
86-
log.info('plugin path:', pluginPath)
87-
if not pluginPath then
88-
return
91+
---@type string[]|string
92+
local pluginConfigPaths = config.get(scp.uri, 'Lua.runtime.plugin')
93+
local args = config.get(scp.uri, 'Lua.runtime.pluginArgs')
94+
if type(pluginConfigPaths) == 'string' then
95+
pluginConfigPaths = {pluginConfigPaths}
8996
end
97+
for i, pluginConfigPath in ipairs(pluginConfigPaths) do
98+
local myArgs = args
99+
for k, v in pairs(args) do
100+
if pluginConfigPath:find(k, 1, true) then
101+
myArgs = v
102+
break
103+
end
104+
end
105+
local pluginPath = ws.getAbsolutePath(scp.uri, pluginConfigPath)
106+
log.info('plugin path:', pluginPath)
107+
if not pluginPath then
108+
return
109+
end
90110

91-
--Adding the plugins path to package.path allows for requires in files
92-
--to find files relative to itself.
93-
local oldPath = package.path
94-
local path = fs.path(pluginPath):parent_path() / '?.lua'
95-
if not package.path:find(path:string(), 1, true) then
96-
package.path = package.path .. ';' .. path:string()
97-
end
111+
--Adding the plugins path to package.path allows for requires in files
112+
--to find files relative to itself.
113+
local oldPath = package.path
114+
local path = fs.path(pluginPath):parent_path() / '?.lua'
115+
if not package.path:find(path:string(), 1, true) then
116+
package.path = package.path .. ';' .. path:string()
117+
end
98118

99-
local pluginLua = util.loadFile(pluginPath)
100-
if not pluginLua then
101-
log.warn('plugin not found:', pluginPath)
102-
package.path = oldPath
103-
return
104-
end
119+
local pluginLua = util.loadFile(pluginPath)
120+
if not pluginLua then
121+
log.warn('plugin not found:', pluginPath)
122+
package.path = oldPath
123+
return
124+
end
105125

106-
scp:set('pluginPath', pluginPath)
126+
scp:set('pluginPath', pluginPath)
107127

108-
local env = setmetatable(interface, { __index = _ENV })
109-
local f, err = load(pluginLua, '@'..pluginPath, "t", env)
110-
if not f then
111-
log.error(err)
112-
m.showError(scp, err)
113-
return
114-
end
115-
if not client.isVSCode() and not checkTrustLoad(scp) then
116-
return
117-
end
118-
local pluginArgs = config.get(scp.uri, 'Lua.runtime.pluginArgs')
119-
local suc, err = xpcall(f, log.error, f, uri, pluginArgs)
120-
if not suc then
121-
m.showError(scp, err)
122-
return
128+
local interface = setmetatable({}, { __index = _ENV })
129+
local f, err = load(pluginLua, '@'..pluginPath, "t", interface)
130+
if not f then
131+
log.error(err)
132+
m.showError(scp, err)
133+
return
134+
end
135+
if not client.isVSCode() and not checkTrustLoad(scp) then
136+
return
137+
end
138+
local suc, err = xpcall(f, log.error, f, uri, myArgs)
139+
if not suc then
140+
m.showError(scp, err)
141+
return
142+
end
143+
interfaces[#interfaces+1] = interface
123144
end
124-
125145
ws.resetFiles(scp)
126146
end)
127147
end

0 commit comments

Comments
 (0)