mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Fix ctrl-d/u issues with scroll_beyond_last_line off (#15395)
Closes #15356 Release Notes: - vim: Fixed issues with `ctrl-d`/`ctrl-u` when `scroll_beyond_last_line` is set to `off` ([#15356](https://github.com/zed-industries/zed/issues/15356)). https://github.com/user-attachments/assets/d3166393-4a4e-4195-9db6-3ff1d4aeec78 --------- Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
parent
518dd3ed3a
commit
5e869dadf9
@ -59,7 +59,7 @@ use convert_case::{Case, Casing};
|
|||||||
use debounced_delay::DebouncedDelay;
|
use debounced_delay::DebouncedDelay;
|
||||||
use display_map::*;
|
use display_map::*;
|
||||||
pub use display_map::{DisplayPoint, FoldPlaceholder};
|
pub use display_map::{DisplayPoint, FoldPlaceholder};
|
||||||
pub use editor_settings::{CurrentLineHighlight, EditorSettings};
|
pub use editor_settings::{CurrentLineHighlight, EditorSettings, ScrollBeyondLastLine};
|
||||||
pub use editor_settings_controls::*;
|
pub use editor_settings_controls::*;
|
||||||
use element::LineWithInvisibles;
|
use element::LineWithInvisibles;
|
||||||
pub use element::{
|
pub use element::{
|
||||||
|
@ -505,7 +505,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(visible_lines) = self.visible_line_count() {
|
if let Some(visible_lines) = self.visible_line_count() {
|
||||||
if newest_head.row() < DisplayRow(screen_top.row().0 + visible_lines as u32) {
|
if newest_head.row() <= DisplayRow(screen_top.row().0 + visible_lines as u32) {
|
||||||
return Ordering::Equal;
|
return Ordering::Equal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,7 @@ fn scroll_editor(
|
|||||||
s.move_with(|map, selection| {
|
s.move_with(|map, selection| {
|
||||||
let mut head = selection.head();
|
let mut head = selection.head();
|
||||||
let top = top_anchor.to_display_point(map);
|
let top = top_anchor.to_display_point(map);
|
||||||
|
let starting_column = head.column();
|
||||||
|
|
||||||
let vertical_scroll_margin =
|
let vertical_scroll_margin =
|
||||||
(vertical_scroll_margin as u32).min(visible_line_count as u32 / 2);
|
(vertical_scroll_margin as u32).min(visible_line_count as u32 / 2);
|
||||||
@ -99,7 +100,7 @@ fn scroll_editor(
|
|||||||
let old_top = old_top_anchor.to_display_point(map);
|
let old_top = old_top_anchor.to_display_point(map);
|
||||||
let new_row = if old_top.row() == top.row() {
|
let new_row = if old_top.row() == top.row() {
|
||||||
DisplayRow(
|
DisplayRow(
|
||||||
top.row()
|
head.row()
|
||||||
.0
|
.0
|
||||||
.saturating_add_signed(amount.lines(visible_line_count) as i32),
|
.saturating_add_signed(amount.lines(visible_line_count) as i32),
|
||||||
)
|
)
|
||||||
@ -108,25 +109,25 @@ fn scroll_editor(
|
|||||||
};
|
};
|
||||||
head = map.clip_point(DisplayPoint::new(new_row, head.column()), Bias::Left)
|
head = map.clip_point(DisplayPoint::new(new_row, head.column()), Bias::Left)
|
||||||
}
|
}
|
||||||
|
|
||||||
let min_row = if top.row().0 == 0 {
|
let min_row = if top.row().0 == 0 {
|
||||||
DisplayRow(0)
|
DisplayRow(0)
|
||||||
} else {
|
} else {
|
||||||
DisplayRow(top.row().0 + vertical_scroll_margin)
|
DisplayRow(top.row().0 + vertical_scroll_margin)
|
||||||
};
|
};
|
||||||
let max_row = DisplayRow(
|
let max_row = DisplayRow(map.max_point().row().0.max(top.row().0.saturating_add(
|
||||||
top.row().0
|
(visible_line_count as u32).saturating_sub(1 + vertical_scroll_margin),
|
||||||
+ (visible_line_count as u32)
|
)));
|
||||||
.saturating_sub(vertical_scroll_margin)
|
|
||||||
.saturating_sub(1),
|
|
||||||
);
|
|
||||||
|
|
||||||
let new_head = if head.row() < min_row {
|
let new_row = if head.row() < min_row {
|
||||||
map.clip_point(DisplayPoint::new(min_row, head.column()), Bias::Left)
|
min_row
|
||||||
} else if head.row() > max_row {
|
} else if head.row() > max_row {
|
||||||
map.clip_point(DisplayPoint::new(max_row, head.column()), Bias::Left)
|
max_row
|
||||||
} else {
|
} else {
|
||||||
head
|
head.row()
|
||||||
};
|
};
|
||||||
|
let new_head = map.clip_point(DisplayPoint::new(new_row, starting_column), Bias::Left);
|
||||||
|
|
||||||
if selection.is_empty() {
|
if selection.is_empty() {
|
||||||
selection.collapse_to(new_head, selection.goal)
|
selection.collapse_to(new_head, selection.goal)
|
||||||
} else {
|
} else {
|
||||||
@ -142,9 +143,24 @@ mod test {
|
|||||||
state::Mode,
|
state::Mode,
|
||||||
test::{NeovimBackedTestContext, VimTestContext},
|
test::{NeovimBackedTestContext, VimTestContext},
|
||||||
};
|
};
|
||||||
|
use editor::{EditorSettings, ScrollBeyondLastLine};
|
||||||
use gpui::{point, px, size, Context};
|
use gpui::{point, px, size, Context};
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
use language::Point;
|
use language::Point;
|
||||||
|
use settings::SettingsStore;
|
||||||
|
|
||||||
|
pub fn sample_text(rows: usize, cols: usize, start_char: char) -> String {
|
||||||
|
let mut text = String::new();
|
||||||
|
for row in 0..rows {
|
||||||
|
let c: char = (start_char as u32 + row as u32) as u8 as char;
|
||||||
|
let mut line = c.to_string().repeat(cols);
|
||||||
|
if row < rows - 1 {
|
||||||
|
line.push('\n');
|
||||||
|
}
|
||||||
|
text += &line;
|
||||||
|
}
|
||||||
|
text
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_scroll(cx: &mut gpui::TestAppContext) {
|
async fn test_scroll(cx: &mut gpui::TestAppContext) {
|
||||||
@ -241,18 +257,6 @@ mod test {
|
|||||||
|
|
||||||
cx.set_scroll_height(10).await;
|
cx.set_scroll_height(10).await;
|
||||||
|
|
||||||
pub fn sample_text(rows: usize, cols: usize, start_char: char) -> String {
|
|
||||||
let mut text = String::new();
|
|
||||||
for row in 0..rows {
|
|
||||||
let c: char = (start_char as u32 + row as u32) as u8 as char;
|
|
||||||
let mut line = c.to_string().repeat(cols);
|
|
||||||
if row < rows - 1 {
|
|
||||||
line.push('\n');
|
|
||||||
}
|
|
||||||
text += &line;
|
|
||||||
}
|
|
||||||
text
|
|
||||||
}
|
|
||||||
let content = "ˇ".to_owned() + &sample_text(26, 2, 'a');
|
let content = "ˇ".to_owned() + &sample_text(26, 2, 'a');
|
||||||
cx.set_shared_state(&content).await;
|
cx.set_shared_state(&content).await;
|
||||||
|
|
||||||
@ -277,4 +281,33 @@ mod test {
|
|||||||
.await;
|
.await;
|
||||||
cx.shared_state().await.assert_matches();
|
cx.shared_state().await.assert_matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_scroll_beyond_last_line(cx: &mut gpui::TestAppContext) {
|
||||||
|
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||||
|
|
||||||
|
cx.set_scroll_height(10).await;
|
||||||
|
cx.neovim.set_option(&format!("scrolloff={}", 0)).await;
|
||||||
|
|
||||||
|
let content = "ˇ".to_owned() + &sample_text(26, 2, 'a');
|
||||||
|
cx.set_shared_state(&content).await;
|
||||||
|
|
||||||
|
cx.update_global(|store: &mut SettingsStore, cx| {
|
||||||
|
store.update_user_settings::<EditorSettings>(cx, |s| {
|
||||||
|
s.scroll_beyond_last_line = Some(ScrollBeyondLastLine::Off)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ctrl-d can reach the end and the cursor stays in the first column
|
||||||
|
cx.simulate_shared_keystrokes("shift-g k").await;
|
||||||
|
cx.shared_state().await.assert_matches();
|
||||||
|
cx.simulate_shared_keystrokes("ctrl-d").await;
|
||||||
|
cx.shared_state().await.assert_matches();
|
||||||
|
|
||||||
|
// ctrl-u from the last line
|
||||||
|
cx.simulate_shared_keystrokes("shift-g").await;
|
||||||
|
cx.shared_state().await.assert_matches();
|
||||||
|
cx.simulate_shared_keystrokes("ctrl-u").await;
|
||||||
|
cx.shared_state().await.assert_matches();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
13
crates/vim/test_data/test_scroll_beyond_last_line.json
Normal file
13
crates/vim/test_data/test_scroll_beyond_last_line.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{"SetOption":{"value":"scrolloff=3"}}
|
||||||
|
{"SetOption":{"value":"lines=12"}}
|
||||||
|
{"SetOption":{"value":"scrolloff=0"}}
|
||||||
|
{"Put":{"state":"ˇaa\nbb\ncc\ndd\nee\nff\ngg\nhh\nii\njj\nkk\nll\nmm\nnn\noo\npp\nqq\nrr\nss\ntt\nuu\nvv\nww\nxx\nyy\nzz"}}
|
||||||
|
{"Key":"shift-g"}
|
||||||
|
{"Key":"k"}
|
||||||
|
{"Get":{"state":"aa\nbb\ncc\ndd\nee\nff\ngg\nhh\nii\njj\nkk\nll\nmm\nnn\noo\npp\nqq\nrr\nss\ntt\nuu\nvv\nww\nxx\nˇyy\nzz","mode":"Normal"}}
|
||||||
|
{"Key":"ctrl-d"}
|
||||||
|
{"Get":{"state":"aa\nbb\ncc\ndd\nee\nff\ngg\nhh\nii\njj\nkk\nll\nmm\nnn\noo\npp\nqq\nrr\nss\ntt\nuu\nvv\nww\nxx\nyy\nˇzz","mode":"Normal"}}
|
||||||
|
{"Key":"shift-g"}
|
||||||
|
{"Get":{"state":"aa\nbb\ncc\ndd\nee\nff\ngg\nhh\nii\njj\nkk\nll\nmm\nnn\noo\npp\nqq\nrr\nss\ntt\nuu\nvv\nww\nxx\nyy\nˇzz","mode":"Normal"}}
|
||||||
|
{"Key":"ctrl-u"}
|
||||||
|
{"Get":{"state":"aa\nbb\ncc\ndd\nee\nff\ngg\nhh\nii\njj\nkk\nll\nmm\nnn\noo\npp\nqq\nrr\nss\ntt\nˇuu\nvv\nww\nxx\nyy\nzz","mode":"Normal"}}
|
@ -258,6 +258,8 @@ There are also a few Zed settings that you may also enjoy if you use vim mode:
|
|||||||
"relative_line_numbers": true,
|
"relative_line_numbers": true,
|
||||||
// hide the scroll bar
|
// hide the scroll bar
|
||||||
"scrollbar": { "show": "never" },
|
"scrollbar": { "show": "never" },
|
||||||
|
// prevent the buffer from scrolling beyond the last line
|
||||||
|
"scroll_beyond_last_line": "off",
|
||||||
// allow cursor to reach edges of screen
|
// allow cursor to reach edges of screen
|
||||||
"vertical_scroll_margin": 0,
|
"vertical_scroll_margin": 0,
|
||||||
"gutter": {
|
"gutter": {
|
||||||
|
Loading…
Reference in New Issue
Block a user