diff options
Diffstat (limited to 'src/selection.rs')
-rw-r--r-- | src/selection.rs | 143 |
1 files changed, 34 insertions, 109 deletions
diff --git a/src/selection.rs b/src/selection.rs index f775f1f6..20b1d601 100644 --- a/src/selection.rs +++ b/src/selection.rs @@ -245,127 +245,52 @@ impl Selection { } fn span_simple<G: Dimensions>(grid: &G, region: &Range<Anchor>) -> Option<Span> { - let mut start = region.start.point; + let start = region.start.point; let start_side = region.start.side; - let mut end = region.end.point; + let end = region.end.point; let end_side = region.end.side; let cols = grid.dimensions().col; - // Handle some edge cases - if start.line > end.line { - if end.col > Column(0) { - start.col += 1; - end.col -= 1; - } - // Special case for when a multi-line selection to the - // bottom ends on a new line with just one cell selected - // and the first cell should not be selected - else { - if start_side == Side::Right { - start.col += 1; - } - - // Remove the single selected cell if mouse left window - if end_side == Side::Left { - end.line += 1; - end.col = cols - 1; - } - - return Some(Span { - cols, - front: end, - tail: start, - ty: SpanType::Inclusive, - }); - } - } else if start.line < end.line { - end.col += 1; - if start.col > Column(0) { - start.col -= 1; - } - // Special case for when a selection is started - // in the first cell of a line - else { - let ty = match end_side { - Side::Left => SpanType::ExcludeTail, - Side::Right => SpanType::Inclusive, - }; - - // Switch start cell to last cell of previous line - if start_side == Side::Left { - start.line += 1; - start.col = cols - 1; - } - - return Some(Span { - ty, - cols, - front: start, - tail: end, - }); - } + // No selection for single cell with identical sides or two cell with right+left sides + if (start == end && start_side == end_side) + || (start_side == Side::Right && end_side == Side::Left && end.col == start.col + 1) + { + return None; } - let (front, tail, front_side, tail_side) = if start > end { - // Selected upward; start/end are swapped - (end, start, end_side, start_side) - } else { - // Selected downward; no swapping - (start, end, start_side, end_side) - }; - - debug_assert!(!(tail < front)); - - // Single-cell selections are a special case - if start == end { - if start_side == end_side { - return None; + // Make sure front is always the "bottom" and tail is always the "top" + let (mut front, mut tail, front_side, tail_side) = + if start.line > end.line || start.line == end.line && start.col <= end.col { + // Selected upward; start/end are swapped + (end, start, end_side, start_side) } else { - return Some(Span { - cols, - ty: SpanType::Inclusive, - front, - tail, - }); + // Selected downward; no swapping + (start, end, start_side, end_side) + }; + + // Remove last cell if selection ends to the left of a cell + if front_side == Side::Left && start != end { + if front.col != Column(0) { + front.col -= 1; + } + // Special case when selection starts to left of first cell + else { + front.col = cols - 1; + front.line += 1; } } - // The other special case is two adjacent cells with no - // selection: [ B][E ] or [ E][B ] - let adjacent = tail.line == front.line && tail.col - front.col == Column(1); - if adjacent && front_side == Side::Right && tail_side == Side::Left { - return None; + // Remove first cell if selection starts at the right of a cell + if tail_side == Side::Right && front != tail { + tail.col += 1; } - Some(match (front_side, tail_side) { - // [FX][XX][XT] - (Side::Left, Side::Right) => Span { - cols, - front, - tail, - ty: SpanType::Inclusive - }, - // [ F][XX][T ] - (Side::Right, Side::Left) => Span { - cols, - front, - tail, - ty: SpanType::Exclusive - }, - // [FX][XX][T ] - (Side::Left, Side::Left) => Span { - cols, - front, - tail, - ty: SpanType::ExcludeTail - }, - // [ F][XX][XT] - (Side::Right, Side::Right) => Span { - cols, - front, - tail, - ty: SpanType::ExcludeFront - }, + // Return the selection with all cells inclusive + Some(Span { + cols, + front, + tail, + ty: SpanType::Inclusive, }) } } |