]> git.lizzy.rs Git - micro.git/blob - internal/action/infopane.go
c72c9ebd9ba15e193afa45cd2383d744d3369a77
[micro.git] / internal / action / infopane.go
1 package action
2
3 import (
4         "bytes"
5         "strings"
6
7         "github.com/zyedidia/micro/v2/internal/buffer"
8         "github.com/zyedidia/micro/v2/internal/display"
9         "github.com/zyedidia/micro/v2/internal/info"
10         "github.com/zyedidia/micro/v2/internal/util"
11         "github.com/zyedidia/tcell"
12 )
13
14 type InfoKeyAction func(*InfoPane)
15
16 type InfoPane struct {
17         *BufPane
18         *info.InfoBuf
19 }
20
21 func NewInfoPane(ib *info.InfoBuf, w display.BWindow, tab *Tab) *InfoPane {
22         ip := new(InfoPane)
23         ip.InfoBuf = ib
24         ip.BufPane = NewBufPane(ib.Buffer, w, tab)
25
26         return ip
27 }
28
29 func NewInfoBar() *InfoPane {
30         ib := info.NewBuffer()
31         w := display.NewInfoWindow(ib)
32         return NewInfoPane(ib, w, nil)
33 }
34
35 func (h *InfoPane) Close() {
36         h.InfoBuf.Close()
37         h.BufPane.Close()
38 }
39
40 func (h *InfoPane) HandleEvent(event tcell.Event) {
41         switch e := event.(type) {
42         case *tcell.EventKey:
43                 ke := KeyEvent{
44                         code: e.Key(),
45                         mod:  e.Modifiers(),
46                         r:    e.Rune(),
47                 }
48
49                 done := h.DoKeyEvent(ke)
50                 hasYN := h.HasYN
51                 if e.Key() == tcell.KeyRune && hasYN {
52                         if e.Rune() == 'y' && hasYN {
53                                 h.YNResp = true
54                                 h.DonePrompt(false)
55                         } else if e.Rune() == 'n' && hasYN {
56                                 h.YNResp = false
57                                 h.DonePrompt(false)
58                         }
59                 }
60                 if e.Key() == tcell.KeyRune && !done && !hasYN {
61                         h.DoRuneInsert(e.Rune())
62                         done = true
63                 }
64                 if done && h.HasPrompt && !hasYN {
65                         resp := string(h.LineBytes(0))
66                         hist := h.History[h.PromptType]
67                         hist[h.HistoryNum] = resp
68                         if h.EventCallback != nil {
69                                 h.EventCallback(resp)
70                         }
71                 }
72         default:
73                 h.BufPane.HandleEvent(event)
74         }
75 }
76
77 // DoKeyEvent executes a key event for the command bar, doing any overridden actions
78 func (h *InfoPane) DoKeyEvent(e KeyEvent) bool {
79         done := false
80         if action, ok := BufKeyBindings[e]; ok {
81                 estr := BufKeyStrings[e]
82                 for _, s := range InfoNones {
83                         if s == estr {
84                                 return false
85                         }
86                 }
87                 for s, a := range InfoOverrides {
88                         // TODO this is a hack and really we should have support
89                         // for having binding overrides for different buffers
90                         if strings.HasPrefix(estr, s) {
91                                 done = true
92                                 a(h)
93                                 break
94                         }
95                 }
96                 if !done {
97                         done = action(h.BufPane)
98                 }
99         }
100         return done
101 }
102
103 // InfoNones is a list of actions that should have no effect when executed
104 // by an infohandler
105 var InfoNones = []string{
106         "Save",
107         "SaveAll",
108         "SaveAs",
109         "Find",
110         "FindNext",
111         "FindPrevious",
112         "Center",
113         "DuplicateLine",
114         "MoveLinesUp",
115         "MoveLinesDown",
116         "OpenFile",
117         "Start",
118         "End",
119         "PageUp",
120         "PageDown",
121         "SelectPageUp",
122         "SelectPageDown",
123         "HalfPageUp",
124         "HalfPageDown",
125         "ToggleHelp",
126         "ToggleKeyMenu",
127         "ToggleDiffGutter",
128         "ToggleRuler",
129         "JumpLine",
130         "ClearStatus",
131         "ShellMode",
132         "CommandMode",
133         "AddTab",
134         "PreviousTab",
135         "NextTab",
136         "NextSplit",
137         "PreviousSplit",
138         "Unsplit",
139         "VSplit",
140         "HSplit",
141         "ToggleMacro",
142         "PlayMacro",
143         "Suspend",
144         "ScrollUp",
145         "ScrollDown",
146         "SpawnMultiCursor",
147         "SpawnMultiCursorSelect",
148         "RemoveMultiCursor",
149         "RemoveAllMultiCursors",
150         "SkipMultiCursor",
151 }
152
153 // InfoOverrides is the list of actions which have been overridden
154 // by the infohandler
155 var InfoOverrides = map[string]InfoKeyAction{
156         "CursorUp":      (*InfoPane).CursorUp,
157         "CursorDown":    (*InfoPane).CursorDown,
158         "InsertNewline": (*InfoPane).InsertNewline,
159         "Autocomplete":  (*InfoPane).Autocomplete,
160         "Escape":        (*InfoPane).Escape,
161         "Quit":          (*InfoPane).Quit,
162         "QuitAll":       (*InfoPane).QuitAll,
163 }
164
165 // CursorUp cycles history up
166 func (h *InfoPane) CursorUp() {
167         h.UpHistory(h.History[h.PromptType])
168 }
169
170 // CursorDown cycles history down
171 func (h *InfoPane) CursorDown() {
172         h.DownHistory(h.History[h.PromptType])
173 }
174
175 // Autocomplete begins autocompletion
176 func (h *InfoPane) Autocomplete() {
177         b := h.Buf
178         if b.HasSuggestions {
179                 b.CycleAutocomplete(true)
180                 return
181         }
182
183         c := b.GetActiveCursor()
184         l := b.LineBytes(0)
185         l = util.SliceStart(l, c.X)
186
187         args := bytes.Split(l, []byte{' '})
188         cmd := string(args[0])
189
190         if h.PromptType == "Command" {
191                 if len(args) == 1 {
192                         b.Autocomplete(CommandComplete)
193                 } else if action, ok := commands[cmd]; ok {
194                         if action.completer != nil {
195                                 b.Autocomplete(action.completer)
196                         }
197                 }
198         } else {
199                 // by default use filename autocompletion
200                 b.Autocomplete(buffer.FileComplete)
201         }
202 }
203
204 // InsertNewline completes the prompt
205 func (h *InfoPane) InsertNewline() {
206         if !h.HasYN {
207                 h.DonePrompt(false)
208         }
209 }
210
211 // Quit cancels the prompt
212 func (h *InfoPane) Quit() {
213         h.DonePrompt(true)
214 }
215
216 // QuitAll cancels the prompt
217 func (h *InfoPane) QuitAll() {
218         h.DonePrompt(true)
219 }
220
221 // Escape cancels the prompt
222 func (h *InfoPane) Escape() {
223         h.DonePrompt(true)
224 }