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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use buffer::{Position, Range};
/// A more concise expression for ranges spanning complete lines.
#[derive(PartialEq, Debug)]
pub struct LineRange {
start: usize,
end: usize,
}
impl LineRange {
/// Creates a new buffer line range. Checks and swaps
/// arguments in the event that the end precedes the start.
pub fn new(start: usize, end: usize) -> LineRange {
if start < end {
LineRange{ start: start, end: end }
} else {
LineRange{ start: end, end: start }
}
}
pub fn start(&self) -> usize {
self.start
}
pub fn end(&self) -> usize {
self.end
}
/// Converts the line range to a regular, zero-offset range.
///
/// # Examples
///
/// ```
/// use scribe::buffer::{LineRange, Position, Range};
///
/// // Build a line range.
/// let line_range = LineRange::new(10, 14);
///
/// // Ensure that the resulting range is a zero-based equivalent.
/// assert_eq!(line_range.to_range(), Range::new(
/// Position{ line: 10, offset: 0 },
/// Position{ line: 14, offset:0 }
/// ));
/// ```
pub fn to_range(&self) -> Range {
Range::new(
Position{ line: self.start, offset: 0 },
Position{ line: self.end, offset:0 }
)
}
/// Converts the line range to a regular, zero-offset range, including
/// the line on which the range ends.
///
/// # Examples
///
/// ```
/// use scribe::buffer::{LineRange, Position, Range};
///
/// // Build a line range.
/// let line_range = LineRange::new(10, 14);
///
/// // Ensure that the resulting range is a zero-based equivalent.
/// assert_eq!(line_range.to_inclusive_range(), Range::new(
/// Position{ line: 10, offset: 0 },
/// Position{ line: 15, offset:0 }
/// ));
/// ```
pub fn to_inclusive_range(&self) -> Range {
Range::new(
Position{ line: self.start, offset: 0 },
Position{ line: self.end+1, offset:0 }
)
}
/// Whether or not the line range includes the specified line.
/// The range is exclusive, such that its ending line is not included.
///
/// # Examples
///
/// ```
/// use scribe::buffer::LineRange;
///
/// // Build a line range.
/// let line_range = LineRange::new(10, 14);
///
/// assert!(line_range.includes(11));
/// assert!(!line_range.includes(14));
/// ```
pub fn includes(&self, line: usize) -> bool {
line >= self.start() && line < self.end()
}
}
#[cfg(test)]
mod tests {
use super::LineRange;
#[test]
fn new_does_not_swap_values_if_end_does_not_precede_start() {
let range = LineRange::new(0, 1);
assert_eq!(range.start(), 0);
assert_eq!(range.end(), 1);
}
#[test]
fn new_swaps_start_and_end_when_end_precedes_start() {
let range = LineRange::new(1, 0);
assert_eq!(range.start(), 0);
assert_eq!(range.end(), 1);
}
}