@@ -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 )
85+ local interfaces = {}
86+ scp :set (' pluginInterfaces ' , interfaces )
8087
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
91+ --- @type string[] | string
92+ local pluginConfigPaths = config .get (scp .uri , ' Lua.runtime.plugin' )
93+ if not pluginConfigPaths then
8894 return
8995 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 }
9799 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
98110
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
105116
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
107124
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
124131
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
125151 ws .resetFiles (scp )
126152 end )
127153end
0 commit comments