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