]> git.lizzy.rs Git - micro.git/blob - cmd/micro/autocomplete.go
Only replace '~' with home if at start of path
[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 func OptionValueComplete(inputOpt, input string) (string, []string) {
146         inputOpt = strings.TrimSpace(inputOpt)
147         var suggestions []string
148         localSettings := DefaultLocalSettings()
149         var optionVal interface{}
150         for k, option := range globalSettings {
151                 if k == inputOpt {
152                         optionVal = option
153                 }
154         }
155         for k, option := range localSettings {
156                 if k == inputOpt {
157                         optionVal = option
158                 }
159         }
160
161         switch optionVal.(type) {
162         case bool:
163                 if strings.HasPrefix("on", input) {
164                         suggestions = append(suggestions, "on")
165                 } else if strings.HasPrefix("true", input) {
166                         suggestions = append(suggestions, "true")
167                 }
168                 if strings.HasPrefix("off", input) {
169                         suggestions = append(suggestions, "off")
170                 } else if strings.HasPrefix("false", input) {
171                         suggestions = append(suggestions, "false")
172                 }
173         case string:
174                 switch inputOpt {
175                 case "colorscheme":
176                         _, suggestions = ColorschemeComplete(input)
177                 case "fileformat":
178                         if strings.HasPrefix("unix", input) {
179                                 suggestions = append(suggestions, "unix")
180                         }
181                         if strings.HasPrefix("dos", input) {
182                                 suggestions = append(suggestions, "dos")
183                         }
184                 }
185         }
186
187         var chosen string
188         if len(suggestions) == 1 {
189                 chosen = suggestions[0]
190         }
191         return chosen, suggestions
192 }
193
194 // MakeCompletion registers a function from a plugin for autocomplete commands
195 func MakeCompletion(function string) Completion {
196         pluginCompletions = append(pluginCompletions, LuaFunctionComplete(function))
197         return Completion(-len(pluginCompletions))
198 }
199
200 // PluginComplete autocompletes from plugin function
201 func PluginComplete(complete Completion, input string) (chosen string, suggestions []string) {
202         idx := int(-complete) - 1
203
204         if len(pluginCompletions) <= idx {
205                 return "", nil
206         }
207         suggestions = pluginCompletions[idx](input)
208
209         if len(suggestions) == 1 {
210                 chosen = suggestions[0]
211         }
212         return
213 }
214
215 func PluginCmdComplete(input string) (chosen string, suggestions []string) {
216         for _, cmd := range []string{"install", "remove", "search", "update", "list"} {
217                 if strings.HasPrefix(cmd, input) {
218                         suggestions = append(suggestions, cmd)
219                 }
220         }
221
222         if len(suggestions) == 1 {
223                 chosen = suggestions[0]
224         }
225         return chosen, suggestions
226 }
227
228 func PluginNameComplete(input string) (chosen string, suggestions []string) {
229         for _, pp := range GetAllPluginPackages() {
230                 if strings.HasPrefix(pp.Name, input) {
231                         suggestions = append(suggestions, pp.Name)
232                 }
233         }
234
235         if len(suggestions) == 1 {
236                 chosen = suggestions[0]
237         }
238         return chosen, suggestions
239 }