refactor: name configurable viewport scroll steps accurately

This commit is contained in:
Valdemar Lorenzen
2026-10-16 10:31:36 +02:00
parent 284ddd3713
commit d1048df345
12 changed files with 80 additions and 54 deletions
+24 -24
View File
@@ -644,13 +644,13 @@ core_actions![
&[Mode::Normal, Mode::Visual]
),
(
"core.scroll_half_up",
Action::ScrollHalfUp,
"core.scroll_step_up",
Action::ScrollStepUp,
&[Mode::Normal, Mode::Visual]
),
(
"core.scroll_half_down",
Action::ScrollHalfDown,
"core.scroll_step_down",
Action::ScrollStepDown,
&[Mode::Normal, Mode::Visual]
),
(
@@ -1342,8 +1342,8 @@ fn default_bindings() -> HashMap<Mode, HashMap<Input, Binding>> {
for (key, action) in [
(Input::Ctrl('k'), CloneAbove),
(Input::Ctrl('e'), CloneBelow),
(Input::Ctrl('u'), ScrollHalfUp),
(Input::Ctrl('d'), ScrollHalfDown),
(Input::Ctrl('u'), ScrollStepUp),
(Input::Ctrl('d'), ScrollStepDown),
(Input::Escape, Normal),
] {
bindings
@@ -2009,7 +2009,7 @@ pub struct Editor {
popup: PopupConfig,
labels: BTreeMap<String, String>,
scroll_distance: Option<usize>,
scroll_half_page_lines: Option<NonZeroUsize>,
scroll_step_lines: Option<NonZeroUsize>,
highlight_trailing_whitespace: bool,
whitespace_characters: BTreeMap<char, char>,
whitespace_scope: WhitespaceScope,
@@ -2120,7 +2120,7 @@ impl Editor {
popup: PopupConfig::default(),
labels: BTreeMap::new(),
scroll_distance: Some(0),
scroll_half_page_lines: None,
scroll_step_lines: None,
highlight_trailing_whitespace: false,
whitespace_characters: BTreeMap::new(),
whitespace_scope: WhitespaceScope::All,
@@ -4118,8 +4118,8 @@ impl Editor {
self.scroll_distance = distance;
}
pub(crate) fn set_scroll_half_page_lines(&mut self, lines: Option<NonZeroUsize>) {
self.scroll_half_page_lines = lines;
pub(crate) fn set_scroll_step_lines(&mut self, lines: Option<NonZeroUsize>) {
self.scroll_step_lines = lines;
}
pub(crate) fn highlight_trailing_whitespace(&self) -> bool {
@@ -4465,8 +4465,8 @@ impl Editor {
| Action::Up
| Action::ScrollUp
| Action::ScrollDown
| Action::ScrollHalfUp
| Action::ScrollHalfDown
| Action::ScrollStepUp
| Action::ScrollStepDown
| Action::LineStart
| Action::LineEnd
| Action::DocumentStart
@@ -4487,8 +4487,8 @@ impl Editor {
Binding::Action(
action @ (Action::ScrollUp
| Action::ScrollDown
| Action::ScrollHalfUp
| Action::ScrollHalfDown),
| Action::ScrollStepUp
| Action::ScrollStepDown),
) => Some(action.entry().name),
_ => None,
}
@@ -5834,12 +5834,12 @@ impl Editor {
}
pub(crate) fn take_viewport_scroll(&self, height: usize) -> isize {
let (rows, halves) = self.active.view.viewport_scroll.take();
let (rows, steps) = self.active.view.viewport_scroll.take();
let lines = self
.scroll_half_page_lines
.scroll_step_lines
.map_or((height / 2).max(1), NonZeroUsize::get);
let lines = isize::try_from(lines).unwrap_or(isize::MAX);
rows.saturating_add(halves.saturating_mul(lines))
rows.saturating_add(steps.saturating_mul(lines))
}
fn reveal_caret(&mut self) {
@@ -8305,22 +8305,22 @@ impl Editor {
Action::JumpForward => self.traverse_jumps(true, count),
Action::ScrollUp
| Action::ScrollDown
| Action::ScrollHalfUp
| Action::ScrollHalfDown => {
| Action::ScrollStepUp
| Action::ScrollStepDown => {
if self.document_actions_available() {
let amount = isize::try_from(count).unwrap_or(isize::MAX);
let amount = if matches!(action, Action::ScrollUp | Action::ScrollHalfUp) {
let amount = if matches!(action, Action::ScrollUp | Action::ScrollStepUp) {
-amount
} else {
amount
};
let (mut rows, mut halves) = self.active.view.viewport_scroll.get();
if matches!(action, Action::ScrollHalfUp | Action::ScrollHalfDown) {
halves = halves.saturating_add(amount);
let (mut rows, mut steps) = self.active.view.viewport_scroll.get();
if matches!(action, Action::ScrollStepUp | Action::ScrollStepDown) {
steps = steps.saturating_add(amount);
} else {
rows = rows.saturating_add(amount);
}
self.active.view.viewport_scroll.set((rows, halves));
self.active.view.viewport_scroll.set((rows, steps));
if let Some(diff) = self.interaction_diff_mut() {
diff.follow_caret = false;
}
+24 -10
View File
@@ -46,7 +46,7 @@ pub struct Config {
pub popup: PopupConfig,
pub labels: BTreeMap<String, String>,
pub scroll_distance: Option<usize>,
pub scroll_half_page_lines: Option<NonZeroUsize>,
pub scroll_step_lines: Option<NonZeroUsize>,
pub highlight_trailing_whitespace: bool,
pub whitespace_characters: BTreeMap<char, char>,
pub whitespace_scope: crate::editor::WhitespaceScope,
@@ -98,7 +98,7 @@ impl Default for Config {
popup: PopupConfig::default(),
labels: BTreeMap::new(),
scroll_distance: Some(0),
scroll_half_page_lines: None,
scroll_step_lines: None,
highlight_trailing_whitespace: false,
whitespace_characters: BTreeMap::new(),
whitespace_scope: crate::editor::WhitespaceScope::All,
@@ -137,7 +137,7 @@ pub fn load_config(path: &Path) -> Result<Config, String> {
popup,
labels,
scroll_distance,
scroll_half_page_lines,
scroll_step_lines,
highlight_trailing_whitespace,
whitespace_characters,
whitespace_scope,
@@ -177,7 +177,7 @@ pub fn load_config(path: &Path) -> Result<Config, String> {
config.popup = popup;
config.labels = labels;
config.scroll_distance = scroll_distance;
config.scroll_half_page_lines = scroll_half_page_lines;
config.scroll_step_lines = scroll_step_lines;
config.highlight_trailing_whitespace = highlight_trailing_whitespace;
config.whitespace_characters = whitespace_characters;
config.whitespace_scope = whitespace_scope;
@@ -516,7 +516,7 @@ struct ConfigFrame {
labels: BTreeMap<String, String>,
#[serde(deserialize_with = "scroll_distance")]
scroll_distance: Option<usize>,
scroll_half_page_lines: Option<NonZeroUsize>,
scroll_step_lines: Option<NonZeroUsize>,
highlight_trailing_whitespace: bool,
#[serde(deserialize_with = "whitespace_characters")]
whitespace_characters: BTreeMap<char, char>,
@@ -1935,7 +1935,7 @@ end
}
#[test]
fn config_scroll_half_page_lines_controls_counted_scrolling_and_rejects_invalid_values() {
fn config_scroll_step_lines_controls_counted_scrolling_and_rejects_invalid_values() {
let fixture = Fixture::new();
for (value, expected) in [
("nil", 30),
@@ -1945,17 +1945,31 @@ end
] {
let path = fixture.file(
"config.rb",
&format!("Vamp.configure {{ |config| config.scroll_half_page_lines = {value} }}"),
&format!(
"Vamp.configure do |config|
config.scroll_step_lines = {value}
config.bind \"alt+j\", config.core.scroll_step_down
config.bind \"alt+k\", config.core.scroll_step_up
end"
),
);
let mut session =
crate::session::EditorSession::open(None, vec![], Some(&path)).unwrap();
session.handle(crate::editor::Input::Char('3'));
session.handle(crate::editor::Input::Ctrl('d'));
session.handle(crate::editor::Input::Alt('j'));
assert_eq!(
session.editor().take_viewport_scroll(20),
expected,
"{value}"
);
session.handle(crate::editor::Input::Char('3'));
session.handle(crate::editor::Input::Alt('k'));
let up = if expected == isize::MAX {
isize::MIN
} else {
-expected
};
assert_eq!(session.editor().take_viewport_scroll(20), up, "{value}");
}
for value in [
"0",
@@ -1968,11 +1982,11 @@ end
] {
let path = fixture.file(
"config.rb",
&format!("Vamp.configure {{ |config| config.scroll_half_page_lines = {value} }}"),
&format!("Vamp.configure {{ |config| config.scroll_step_lines = {value} }}"),
);
let error = load_config(&path).unwrap_err();
assert!(
error.contains("scroll_half_page_lines") && error.contains("must be"),
error.contains("scroll_step_lines") && error.contains("must be"),
"{value}: {error}"
);
}
+4 -4
View File
@@ -145,7 +145,7 @@ module Vamp
@popup = PopupConfig.new
@labels = {}
@scroll_distance = 0
@scroll_half_page_lines = nil
@scroll_step_lines = nil
@highlight_trailing_whitespace = false
@whitespace_characters = {}
@whitespace_scope = "all"
@@ -232,8 +232,8 @@ module Vamp
# @param lines [Integer, nil] positive screen rows, or nil for half the viewport
# @return [Integer, nil]
def scroll_half_page_lines=(lines)
@scroll_half_page_lines = lines.nil? ? nil : diff_line_count!(lines, "scroll_half_page_lines", 1)
def scroll_step_lines=(lines)
@scroll_step_lines = lines.nil? ? nil : diff_line_count!(lines, "scroll_step_lines", 1)
end
# @param enabled [Boolean]
@@ -350,7 +350,7 @@ module Vamp
"git_blame" => @git_blame,
"git_gutter" => @git_gutter,
"scroll_distance" => @scroll_distance,
"scroll_half_page_lines" => @scroll_half_page_lines,
"scroll_step_lines" => @scroll_step_lines,
"highlight_trailing_whitespace" => @highlight_trailing_whitespace,
"whitespace_characters" => @whitespace_characters,
"whitespace_scope" => @whitespace_scope,
+1 -1
View File
@@ -512,7 +512,7 @@ impl EditorSession {
editor.set_git_blame(config.git_blame);
editor.set_gutter_style(config.git_gutter);
editor.set_scroll_distance(config.scroll_distance);
editor.set_scroll_half_page_lines(config.scroll_half_page_lines);
editor.set_scroll_step_lines(config.scroll_step_lines);
editor.set_highlight_trailing_whitespace(config.highlight_trailing_whitespace);
editor.set_whitespace_characters(config.whitespace_characters);
editor.set_whitespace_scope(config.whitespace_scope);
+1 -1
View File
@@ -12617,7 +12617,7 @@ end
editor.handle(Input::Ctrl('u'));
render(&mut terminal, &mut views, &mut editor);
assert_eq!(offset(&views), initial);
editor.set_scroll_half_page_lines(std::num::NonZeroUsize::new(3));
editor.set_scroll_step_lines(std::num::NonZeroUsize::new(3));
editor.handle(Input::Char('2'));
editor.handle(Input::Ctrl('d'));
render(&mut terminal, &mut views, &mut editor);