vim: Fix % not working for multi-char bracket pairs (#23471)

Thorsten Ball and Conrad created

Closes #23358

Demo/proof:


https://github.com/user-attachments/assets/2036d183-8830-415b-9155-0d3efe3d824c




Release Notes:

- Fixed `%` in Vim mode not working correctly for multi-char brackets,
such as `do/end` in Elixir or `\begin` and `\end` in LaTeX.

Co-authored-by: Conrad <conrad@zed.dev>

Change summary

crates/vim/src/motion.rs | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)

Detailed changes

crates/vim/src/motion.rs 🔗

@@ -2043,17 +2043,21 @@ fn matching(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint
                 }
             }
 
-            if open_range.start >= offset && line_range.contains(&open_range.start) {
-                let distance = open_range.start - offset;
+            if (open_range.contains(&offset) || open_range.start >= offset)
+                && line_range.contains(&open_range.start)
+            {
+                let distance = open_range.start.saturating_sub(offset);
                 if distance < closest_distance {
-                    closest_pair_destination = Some(close_range.end - 1);
+                    closest_pair_destination = Some(close_range.start);
                     closest_distance = distance;
                     continue;
                 }
             }
 
-            if close_range.start >= offset && line_range.contains(&close_range.start) {
-                let distance = close_range.start - offset;
+            if (close_range.contains(&offset) || close_range.start >= offset)
+                && line_range.contains(&close_range.start)
+            {
+                let distance = close_range.start.saturating_sub(offset);
                 if distance < closest_distance {
                     closest_pair_destination = Some(open_range.start);
                     closest_distance = distance;