]> git.lizzy.rs Git - micro.git/blob - cmd/micro/info/infobuffer.go
Fix yn callback bug
[micro.git] / cmd / micro / info / infobuffer.go
1 package info
2
3 import (
4         "fmt"
5         "strings"
6
7         "github.com/zyedidia/micro/cmd/micro/buffer"
8 )
9
10 // The InfoBuf displays messages and other info at the bottom of the screen.
11 // It is respresented as a buffer and a message with a style.
12 type InfoBuf struct {
13         *buffer.Buffer
14
15         HasPrompt  bool
16         HasMessage bool
17         HasError   bool
18         HasYN      bool
19
20         PromptType string
21
22         Msg    string
23         YNResp bool
24
25         // This map stores the history for all the different kinds of uses Prompt has
26         // It's a map of history type -> history array
27         History    map[string][]string
28         HistoryNum int
29
30         // Is the current message a message from the gutter
31         HasGutter bool
32
33         PromptCallback func(resp string, canceled bool)
34         EventCallback  func(resp string)
35         YNCallback     func(yes bool, canceled bool)
36 }
37
38 // NewBuffer returns a new infobuffer
39 func NewBuffer() *InfoBuf {
40         ib := new(InfoBuf)
41         ib.History = make(map[string][]string)
42
43         ib.Buffer = buffer.NewBufferFromString("", "infobar", buffer.BTInfo)
44         ib.LoadHistory()
45
46         return ib
47 }
48
49 // Close performs any cleanup necessary when shutting down the infobuffer
50 func (i *InfoBuf) Close() {
51         i.SaveHistory()
52 }
53
54 // Message sends a message to the user
55 func (i *InfoBuf) Message(msg ...interface{}) {
56         // only display a new message if there isn't an active prompt
57         // this is to prevent overwriting an existing prompt to the user
58         if i.HasPrompt == false {
59                 displayMessage := fmt.Sprint(msg...)
60                 // if there is no active prompt then style and display the message as normal
61                 i.Msg = displayMessage
62                 i.HasMessage = true
63         }
64 }
65
66 // GutterMessage displays a message and marks it as a gutter message
67 func (i *InfoBuf) GutterMessage(msg ...interface{}) {
68         i.Message(msg...)
69         i.HasGutter = true
70 }
71
72 // ClearGutter clears the info bar and unmarks the message
73 func (i *InfoBuf) ClearGutter() {
74         i.HasGutter = false
75         i.Message("")
76 }
77
78 // Error sends an error message to the user
79 func (i *InfoBuf) Error(msg ...interface{}) {
80         // only display a new message if there isn't an active prompt
81         // this is to prevent overwriting an existing prompt to the user
82         if i.HasPrompt == false {
83                 // if there is no active prompt then style and display the message as normal
84                 i.Msg = fmt.Sprint(msg...)
85                 i.HasMessage, i.HasError = false, true
86         }
87         // TODO: add to log?
88 }
89
90 // Prompt starts a prompt for the user, it takes a prompt, a possibly partially filled in msg
91 // and callbacks executed when the user executes an event and when the user finishes the prompt
92 // The eventcb passes the current user response as the argument and donecb passes the user's message
93 // and a boolean indicating if the prompt was canceled
94 func (i *InfoBuf) Prompt(prompt string, msg string, ptype string, eventcb func(string), donecb func(string, bool)) {
95         // If we get another prompt mid-prompt we cancel the one getting overwritten
96         if i.HasPrompt {
97                 i.DonePrompt(true)
98         }
99
100         if _, ok := i.History[ptype]; !ok {
101                 i.History[ptype] = []string{""}
102         } else {
103                 i.History[ptype] = append(i.History[ptype], "")
104         }
105         i.HistoryNum = len(i.History[ptype]) - 1
106
107         i.PromptType = ptype
108         i.Msg = prompt
109         i.HasPrompt = true
110         i.HasMessage, i.HasError, i.HasYN = false, false, false
111         i.HasGutter = false
112         i.PromptCallback = donecb
113         i.EventCallback = eventcb
114         i.Buffer.Insert(i.Buffer.Start(), []byte(msg))
115 }
116
117 func (i *InfoBuf) YNPrompt(prompt string, donecb func(bool, bool)) {
118         if i.HasPrompt {
119                 i.DonePrompt(true)
120         }
121
122         i.Msg = prompt
123         i.HasPrompt = true
124         i.HasYN = true
125         i.HasMessage, i.HasError = false, false
126         i.HasGutter = false
127         i.YNCallback = donecb
128 }
129
130 // DonePrompt finishes the current prompt and indicates whether or not it was canceled
131 func (i *InfoBuf) DonePrompt(canceled bool) {
132         hadYN := i.HasYN
133         i.HasPrompt = false
134         i.HasYN = false
135         i.HasGutter = false
136         if !hadYN {
137                 if i.PromptCallback != nil {
138                         if canceled {
139                                 i.PromptCallback("", true)
140                                 h := i.History[i.PromptType]
141                                 i.History[i.PromptType] = h[:len(h)-1]
142                         } else {
143                                 resp := strings.TrimSpace(string(i.LineBytes(0)))
144                                 i.PromptCallback(resp, false)
145                                 h := i.History[i.PromptType]
146                                 h[len(h)-1] = resp
147                         }
148                         i.PromptCallback = nil
149                         i.EventCallback = nil
150                 }
151                 if i.EventCallback != nil {
152                         i.EventCallback = nil
153                 }
154                 i.Replace(i.Start(), i.End(), []byte{})
155         }
156         if i.YNCallback != nil && hadYN {
157                 i.YNCallback(i.YNResp, canceled)
158                 i.YNCallback = nil
159         }
160 }
161
162 // Reset resets the infobuffer's msg and info
163 func (i *InfoBuf) Reset() {
164         i.Msg = ""
165         i.HasPrompt, i.HasMessage, i.HasError = false, false, false
166         i.HasGutter = false
167 }