]> git.lizzy.rs Git - micro.git/blob - src/eventhandler.go
Include newlines in selection
[micro.git] / src / eventhandler.go
1 package main
2
3 import (
4         "time"
5 )
6
7 const (
8         // TextEventInsert repreasents an insertion event
9         TextEventInsert = 1
10         // TextEventRemove represents a deletion event
11         TextEventRemove = -1
12 )
13
14 // TextEvent holds data for a manipulation on some text that can be undone
15 type TextEvent struct {
16         c Cursor
17
18         eventType int
19         text      string
20         start     int
21         end       int
22         buf       *Buffer
23         time      time.Time
24 }
25
26 // ExecuteTextEvent runs a text event
27 func ExecuteTextEvent(t *TextEvent) {
28         if t.eventType == TextEventInsert {
29                 t.buf.Insert(t.start, t.text)
30         } else if t.eventType == TextEventRemove {
31                 t.text = t.buf.Remove(t.start, t.end)
32         }
33 }
34
35 // UndoTextEvent undoes a text event
36 func UndoTextEvent(t *TextEvent) {
37         t.eventType = -t.eventType
38         ExecuteTextEvent(t)
39 }
40
41 // EventHandler executes text manipulations and allows undoing and redoing
42 type EventHandler struct {
43         v    *View
44         undo *Stack
45         redo *Stack
46 }
47
48 // NewEventHandler returns a new EventHandler
49 func NewEventHandler(v *View) *EventHandler {
50         eh := new(EventHandler)
51         eh.undo = new(Stack)
52         eh.redo = new(Stack)
53         eh.v = v
54         return eh
55 }
56
57 // Insert creates an insert text event and executes it
58 func (eh *EventHandler) Insert(start int, text string) {
59         e := &TextEvent{
60                 c:         eh.v.cursor,
61                 eventType: TextEventInsert,
62                 text:      text,
63                 start:     start,
64                 end:       start + Count(text),
65                 buf:       eh.v.buf,
66                 time:      time.Now(),
67         }
68         eh.Execute(e)
69 }
70
71 // Remove creates a remove text event and executes it
72 func (eh *EventHandler) Remove(start, end int) {
73         e := &TextEvent{
74                 c:         eh.v.cursor,
75                 eventType: TextEventRemove,
76                 start:     start,
77                 end:       end,
78                 buf:       eh.v.buf,
79                 time:      time.Now(),
80         }
81         eh.Execute(e)
82 }
83
84 // Execute a textevent and add it to the undo stack
85 func (eh *EventHandler) Execute(t *TextEvent) {
86         if eh.redo.Len() > 0 {
87                 eh.redo = new(Stack)
88         }
89         eh.undo.Push(t)
90         ExecuteTextEvent(t)
91 }
92
93 // Undo the first event in the undo stack
94 func (eh *EventHandler) Undo() {
95         t := eh.undo.Pop()
96         if t == nil {
97                 return
98         }
99
100         te := t.(*TextEvent)
101         // Modifies the text event
102         UndoTextEvent(te)
103
104         teCursor := te.c
105         te.c = eh.v.cursor
106         eh.v.cursor = teCursor
107
108         eh.redo.Push(te)
109 }
110
111 // Redo the first event in the redo stack
112 func (eh *EventHandler) Redo() {
113         t := eh.redo.Pop()
114         if t == nil {
115                 return
116         }
117
118         te := t.(*TextEvent)
119         // Modifies the text event
120         UndoTextEvent(te)
121
122         teCursor := te.c
123         te.c = eh.v.cursor
124         eh.v.cursor = teCursor
125
126         eh.undo.Push(te)
127 }