mirror of
https://github.com/Hopiu/micro.git
synced 2026-03-23 01:10:23 +00:00
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:
parent
00718f99cf
commit
21840d3ffe
6 changed files with 58 additions and 23 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -1085,6 +1085,7 @@ function onRune(r, v)
|
|||
-- when converting go structs to lua
|
||||
-- It needs to be dereferenced because the function expects a non pointer struct
|
||||
v.Buf:Insert(-v.Cursor.Loc, charAt(autoclosePairs[i], 2))
|
||||
v:CursorLeft(false)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
|
@ -1107,6 +1108,7 @@ function preInsertNewline(v)
|
|||
v:InsertNewline(false)
|
||||
v:InsertTab(false)
|
||||
v.Buf:Insert(-v.Cursor.Loc, "\n" .. ws)
|
||||
v:CursorLeft(false)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue