vim: Fix ctrl-u/ctrl-d with high `vertical_scroll_margin` (#16031)

Thorsten Ball and Bennet created

This makes sure that the `vertical_scroll_margin` doesn't leave the
cursor out of screen or somewhere it shouldn't go when it's higher than
the visible lines on screen.

So we cap it to `visible_line_count / 2`, similar to nvim:


https://github.com/neovim/neovim/blob/5aa1a9532cbac835ad027ebdf04311c7e8fb7007/src/nvim/window.c#L6560

Fixes #15101

Release Notes:

- Fixed `ctrl-u`/`ctrl-d` in Vim mode not working correctly when
`vertical_scroll_margin` is set to a really high value.

Co-authored-by: Bennet <bennet@zed.dev>

Change summary

crates/vim/src/normal/scroll.rs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

Detailed changes

crates/vim/src/normal/scroll.rs 🔗

@@ -92,6 +92,9 @@ fn scroll_editor(
             let mut head = selection.head();
             let top = top_anchor.to_display_point(map);
 
+            let vertical_scroll_margin =
+                (vertical_scroll_margin as u32).min(visible_line_count as u32 / 2);
+
             if preserve_cursor_position {
                 let old_top = old_top_anchor.to_display_point(map);
                 let new_row = if old_top.row() == top.row() {
@@ -108,12 +111,12 @@ fn scroll_editor(
             let min_row = if top.row().0 == 0 {
                 DisplayRow(0)
             } else {
-                DisplayRow(top.row().0 + vertical_scroll_margin as u32)
+                DisplayRow(top.row().0 + vertical_scroll_margin)
             };
             let max_row = DisplayRow(
                 top.row().0
                     + (visible_line_count as u32)
-                        .saturating_sub(vertical_scroll_margin as u32)
+                        .saturating_sub(vertical_scroll_margin)
                         .saturating_sub(1),
             );