This Pull Request introduces various changes to the editor's horizontal scrolling, mostly focused on vim mode's horizontal scroll motions (`z l`, `z h`, `z shift-l`, `z shift-h`). In order to make it easier to review, the logical changes have been split into different sections. ## Cursor Position Update Changes introduced on https://github.com/zed-industries/zed/pull/32558 added both `z l` and `z h` to vim mode but it only scrolled the editor's content, without changing the cursor position. This doesn't reflect the actual behavior of those motions in vim, so these two commits tackled that, ensuring that the cursor position is updated, only when the cursor is on the left or right edges of the editor: - https://github.com/zed-industries/zed/commit/ea3b866a763ba0bcfc12999ee1741c6528c895b7 - https://github.com/zed-industries/zed/commit/805f41a913c6e86ef8be550d363a3cc2caeccbe9 ## Horizontal Autoscroll Fix After introducing the cursor position update to both `z l` and `z h` it was noted that there was a bug with using `z l`, followed by `0` and then `z l` again, as on the second use `z l` the cursor would not be updated. This would only happen on the first line in the editor, and it was concluded that it was because the `editor::scroll::autoscroll::Editor.autoscroll_horizontally` method was directly updating the scroll manager's anchor offset, instead of using the `editor::scroll::Editor.set_scroll_position_internal` method, like is being done by the vertical autoscroll (`editor::scroll::autoscroll::Editor.autoscroll_vertically`). This wouldn't update the scroll manager's anchor, which would still think it was at `(0, 1)` so the cursor position would not be updated. The changes in [this commit](https://github.com/zed-industries/zed/commit/3957f02e189018ef559cd28516f0b872026b0ce1) updated the horizontal autoscrolling method to also leverage `set_scroll_position_internal`. ## Visible Column Count & Page Width Scroll Amount The changes in https://github.com/zed-industries/zed/commit/d83652c3ae1d0356fd7dca7b8922a0116de39ff0 add a `visible_column_count` field to `editor::scroll::ScrollManager` struct, which allowed the introduction of the `ScrollAmount::PageWidth` enum. With these changes, two new actions are introduced, `vim::normal::scroll::HalfPageRight` and `vim::normal::scroll::HalfPageLeft` (in https://github.com/zed-industries/zed/commit/7f344304d56337654a34b1b461a1dc69defd2e4e), which move the editor half page to the right and half page to the left, as well as the cursor position, which have also been mapped to `z shift-l` and `z shift-h`, respectively. Closes #17219 Release Notes: - Improved `z l` and `z h` to actually move the cursor position, similar to vim's behavior - Added `z shift-l` and `z shift-h` to scroll half of the page width's to the right or to the left, respectively --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
86 lines
2.8 KiB
Rust
86 lines
2.8 KiB
Rust
use serde::Deserialize;
|
|
use ui::{Pixels, px};
|
|
|
|
#[derive(Debug)]
|
|
pub enum ScrollDirection {
|
|
Upwards,
|
|
Downwards,
|
|
Rightwards,
|
|
Leftwards,
|
|
}
|
|
|
|
impl ScrollDirection {
|
|
pub fn is_upwards(&self) -> bool {
|
|
matches!(self, ScrollDirection::Upwards)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
pub enum ScrollAmount {
|
|
// Scroll N lines (positive is towards the end of the document)
|
|
Line(f32),
|
|
// Scroll N pages (positive is towards the end of the document)
|
|
Page(f32),
|
|
// Scroll N columns (positive is towards the right of the document)
|
|
Column(f32),
|
|
// Scroll N page width (positive is towards the right of the document)
|
|
PageWidth(f32),
|
|
}
|
|
|
|
impl ScrollAmount {
|
|
pub fn lines(&self, mut visible_line_count: f32) -> f32 {
|
|
match self {
|
|
Self::Line(count) => *count,
|
|
Self::Page(count) => {
|
|
// for full pages subtract one to leave an anchor line
|
|
if self.is_full_page() {
|
|
visible_line_count -= 1.0
|
|
}
|
|
(visible_line_count * count).trunc()
|
|
}
|
|
Self::Column(_count) => 0.0,
|
|
Self::PageWidth(_count) => 0.0,
|
|
}
|
|
}
|
|
|
|
pub fn columns(&self, visible_column_count: f32) -> f32 {
|
|
match self {
|
|
Self::Line(_count) => 0.0,
|
|
Self::Page(_count) => 0.0,
|
|
Self::Column(count) => *count,
|
|
Self::PageWidth(count) => (visible_column_count * count).trunc(),
|
|
}
|
|
}
|
|
|
|
pub fn pixels(&self, line_height: Pixels, height: Pixels) -> Pixels {
|
|
match self {
|
|
ScrollAmount::Line(x) => px(line_height.0 * x),
|
|
ScrollAmount::Page(x) => px(height.0 * x),
|
|
// This function seems to only be leveraged by the popover that is
|
|
// displayed by the editor when, for example, viewing a function's
|
|
// documentation. Right now that only supports vertical scrolling,
|
|
// so I'm leaving this at 0.0 for now to try and make it clear that
|
|
// this should not have an impact on that?
|
|
ScrollAmount::Column(_) => px(0.0),
|
|
ScrollAmount::PageWidth(_) => px(0.0),
|
|
}
|
|
}
|
|
|
|
pub fn is_full_page(&self) -> bool {
|
|
match self {
|
|
ScrollAmount::Page(count) if count.abs() == 1.0 => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
|
|
pub fn direction(&self) -> ScrollDirection {
|
|
match self {
|
|
Self::Line(amount) if amount.is_sign_positive() => ScrollDirection::Downwards,
|
|
Self::Page(amount) if amount.is_sign_positive() => ScrollDirection::Downwards,
|
|
Self::Column(amount) if amount.is_sign_positive() => ScrollDirection::Rightwards,
|
|
Self::Column(amount) if amount.is_sign_negative() => ScrollDirection::Leftwards,
|
|
_ => ScrollDirection::Upwards,
|
|
}
|
|
}
|
|
}
|