@@ -18,30 +18,37 @@ function m.showError(scp, err)
1818 client .showMessage (' Error' , lang .script (' PLUGIN_RUNTIME_ERROR' , scp :get (' pluginPath' ), err ))
1919end
2020
21+ --- @alias plugin.event ' OnSetText' | ' OnTransformAst'
22+
23+ --- @param event plugin.event
2124function 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
4552end
4653
4754--- @async
7582local 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 )
127147end
0 commit comments