From 881f57b0473c71917535f9f9ea2736374e02596f Mon Sep 17 00:00:00 2001 From: boombuler Date: Fri, 2 Sep 2016 19:41:13 +0200 Subject: [PATCH 1/2] 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...))...) From c5ac5be76438392d6f96775776e1301afbf5d5e5 Mon Sep 17 00:00:00 2001 From: boombuler Date: Fri, 2 Sep 2016 19:50:19 +0200 Subject: [PATCH 2/2] updated plugin help --- runtime/help/plugins.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/runtime/help/plugins.md b/runtime/help/plugins.md index e142d020..68fed73a 100644 --- a/runtime/help/plugins.md +++ b/runtime/help/plugins.md @@ -66,6 +66,9 @@ as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...) creates a command with `name` which will call `function` when executed. Use 0 for completions to get NoCompletion. +* `MakeCompletion(function string)`: + creates a `Completion` to use with `MakeCommand`. + * `CurView()`: returns the current view * `HandleCommand(cmd string)`: runs the given command @@ -104,6 +107,36 @@ The possible methods which you can call using the `messenger` variable are: If you want a standard prompt, just use `messenger.Prompt(prompt, "", 0)` +# Autocomplete command arguments + +See this example to learn how to use `MakeCompletion` and `MakeCommand` + +```lua +local function StartsWith(String,Start) + String = String:upper() + Start = Start:upper() + return string.sub(String,1,string.len(Start))==Start +end + +function complete(input) + local allCompletions = {"Hello", "World", "Foo", "Bar"} + local result = {} + + for i,v in pairs(allCompletions) do + if StartsWith(v, input) then + table.insert(result, v) + end + end + return result +end + +function foo(arg) + messenger:Message(arg) +end + +MakeCommand("foo", "example.foo", MakeCompletion("example.complete")) +``` + # Default plugins For examples of plugins, see the default plugins `linter`, `go`, and `autoclose`.