6 "github.com/zyedidia/micro/cmd/micro/buffer"
7 "github.com/zyedidia/micro/cmd/micro/util"
8 "github.com/zyedidia/tcell"
11 type BufKeyAction func(*BufHandler) bool
12 type BufMouseAction func(*BufHandler, *tcell.EventMouse) bool
14 var BufKeyBindings map[KeyEvent]BufKeyAction
15 var BufMouseBindings map[MouseEvent]BufMouseAction
18 BufKeyBindings = make(map[KeyEvent]BufKeyAction)
19 BufMouseBindings = make(map[MouseEvent]BufMouseAction)
22 func BufMapKey(k KeyEvent, action string) {
23 if f, ok := BufKeyActions[action]; ok {
26 util.TermMessage("Error:", action, "does not exist")
29 func BufMapMouse(k MouseEvent, action string) {
30 if f, ok := BufMouseActions[action]; ok {
31 BufMouseBindings[k] = f
32 } else if f, ok := BufKeyActions[action]; ok {
33 // allowed to map mouse buttons to key actions
34 BufMouseBindings[k] = func(h *BufHandler, e *tcell.EventMouse) bool {
38 util.TermMessage("Error:", action, "does not exist")
42 // The BufHandler connects the buffer and the window
43 // It provides a cursor (or multiple) and defines a set of actions
44 // that can be taken on the buffer
45 // The ActionHandler can access the window for necessary info about
46 // visual positions for mouse clicks and scrolling
47 type BufHandler struct {
50 cursors []*buffer.Cursor
51 Cursor *buffer.Cursor // the active cursor
53 StartLine int // Vertical scrolling
54 StartCol int // Horizontal scrolling
56 // Since tcell doesn't differentiate between a mouse release event
57 // and a mouse move event with no keys pressed, we need to keep
58 // track of whether or not the mouse was pressed (or not released) last event to determine
59 // mouse release events
62 // We need to keep track of insert key press toggle
64 // This stores when the last click was
65 // This is useful for detecting double and triple clicks
66 lastClickTime time.Time
69 // lastCutTime stores when the last ctrl+k was issued.
70 // It is used for clearing the clipboard to replace it with fresh cut lines.
73 // freshClip returns true if the clipboard has never been pasted.
76 // Was the last mouse event actually a double click?
77 // Useful for detecting triple clicks -- if a double click is detected
78 // but the last mouse event was actually a double click, it's a triple click
80 // Same here, just to keep track for mouse move events
84 func NewBufHandler(buf *buffer.Buffer) *BufHandler {
88 h.cursors = []*buffer.Cursor{buffer.NewCursor(buf, buf.StartCursor)}
89 h.Cursor = h.cursors[0]
91 buf.SetCursors(h.cursors)
95 // HandleEvent executes the tcell event properly
96 // TODO: multiple actions bound to one key
97 func (h *BufHandler) HandleEvent(event tcell.Event) {
98 switch e := event.(type) {
105 done := h.DoKeyEvent(ke)
106 if !done && e.Key() == tcell.KeyRune {
107 h.DoRuneInsert(e.Rune())
109 case *tcell.EventMouse:
114 h.DoMouseEvent(me, e)
118 func (h *BufHandler) DoKeyEvent(e KeyEvent) bool {
119 if action, ok := BufKeyBindings[e]; ok {
126 func (h *BufHandler) DoMouseEvent(e MouseEvent, te *tcell.EventMouse) bool {
127 if action, ok := BufMouseBindings[e]; ok {
134 func (h *BufHandler) DoRuneInsert(r rune) {
135 // Insert a character
136 if h.Cursor.HasSelection() {
137 h.Cursor.DeleteSelection()
138 h.Cursor.ResetSelection()
141 if h.isOverwriteMode {
144 h.Buf.Replace(h.Cursor.Loc, next, string(r))
146 h.Buf.Insert(h.Cursor.Loc, string(r))
150 var BufKeyActions = map[string]BufKeyAction{
151 "CursorUp": (*BufHandler).CursorUp,
152 "CursorDown": (*BufHandler).CursorDown,
153 "CursorPageUp": (*BufHandler).CursorPageUp,
154 "CursorPageDown": (*BufHandler).CursorPageDown,
155 "CursorLeft": (*BufHandler).CursorLeft,
156 "CursorRight": (*BufHandler).CursorRight,
157 "CursorStart": (*BufHandler).CursorStart,
158 "CursorEnd": (*BufHandler).CursorEnd,
159 "SelectToStart": (*BufHandler).SelectToStart,
160 "SelectToEnd": (*BufHandler).SelectToEnd,
161 "SelectUp": (*BufHandler).SelectUp,
162 "SelectDown": (*BufHandler).SelectDown,
163 "SelectLeft": (*BufHandler).SelectLeft,
164 "SelectRight": (*BufHandler).SelectRight,
165 "WordRight": (*BufHandler).WordRight,
166 "WordLeft": (*BufHandler).WordLeft,
167 "SelectWordRight": (*BufHandler).SelectWordRight,
168 "SelectWordLeft": (*BufHandler).SelectWordLeft,
169 "DeleteWordRight": (*BufHandler).DeleteWordRight,
170 "DeleteWordLeft": (*BufHandler).DeleteWordLeft,
171 "SelectLine": (*BufHandler).SelectLine,
172 "SelectToStartOfLine": (*BufHandler).SelectToStartOfLine,
173 "SelectToEndOfLine": (*BufHandler).SelectToEndOfLine,
174 "ParagraphPrevious": (*BufHandler).ParagraphPrevious,
175 "ParagraphNext": (*BufHandler).ParagraphNext,
176 "InsertNewline": (*BufHandler).InsertNewline,
177 "InsertSpace": (*BufHandler).InsertSpace,
178 "Backspace": (*BufHandler).Backspace,
179 "Delete": (*BufHandler).Delete,
180 "InsertTab": (*BufHandler).InsertTab,
181 "Save": (*BufHandler).Save,
182 "SaveAll": (*BufHandler).SaveAll,
183 "SaveAs": (*BufHandler).SaveAs,
184 "Find": (*BufHandler).Find,
185 "FindNext": (*BufHandler).FindNext,
186 "FindPrevious": (*BufHandler).FindPrevious,
187 "Center": (*BufHandler).Center,
188 "Undo": (*BufHandler).Undo,
189 "Redo": (*BufHandler).Redo,
190 "Copy": (*BufHandler).Copy,
191 "Cut": (*BufHandler).Cut,
192 "CutLine": (*BufHandler).CutLine,
193 "DuplicateLine": (*BufHandler).DuplicateLine,
194 "DeleteLine": (*BufHandler).DeleteLine,
195 "MoveLinesUp": (*BufHandler).MoveLinesUp,
196 "MoveLinesDown": (*BufHandler).MoveLinesDown,
197 "IndentSelection": (*BufHandler).IndentSelection,
198 "OutdentSelection": (*BufHandler).OutdentSelection,
199 "OutdentLine": (*BufHandler).OutdentLine,
200 "Paste": (*BufHandler).Paste,
201 "PastePrimary": (*BufHandler).PastePrimary,
202 "SelectAll": (*BufHandler).SelectAll,
203 "OpenFile": (*BufHandler).OpenFile,
204 "Start": (*BufHandler).Start,
205 "End": (*BufHandler).End,
206 "PageUp": (*BufHandler).PageUp,
207 "PageDown": (*BufHandler).PageDown,
208 "SelectPageUp": (*BufHandler).SelectPageUp,
209 "SelectPageDown": (*BufHandler).SelectPageDown,
210 "HalfPageUp": (*BufHandler).HalfPageUp,
211 "HalfPageDown": (*BufHandler).HalfPageDown,
212 "StartOfLine": (*BufHandler).StartOfLine,
213 "EndOfLine": (*BufHandler).EndOfLine,
214 "ToggleHelp": (*BufHandler).ToggleHelp,
215 "ToggleKeyMenu": (*BufHandler).ToggleKeyMenu,
216 "ToggleRuler": (*BufHandler).ToggleRuler,
217 "JumpLine": (*BufHandler).JumpLine,
218 "ClearStatus": (*BufHandler).ClearStatus,
219 "ShellMode": (*BufHandler).ShellMode,
220 "CommandMode": (*BufHandler).CommandMode,
221 "ToggleOverwriteMode": (*BufHandler).ToggleOverwriteMode,
222 "Escape": (*BufHandler).Escape,
223 "Quit": (*BufHandler).Quit,
224 "QuitAll": (*BufHandler).QuitAll,
225 "AddTab": (*BufHandler).AddTab,
226 "PreviousTab": (*BufHandler).PreviousTab,
227 "NextTab": (*BufHandler).NextTab,
228 "NextSplit": (*BufHandler).NextSplit,
229 "PreviousSplit": (*BufHandler).PreviousSplit,
230 "Unsplit": (*BufHandler).Unsplit,
231 "VSplit": (*BufHandler).VSplitBinding,
232 "HSplit": (*BufHandler).HSplitBinding,
233 "ToggleMacro": (*BufHandler).ToggleMacro,
234 "PlayMacro": (*BufHandler).PlayMacro,
235 "Suspend": (*BufHandler).Suspend,
236 "ScrollUp": (*BufHandler).ScrollUpAction,
237 "ScrollDown": (*BufHandler).ScrollDownAction,
238 "SpawnMultiCursor": (*BufHandler).SpawnMultiCursor,
239 "SpawnMultiCursorSelect": (*BufHandler).SpawnMultiCursorSelect,
240 "RemoveMultiCursor": (*BufHandler).RemoveMultiCursor,
241 "RemoveAllMultiCursors": (*BufHandler).RemoveAllMultiCursors,
242 "SkipMultiCursor": (*BufHandler).SkipMultiCursor,
243 "JumpToMatchingBrace": (*BufHandler).JumpToMatchingBrace,
245 // This was changed to InsertNewline but I don't want to break backwards compatibility
246 "InsertEnter": (*BufHandler).InsertNewline,
248 var BufMouseActions = map[string]BufMouseAction{
249 "MousePress": (*BufHandler).MousePress,
250 "MouseMultiCursor": (*BufHandler).MouseMultiCursor,