]> git.lizzy.rs Git - micro.git/blob - cmd/micro/loc.go
Add support for skipping and remove need for lookbehind
[micro.git] / cmd / micro / loc.go
1 package main
2
3 // FromCharPos converts from a character position to an x, y position
4 func FromCharPos(loc int, buf *Buffer) Loc {
5         charNum := 0
6         x, y := 0, 0
7
8         lineLen := Count(buf.Line(y)) + 1
9         for charNum+lineLen <= loc {
10                 charNum += lineLen
11                 y++
12                 lineLen = Count(buf.Line(y)) + 1
13         }
14         x = loc - charNum
15
16         return Loc{x, y}
17 }
18
19 // ToCharPos converts from an x, y position to a character position
20 func ToCharPos(start Loc, buf *Buffer) int {
21         x, y := start.X, start.Y
22         loc := 0
23         for i := 0; i < y; i++ {
24                 // + 1 for the newline
25                 loc += Count(buf.Line(i)) + 1
26         }
27         loc += x
28         return loc
29 }
30
31 // InBounds returns whether the given location is a valid character position in the given buffer
32 func InBounds(pos Loc, buf *Buffer) bool {
33         if pos.Y < 0 || pos.Y >= buf.NumLines || pos.X < 0 || pos.X > Count(buf.Line(pos.Y)) {
34                 return false
35         }
36
37         return true
38 }
39
40 // ByteOffset is just like ToCharPos except it counts bytes instead of runes
41 func ByteOffset(pos Loc, buf *Buffer) int {
42         x, y := pos.X, pos.Y
43         loc := 0
44         for i := 0; i < y; i++ {
45                 // + 1 for the newline
46                 loc += len(buf.Line(i)) + 1
47         }
48         loc += len(buf.Line(y)[:x])
49         return loc
50 }
51
52 // Loc stores a location
53 type Loc struct {
54         X, Y int
55 }
56
57 // LessThan returns true if b is smaller
58 func (l Loc) LessThan(b Loc) bool {
59         if l.Y < b.Y {
60                 return true
61         }
62         if l.Y == b.Y && l.X < b.X {
63                 return true
64         }
65         return false
66 }
67
68 // GreaterThan returns true if b is bigger
69 func (l Loc) GreaterThan(b Loc) bool {
70         if l.Y > b.Y {
71                 return true
72         }
73         if l.Y == b.Y && l.X > b.X {
74                 return true
75         }
76         return false
77 }
78
79 // GreaterEqual returns true if b is greater than or equal to b
80 func (l Loc) GreaterEqual(b Loc) bool {
81         if l.Y > b.Y {
82                 return true
83         }
84         if l.Y == b.Y && l.X > b.X {
85                 return true
86         }
87         if l == b {
88                 return true
89         }
90         return false
91 }
92
93 // LessEqual returns true if b is less than or equal to b
94 func (l Loc) LessEqual(b Loc) bool {
95         if l.Y < b.Y {
96                 return true
97         }
98         if l.Y == b.Y && l.X < b.X {
99                 return true
100         }
101         if l == b {
102                 return true
103         }
104         return false
105 }
106
107 // This moves the location one character to the right
108 func (l Loc) right(buf *Buffer) Loc {
109         if l == buf.End() {
110                 return Loc{l.X + 1, l.Y}
111         }
112         var res Loc
113         if l.X < Count(buf.Line(l.Y)) {
114                 res = Loc{l.X + 1, l.Y}
115         } else {
116                 res = Loc{0, l.Y + 1}
117         }
118         return res
119 }
120
121 // This moves the given location one character to the left
122 func (l Loc) left(buf *Buffer) Loc {
123         if l == buf.Start() {
124                 return Loc{l.X - 1, l.Y}
125         }
126         var res Loc
127         if l.X > 0 {
128                 res = Loc{l.X - 1, l.Y}
129         } else {
130                 res = Loc{Count(buf.Line(l.Y - 1)), l.Y - 1}
131         }
132         return res
133 }
134
135 // Move moves the cursor n characters to the left or right
136 // It moves the cursor left if n is negative
137 func (l Loc) Move(n int, buf *Buffer) Loc {
138         if n > 0 {
139                 for i := 0; i < n; i++ {
140                         l = l.right(buf)
141                 }
142                 return l
143         }
144         for i := 0; i < Abs(n); i++ {
145                 l = l.left(buf)
146         }
147         return l
148 }