diff --git a/crates/vim/src/visual.rs b/crates/vim/src/visual.rs index f8ef8e32586ca11800b5d3872aafaead3275bd37..455061c22b2231847151d4d9c92a296075ae3593 100644 --- a/crates/vim/src/visual.rs +++ b/crates/vim/src/visual.rs @@ -369,6 +369,8 @@ impl Vim { let mut selections = Vec::new(); let mut row = tail.row(); + let going_up = tail.row() > head.row(); + let direction = if going_up { -1 } else { 1 }; loop { let laid_out_line = map.layout_row(row, &text_layout_details); @@ -399,13 +401,18 @@ impl Vim { selections.push(selection); } - if row == head.row() { + + // When dealing with soft wrapped lines, it's possible that + // `row` ends up being set to a value other than `head.row()` as + // `head.row()` might be a `DisplayPoint` mapped to a soft + // wrapped line, hence the need for `<=` and `>=` instead of + // `==`. + if going_up && row <= head.row() || !going_up && row >= head.row() { break; } - // Move to the next or previous buffer row, ensuring that - // wrapped lines are handled correctly. - let direction = if tail.row() > head.row() { -1 } else { 1 }; + // Find the next or previous buffer row where the `row` should + // be moved to, so that wrapped lines are skipped. row = start_of_relative_buffer_row(map, DisplayPoint::new(row, 0), direction).row(); }