vim: Fix ap text object selection when there is line wrapping (#35485)

In Vim mode, `ap` text object (used in `vap`, `dap`, `cap`) was
selecting multiple paragraphs when soft wrap was enabled. The bug was
caused by using DisplayRow coordinates for arithmetic instead of buffer
row coordinates in the paragraph boundary calculation.

Fix by converting to buffer coordinates before arithmetic, then back to
display coordinates for the final result.

Closes #35085

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
Lucas Vieira
2025-08-18 09:57:53 -06:00
committed by GitHub
co-authored by Conrad Irwin
parent e1d31cfcc3
commit 768b2de368
7 changed files with 365 additions and 4 deletions
+33
View File
@@ -414,6 +414,8 @@ impl Vim {
);
}
let original_point = selection.tail().to_point(&map);
if let Some(range) = object.range(map, mut_selection, around, count) {
if !range.is_empty() {
let expand_both_ways = object.always_expands_both_ways()
@@ -462,6 +464,37 @@ impl Vim {
};
selection.end = new_selection_end.to_display_point(map);
}
// To match vim, if the range starts of the same line as it originally
// did, we keep the tail of the selection in the same place instead of
// snapping it to the start of the line
if target_mode == Mode::VisualLine {
let new_start_point = selection.start.to_point(map);
if new_start_point.row == original_point.row {
if selection.end.to_point(map).row > new_start_point.row {
if original_point.column
== map
.buffer_snapshot
.line_len(MultiBufferRow(original_point.row))
{
selection.start = movement::saturating_left(
map,
original_point.to_display_point(map),
)
} else {
selection.start = original_point.to_display_point(map)
}
} else {
selection.end = movement::saturating_right(
map,
original_point.to_display_point(map),
);
if original_point.column > 0 {
selection.reversed = true
}
}
}
}
}
});
});