return loc
}
+// InBounds returns whether the given location is a valid character position in the given buffer
+func InBounds(pos Loc, buf *Buffer) bool {
+ if pos.Y < 0 || pos.Y >= buf.NumLines || pos.X < 0 || pos.X > Count(buf.Line(pos.Y)) {
+ return false
+ }
+
+ return true
+}
+
+// ByteOffset is just like ToCharPos except it counts bytes instead of runes
+func ByteOffset(pos Loc, buf *Buffer) int {
+ x, y := pos.X, pos.Y
+ loc := 0
+ for i := 0; i < y; i++ {
+ // + 1 for the newline
+ loc += len(buf.Line(i)) + 1
+ }
+ loc += len(buf.Line(y)[:x])
+ return loc
+}
+
// Loc stores a location
type Loc struct {
X, Y int
}
+// Diff returns the distance between two locations
+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 {
return false
}
+// This moves the location one character to the right
func (l Loc) right(buf *Buffer) Loc {
if l == buf.End() {
- return l
+ return Loc{l.X + 1, l.Y}
}
var res Loc
if l.X < Count(buf.Line(l.Y)) {
}
return res
}
+
+// This moves the given location one character to the left
func (l Loc) left(buf *Buffer) Loc {
if l == buf.Start() {
- return l
+ return Loc{l.X - 1, l.Y}
}
var res Loc
if l.X > 0 {
return res
}
+// Move moves the cursor n characters to the left or right
+// It moves the cursor left if n is negative
func (l Loc) Move(n int, buf *Buffer) Loc {
if n > 0 {
for i := 0; i < n; i++ {
}
return l
}
- for i := 0; i < n; i++ {
- return l.left(buf)
+ for i := 0; i < Abs(n); i++ {
+ l = l.left(buf)
}
return l
}
-
-// func (l Loc) DistanceTo(b Loc, buf *Buffer) int {
-//
-// }