]> git.lizzy.rs Git - micro.git/blob - cmd/micro/command.go
boss mode: Single line output stays in messenger, multiline output goes to a help...
[micro.git] / cmd / micro / command.go
1 package main
2
3 import (
4         "os"
5         "os/exec"
6         "regexp"
7         "strings"
8
9         "github.com/gdamore/tcell"
10 )
11
12 func HandleShellCommand(input string, view *View) {
13         inputCmd := strings.Split(input, " ")[0]
14         args := strings.Split(input, " ")[1:]
15
16         // Execute Command
17         cmdout := exec.Command(inputCmd, args...)
18         output, _ := cmdout.CombinedOutput()
19         outstring := string(output)
20         totalLines := strings.Split(outstring, "\n")
21         if len(totalLines) == 2 {
22                 messenger.Message(outstring)
23                 return
24         }
25         if outstring != "" {
26                 // Display nonblank output
27                 DisplayBlock(outstring)
28         }
29 }
30
31 // DisplayBlock displays txt
32 // It blocks the main loop
33 func DisplayBlock(text string) {
34         topline := 0
35         _, height := screen.Size()
36         screen.HideCursor()
37         totalLines := strings.Split(text, "\n")
38         for {
39                 screen.Clear()
40
41                 lineEnd := topline + height
42                 if lineEnd > len(totalLines) {
43                         lineEnd = len(totalLines)
44                 }
45                 lines := totalLines[topline:lineEnd]
46                 for y, line := range lines {
47                         for x, ch := range line {
48                                 st := defStyle
49                                 screen.SetContent(x, y, ch, nil, st)
50                         }
51                 }
52
53                 screen.Show()
54
55                 event := screen.PollEvent()
56                 switch e := event.(type) {
57                 case *tcell.EventResize:
58                         _, height = e.Size()
59                 case *tcell.EventKey:
60                         switch e.Key() {
61                         case tcell.KeyUp:
62                                 if topline > 0 {
63                                         topline--
64                                 }
65                         case tcell.KeyDown:
66                                 if topline < len(totalLines)-height {
67                                         topline++
68                                 }
69                         case tcell.KeyCtrlQ, tcell.KeyCtrlW, tcell.KeyEscape, tcell.KeyCtrlC:
70                                 return
71                         }
72                 }
73         }
74 }
75
76 // HandleCommand handles input from the user
77 func HandleCommand(input string, view *View) {
78         inputCmd := strings.Split(input, " ")[0]
79         args := strings.Split(input, " ")[1:]
80
81         commands := []string{"set", "quit", "save", "replace"}
82
83         i := 0
84         cmd := inputCmd
85
86         for _, c := range commands {
87                 if strings.HasPrefix(c, inputCmd) {
88                         i++
89                         cmd = c
90                 }
91         }
92         if i == 1 {
93                 inputCmd = cmd
94         }
95
96         switch inputCmd {
97         case "set":
98                 SetOption(view, args)
99         case "quit":
100                 if view.CanClose("Quit anyway? ") {
101                         screen.Fini()
102                         os.Exit(0)
103                 }
104         case "save":
105                 view.Save()
106         case "replace":
107                 r := regexp.MustCompile(`"[^"\\]*(?:\\.[^"\\]*)*"|[^\s]*`)
108                 replaceCmd := r.FindAllString(strings.Join(args, " "), -1)
109                 if len(replaceCmd) < 2 {
110                         messenger.Error("Invalid replace statement: " + strings.Join(args, " "))
111                         return
112                 }
113
114                 var flags string
115                 if len(replaceCmd) == 3 {
116                         // The user included some flags
117                         flags = replaceCmd[2]
118                 }
119
120                 search := string(replaceCmd[0])
121                 replace := string(replaceCmd[1])
122
123                 if strings.HasPrefix(search, `"`) && strings.HasSuffix(search, `"`) {
124                         search = search[1 : len(search)-1]
125                 }
126                 if strings.HasPrefix(replace, `"`) && strings.HasSuffix(replace, `"`) {
127                         replace = replace[1 : len(replace)-1]
128                 }
129
130                 search = strings.Replace(search, `\"`, `"`, -1)
131                 replace = strings.Replace(replace, `\"`, `"`, -1)
132
133                 // messenger.Error(search + " -> " + replace)
134
135                 regex, err := regexp.Compile(search)
136                 if err != nil {
137                         messenger.Error(err.Error())
138                         return
139                 }
140
141                 found := false
142                 for {
143                         match := regex.FindStringIndex(view.buf.text)
144                         if match == nil {
145                                 break
146                         }
147                         found = true
148                         if strings.Contains(flags, "c") {
149                                 //      // The 'check' flag was used
150                                 //      if messenger.YesNoPrompt("Perform replacement?") {
151                                 //              view.eh.Replace(match[0], match[1], replace)
152                                 //      } else {
153                                 //              continue
154                                 //      }
155                         }
156                         view.eh.Replace(match[0], match[1], replace)
157                 }
158                 if !found {
159                         messenger.Message("Nothing matched " + search)
160                 }
161         default:
162                 messenger.Error("Unknown command: " + inputCmd)
163         }
164 }