1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
// Package buffer holds the text of one edited file, together with the cursor,
// the selection and the undo history.
//
// It knows nothing about terminals, rendering or syntax colouring: everything
// here is plain data manipulation, which makes it fully testable on its own.
// Positions are expressed in runes, never in bytes, so that accented letters
// and CJK characters count as one column like any other character.
package buffer
// Position is a place in the text, as a zero-based line number and a
// zero-based column counted in runes.
//
// A column equal to the line length is legal: it is the position just after
// the last character, where the cursor sits when you press End.
type Position struct {
Line int
Col int
}
// Before reports whether p comes strictly earlier in the text than other.
func (p Position) Before(other Position) bool {
if p.Line != other.Line {
return p.Line < other.Line
}
return p.Col < other.Col
}
// After reports whether p comes strictly later in the text than other.
func (p Position) After(other Position) bool {
return other.Before(p)
}
// Range is a half-open span of text: Start is included, End is excluded.
//
// A range whose Start equals its End is empty and covers no character; that is
// how an insertion point is expressed.
type Range struct {
Start Position
End Position
}
// NewRange returns the range covering a and b, whichever of the two comes
// first in the text. Use it when a range is built from two user-supplied
// points, such as a selection anchor and the cursor.
func NewRange(a, b Position) Range {
if b.Before(a) {
return Range{Start: b, End: a}
}
return Range{Start: a, End: b}
}
// IsEmpty reports whether the range covers no character at all.
func (r Range) IsEmpty() bool {
return r.Start == r.End
}
// Contains reports whether p falls inside the range. The start is included and
// the end is excluded, so an empty range contains nothing.
func (r Range) Contains(p Position) bool {
return !p.Before(r.Start) && p.Before(r.End)
}
|