diff --git a/src/lines.rs b/src/lines.rs index 80ce02b73..abf2d35df 100644 --- a/src/lines.rs +++ b/src/lines.rs @@ -74,82 +74,66 @@ impl NewlinePositions { } } - /// Convert absolute string ranges to line-relative ranges. If the - /// absolute range crosses a newline, split it into multiple - /// line-relative ranges. - pub fn from_ranges(self: &NewlinePositions, ranges: &[Range]) -> Vec { - let mut rel_positions = vec![]; - for range in ranges { - let start_pos = line_position(range.start, &self.positions); - let end_pos = line_position(range.end, &self.positions); - - rel_positions.extend(split_line_boundaries(start_pos, end_pos, &self.positions)); + // Given a range within a string, split it into ranges where each + // range is on a single line. + fn split_line_boundaries( + self: &NewlinePositions, + start: LinePosition, + end: LinePosition, + ) -> Vec { + let mut ranges = vec![]; + + if start.line == end.line { + ranges.push(LineRange { + line: start.line, + start: start.column, + end: end.column, + }); + return ranges; + } else { + let first_line_end_pos = self.positions[start.line.number + 1] - 1; + let first_line_length = first_line_end_pos - self.positions[start.line.number]; + ranges.push(LineRange { + line: start.line, + start: start.column, + end: first_line_length, + }); } - rel_positions - } -} - -fn line_position(offset: usize, newline_positions: &[usize]) -> LinePosition { - for line_num in (0..newline_positions.len()).rev() { - if offset > newline_positions[line_num as usize] { - return LinePosition { - line: LineNumber::from(line_num as usize), - column: offset - newline_positions[line_num as usize], - }; + for line_num in (start.line.number + 1)..end.line.number { + let line_end_pos = self.positions[line_num + 1] - 1; + let line_length = line_end_pos - self.positions[line_num]; + ranges.push(LineRange { + line: LineNumber::from(line_num), + start: 0, + end: line_length, + }); } - } - - LinePosition { - line: LineNumber::from(0), - column: offset, - } -} - -// Given a range within a string, split it into ranges where each -// range is on a single line. -fn split_line_boundaries( - start: LinePosition, - end: LinePosition, - line_start_positions: &[usize], -) -> Vec { - let mut ranges = vec![]; - if start.line == end.line { + // Last line, up to end. ranges.push(LineRange { - line: start.line, - start: start.column, + line: end.line, + start: 0, end: end.column, }); - return ranges; - } else { - let first_line_end_pos = line_start_positions[start.line.number + 1] - 1; - let first_line_length = first_line_end_pos - line_start_positions[start.line.number]; - ranges.push(LineRange { - line: start.line, - start: start.column, - end: first_line_length, - }); - } - for line_num in (start.line.number + 1)..end.line.number { - let line_end_pos = line_start_positions[line_num + 1] - 1; - let line_length = line_end_pos - line_start_positions[line_num]; - ranges.push(LineRange { - line: LineNumber::from(line_num), - start: 0, - end: line_length, - }); + ranges } - // Last line, up to end. - ranges.push(LineRange { - line: end.line, - start: 0, - end: end.column, - }); + /// Convert absolute string ranges to line-relative ranges. If the + /// absolute range crosses a newline, split it into multiple + /// line-relative ranges. + pub fn from_ranges(self: &NewlinePositions, ranges: &[Range]) -> Vec { + let mut rel_positions = vec![]; + for range in ranges { + let start_pos = self.from_offset(range.start); + let end_pos = self.from_offset(range.end); - ranges + rel_positions.extend(self.split_line_boundaries(start_pos, end_pos)); + } + + rel_positions + } } #[test]