]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/plugin.go
Code optimisation (#1117)
[micro.git] / cmd / micro / plugin.go
index 0c84ae62dce9ea4545b8a7e052a7d4d42a191e6b..b335078070ba02a4bb7471efe5b276c9d0061f16 100644 (file)
@@ -4,20 +4,14 @@ import (
        "errors"
        "io/ioutil"
        "os"
-       "path/filepath"
        "strings"
 
-       "github.com/layeh/gopher-luar"
        "github.com/yuin/gopher-lua"
+       "github.com/zyedidia/tcell"
+       "layeh.com/gopher-luar"
 )
 
-var loadedPlugins []string
-
-var preInstalledPlugins = []string{
-       "go",
-       "linter",
-       "autoclose",
-}
+var loadedPlugins map[string]string
 
 // Call calls the lua function 'function'
 // If it does not exist nothing happens, if there is an error,
@@ -67,6 +61,20 @@ func LuaFunctionBinding(function string) func(*View, bool) bool {
        }
 }
 
+// LuaFunctionMouseBinding 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 mouse binding because this is used
+// to bind mouse actions to lua functions
+func LuaFunctionMouseBinding(function string) func(*View, bool, *tcell.EventMouse) bool {
+       return func(v *View, _ bool, e *tcell.EventMouse) bool {
+               _, err := Call(function, e)
+               if err != nil {
+                       TermMessage(err)
+               }
+               return false
+       }
+}
+
 func unpack(old []string) []interface{} {
        new := make([]interface{}, len(old))
        for i, v := range old {
@@ -110,71 +118,67 @@ func LuaFunctionComplete(function string) func(string) []string {
        }
 }
 
+// LuaFunctionJob returns a function that will call the given lua function
+// structured as a job call i.e. the job output and arguments are provided
+// to the lua function
 func LuaFunctionJob(function string) func(string, ...string) {
        return func(output string, args ...string) {
                _, err := Call(function, unpack(append([]string{output}, args...))...)
-               if err != nil {
+               if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
                        TermMessage(err)
                }
        }
 }
 
+// luaPluginName convert a human-friendly plugin name into a valid lua variable name.
+func luaPluginName(name string) string {
+       return strings.Replace(name, "-", "_", -1)
+}
+
 // LoadPlugins loads the pre-installed plugins and the plugins located in ~/.config/micro/plugins
 func LoadPlugins() {
-       files, _ := ioutil.ReadDir(configDir + "/plugins")
-       for _, plugin := range files {
-               if plugin.IsDir() {
-                       pluginName := plugin.Name()
-                       files, _ := ioutil.ReadDir(configDir + "/plugins/" + pluginName)
-                       for _, f := range files {
-                               fullPath := filepath.Join(configDir, "plugins", pluginName, f.Name())
-                               if f.Name() == pluginName+".lua" {
-                                       data, _ := ioutil.ReadFile(fullPath)
-                                       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)
-                               } else if f.Name() == "help.md" {
-                                       AddPluginHelp(pluginName, fullPath)
-                               }
-                       }
+       loadedPlugins = make(map[string]string)
+
+       for _, plugin := range ListRuntimeFiles(RTPlugin) {
+               pluginName := plugin.Name()
+               if _, ok := loadedPlugins[pluginName]; ok {
+                       continue
                }
-       }
 
-       for _, pluginName := range preInstalledPlugins {
-               alreadyExists := false
-               for _, pl := range loadedPlugins {
-                       if pl == pluginName {
-                               alreadyExists = true
-                               break
-                       }
+               data, err := plugin.Data()
+               if err != nil {
+                       TermMessage("Error loading plugin: " + pluginName)
+                       continue
                }
-               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)
+               pluginLuaName := luaPluginName(pluginName)
+
+               if err := LoadFile(pluginLuaName, pluginLuaName, string(data)); err != nil {
+                       TermMessage(err)
+                       continue
                }
+
+               loadedPlugins[pluginName] = pluginLuaName
+
        }
 
        if _, err := os.Stat(configDir + "/init.lua"); err == nil {
-               pluginDef := "\nlocal P = {}\n" + "init" + " = P\nsetmetatable(" + "init" + ", {__index = _G})\nsetfenv(1, P)\n"
                data, _ := ioutil.ReadFile(configDir + "/init.lua")
-               if err := L.DoString(pluginDef + string(data)); err != nil {
+               if err := LoadFile("init", configDir+"init.lua", string(data)); err != nil {
+                       TermMessage(err)
+               }
+               loadedPlugins["init"] = "init"
+       }
+}
+
+// GlobalCall makes a call to a function in every plugin that is currently
+// loaded
+func GlobalPluginCall(function string, args ...interface{}) {
+       for pl := range loadedPlugins {
+               _, err := Call(pl+"."+function, args...)
+               if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
                        TermMessage(err)
+                       continue
                }
-               loadedPlugins = append(loadedPlugins, "init")
        }
 }