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