Get undo working properly with multiple cursors

This commit is contained in:
Zachary Yedidia
2017-06-16 22:19:33 -04:00
parent 21840d3ffe
commit f933b90c66
5 changed files with 52 additions and 25 deletions

View File

@@ -1848,6 +1848,7 @@ func (v *View) SpawnMultiCursor(usePlugin bool) bool {
}
}
v.Buf.cursors = append(v.Buf.cursors, c)
v.Buf.UpdateCursors()
v.Relocate()
v.Cursor = spawner
}
@@ -1879,6 +1880,7 @@ func (v *View) MouseMultiCursor(usePlugin bool, e *tcell.EventMouse) bool {
v.Cursor = &v.Buf.Cursor
v.Buf.cursors = append(v.Buf.cursors, c)
v.Buf.UpdateCursors()
if usePlugin {
PostActionCall("SpawnMultiCursorAtMouse", v)
@@ -1923,6 +1925,7 @@ func (v *View) RemoveMultiCursor(usePlugin bool) bool {
if end > 1 {
v.Buf.cursors[end-1] = nil
v.Buf.cursors = v.Buf.cursors[:end-1]
v.Buf.UpdateCursors()
}
v.Relocate()
@@ -1948,6 +1951,7 @@ func (v *View) RemoveAllMultiCursors(usePlugin bool) bool {
v.Buf.cursors[i] = nil
}
v.Buf.cursors = v.Buf.cursors[:1]
v.Buf.UpdateCursors()
v.Cursor.ResetSelection()
v.Relocate()

View File

@@ -28,8 +28,9 @@ type Buffer struct {
// This stores all the text in the buffer as an array of lines
*LineArray
Cursor Cursor
cursors []*Cursor // for multiple cursors
Cursor Cursor
cursors []*Cursor // for multiple cursors
curCursor int // the current cursor
// Path to the file on disk
Path string
@@ -308,6 +309,12 @@ func (b *Buffer) Update() {
b.NumLines = len(b.lines)
}
func (b *Buffer) UpdateCursors() {
for i, c := range b.cursors {
c.Num = i
}
}
// Save saves the buffer to its default path
func (b *Buffer) Save() error {
return b.SaveAs(b.Path)

View File

@@ -21,6 +21,9 @@ type Cursor struct {
// This is used for line and word selection where it is necessary
// to know what the original selection was
OrigSelection [2]Loc
// Which cursor index is this (for multiple cursors)
Num int
}
// Goto puts the cursor at the given cursor's location and gives the current cursor its selection too

View File

@@ -97,7 +97,7 @@ func (eh *EventHandler) ApplyDiff(new string) {
// Insert creates an insert text event and executes it
func (eh *EventHandler) Insert(start Loc, text string) {
e := &TextEvent{
C: eh.buf.Cursor,
C: *eh.buf.cursors[eh.buf.curCursor],
EventType: TextEventInsert,
Deltas: []Delta{Delta{text, start, Loc{0, 0}}},
Time: time.Now(),
@@ -119,7 +119,7 @@ func (eh *EventHandler) Insert(start Loc, text string) {
// Remove creates a remove text event and executes it
func (eh *EventHandler) Remove(start, end Loc) {
e := &TextEvent{
C: eh.buf.Cursor,
C: *eh.buf.cursors[eh.buf.curCursor],
EventType: TextEventRemove,
Deltas: []Delta{Delta{"", start, end}},
Time: time.Now(),
@@ -141,7 +141,7 @@ func (eh *EventHandler) Remove(start, end Loc) {
// MultipleReplace creates an multiple insertions executes them
func (eh *EventHandler) MultipleReplace(deltas []Delta) {
e := &TextEvent{
C: eh.buf.Cursor,
C: *eh.buf.cursors[eh.buf.curCursor],
EventType: TextEventReplace,
Deltas: deltas,
Time: time.Now(),
@@ -216,8 +216,12 @@ func (eh *EventHandler) UndoOneEvent() {
// Set the cursor in the right place
teCursor := t.C
t.C = eh.buf.Cursor
eh.buf.Cursor.Goto(teCursor)
if teCursor.Num >= 0 && teCursor.Num < len(eh.buf.cursors) {
t.C = *eh.buf.cursors[teCursor.Num]
eh.buf.cursors[teCursor.Num].Goto(teCursor)
} else {
teCursor.Num = -1
}
// Push it to the redo stack
eh.RedoStack.Push(t)
@@ -259,8 +263,12 @@ func (eh *EventHandler) RedoOneEvent() {
UndoTextEvent(t, eh.buf)
teCursor := t.C
t.C = eh.buf.Cursor
eh.buf.Cursor.Goto(teCursor)
if teCursor.Num >= 0 && teCursor.Num < len(eh.buf.cursors) {
t.C = *eh.buf.cursors[teCursor.Num]
eh.buf.cursors[teCursor.Num].Goto(teCursor)
} else {
teCursor.Num = -1
}
eh.UndoStack.Push(t)
}

View File

@@ -479,6 +479,11 @@ func (v *View) ExecuteActions(actions []func(*View, bool) bool) bool {
return relocate
}
func (v *View) SetCursor(c *Cursor) {
v.Cursor = c
v.Buf.curCursor = c.Num
}
// HandleEvent handles an event passed by the main loop
func (v *View) HandleEvent(event tcell.Event) {
// This bool determines whether the view is relocated at the end of the function
@@ -500,12 +505,12 @@ func (v *View) HandleEvent(event tcell.Event) {
}
if e.Modifiers() == key.modifiers {
for _, c := range v.Buf.cursors {
v.Cursor = c
v.SetCursor(c)
relocate = false
isBinding = true
relocate = v.ExecuteActions(actions) || relocate
}
v.Cursor = &v.Buf.Cursor
v.SetCursor(&v.Buf.Cursor)
break
}
}
@@ -514,7 +519,7 @@ func (v *View) HandleEvent(event tcell.Event) {
// Check viewtype if readonly don't insert a rune (readonly help and log view etc.)
if v.Type.readonly == false {
for _, c := range v.Buf.cursors {
v.Cursor = c
v.SetCursor(c)
// Insert a character
if v.Cursor.HasSelection() {
@@ -534,7 +539,7 @@ func (v *View) HandleEvent(event tcell.Event) {
curMacro = append(curMacro, e.Rune())
}
}
v.Cursor = &v.Buf.Cursor
v.SetCursor(&v.Buf.Cursor)
}
}
case *tcell.EventPaste:
@@ -545,11 +550,11 @@ func (v *View) HandleEvent(event tcell.Event) {
}
for _, c := range v.Buf.cursors {
v.Cursor = c
v.SetCursor(c)
v.paste(e.Text())
}
v.Cursor = &v.Buf.Cursor
v.SetCursor(&v.Buf.Cursor)
PostActionCall("Paste", v)
}
@@ -562,10 +567,10 @@ func (v *View) HandleEvent(event tcell.Event) {
for key, actions := range bindings {
if button == key.buttons && e.Modifiers() == key.modifiers {
for _, c := range v.Buf.cursors {
v.Cursor = c
v.SetCursor(c)
relocate = v.ExecuteActions(actions) || relocate
}
v.Cursor = &v.Buf.Cursor
v.SetCursor(&v.Buf.Cursor)
}
}
@@ -841,7 +846,7 @@ func (v *View) DisplayView() {
charLoc := char.realLoc
for _, c := range v.Buf.cursors {
v.Cursor = c
v.SetCursor(c)
if v.Cursor.HasSelection() &&
(charLoc.GreaterEqual(v.Cursor.CurSelection[0]) && charLoc.LessThan(v.Cursor.CurSelection[1]) ||
charLoc.LessThan(v.Cursor.CurSelection[0]) && charLoc.GreaterEqual(v.Cursor.CurSelection[1])) {
@@ -853,7 +858,7 @@ func (v *View) DisplayView() {
}
}
}
v.Cursor = &v.Buf.Cursor
v.SetCursor(&v.Buf.Cursor)
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num &&
!v.Cursor.HasSelection() && v.Cursor.Y == realLineN {
@@ -865,14 +870,14 @@ func (v *View) DisplayView() {
screen.SetContent(xOffset+char.visualLoc.X, yOffset+char.visualLoc.Y, char.drawChar, nil, lineStyle)
for i, c := range v.Buf.cursors {
v.Cursor = c
v.SetCursor(c)
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
v.Cursor.Y == char.realLoc.Y && v.Cursor.X == char.realLoc.X && (!cursorSet || i != 0) {
ShowMultiCursor(xOffset+char.visualLoc.X, yOffset+char.visualLoc.Y, i)
cursorSet = true
}
}
v.Cursor = &v.Buf.Cursor
v.SetCursor(&v.Buf.Cursor)
lastChar = char
}
@@ -885,26 +890,26 @@ func (v *View) DisplayView() {
if lastChar != nil {
lastX = xOffset + lastChar.visualLoc.X + lastChar.width
for i, c := range v.Buf.cursors {
v.Cursor = c
v.SetCursor(c)
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
v.Cursor.Y == lastChar.realLoc.Y && v.Cursor.X == lastChar.realLoc.X+1 {
ShowMultiCursor(lastX, yOffset+lastChar.visualLoc.Y, i)
cx, cy = lastX, yOffset+lastChar.visualLoc.Y
}
}
v.Cursor = &v.Buf.Cursor
v.SetCursor(&v.Buf.Cursor)
realLoc = Loc{lastChar.realLoc.X + 1, realLineN}
visualLoc = Loc{lastX - xOffset, lastChar.visualLoc.Y}
} else if len(line) == 0 {
for i, c := range v.Buf.cursors {
v.Cursor = c
v.SetCursor(c)
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
v.Cursor.Y == realLineN {
ShowMultiCursor(xOffset, yOffset+visualLineN, i)
cx, cy = xOffset, yOffset+visualLineN
}
}
v.Cursor = &v.Buf.Cursor
v.SetCursor(&v.Buf.Cursor)
lastX = xOffset
realLoc = Loc{0, realLineN}
visualLoc = Loc{0, visualLineN}