]> git.lizzy.rs Git - micro.git/blob - internal/config/plugin.go
Remove local settings
[micro.git] / internal / config / plugin.go
1 package config
2
3 import (
4         "errors"
5
6         lua "github.com/yuin/gopher-lua"
7         ulua "github.com/zyedidia/micro/internal/lua"
8 )
9
10 var ErrNoSuchFunction = errors.New("No such function exists")
11
12 // LoadAllPlugins loads all detected plugins (in runtime/plugins and ConfigDir/plugins)
13 func LoadAllPlugins() error {
14         var reterr error
15         for _, p := range Plugins {
16                 err := p.Load()
17                 if err != nil {
18                         reterr = err
19                 }
20         }
21         return reterr
22 }
23
24 // RunPluginFn runs a given function in all plugins
25 // returns an error if any of the plugins had an error
26 func RunPluginFn(fn string, args ...lua.LValue) error {
27         var reterr error
28         for _, p := range Plugins {
29                 if !p.IsEnabled() {
30                         continue
31                 }
32                 _, err := p.Call(fn, args...)
33                 if err != nil && err != ErrNoSuchFunction {
34                         reterr = errors.New("Plugin " + p.Name + ": " + err.Error())
35                 }
36         }
37         return reterr
38 }
39
40 // RunPluginFnBool runs a function in all plugins and returns
41 // false if any one of them returned false
42 // also returns an error if any of the plugins had an error
43 func RunPluginFnBool(fn string, args ...lua.LValue) (bool, error) {
44         var reterr error
45         retbool := true
46         for _, p := range Plugins {
47                 if !p.IsEnabled() {
48                         continue
49                 }
50                 val, err := p.Call(fn, args...)
51                 if err == ErrNoSuchFunction {
52                         continue
53                 }
54                 if err != nil {
55                         reterr = errors.New("Plugin " + p.Name + ": " + err.Error())
56                         continue
57                 }
58                 if v, ok := val.(lua.LBool); !ok {
59                         reterr = errors.New(p.Name + "." + fn + " should return a boolean")
60                 } else {
61                         retbool = retbool && bool(v)
62                 }
63         }
64         return retbool, reterr
65 }
66
67 type Plugin struct {
68         Name   string        // name of plugin
69         Info   RuntimeFile   // json file containing info
70         Srcs   []RuntimeFile // lua files
71         Loaded bool
72 }
73
74 func (p *Plugin) IsEnabled() bool {
75         if v, ok := GlobalSettings[p.Name]; ok {
76                 return v.(bool) && p.Loaded
77         }
78         return true
79 }
80
81 var Plugins []*Plugin
82
83 func (p *Plugin) Load() error {
84         for _, f := range p.Srcs {
85                 if v, ok := GlobalSettings[p.Name]; ok && !v.(bool) {
86                         return nil
87                 }
88                 dat, err := f.Data()
89                 if err != nil {
90                         return err
91                 }
92                 err = ulua.LoadFile(p.Name, f.Name(), dat)
93                 if err != nil {
94                         return err
95                 }
96                 p.Loaded = true
97                 RegisterGlobalOption(p.Name, true)
98         }
99         return nil
100 }
101
102 func (p *Plugin) Call(fn string, args ...lua.LValue) (lua.LValue, error) {
103         plug := ulua.L.GetGlobal(p.Name)
104         luafn := ulua.L.GetField(plug, fn)
105         if luafn == lua.LNil {
106                 return nil, ErrNoSuchFunction
107         }
108         err := ulua.L.CallByParam(lua.P{
109                 Fn:      luafn,
110                 NRet:    1,
111                 Protect: true,
112         }, args...)
113         if err != nil {
114                 return nil, err
115         }
116         ret := ulua.L.Get(-1)
117         ulua.L.Pop(1)
118         return ret, nil
119 }
120
121 func FindPlugin(name string) *Plugin {
122         var pl *Plugin
123         for _, p := range Plugins {
124                 if p.Name == name {
125                         pl = p
126                         break
127                 }
128         }
129         return pl
130 }