]> git.lizzy.rs Git - micro.git/blob - src/message.go
Include newlines in selection
[micro.git] / src / message.go
1 package main
2
3 import (
4         "github.com/gdamore/tcell"
5 )
6
7 // Messenger is an object that can send messages to the user and get input from the user (with a prompt)
8 type Messenger struct {
9         hasPrompt  bool
10         hasMessage bool
11
12         message  string
13         response string
14         style    tcell.Style
15
16         cursorx int
17
18         s tcell.Screen
19 }
20
21 // NewMessenger returns a new Messenger struct
22 func NewMessenger(s tcell.Screen) *Messenger {
23         m := new(Messenger)
24         m.s = s
25         return m
26 }
27
28 // Message sends a message to the user
29 func (m *Messenger) Message(msg string) {
30         m.message = msg
31         m.style = tcell.StyleDefault
32
33         if _, ok := colorscheme["message"]; ok {
34                 m.style = colorscheme["message"]
35         }
36         m.hasMessage = true
37 }
38
39 // Error sends an error message to the user
40 func (m *Messenger) Error(msg string) {
41         m.message = msg
42         m.style = tcell.StyleDefault.
43                 Foreground(tcell.ColorBlack).
44                 Background(tcell.ColorMaroon)
45
46         if _, ok := colorscheme["error-message"]; ok {
47                 m.style = colorscheme["error-message"]
48         }
49         m.hasMessage = true
50 }
51
52 // Prompt sends the user a message and waits for a response to be typed in
53 // This function blocks the main loop while waiting for input
54 func (m *Messenger) Prompt(prompt string) (string, bool) {
55         m.hasPrompt = true
56         m.Message(prompt)
57
58         response, canceled := "", true
59
60         for m.hasPrompt {
61                 m.Clear()
62                 m.Display()
63
64                 event := m.s.PollEvent()
65
66                 switch e := event.(type) {
67                 case *tcell.EventKey:
68                         if e.Key() == tcell.KeyEscape {
69                                 // Cancel
70                                 m.hasPrompt = false
71                         } else if e.Key() == tcell.KeyCtrlC {
72                                 // Cancel
73                                 m.hasPrompt = false
74                         } else if e.Key() == tcell.KeyCtrlQ {
75                                 // Cancel
76                                 m.hasPrompt = false
77                         } else if e.Key() == tcell.KeyEnter {
78                                 // User is done entering their response
79                                 m.hasPrompt = false
80                                 response, canceled = m.response, false
81                         }
82                 }
83
84                 m.HandleEvent(event)
85         }
86
87         m.Reset()
88         return response, canceled
89 }
90
91 // HandleEvent handles an event for the prompter
92 func (m *Messenger) HandleEvent(event tcell.Event) {
93         switch e := event.(type) {
94         case *tcell.EventKey:
95                 switch e.Key() {
96                 case tcell.KeyLeft:
97                         m.cursorx--
98                 case tcell.KeyRight:
99                         m.cursorx++
100                 case tcell.KeyBackspace2:
101                         if m.cursorx > 0 {
102                                 m.response = string([]rune(m.response)[:Count(m.response)-1])
103                                 m.cursorx--
104                         }
105                 case tcell.KeySpace:
106                         m.response += " "
107                         m.cursorx++
108                 case tcell.KeyRune:
109                         m.response += string(e.Rune())
110                         m.cursorx++
111                 }
112         }
113         if m.cursorx < 0 {
114                 m.cursorx = 0
115         }
116 }
117
118 // Reset resets the messenger's cursor, message and response
119 func (m *Messenger) Reset() {
120         m.cursorx = 0
121         m.message = ""
122         m.response = ""
123 }
124
125 // Clear clears the line at the bottom of the editor
126 func (m *Messenger) Clear() {
127         w, h := m.s.Size()
128         for x := 0; x < w; x++ {
129                 m.s.SetContent(x, h-1, ' ', nil, tcell.StyleDefault)
130         }
131 }
132
133 // Display displays and messages or prompts
134 func (m *Messenger) Display() {
135         _, h := m.s.Size()
136         if m.hasMessage {
137                 runes := []rune(m.message + m.response)
138                 for x := 0; x < len(runes); x++ {
139                         m.s.SetContent(x, h-1, runes[x], nil, m.style)
140                 }
141         }
142         if m.hasPrompt {
143                 m.s.ShowCursor(Count(m.message)+m.cursorx, h-1)
144                 m.s.Show()
145         }
146 }