10 "github.com/zyedidia/tcell"
13 // TermMessage sends a message to the user in the terminal. This usually occurs before
14 // micro has been fully initialized -- ie if there is an error in the syntax highlighting
15 // regular expressions
16 // The function must be called when the screen is not initialized
17 // This will write the message, and wait for the user
18 // to press and key to continue
19 func TermMessage(msg ...interface{}) {
20 screenWasNil := screen == nil
26 fmt.Print("\nPress enter to continue")
28 reader := bufio.NewReader(os.Stdin)
29 reader.ReadString('\n')
36 // TermError sends an error to the user in the terminal. Like TermMessage except formatted
38 func TermError(filename string, lineNum int, err string) {
39 TermMessage(filename + ", " + strconv.Itoa(lineNum) + ": " + err)
42 // Messenger is an object that makes it easy to send messages to the user
43 // and get input from the user
44 type Messenger struct {
45 // Are we currently prompting the user?
47 // Is there a message to print
52 // The user's response to a prompt
54 // style to use when drawing the message
57 // We have to keep track of the cursor for prompting
60 // This map stores the history for all the different kinds of uses Prompt has
61 // It's a map of history type -> history array
62 history map[string][]string
65 // Is the current message a message from the gutter
69 // Message sends a message to the user
70 func (m *Messenger) Message(msg ...interface{}) {
71 buf := new(bytes.Buffer)
72 fmt.Fprint(buf, msg...)
73 m.message = buf.String()
76 if _, ok := colorscheme["message"]; ok {
77 m.style = colorscheme["message"]
82 // Error sends an error message to the user
83 func (m *Messenger) Error(msg ...interface{}) {
84 buf := new(bytes.Buffer)
85 fmt.Fprint(buf, msg...)
86 m.message = buf.String()
88 Foreground(tcell.ColorBlack).
89 Background(tcell.ColorMaroon)
91 if _, ok := colorscheme["error-message"]; ok {
92 m.style = colorscheme["error-message"]
97 // YesNoPrompt asks the user a yes or no question (waits for y or n) and returns the result
98 func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
101 _, h := screen.Size()
105 screen.ShowCursor(Count(m.message), h-1)
107 event := screen.PollEvent()
109 switch e := event.(type) {
110 case *tcell.EventKey:
115 } else if e.Rune() == 'n' {
118 case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape:
125 // Prompt sends the user a message and waits for a response to be typed in
126 // This function blocks the main loop while waiting for input
127 func (m *Messenger) Prompt(prompt, historyType string) (string, bool) {
130 if _, ok := m.history[historyType]; !ok {
131 m.history[historyType] = []string{""}
133 m.history[historyType] = append(m.history[historyType], "")
135 m.historyNum = len(m.history[historyType]) - 1
137 response, canceled := "", true
143 event := screen.PollEvent()
145 switch e := event.(type) {
146 case *tcell.EventKey:
148 case tcell.KeyCtrlQ, tcell.KeyCtrlC, tcell.KeyEscape:
152 // User is done entering their response
154 response, canceled = m.response, false
155 m.history[historyType][len(m.history[historyType])-1] = response
159 m.HandleEvent(event, m.history[historyType])
168 return response, canceled
171 // HandleEvent handles an event for the prompter
172 func (m *Messenger) HandleEvent(event tcell.Event, history []string) {
173 switch e := event.(type) {
174 case *tcell.EventKey:
177 if m.historyNum > 0 {
179 m.response = history[m.historyNum]
180 m.cursorx = len(m.response)
183 if m.historyNum < len(history)-1 {
185 m.response = history[m.historyNum]
186 m.cursorx = len(m.response)
193 if m.cursorx < Count(m.response) {
196 case tcell.KeyBackspace2, tcell.KeyBackspace:
198 m.response = string([]rune(m.response)[:m.cursorx-1]) + string(m.response[m.cursorx:])
202 m.response = Insert(m.response, m.cursorx, string(e.Rune()))
205 history[m.historyNum] = m.response
209 // Reset resets the messenger's cursor, message and response
210 func (m *Messenger) Reset() {
216 // Clear clears the line at the bottom of the editor
217 func (m *Messenger) Clear() {
218 w, h := screen.Size()
219 for x := 0; x < w; x++ {
220 screen.SetContent(x, h-1, ' ', nil, defStyle)
224 // Display displays messages or prompts
225 func (m *Messenger) Display() {
226 _, h := screen.Size()
228 runes := []rune(m.message + m.response)
229 for x := 0; x < len(runes); x++ {
230 screen.SetContent(x, h-1, runes[x], nil, m.style)
234 screen.ShowCursor(Count(m.message)+m.cursorx, h-1)
239 // A GutterMessage is a message displayed on the side of the editor
240 type GutterMessage struct {
246 // These are the different types of messages
248 // GutterInfo represents a simple info message
250 // GutterWarning represents a compiler warning
252 // GutterError represents a compiler error