Make cursor movement automatic on insert + remove

This changes the behavior of cursor movement so that all cursors are
adjusted when a change is made to the buffer. Cursors don't have to be
manually moved after calling Insert or Remove, those functions will move
the cursor properly on their own.

This should fix issues 1-3 mentioned in the multiple cursors discussion.

Ref #5
This commit is contained in:
Zachary Yedidia
2017-06-15 18:52:51 -04:00
parent 00718f99cf
commit 21840d3ffe
6 changed files with 58 additions and 23 deletions

View File

@@ -554,7 +554,7 @@ func (v *View) InsertSpace(usePlugin bool) bool {
v.Cursor.ResetSelection()
}
v.Buf.Insert(v.Cursor.Loc, " ")
v.Cursor.Right()
// v.Cursor.Right()
if usePlugin {
return PostActionCall("InsertSpace", v)
@@ -574,15 +574,15 @@ func (v *View) InsertNewline(usePlugin bool) bool {
v.Cursor.ResetSelection()
}
v.Buf.Insert(v.Cursor.Loc, "\n")
ws := GetLeadingWhitespace(v.Buf.Line(v.Cursor.Y))
v.Cursor.Right()
v.Buf.Insert(v.Cursor.Loc, "\n")
// v.Cursor.Right()
if v.Buf.Settings["autoindent"].(bool) {
v.Buf.Insert(v.Cursor.Loc, ws)
for i := 0; i < len(ws); i++ {
v.Cursor.Right()
}
// for i := 0; i < len(ws); i++ {
// v.Cursor.Right()
// }
// Remove the whitespaces if keepautoindent setting is off
if IsSpacesOrTabs(v.Buf.Line(v.Cursor.Y-1)) && !v.Buf.Settings["keepautoindent"].(bool) {
@@ -622,18 +622,10 @@ func (v *View) Backspace(usePlugin bool) bool {
tabSize := int(v.Buf.Settings["tabsize"].(float64))
if v.Buf.Settings["tabstospaces"].(bool) && IsSpaces(lineStart) && len(lineStart) != 0 && len(lineStart)%tabSize == 0 {
loc := v.Cursor.Loc
v.Cursor.Loc = loc.Move(-tabSize, v.Buf)
cx, cy := v.Cursor.X, v.Cursor.Y
v.Cursor.Loc = loc
v.Buf.Remove(loc.Move(-tabSize, v.Buf), loc)
v.Cursor.X, v.Cursor.Y = cx, cy
} else {
v.Cursor.Left()
cx, cy := v.Cursor.X, v.Cursor.Y
v.Cursor.Right()
loc := v.Cursor.Loc
v.Buf.Remove(loc.Move(-1, v.Buf), loc)
v.Cursor.X, v.Cursor.Y = cx, cy
}
}
v.Cursor.LastVisualX = v.Cursor.GetVisualX()
@@ -753,7 +745,6 @@ func (v *View) OutdentLine(usePlugin bool) bool {
break
}
v.Buf.Remove(Loc{0, v.Cursor.Y}, Loc{1, v.Cursor.Y})
v.Cursor.X -= 1
}
v.Cursor.Relocate()
@@ -816,9 +807,9 @@ func (v *View) InsertTab(usePlugin bool) bool {
tabBytes := len(v.Buf.IndentString())
bytesUntilIndent := tabBytes - (v.Cursor.GetVisualX() % tabBytes)
v.Buf.Insert(v.Cursor.Loc, v.Buf.IndentString()[:bytesUntilIndent])
for i := 0; i < bytesUntilIndent; i++ {
v.Cursor.Right()
}
// for i := 0; i < bytesUntilIndent; i++ {
// v.Cursor.Right()
// }
if usePlugin {
return PostActionCall("InsertTab", v)
@@ -1088,7 +1079,7 @@ func (v *View) DuplicateLine(usePlugin bool) bool {
} else {
v.Cursor.End()
v.Buf.Insert(v.Cursor.Loc, "\n"+v.Buf.Line(v.Cursor.Y))
v.Cursor.Right()
// v.Cursor.Right()
}
messenger.Message("Duplicated line")
@@ -1810,7 +1801,7 @@ func (v *View) PlayMacro(usePlugin bool) bool {
v.Cursor.ResetSelection()
}
v.Buf.Insert(v.Cursor.Loc, string(t))
v.Cursor.Right()
// v.Cursor.Right()
for pl := range loadedPlugins {
_, err := Call(pl+".onRune", string(t), v)

View File

@@ -104,6 +104,16 @@ func (eh *EventHandler) Insert(start Loc, text string) {
}
eh.Execute(e)
e.Deltas[0].End = start.Move(Count(text), eh.buf)
end := e.Deltas[0].End
for _, c := range eh.buf.cursors {
if start.Y != end.Y && c.GreaterThan(start) {
c.Loc.Y += end.Y - start.Y
} else if c.Y == start.Y && c.GreaterEqual(start) {
c.Loc = c.Move(Count(text), eh.buf)
}
c.LastVisualX = c.GetVisualX()
}
}
// Remove creates a remove text event and executes it
@@ -115,6 +125,17 @@ func (eh *EventHandler) Remove(start, end Loc) {
Time: time.Now(),
}
eh.Execute(e)
for _, c := range eh.buf.cursors {
if start.Y != end.Y && c.GreaterThan(end) {
c.Loc.Y -= end.Y - start.Y
} else if c.Y == end.Y && c.GreaterEqual(end) {
// TermMessage(start, end)
c.Loc = c.Move(-Diff(start, end, eh.buf), eh.buf)
// c.Loc = c.Move(ToCharPos(start, eh.buf)-ToCharPos(end, eh.buf), eh.buf)
}
c.LastVisualX = c.GetVisualX()
}
}
// MultipleReplace creates an multiple insertions executes them

View File

@@ -54,6 +54,28 @@ type Loc struct {
X, Y int
}
func Diff(a, b Loc, buf *Buffer) int {
if a.Y == b.Y {
if a.X > b.X {
return a.X - b.X
}
return b.X - a.X
}
// Make sure a is guaranteed to be less than b
if b.LessThan(a) {
a, b = b, a
}
loc := 0
for i := a.Y + 1; i < b.Y; i++ {
// + 1 for the newline
loc += Count(buf.Line(i)) + 1
}
loc += Count(buf.Line(a.Y)) - a.X + b.X + 1
return loc
}
// LessThan returns true if b is smaller
func (l Loc) LessThan(b Loc) bool {
if l.Y < b.Y {

File diff suppressed because one or more lines are too long

View File

@@ -169,7 +169,7 @@ func (v *View) paste(clip string) {
}
clip = strings.Replace(clip, "\n", "\n"+leadingWS, -1)
v.Buf.Insert(v.Cursor.Loc, clip)
v.Cursor.Loc = v.Cursor.Loc.Move(Count(clip), v.Buf)
// v.Cursor.Loc = v.Cursor.Loc.Move(Count(clip), v.Buf)
v.freshClip = false
messenger.Message("Pasted clipboard")
}
@@ -522,7 +522,6 @@ func (v *View) HandleEvent(event tcell.Event) {
v.Cursor.ResetSelection()
}
v.Buf.Insert(v.Cursor.Loc, string(e.Rune()))
v.Cursor.Right()
for pl := range loadedPlugins {
_, err := Call(pl+".onRune", string(e.Rune()), v)