@@ -18,30 +18,37 @@ function m.showError(scp, err)
18
18
client .showMessage (' Error' , lang .script (' PLUGIN_RUNTIME_ERROR' , scp :get (' pluginPath' ), err ))
19
19
end
20
20
21
+ --- @alias plugin.event ' OnSetText' | ' OnTransformAst'
22
+
23
+ --- @param event plugin.event
21
24
function m .dispatch (event , uri , ...)
22
25
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
29
28
return false
30
29
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
43
50
end
44
- return false , res1
51
+ return failed == 0 , res1 , res2
45
52
end
46
53
47
54
--- @async
75
82
local function initPlugin (uri )
76
83
await .call (function () --- @async
77
84
local scp = scope .getScope (uri )
78
- local interface = {}
79
- scp :set (' pluginInterface ' , interface )
85
+ local interfaces = {}
86
+ scp :set (' pluginInterfaces ' , interfaces )
80
87
81
88
if not scp .uri then
82
89
return
83
90
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
91
+ --- @type string[] | string
92
+ local pluginConfigPaths = config .get (scp .uri , ' Lua.runtime.plugin' )
93
+ if not pluginConfigPaths then
88
94
return
89
95
end
90
-
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 ()
96
+ local args = config .get (scp .uri , ' Lua.runtime.pluginArgs' )
97
+ if type (pluginConfigPaths ) == ' string' then
98
+ pluginConfigPaths = { pluginConfigPaths }
97
99
end
100
+ for i , pluginConfigPath in ipairs (pluginConfigPaths ) do
101
+ local myArgs = args
102
+ if args then
103
+ for k , v in pairs (args ) do
104
+ if pluginConfigPath :find (k , 1 , true ) then
105
+ myArgs = v
106
+ break
107
+ end
108
+ end
109
+ end
98
110
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
111
+ local pluginPath = ws .getAbsolutePath (scp .uri , pluginConfigPath )
112
+ log .info (' plugin path:' , pluginPath )
113
+ if not pluginPath then
114
+ return
115
+ end
105
116
106
- scp :set (' pluginPath' , pluginPath )
117
+ -- Adding the plugins path to package.path allows for requires in files
118
+ -- to find files relative to itself.
119
+ local oldPath = package.path
120
+ local path = fs .path (pluginPath ):parent_path () / ' ?.lua'
121
+ if not package.path :find (path :string (), 1 , true ) then
122
+ package.path = package.path .. ' ;' .. path :string ()
123
+ end
107
124
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
123
- end
125
+ local pluginLua = util .loadFile (pluginPath )
126
+ if not pluginLua then
127
+ log .warn (' plugin not found:' , pluginPath )
128
+ package.path = oldPath
129
+ return
130
+ end
124
131
132
+ scp :set (' pluginPath' , pluginPath )
133
+
134
+ local interface = setmetatable ({}, { __index = _ENV })
135
+ local f , err = load (pluginLua , ' @' .. pluginPath , " t" , interface )
136
+ if not f then
137
+ log .error (err )
138
+ m .showError (scp , err )
139
+ return
140
+ end
141
+ if not client .isVSCode () and not checkTrustLoad (scp ) then
142
+ return
143
+ end
144
+ local suc , err = xpcall (f , log .error , f , uri , myArgs )
145
+ if not suc then
146
+ m .showError (scp , err )
147
+ return
148
+ end
149
+ interfaces [# interfaces + 1 ] = interface
150
+ end
125
151
ws .resetFiles (scp )
126
152
end )
127
153
end
0 commit comments