9 "layeh.com/gopher-luar"
10 "github.com/yuin/gopher-lua"
13 var loadedPlugins map[string]string
15 // Call calls the lua function 'function'
16 // If it does not exist nothing happens, if there is an error,
17 // the error is returned
18 func Call(function string, args ...interface{}) (lua.LValue, error) {
19 var luaFunc lua.LValue
20 if strings.Contains(function, ".") {
21 plugin := L.GetGlobal(strings.Split(function, ".")[0])
22 if plugin.String() == "nil" {
23 return nil, errors.New("function does not exist: " + function)
25 luaFunc = L.GetField(plugin, strings.Split(function, ".")[1])
27 luaFunc = L.GetGlobal(function)
30 if luaFunc.String() == "nil" {
31 return nil, errors.New("function does not exist: " + function)
33 var luaArgs []lua.LValue
34 for _, v := range args {
35 luaArgs = append(luaArgs, luar.New(L, v))
37 err := L.CallByParam(lua.P{
42 ret := L.Get(-1) // returned value
43 if ret.String() != "nil" {
44 L.Pop(1) // remove received value
49 // LuaFunctionBinding is a function generator which takes the name of a lua function
50 // and creates a function that will call that lua function
51 // Specifically it creates a function that can be called as a binding because this is used
52 // to bind keys to lua functions
53 func LuaFunctionBinding(function string) func(*View, bool) bool {
54 return func(v *View, _ bool) bool {
55 _, err := Call(function, nil)
63 func unpack(old []string) []interface{} {
64 new := make([]interface{}, len(old))
65 for i, v := range old {
71 // LuaFunctionCommand is the same as LuaFunctionBinding except it returns a normal function
72 // so that a command can be bound to a lua function
73 func LuaFunctionCommand(function string) func([]string) {
74 return func(args []string) {
75 _, err := Call(function, unpack(args)...)
82 // LuaFunctionComplete returns a function which can be used for autocomplete in plugins
83 func LuaFunctionComplete(function string) func(string) []string {
84 return func(input string) (result []string) {
86 res, err := Call(function, input)
90 if tbl, ok := res.(*lua.LTable); !ok {
91 TermMessage(function, "should return a table of strings")
93 for i := 1; i <= tbl.Len(); i++ {
94 val := tbl.RawGetInt(i)
95 if v, ok := val.(lua.LString); !ok {
96 TermMessage(function, "should return a table of strings")
98 result = append(result, string(v))
106 func LuaFunctionJob(function string) func(string, ...string) {
107 return func(output string, args ...string) {
108 _, err := Call(function, unpack(append([]string{output}, args...))...)
115 // luaPluginName convert a human-friendly plugin name into a valid lua variable name.
116 func luaPluginName(name string) string {
117 return strings.Replace(name, "-", "_", -1)
120 // LoadPlugins loads the pre-installed plugins and the plugins located in ~/.config/micro/plugins
123 loadedPlugins = make(map[string]string)
125 for _, plugin := range ListRuntimeFiles(RTPlugin) {
127 pluginName := plugin.Name()
128 if _, ok := loadedPlugins[pluginName]; ok {
132 data, err := plugin.Data()
134 TermMessage("Error loading plugin: " + pluginName)
138 pluginLuaName := luaPluginName(pluginName)
139 pluginDef := "\nlocal P = {}\n" + pluginLuaName + " = P\nsetmetatable(" + pluginLuaName + ", {__index = _G})\nsetfenv(1, P)\n"
141 if err := L.DoString(pluginDef + string(data)); err != nil {
146 loadedPlugins[pluginName] = pluginLuaName
150 if _, err := os.Stat(configDir + "/init.lua"); err == nil {
151 pluginDef := "\nlocal P = {}\n" + "init" + " = P\nsetmetatable(" + "init" + ", {__index = _G})\nsetfenv(1, P)\n"
152 data, _ := ioutil.ReadFile(configDir + "/init.lua")
153 if err := L.DoString(pluginDef + string(data)); err != nil {
156 loadedPlugins["init"] = "init"