From 68189fd4066ea7b41455535c2b0810b09bc3b479 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Mon, 30 May 2016 09:12:04 -0400 Subject: [PATCH] Add ability to bind lua functions defined in plugins --- cmd/micro/bindings.go | 36 ++++++++++++++++-------------------- cmd/micro/plugin.go | 31 +++++++++++++++++++++++++++++-- cmd/micro/runtime.go | 2 +- cmd/micro/view.go | 2 +- 4 files changed, 47 insertions(+), 24 deletions(-) diff --git a/cmd/micro/bindings.go b/cmd/micro/bindings.go index 4d7a1b32..cfb8390f 100644 --- a/cmd/micro/bindings.go +++ b/cmd/micro/bindings.go @@ -247,36 +247,32 @@ func InitBindings() { } } - for k, v := range defaults { + parse(defaults, actions, keys) + parse(parsed, actions, keys) +} + +func parse(userBindings map[string]string, actions map[string]func(*View) bool, keys map[string]Key) { + for k, v := range userBindings { + var key Key if strings.Contains(k, "Alt-") { split := strings.Split(k, "-") - var key Key if len(split[1]) > 1 { key = Key{keys[split[1]].keyCode, keys[k].modifiers | tcell.ModAlt, 0} } else { key = Key{tcell.KeyRune, tcell.ModAlt, rune(k[len(k)-1])} } - bindings[key] = actions[v] } else { - bindings[keys[k]] = actions[v] + key = keys[k] } - if v == "ToggleHelp" { - helpBinding = k - } - } - for k, v := range parsed { - if strings.Contains(k, "Alt-") { - split := strings.Split(k, "-") - var key Key - if len(split[1]) > 1 { - key = Key{keys[split[1]].keyCode, keys[k].modifiers | tcell.ModAlt, 0} - } else { - key = Key{tcell.KeyRune, tcell.ModAlt, rune(k[len(k)-1])} - } - bindings[key] = actions[v] - } else { - bindings[keys[k]] = actions[v] + + action := actions[v] + if _, ok := actions[v]; !ok { + // If the user seems to be binding a function that doesn't exist + // We hope that it's a lua function that exists and bind it to that + action = LuaFunctionBinding(v) } + + bindings[key] = action if v == "ToggleHelp" { helpBinding = k } diff --git a/cmd/micro/plugin.go b/cmd/micro/plugin.go index 4138e3a0..6401970b 100644 --- a/cmd/micro/plugin.go +++ b/cmd/micro/plugin.go @@ -1,8 +1,10 @@ package main import ( - "github.com/yuin/gopher-lua" + "errors" "io/ioutil" + + "github.com/yuin/gopher-lua" ) var loadedPlugins []string @@ -18,7 +20,7 @@ var preInstalledPlugins = []string{ func Call(function string) error { luaFunc := L.GetGlobal(function) if luaFunc.String() == "nil" { - return nil + return errors.New("function does not exist: " + function) } err := L.CallByParam(lua.P{ Fn: luaFunc, @@ -28,6 +30,31 @@ func Call(function string) error { return 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 { + return func(v *View) bool { + err := Call(function) + 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() { + return func() { + err := Call(function) + if err != nil { + TermMessage(err) + } + } +} + // LoadPlugins loads the pre-installed plugins and the plugins located in ~/.config/micro/plugins func LoadPlugins() { files, _ := ioutil.ReadDir(configDir + "/plugins") diff --git a/cmd/micro/runtime.go b/cmd/micro/runtime.go index 36178329..3e1a494a 100644 --- a/cmd/micro/runtime.go +++ b/cmd/micro/runtime.go @@ -275,7 +275,7 @@ func runtimePluginsGoGoLua() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "runtime/plugins/go/go.lua", size: 927, mode: os.FileMode(420), modTime: time.Unix(1464457319, 0)} + info := bindataFileInfo{name: "runtime/plugins/go/go.lua", size: 927, mode: os.FileMode(420), modTime: time.Unix(1464613212, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/cmd/micro/view.go b/cmd/micro/view.go index c576cca8..eb9ea807 100644 --- a/cmd/micro/view.go +++ b/cmd/micro/view.go @@ -302,7 +302,7 @@ func (v *View) HandleEvent(event tcell.Event) { for _, pl := range loadedPlugins { funcName := strings.Split(runtime.FuncForPC(reflect.ValueOf(action).Pointer()).Name(), ".") err := Call(pl + "_on" + funcName[len(funcName)-1]) - if err != nil { + if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") { TermMessage(err) } }