]> git.lizzy.rs Git - micro.git/blob - cmd/micro/plugin.go
Fix some issues with unicode handling
[micro.git] / cmd / micro / plugin.go
1 package main
2
3 import (
4         "errors"
5         "io/ioutil"
6         "strings"
7
8         "github.com/layeh/gopher-luar"
9         "github.com/yuin/gopher-lua"
10 )
11
12 var loadedPlugins []string
13
14 var preInstalledPlugins = []string{
15         "go",
16         "linter",
17         "autoclose",
18 }
19
20 // Call calls the lua function 'function'
21 // If it does not exist nothing happens, if there is an error,
22 // the error is returned
23 func Call(function string, args []string) (lua.LValue, error) {
24         var luaFunc lua.LValue
25         if strings.Contains(function, ".") {
26                 plugin := L.GetGlobal(strings.Split(function, ".")[0])
27                 if plugin.String() == "nil" {
28                         return nil, errors.New("function does not exist: " + function)
29                 }
30                 luaFunc = L.GetField(plugin, strings.Split(function, ".")[1])
31         } else {
32                 luaFunc = L.GetGlobal(function)
33         }
34
35         if luaFunc.String() == "nil" {
36                 return nil, errors.New("function does not exist: " + function)
37         }
38         var luaArgs []lua.LValue
39         for _, v := range args {
40                 luaArgs = append(luaArgs, luar.New(L, v))
41         }
42         err := L.CallByParam(lua.P{
43                 Fn:      luaFunc,
44                 NRet:    1,
45                 Protect: true,
46         }, luaArgs...)
47         ret := L.Get(-1) // returned value
48         if ret.String() != "nil" {
49                 L.Pop(1) // remove received value
50         }
51         return ret, err
52 }
53
54 // LuaFunctionBinding is a function generator which takes the name of a lua function
55 // and creates a function that will call that lua function
56 // Specifically it creates a function that can be called as a binding because this is used
57 // to bind keys to lua functions
58 func LuaFunctionBinding(function string) func(*View, bool) bool {
59         return func(v *View, _ bool) bool {
60                 _, err := Call(function, nil)
61                 if err != nil {
62                         TermMessage(err)
63                 }
64                 return false
65         }
66 }
67
68 // LuaFunctionCommand is the same as LuaFunctionBinding except it returns a normal function
69 // so that a command can be bound to a lua function
70 func LuaFunctionCommand(function string) func([]string) {
71         return func(args []string) {
72                 _, err := Call(function, args)
73                 if err != nil {
74                         TermMessage(err)
75                 }
76         }
77 }
78
79 func LuaFunctionJob(function string) func(string, ...string) {
80         return func(output string, args ...string) {
81                 _, err := Call(function, append([]string{output}, args...))
82                 if err != nil {
83                         TermMessage(err)
84                 }
85         }
86 }
87
88 // LoadPlugins loads the pre-installed plugins and the plugins located in ~/.config/micro/plugins
89 func LoadPlugins() {
90         files, _ := ioutil.ReadDir(configDir + "/plugins")
91         for _, plugin := range files {
92                 if plugin.IsDir() {
93                         pluginName := plugin.Name()
94                         files, _ := ioutil.ReadDir(configDir + "/plugins/" + pluginName)
95                         for _, f := range files {
96                                 if f.Name() == pluginName+".lua" {
97                                         data, _ := ioutil.ReadFile(configDir + "/plugins/" + pluginName + "/" + f.Name())
98                                         pluginDef := "\nlocal P = {}\n" + pluginName + " = P\nsetmetatable(" + pluginName + ", {__index = _G})\nsetfenv(1, P)\n"
99
100                                         if err := L.DoString(pluginDef + string(data)); err != nil {
101                                                 TermMessage(err)
102                                                 continue
103                                         }
104                                         loadedPlugins = append(loadedPlugins, pluginName)
105                                 }
106                         }
107                 }
108         }
109
110         for _, pluginName := range preInstalledPlugins {
111                 alreadyExists := false
112                 for _, pl := range loadedPlugins {
113                         if pl == pluginName {
114                                 alreadyExists = true
115                                 break
116                         }
117                 }
118                 if !alreadyExists {
119                         plugin := "runtime/plugins/" + pluginName + "/" + pluginName + ".lua"
120                         data, err := Asset(plugin)
121                         if err != nil {
122                                 TermMessage("Error loading pre-installed plugin: " + pluginName)
123                                 continue
124                         }
125                         pluginDef := "\nlocal P = {}\n" + pluginName + " = P\nsetmetatable(" + pluginName + ", {__index = _G})\nsetfenv(1, P)\n"
126                         if err := L.DoString(pluginDef + string(data)); err != nil {
127                                 TermMessage(err)
128                                 continue
129                         }
130
131                         loadedPlugins = append(loadedPlugins, pluginName)
132                 }
133         }
134 }