From 881f57b0473c71917535f9f9ea2736374e02596f Mon Sep 17 00:00:00 2001 From: boombuler Date: Fri, 2 Sep 2016 19:41:13 +0200 Subject: [PATCH] allow plugins to register autocomplete functions --- cmd/micro/autocomplete.go | 23 +++++++++++++++++++++++ cmd/micro/messenger.go | 2 ++ cmd/micro/micro.go | 1 + cmd/micro/plugin.go | 24 ++++++++++++++++++++++++ 4 files changed, 50 insertions(+) diff --git a/cmd/micro/autocomplete.go b/cmd/micro/autocomplete.go index 26c32d0f..3c74501e 100644 --- a/cmd/micro/autocomplete.go +++ b/cmd/micro/autocomplete.go @@ -8,6 +8,8 @@ import ( "github.com/mitchellh/go-homedir" ) +var pluginCompletions []func(string) []string + // This file is meant (for now) for autocompletion in command mode, not // while coding. This helps micro autocomplete commands and then filenames // for example with `vsplit filename`. @@ -122,3 +124,24 @@ func OptionComplete(input string) (string, []string) { } return chosen, suggestions } + +// MakeCompletion registeres a function from a plugin for autocomplete commands +func MakeCompletion(function string) Completion { + pluginCompletions = append(pluginCompletions, LuaFunctionComplete(function)) + return Completion(-len(pluginCompletions)) +} + +// PluginComplete autocompletes from plugin function +func PluginComplete(complete Completion, input string) (chosen string, suggestions []string) { + idx := int(-complete) - 1 + + if len(pluginCompletions) <= idx { + return "", nil + } + suggestions = pluginCompletions[idx](input) + + if len(suggestions) == 1 { + chosen = suggestions[0] + } + return +} diff --git a/cmd/micro/messenger.go b/cmd/micro/messenger.go index b57d7ff1..c7008063 100644 --- a/cmd/micro/messenger.go +++ b/cmd/micro/messenger.go @@ -222,6 +222,8 @@ func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Comple chosen, suggestions = HelpComplete(currentArg) } else if completionType == OptionCompletion { chosen, suggestions = OptionComplete(currentArg) + } else if completionType < NoCompletion { + chosen, suggestions = PluginComplete(completionType, currentArg) } if len(suggestions) > 1 { diff --git a/cmd/micro/micro.go b/cmd/micro/micro.go index 8ee384b9..146336cb 100644 --- a/cmd/micro/micro.go +++ b/cmd/micro/micro.go @@ -294,6 +294,7 @@ func main() { L.SetGlobal("HandleCommand", luar.New(L, HandleCommand)) L.SetGlobal("HandleShellCommand", luar.New(L, HandleShellCommand)) L.SetGlobal("GetLeadingWhitespace", luar.New(L, GetLeadingWhitespace)) + L.SetGlobal("MakeCompletion", luar.New(L, MakeCompletion)) // Used for asynchronous jobs L.SetGlobal("JobStart", luar.New(L, JobStart)) diff --git a/cmd/micro/plugin.go b/cmd/micro/plugin.go index f02f75df..607eb2b6 100644 --- a/cmd/micro/plugin.go +++ b/cmd/micro/plugin.go @@ -85,6 +85,30 @@ func LuaFunctionCommand(function string) func([]string) { } } +// LuaFunctionComplete returns a function which can be used for autocomplete in plugins +func LuaFunctionComplete(function string) func(string) []string { + return func(input string) (result []string) { + + res, err := Call(function, input) + if err != nil { + TermMessage(err) + } + if tbl, ok := res.(*lua.LTable); !ok { + TermMessage(function, "should return a table of strings") + } else { + for i := 1; i <= tbl.Len(); i++ { + val := tbl.RawGetInt(i) + if v, ok := val.(lua.LString); !ok { + TermMessage(function, "should return a table of strings") + } else { + result = append(result, string(v)) + } + } + } + return result + } +} + func LuaFunctionJob(function string) func(string, ...string) { return func(output string, args ...string) { _, err := Call(function, unpack(append([]string{output}, args...))...)