10 "github.com/layeh/gopher-luar"
11 "github.com/yuin/gopher-lua"
14 var loadedPlugins []string
16 var preInstalledPlugins = []string{
22 // Call calls the lua function 'function'
23 // If it does not exist nothing happens, if there is an error,
24 // the error is returned
25 func Call(function string, args ...interface{}) (lua.LValue, error) {
26 var luaFunc lua.LValue
27 if strings.Contains(function, ".") {
28 plugin := L.GetGlobal(strings.Split(function, ".")[0])
29 if plugin.String() == "nil" {
30 return nil, errors.New("function does not exist: " + function)
32 luaFunc = L.GetField(plugin, strings.Split(function, ".")[1])
34 luaFunc = L.GetGlobal(function)
37 if luaFunc.String() == "nil" {
38 return nil, errors.New("function does not exist: " + function)
40 var luaArgs []lua.LValue
41 for _, v := range args {
42 luaArgs = append(luaArgs, luar.New(L, v))
44 err := L.CallByParam(lua.P{
49 ret := L.Get(-1) // returned value
50 if ret.String() != "nil" {
51 L.Pop(1) // remove received value
56 // LuaFunctionBinding is a function generator which takes the name of a lua function
57 // and creates a function that will call that lua function
58 // Specifically it creates a function that can be called as a binding because this is used
59 // to bind keys to lua functions
60 func LuaFunctionBinding(function string) func(*View, bool) bool {
61 return func(v *View, _ bool) bool {
62 _, err := Call(function, nil)
70 func unpack(old []string) []interface{} {
71 new := make([]interface{}, len(old))
72 for i, v := range old {
78 // LuaFunctionCommand is the same as LuaFunctionBinding except it returns a normal function
79 // so that a command can be bound to a lua function
80 func LuaFunctionCommand(function string) func([]string) {
81 return func(args []string) {
82 _, err := Call(function, unpack(args)...)
89 // LuaFunctionComplete returns a function which can be used for autocomplete in plugins
90 func LuaFunctionComplete(function string) func(string) []string {
91 return func(input string) (result []string) {
93 res, err := Call(function, input)
97 if tbl, ok := res.(*lua.LTable); !ok {
98 TermMessage(function, "should return a table of strings")
100 for i := 1; i <= tbl.Len(); i++ {
101 val := tbl.RawGetInt(i)
102 if v, ok := val.(lua.LString); !ok {
103 TermMessage(function, "should return a table of strings")
105 result = append(result, string(v))
113 func LuaFunctionJob(function string) func(string, ...string) {
114 return func(output string, args ...string) {
115 _, err := Call(function, unpack(append([]string{output}, args...))...)
122 // LoadPlugins loads the pre-installed plugins and the plugins located in ~/.config/micro/plugins
124 files, _ := ioutil.ReadDir(configDir + "/plugins")
125 for _, plugin := range files {
127 pluginName := plugin.Name()
128 files, _ := ioutil.ReadDir(configDir + "/plugins/" + pluginName)
129 for _, f := range files {
130 fullPath := filepath.Join(configDir, "plugins", pluginName, f.Name())
131 if f.Name() == pluginName+".lua" {
132 data, _ := ioutil.ReadFile(fullPath)
133 pluginDef := "\nlocal P = {}\n" + pluginName + " = P\nsetmetatable(" + pluginName + ", {__index = _G})\nsetfenv(1, P)\n"
135 if err := L.DoString(pluginDef + string(data)); err != nil {
139 loadedPlugins = append(loadedPlugins, pluginName)
140 } else if f.Name() == "help.md" {
141 AddRuntimeFile(FILE_Help, namedFile{realFile(fullPath), pluginName})
147 for _, pluginName := range preInstalledPlugins {
148 alreadyExists := false
149 for _, pl := range loadedPlugins {
150 if pl == pluginName {
156 plugin := "runtime/plugins/" + pluginName + "/" + pluginName + ".lua"
157 data, err := Asset(plugin)
159 TermMessage("Error loading pre-installed plugin: " + pluginName)
162 pluginDef := "\nlocal P = {}\n" + pluginName + " = P\nsetmetatable(" + pluginName + ", {__index = _G})\nsetfenv(1, P)\n"
163 if err := L.DoString(pluginDef + string(data)); err != nil {
168 loadedPlugins = append(loadedPlugins, pluginName)
172 if _, err := os.Stat(configDir + "/init.lua"); err == nil {
173 pluginDef := "\nlocal P = {}\n" + "init" + " = P\nsetmetatable(" + "init" + ", {__index = _G})\nsetfenv(1, P)\n"
174 data, _ := ioutil.ReadFile(configDir + "/init.lua")
175 if err := L.DoString(pluginDef + string(data)); err != nil {
178 loadedPlugins = append(loadedPlugins, "init")