]> git.lizzy.rs Git - micro.git/blob - cmd/micro/action/command.go
27b16729aed09ff6ffedf0dec36da27ac43103f1
[micro.git] / cmd / micro / action / command.go
1 package action
2
3 import (
4         "os"
5
6         "github.com/zyedidia/micro/cmd/micro/buffer"
7         "github.com/zyedidia/micro/cmd/micro/screen"
8         "github.com/zyedidia/micro/cmd/micro/shell"
9         "github.com/zyedidia/micro/cmd/micro/shellwords"
10         "github.com/zyedidia/micro/cmd/micro/util"
11 )
12
13 // A Command contains an action (a function to call) as well as information about how to autocomplete the command
14 type Command struct {
15         action      func([]string)
16         completions []Completion
17 }
18
19 // A StrCommand is similar to a command but keeps the name of the action
20 type StrCommand struct {
21         action      string
22         completions []Completion
23 }
24
25 var commands map[string]Command
26
27 var commandActions map[string]func([]string)
28
29 func init() {
30         commandActions = map[string]func([]string){
31                 "Set":        Set,
32                 "SetLocal":   SetLocal,
33                 "Show":       Show,
34                 "ShowKey":    ShowKey,
35                 "Run":        Run,
36                 "Bind":       Bind,
37                 "Quit":       Quit,
38                 "Save":       Save,
39                 "Replace":    Replace,
40                 "ReplaceAll": ReplaceAll,
41                 "VSplit":     VSplit,
42                 "HSplit":     HSplit,
43                 "Tab":        NewTab,
44                 "Help":       Help,
45                 "Eval":       Eval,
46                 "ToggleLog":  ToggleLog,
47                 "Plugin":     PluginCmd,
48                 "Reload":     Reload,
49                 "Cd":         Cd,
50                 "Pwd":        Pwd,
51                 "Open":       Open,
52                 "TabSwitch":  TabSwitch,
53                 "Term":       Term,
54                 "MemUsage":   MemUsage,
55                 "Retab":      Retab,
56                 "Raw":        Raw,
57         }
58 }
59
60 // InitCommands initializes the default commands
61 func InitCommands() {
62         commands = make(map[string]Command)
63
64         defaults := DefaultCommands()
65         parseCommands(defaults)
66 }
67
68 func parseCommands(userCommands map[string]StrCommand) {
69         for k, v := range userCommands {
70                 MakeCommand(k, v.action, v.completions...)
71         }
72 }
73
74 // MakeCommand is a function to easily create new commands
75 // This can be called by plugins in Lua so that plugins can define their own commands
76 func MakeCommand(name, function string, completions ...Completion) {
77         action := commandActions[function]
78         // if _, ok := commandActions[function]; !ok {
79         // If the user seems to be binding a function that doesn't exist
80         // We hope that it's a lua function that exists and bind it to that
81         // action = LuaFunctionCommand(function)
82         // }
83
84         commands[name] = Command{action, completions}
85 }
86
87 // DefaultCommands returns a map containing micro's default commands
88 func DefaultCommands() map[string]StrCommand {
89         return map[string]StrCommand{
90                 "set":        {"Set", []Completion{OptionCompletion, OptionValueCompletion}},
91                 "setlocal":   {"SetLocal", []Completion{OptionCompletion, OptionValueCompletion}},
92                 "show":       {"Show", []Completion{OptionCompletion, NoCompletion}},
93                 "showkey":    {"ShowKey", []Completion{NoCompletion}},
94                 "bind":       {"Bind", []Completion{NoCompletion}},
95                 "run":        {"Run", []Completion{NoCompletion}},
96                 "quit":       {"Quit", []Completion{NoCompletion}},
97                 "save":       {"Save", []Completion{NoCompletion}},
98                 "replace":    {"Replace", []Completion{NoCompletion}},
99                 "replaceall": {"ReplaceAll", []Completion{NoCompletion}},
100                 "vsplit":     {"VSplit", []Completion{FileCompletion, NoCompletion}},
101                 "hsplit":     {"HSplit", []Completion{FileCompletion, NoCompletion}},
102                 "tab":        {"Tab", []Completion{FileCompletion, NoCompletion}},
103                 "help":       {"Help", []Completion{HelpCompletion, NoCompletion}},
104                 "eval":       {"Eval", []Completion{NoCompletion}},
105                 "log":        {"ToggleLog", []Completion{NoCompletion}},
106                 "plugin":     {"Plugin", []Completion{PluginCmdCompletion, PluginNameCompletion}},
107                 "reload":     {"Reload", []Completion{NoCompletion}},
108                 "cd":         {"Cd", []Completion{FileCompletion}},
109                 "pwd":        {"Pwd", []Completion{NoCompletion}},
110                 "open":       {"Open", []Completion{FileCompletion}},
111                 "tabswitch":  {"TabSwitch", []Completion{NoCompletion}},
112                 "term":       {"Term", []Completion{NoCompletion}},
113                 "memusage":   {"MemUsage", []Completion{NoCompletion}},
114                 "retab":      {"Retab", []Completion{NoCompletion}},
115                 "raw":        {"Raw", []Completion{NoCompletion}},
116         }
117 }
118
119 // CommandEditAction returns a bindable function that opens a prompt with
120 // the given string and executes the command when the user presses
121 // enter
122 func CommandEditAction(prompt string) BufKeyAction {
123         return func(h *BufHandler) bool {
124                 InfoBar.Prompt("> ", prompt, "Command", nil, func(resp string, canceled bool) {
125                         if !canceled {
126                                 HandleCommand(resp)
127                         }
128                 })
129                 return false
130         }
131 }
132
133 // CommandAction returns a bindable function which executes the
134 // given command
135 func CommandAction(cmd string) BufKeyAction {
136         return func(h *BufHandler) bool {
137                 HandleCommand(cmd)
138                 return false
139         }
140 }
141
142 // PluginCmd installs, removes, updates, lists, or searches for given plugins
143 func PluginCmd(args []string) {
144 }
145
146 // Retab changes all spaces to tabs or all tabs to spaces
147 // depending on the user's settings
148 func Retab(args []string) {
149 }
150
151 // Raw opens a new raw view which displays the escape sequences micro
152 // is receiving in real-time
153 func Raw(args []string) {
154 }
155
156 // TabSwitch switches to a given tab either by name or by number
157 func TabSwitch(args []string) {
158 }
159
160 // Cd changes the current working directory
161 func Cd(args []string) {
162 }
163
164 // MemUsage prints micro's memory usage
165 // Alloc shows how many bytes are currently in use
166 // Sys shows how many bytes have been requested from the operating system
167 // NumGC shows how many times the GC has been run
168 // Note that Go commonly reserves more memory from the OS than is currently in-use/required
169 // Additionally, even if Go returns memory to the OS, the OS does not always claim it because
170 // there may be plenty of memory to spare
171 func MemUsage(args []string) {
172         InfoBar.Message(util.GetMemStats())
173 }
174
175 // Pwd prints the current working directory
176 func Pwd(args []string) {
177         wd, err := os.Getwd()
178         if err != nil {
179                 InfoBar.Message(err.Error())
180         } else {
181                 InfoBar.Message(wd)
182         }
183 }
184
185 // Open opens a new buffer with a given filename
186 func Open(args []string) {
187 }
188
189 // ToggleLog toggles the log view
190 func ToggleLog(args []string) {
191 }
192
193 // Reload reloads all files (syntax files, colorschemes...)
194 func Reload(args []string) {
195 }
196
197 // Help tries to open the given help page in a horizontal split
198 func Help(args []string) {
199 }
200
201 // VSplit opens a vertical split with file given in the first argument
202 // If no file is given, it opens an empty buffer in a new split
203 func VSplit(args []string) {
204         buf, err := buffer.NewBufferFromFile(args[0], buffer.BTDefault)
205         if err != nil {
206                 InfoBar.Error(err)
207                 return
208         }
209
210         MainTab().CurPane().vsplit(buf)
211 }
212
213 // HSplit opens a horizontal split with file given in the first argument
214 // If no file is given, it opens an empty buffer in a new split
215 func HSplit(args []string) {
216         buf, err := buffer.NewBufferFromFile(args[0], buffer.BTDefault)
217         if err != nil {
218                 InfoBar.Error(err)
219                 return
220         }
221
222         MainTab().CurPane().hsplit(buf)
223 }
224
225 // Eval evaluates a lua expression
226 func Eval(args []string) {
227 }
228
229 // NewTab opens the given file in a new tab
230 func NewTab(args []string) {
231 }
232
233 // Set sets an option
234 func Set(args []string) {
235 }
236
237 // SetLocal sets an option local to the buffer
238 func SetLocal(args []string) {
239 }
240
241 // Show shows the value of the given option
242 func Show(args []string) {
243 }
244
245 // ShowKey displays the action that a key is bound to
246 func ShowKey(args []string) {
247         if len(args) < 1 {
248                 InfoBar.Error("Please provide a key to show")
249                 return
250         }
251
252         if action, ok := Bindings[args[0]]; ok {
253                 InfoBar.Message(action)
254         } else {
255                 InfoBar.Message(args[0], " has no binding")
256         }
257 }
258
259 // Bind creates a new keybinding
260 func Bind(args []string) {
261 }
262
263 // Run runs a shell command in the background
264 func Run(args []string) {
265         runf, err := shell.RunBackgroundShell(shellwords.Join(args...))
266         if err != nil {
267                 InfoBar.Error(err)
268         } else {
269                 go func() {
270                         InfoBar.Message(runf())
271                         screen.Redraw()
272                 }()
273         }
274 }
275
276 // Quit closes the main view
277 func Quit(args []string) {
278 }
279
280 // Save saves the buffer in the main view
281 func Save(args []string) {
282 }
283
284 // Replace runs search and replace
285 func Replace(args []string) {
286 }
287
288 // ReplaceAll replaces search term all at once
289 func ReplaceAll(args []string) {
290 }
291
292 // Term opens a terminal in the current view
293 func Term(args []string) {
294 }
295
296 // HandleCommand handles input from the user
297 func HandleCommand(input string) {
298         args, err := shellwords.Split(input)
299         if err != nil {
300                 InfoBar.Error("Error parsing args ", err)
301                 return
302         }
303
304         inputCmd := args[0]
305
306         if _, ok := commands[inputCmd]; !ok {
307                 InfoBar.Error("Unknown command ", inputCmd)
308         } else {
309                 commands[inputCmd].action(args[1:])
310         }
311 }