]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/autocomplete.go
Merge pull request #1125 from nabeelomer/master
[micro.git] / cmd / micro / autocomplete.go
index 61f00f11919cded6c2f298d06d321d2d0e069a2a..3ecc3f16569bf300612b95561e0cf6f3dffd7552 100644 (file)
@@ -6,15 +6,28 @@ import (
        "strings"
 )
 
+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`.
+
+// FileComplete autocompletes filenames
 func FileComplete(input string) (string, []string) {
-       dirs := strings.Split(input, "/")
+       var sep string = string(os.PathSeparator)
+       dirs := strings.Split(input, sep)
+
        var files []os.FileInfo
        var err error
        if len(dirs) > 1 {
-               files, err = ioutil.ReadDir(strings.Join(dirs[:len(dirs)-1], "/"))
+               directories := strings.Join(dirs[:len(dirs)-1], sep) + sep
+
+               directories = ReplaceHome(directories)
+               files, err = ioutil.ReadDir(directories)
        } else {
                files, err = ioutil.ReadDir(".")
        }
+
        var suggestions []string
        if err != nil {
                return "", suggestions
@@ -22,7 +35,7 @@ func FileComplete(input string) (string, []string) {
        for _, f := range files {
                name := f.Name()
                if f.IsDir() {
-                       name += "/"
+                       name += sep
                }
                if strings.HasPrefix(name, dirs[len(dirs)-1]) {
                        suggestions = append(suggestions, name)
@@ -32,15 +45,20 @@ func FileComplete(input string) (string, []string) {
        var chosen string
        if len(suggestions) == 1 {
                if len(dirs) > 1 {
-                       chosen = strings.Join(dirs[:len(dirs)-1], "/") + "/" + suggestions[0]
+                       chosen = strings.Join(dirs[:len(dirs)-1], sep) + sep + suggestions[0]
                } else {
                        chosen = suggestions[0]
                }
+       } else {
+               if len(dirs) > 1 {
+                       chosen = strings.Join(dirs[:len(dirs)-1], sep) + sep
+               }
        }
 
        return chosen, suggestions
 }
 
+// CommandComplete autocompletes commands
 func CommandComplete(input string) (string, []string) {
        var suggestions []string
        for cmd := range commands {
@@ -56,12 +74,13 @@ func CommandComplete(input string) (string, []string) {
        return chosen, suggestions
 }
 
+// HelpComplete autocompletes help topics
 func HelpComplete(input string) (string, []string) {
        var suggestions []string
 
-       for _, topic := range helpFiles {
+       for _, file := range ListRuntimeFiles(RTHelp) {
+               topic := file.Name()
                if strings.HasPrefix(topic, input) {
-
                        suggestions = append(suggestions, topic)
                }
        }
@@ -73,13 +92,105 @@ func HelpComplete(input string) (string, []string) {
        return chosen, suggestions
 }
 
+// ColorschemeComplete tab-completes names of colorschemes.
+func ColorschemeComplete(input string) (string, []string) {
+       var suggestions []string
+       files := ListRuntimeFiles(RTColorscheme)
+
+       for _, f := range files {
+               if strings.HasPrefix(f.Name(), input) {
+                       suggestions = append(suggestions, f.Name())
+               }
+       }
+
+       var chosen string
+       if len(suggestions) == 1 {
+               chosen = suggestions[0]
+       }
+
+       return chosen, suggestions
+}
+
+func contains(s []string, e string) bool {
+       for _, a := range s {
+               if a == e {
+                       return true
+               }
+       }
+       return false
+}
+
+// OptionComplete autocompletes options
 func OptionComplete(input string) (string, []string) {
        var suggestions []string
-       for option := range settings {
+       localSettings := DefaultLocalSettings()
+       for option := range globalSettings {
                if strings.HasPrefix(option, input) {
                        suggestions = append(suggestions, option)
                }
        }
+       for option := range localSettings {
+               if strings.HasPrefix(option, input) && !contains(suggestions, option) {
+                       suggestions = append(suggestions, option)
+               }
+       }
+
+       var chosen string
+       if len(suggestions) == 1 {
+               chosen = suggestions[0]
+       }
+       return chosen, suggestions
+}
+
+// OptionValueComplete completes values for various options
+func OptionValueComplete(inputOpt, input string) (string, []string) {
+       inputOpt = strings.TrimSpace(inputOpt)
+       var suggestions []string
+       localSettings := DefaultLocalSettings()
+       var optionVal interface{}
+       for k, option := range globalSettings {
+               if k == inputOpt {
+                       optionVal = option
+               }
+       }
+       for k, option := range localSettings {
+               if k == inputOpt {
+                       optionVal = option
+               }
+       }
+
+       switch optionVal.(type) {
+       case bool:
+               if strings.HasPrefix("on", input) {
+                       suggestions = append(suggestions, "on")
+               } else if strings.HasPrefix("true", input) {
+                       suggestions = append(suggestions, "true")
+               }
+               if strings.HasPrefix("off", input) {
+                       suggestions = append(suggestions, "off")
+               } else if strings.HasPrefix("false", input) {
+                       suggestions = append(suggestions, "false")
+               }
+       case string:
+               switch inputOpt {
+               case "colorscheme":
+                       _, suggestions = ColorschemeComplete(input)
+               case "fileformat":
+                       if strings.HasPrefix("unix", input) {
+                               suggestions = append(suggestions, "unix")
+                       }
+                       if strings.HasPrefix("dos", input) {
+                               suggestions = append(suggestions, "dos")
+                       }
+               case "sucmd":
+                       if strings.HasPrefix("sudo", input) {
+                               suggestions = append(suggestions, "sudo")
+                       }
+                       if strings.HasPrefix("doas", input) {
+                               suggestions = append(suggestions, "doas")
+                       }
+               }
+       }
 
        var chosen string
        if len(suggestions) == 1 {
@@ -87,3 +198,52 @@ func OptionComplete(input string) (string, []string) {
        }
        return chosen, suggestions
 }
+
+// MakeCompletion registers 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
+}
+
+// PluginCmdComplete completes with possible choices for the `> plugin` command
+func PluginCmdComplete(input string) (chosen string, suggestions []string) {
+       for _, cmd := range []string{"install", "remove", "search", "update", "list"} {
+               if strings.HasPrefix(cmd, input) {
+                       suggestions = append(suggestions, cmd)
+               }
+       }
+
+       if len(suggestions) == 1 {
+               chosen = suggestions[0]
+       }
+       return chosen, suggestions
+}
+
+// PluginnameComplete completes with the names of loaded plugins
+func PluginNameComplete(input string) (chosen string, suggestions []string) {
+       for _, pp := range GetAllPluginPackages() {
+               if strings.HasPrefix(pp.Name, input) {
+                       suggestions = append(suggestions, pp.Name)
+               }
+       }
+
+       if len(suggestions) == 1 {
+               chosen = suggestions[0]
+       }
+       return chosen, suggestions
+}