-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathundo.go
77 lines (68 loc) · 1.54 KB
/
undo.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main
// undoType determines how the history entry should behandled,
// undoTypeDelete removes lines and undoTypeAdd adds lines.
type undoType int
const (
undoTypeAdd undoType = iota
undoTypeDelete
)
type undoAction struct {
cursor
typ undoType
lines []string
}
type undo struct {
action []undoAction // history for a command in progress
history [][]undoAction
global []undoAction
}
func (u *undo) clear() { u.action = []undoAction{} }
func (u *undo) reset() {
u.clear()
u.history = [][]undoAction{}
}
func (u *undo) pop(ed *Editor) error {
if len(u.history) < 1 {
return ErrNothingToUndo
}
action := u.history[len(u.history)-1]
for i := len(action) - 1; i >= 0; i-- {
a := action[i]
before := ed.file.lines[:a.first-1]
after := ed.file.lines[a.first-1:]
switch a.typ {
case undoTypeDelete:
after = ed.file.lines[a.second:]
ed.file.lines = append(before, after...)
case undoTypeAdd:
ed.file.lines = append(before, append(a.lines, after...)...)
}
ed.dot = a.dot
ed.file.dirty = true
}
if count := len(u.history) - 1; count > 0 {
u.history = u.history[:count]
} else {
u.history = [][]undoAction{}
}
return nil
}
func (u *undo) append(typ undoType, cur cursor, lines []string) {
u.action = append(u.action, undoAction{
typ: typ,
cursor: cur,
lines: lines,
})
}
func (u *undo) store(g bool) {
if g {
u.global = append(u.global, u.action...)
} else {
u.history = append(u.history, u.action)
}
u.clear()
}
func (u *undo) storeGlobal() {
u.history = append(u.history, u.global)
u.clear()
}