diff --git a/crates/vim/src/visual.rs b/crates/vim/src/visual.rs index bce49eb7d4a3c21b00a8076f0474d9da591cc993..59555205d9862e51c2778eec1f321338fd5e7569 100644 --- a/crates/vim/src/visual.rs +++ b/crates/vim/src/visual.rs @@ -366,6 +366,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); @@ -396,13 +398,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 = map .start_of_relative_buffer_row(DisplayPoint::new(row, 0), direction) .row();