]> git.lizzy.rs Git - micro.git/blob - cmd/micro/autocomplete.go
3ecc3f16569bf300612b95561e0cf6f3dffd7552
[micro.git] / cmd / micro / autocomplete.go
1 package main
2
3 import (
4         "io/ioutil"
5         "os"
6         "strings"
7 )
8
9 var pluginCompletions []func(string) []string
10
11 // This file is meant (for now) for autocompletion in command mode, not
12 // while coding. This helps micro autocomplete commands and then filenames
13 // for example with `vsplit filename`.
14
15 // FileComplete autocompletes filenames
16 func FileComplete(input string) (string, []string) {
17         var sep string = string(os.PathSeparator)
18         dirs := strings.Split(input, sep)
19
20         var files []os.FileInfo
21         var err error
22         if len(dirs) > 1 {
23                 directories := strings.Join(dirs[:len(dirs)-1], sep) + sep
24
25                 directories = ReplaceHome(directories)
26                 files, err = ioutil.ReadDir(directories)
27         } else {
28                 files, err = ioutil.ReadDir(".")
29         }
30
31         var suggestions []string
32         if err != nil {
33                 return "", suggestions
34         }
35         for _, f := range files {
36                 name := f.Name()
37                 if f.IsDir() {
38                         name += sep
39                 }
40                 if strings.HasPrefix(name, dirs[len(dirs)-1]) {
41                         suggestions = append(suggestions, name)
42                 }
43         }
44
45         var chosen string
46         if len(suggestions) == 1 {
47                 if len(dirs) > 1 {
48                         chosen = strings.Join(dirs[:len(dirs)-1], sep) + sep + suggestions[0]
49                 } else {
50                         chosen = suggestions[0]
51                 }
52         } else {
53                 if len(dirs) > 1 {
54                         chosen = strings.Join(dirs[:len(dirs)-1], sep) + sep
55                 }
56         }
57
58         return chosen, suggestions
59 }
60
61 // CommandComplete autocompletes commands
62 func CommandComplete(input string) (string, []string) {
63         var suggestions []string
64         for cmd := range commands {
65                 if strings.HasPrefix(cmd, input) {
66                         suggestions = append(suggestions, cmd)
67                 }
68         }
69
70         var chosen string
71         if len(suggestions) == 1 {
72                 chosen = suggestions[0]
73         }
74         return chosen, suggestions
75 }
76
77 // HelpComplete autocompletes help topics
78 func HelpComplete(input string) (string, []string) {
79         var suggestions []string
80
81         for _, file := range ListRuntimeFiles(RTHelp) {
82                 topic := file.Name()
83                 if strings.HasPrefix(topic, input) {
84                         suggestions = append(suggestions, topic)
85                 }
86         }
87
88         var chosen string
89         if len(suggestions) == 1 {
90                 chosen = suggestions[0]
91         }
92         return chosen, suggestions
93 }
94
95 // ColorschemeComplete tab-completes names of colorschemes.
96 func ColorschemeComplete(input string) (string, []string) {
97         var suggestions []string
98         files := ListRuntimeFiles(RTColorscheme)
99
100         for _, f := range files {
101                 if strings.HasPrefix(f.Name(), input) {
102                         suggestions = append(suggestions, f.Name())
103                 }
104         }
105
106         var chosen string
107         if len(suggestions) == 1 {
108                 chosen = suggestions[0]
109         }
110
111         return chosen, suggestions
112 }
113
114 func contains(s []string, e string) bool {
115         for _, a := range s {
116                 if a == e {
117                         return true
118                 }
119         }
120         return false
121 }
122
123 // OptionComplete autocompletes options
124 func OptionComplete(input string) (string, []string) {
125         var suggestions []string
126         localSettings := DefaultLocalSettings()
127         for option := range globalSettings {
128                 if strings.HasPrefix(option, input) {
129                         suggestions = append(suggestions, option)
130                 }
131         }
132         for option := range localSettings {
133                 if strings.HasPrefix(option, input) && !contains(suggestions, option) {
134                         suggestions = append(suggestions, option)
135                 }
136         }
137
138         var chosen string
139         if len(suggestions) == 1 {
140                 chosen = suggestions[0]
141         }
142         return chosen, suggestions
143 }
144
145 // OptionValueComplete completes values for various options
146 func OptionValueComplete(inputOpt, input string) (string, []string) {
147         inputOpt = strings.TrimSpace(inputOpt)
148         var suggestions []string
149         localSettings := DefaultLocalSettings()
150         var optionVal interface{}
151         for k, option := range globalSettings {
152                 if k == inputOpt {
153                         optionVal = option
154                 }
155         }
156         for k, option := range localSettings {
157                 if k == inputOpt {
158                         optionVal = option
159                 }
160         }
161
162         switch optionVal.(type) {
163         case bool:
164                 if strings.HasPrefix("on", input) {
165                         suggestions = append(suggestions, "on")
166                 } else if strings.HasPrefix("true", input) {
167                         suggestions = append(suggestions, "true")
168                 }
169                 if strings.HasPrefix("off", input) {
170                         suggestions = append(suggestions, "off")
171                 } else if strings.HasPrefix("false", input) {
172                         suggestions = append(suggestions, "false")
173                 }
174         case string:
175                 switch inputOpt {
176                 case "colorscheme":
177                         _, suggestions = ColorschemeComplete(input)
178                 case "fileformat":
179                         if strings.HasPrefix("unix", input) {
180                                 suggestions = append(suggestions, "unix")
181                         }
182                         if strings.HasPrefix("dos", input) {
183                                 suggestions = append(suggestions, "dos")
184                         }
185                 case "sucmd":
186                         if strings.HasPrefix("sudo", input) {
187                                 suggestions = append(suggestions, "sudo")
188                         }
189                         if strings.HasPrefix("doas", input) {
190                                 suggestions = append(suggestions, "doas")
191                         }
192                 }
193         }
194
195         var chosen string
196         if len(suggestions) == 1 {
197                 chosen = suggestions[0]
198         }
199         return chosen, suggestions
200 }
201
202 // MakeCompletion registers a function from a plugin for autocomplete commands
203 func MakeCompletion(function string) Completion {
204         pluginCompletions = append(pluginCompletions, LuaFunctionComplete(function))
205         return Completion(-len(pluginCompletions))
206 }
207
208 // PluginComplete autocompletes from plugin function
209 func PluginComplete(complete Completion, input string) (chosen string, suggestions []string) {
210         idx := int(-complete) - 1
211
212         if len(pluginCompletions) <= idx {
213                 return "", nil
214         }
215         suggestions = pluginCompletions[idx](input)
216
217         if len(suggestions) == 1 {
218                 chosen = suggestions[0]
219         }
220         return
221 }
222
223 // PluginCmdComplete completes with possible choices for the `> plugin` command
224 func PluginCmdComplete(input string) (chosen string, suggestions []string) {
225         for _, cmd := range []string{"install", "remove", "search", "update", "list"} {
226                 if strings.HasPrefix(cmd, input) {
227                         suggestions = append(suggestions, cmd)
228                 }
229         }
230
231         if len(suggestions) == 1 {
232                 chosen = suggestions[0]
233         }
234         return chosen, suggestions
235 }
236
237 // PluginnameComplete completes with the names of loaded plugins
238 func PluginNameComplete(input string) (chosen string, suggestions []string) {
239         for _, pp := range GetAllPluginPackages() {
240                 if strings.HasPrefix(pp.Name, input) {
241                         suggestions = append(suggestions, pp.Name)
242                 }
243         }
244
245         if len(suggestions) == 1 {
246                 chosen = suggestions[0]
247         }
248         return chosen, suggestions
249 }