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