micro/internal/config/plugin.go

146 lines
3.3 KiB
Go
Raw Permalink Normal View History

2019-03-18 22:40:53 +00:00
package config
import (
"errors"
2020-01-29 03:06:58 +00:00
"log"
2019-03-18 22:40:53 +00:00
lua "github.com/yuin/gopher-lua"
2020-05-04 14:16:15 +00:00
ulua "github.com/zyedidia/micro/v2/internal/lua"
2019-03-18 22:40:53 +00:00
)
// ErrNoSuchFunction is returned when Call is executed on a function that does not exist
2019-03-18 22:40:53 +00:00
var ErrNoSuchFunction = errors.New("No such function exists")
2019-03-19 22:28:51 +00:00
// LoadAllPlugins loads all detected plugins (in runtime/plugins and ConfigDir/plugins)
2019-08-03 06:46:25 +00:00
func LoadAllPlugins() error {
var reterr error
2019-03-18 22:40:53 +00:00
for _, p := range Plugins {
2019-08-03 06:46:25 +00:00
err := p.Load()
if err != nil {
reterr = err
}
2019-03-18 22:40:53 +00:00
}
2019-08-03 06:46:25 +00:00
return reterr
2019-03-18 22:40:53 +00:00
}
2019-03-19 22:28:51 +00:00
// RunPluginFn runs a given function in all plugins
2019-08-02 21:48:59 +00:00
// returns an error if any of the plugins had an error
2019-03-19 22:28:51 +00:00
func RunPluginFn(fn string, args ...lua.LValue) error {
var reterr error
for _, p := range Plugins {
if !p.IsLoaded() {
continue
}
2019-03-19 22:28:51 +00:00
_, err := p.Call(fn, args...)
if err != nil && err != ErrNoSuchFunction {
reterr = errors.New("Plugin " + p.Name + ": " + err.Error())
}
}
return reterr
}
2019-08-02 21:48:59 +00:00
// RunPluginFnBool runs a function in all plugins and returns
// false if any one of them returned false
// also returns an error if any of the plugins had an error
func RunPluginFnBool(settings map[string]interface{}, fn string, args ...lua.LValue) (bool, error) {
2019-08-02 21:48:59 +00:00
var reterr error
retbool := true
for _, p := range Plugins {
if !p.IsLoaded() || (settings != nil && settings[p.Name] == false) {
2019-08-02 21:48:59 +00:00
continue
}
val, err := p.Call(fn, args...)
if err == ErrNoSuchFunction {
continue
}
if err != nil {
reterr = errors.New("Plugin " + p.Name + ": " + err.Error())
continue
}
2020-02-05 22:16:31 +00:00
if v, ok := val.(lua.LBool); ok {
2019-08-02 21:48:59 +00:00
retbool = retbool && bool(v)
}
}
return retbool, reterr
}
// Plugin stores information about the source files/info for a plugin
2019-03-18 22:40:53 +00:00
type Plugin struct {
2019-12-28 01:28:25 +00:00
DirName string // name of plugin folder
2019-08-07 05:24:03 +00:00
Name string // name of plugin
Info *PluginInfo // json file containing info
Srcs []RuntimeFile // lua files
Loaded bool
2025-03-24 22:04:06 +00:00
Default bool // pre-installed plugin
}
// IsLoaded returns if a plugin is enabled
func (p *Plugin) IsLoaded() bool {
if v, ok := GlobalSettings[p.Name]; ok {
2019-08-03 06:46:25 +00:00
return v.(bool) && p.Loaded
}
return true
2019-03-18 22:40:53 +00:00
}
// Plugins is a list of all detected plugins (enabled or disabled)
2019-03-18 22:40:53 +00:00
var Plugins []*Plugin
// Load creates an option for the plugin and runs all source files
2019-03-18 22:40:53 +00:00
func (p *Plugin) Load() error {
if v, ok := GlobalSettings[p.Name]; ok && !v.(bool) {
return nil
}
2019-03-18 22:40:53 +00:00
for _, f := range p.Srcs {
dat, err := f.Data()
if err != nil {
return err
}
err = ulua.LoadFile(p.Name, f.Name(), dat)
if err != nil {
return err
}
}
p.Loaded = true
RegisterCommonOption(p.Name, true)
2019-03-18 22:40:53 +00:00
return nil
}
// Call calls a given function in this plugin
2019-03-18 22:40:53 +00:00
func (p *Plugin) Call(fn string, args ...lua.LValue) (lua.LValue, error) {
plug := ulua.L.GetGlobal(p.Name)
2020-01-29 03:06:58 +00:00
if plug == lua.LNil {
log.Println("Plugin does not exist:", p.Name, "at", p.DirName, ":", p)
return nil, nil
}
2019-03-18 22:40:53 +00:00
luafn := ulua.L.GetField(plug, fn)
if luafn == lua.LNil {
return nil, ErrNoSuchFunction
}
err := ulua.L.CallByParam(lua.P{
Fn: luafn,
NRet: 1,
Protect: true,
}, args...)
if err != nil {
return nil, err
}
ret := ulua.L.Get(-1)
ulua.L.Pop(1)
return ret, nil
}
2019-08-03 01:29:47 +00:00
// FindPlugin returns the plugin with the given name
2019-08-03 01:29:47 +00:00
func FindPlugin(name string) *Plugin {
var pl *Plugin
for _, p := range Plugins {
if !p.IsLoaded() {
continue
}
if p.Name == name {
pl = p
break
}
}
return pl
}