]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/plugin.go
Small fix to redraw location
[micro.git] / cmd / micro / plugin.go
index 4138e3a0c579a9fc07758ce8746186ac01a28665..f2091bfcf58266eefdf58ff1b9daba4fcee9e052 100644 (file)
@@ -1,8 +1,13 @@
 package main
 
 import (
-       "github.com/yuin/gopher-lua"
+       "errors"
        "io/ioutil"
+       "os"
+       "strings"
+
+       "github.com/layeh/gopher-luar"
+       "github.com/yuin/gopher-lua"
 )
 
 var loadedPlugins []string
@@ -10,22 +15,75 @@ var loadedPlugins []string
 var preInstalledPlugins = []string{
        "go",
        "linter",
+       "autoclose",
 }
 
 // Call calls the lua function 'function'
 // If it does not exist nothing happens, if there is an error,
 // the error is returned
-func Call(function string) error {
-       luaFunc := L.GetGlobal(function)
+func Call(function string, args []string) (lua.LValue, error) {
+       var luaFunc lua.LValue
+       if strings.Contains(function, ".") {
+               plugin := L.GetGlobal(strings.Split(function, ".")[0])
+               if plugin.String() == "nil" {
+                       return nil, errors.New("function does not exist: " + function)
+               }
+               luaFunc = L.GetField(plugin, strings.Split(function, ".")[1])
+       } else {
+               luaFunc = L.GetGlobal(function)
+       }
+
        if luaFunc.String() == "nil" {
-               return nil
+               return nil, errors.New("function does not exist: " + function)
+       }
+       var luaArgs []lua.LValue
+       for _, v := range args {
+               luaArgs = append(luaArgs, luar.New(L, v))
        }
        err := L.CallByParam(lua.P{
                Fn:      luaFunc,
-               NRet:    0,
+               NRet:    1,
                Protect: true,
-       })
-       return err
+       }, luaArgs...)
+       ret := L.Get(-1) // returned value
+       if ret.String() != "nil" {
+               L.Pop(1) // remove received value
+       }
+       return ret, err
+}
+
+// LuaFunctionBinding is a function generator which takes the name of a lua function
+// and creates a function that will call that lua function
+// Specifically it creates a function that can be called as a binding because this is used
+// to bind keys to lua functions
+func LuaFunctionBinding(function string) func(*View, bool) bool {
+       return func(v *View, _ bool) bool {
+               _, err := Call(function, nil)
+               if err != nil {
+                       TermMessage(err)
+               }
+               return false
+       }
+}
+
+// LuaFunctionCommand is the same as LuaFunctionBinding except it returns a normal function
+// so that a command can be bound to a lua function
+func LuaFunctionCommand(function string) func([]string) {
+       return func(args []string) {
+               _, err := Call(function, args)
+               if err != nil {
+                       TermMessage(err)
+               }
+       }
+}
+
+func LuaFunctionJob(function string) func(string, ...string) {
+       return func(output string, args ...string) {
+               _, err := Call(function, append([]string{output}, args...))
+               if err != nil {
+                       TermMessage(err)
+               }
+       }
 }
 
 // LoadPlugins loads the pre-installed plugins and the plugins located in ~/.config/micro/plugins
@@ -37,7 +95,10 @@ func LoadPlugins() {
                        files, _ := ioutil.ReadDir(configDir + "/plugins/" + pluginName)
                        for _, f := range files {
                                if f.Name() == pluginName+".lua" {
-                                       if err := L.DoFile(configDir + "/plugins/" + pluginName + "/" + f.Name()); err != nil {
+                                       data, _ := ioutil.ReadFile(configDir + "/plugins/" + pluginName + "/" + f.Name())
+                                       pluginDef := "\nlocal P = {}\n" + pluginName + " = P\nsetmetatable(" + pluginName + ", {__index = _G})\nsetfenv(1, P)\n"
+
+                                       if err := L.DoString(pluginDef + string(data)); err != nil {
                                                TermMessage(err)
                                                continue
                                        }
@@ -48,16 +109,33 @@ func LoadPlugins() {
        }
 
        for _, pluginName := range preInstalledPlugins {
-               plugin := "runtime/plugins/" + pluginName + "/" + pluginName + ".lua"
-               data, err := Asset(plugin)
-               if err != nil {
-                       TermMessage("Error loading pre-installed plugin: " + pluginName)
-                       continue
+               alreadyExists := false
+               for _, pl := range loadedPlugins {
+                       if pl == pluginName {
+                               alreadyExists = true
+                               break
+                       }
+               }
+               if !alreadyExists {
+                       plugin := "runtime/plugins/" + pluginName + "/" + pluginName + ".lua"
+                       data, err := Asset(plugin)
+                       if err != nil {
+                               TermMessage("Error loading pre-installed plugin: " + pluginName)
+                               continue
+                       }
+                       pluginDef := "\nlocal P = {}\n" + pluginName + " = P\nsetmetatable(" + pluginName + ", {__index = _G})\nsetfenv(1, P)\n"
+                       if err := L.DoString(pluginDef + string(data)); err != nil {
+                               TermMessage(err)
+                               continue
+                       }
+
+                       loadedPlugins = append(loadedPlugins, pluginName)
                }
-               if err := L.DoString(string(data)); err != nil {
+       }
+
+       if _, err := os.Stat(configDir + "/init.lua"); err == nil {
+               if err := L.DoFile(configDir + "/init.lua"); err != nil {
                        TermMessage(err)
-                       continue
                }
-               loadedPlugins = append(loadedPlugins, pluginName)
        }
 }