From e01f9c0e7d9bde4556afea758c828bddd415e937 Mon Sep 17 00:00:00 2001 From: Howard Huang Date: Tue, 11 Jan 2022 21:49:36 -0800 Subject: [PATCH] FEATURE: Allow ScrollByPage f64 values `ScrollByPage` can accept non-integer values in the configuration. This allows fractional page scrolling, such as by half a page. The default remains the same, at 1 page. --- Cargo.lock | 2 ++ config/Cargo.toml | 1 + config/src/keyassignment.rs | 13 ++++++++++--- config/src/lib.rs | 9 +++++++++ docs/config/lua/keyassignment/ScrollByPage.md | 14 ++++++++++++++ wezterm-gui/src/termwindow/mod.rs | 10 +++++----- 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc59d1124..52ec7fddb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -683,6 +683,7 @@ dependencies = [ "mlua", "notify", "open", + "ordered-float", "portable-pty", "pretty_env_logger", "promise", @@ -2674,6 +2675,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" dependencies = [ "num-traits", + "serde", ] [[package]] diff --git a/config/Cargo.toml b/config/Cargo.toml index 9a1a199a3..23a7ff455 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -29,6 +29,7 @@ mlua = {version="0.7", features=["vendored", "lua54", "async", "send"]} # file change notification notify = "4.0" open = "2.0" +ordered-float = { version = "2.10", features = ["serde"] } portable-pty = { path = "../pty", features = ["serde_support"]} promise = { path = "../promise" } serde = {version="1.0", features = ["rc", "derive"]} diff --git a/config/src/keyassignment.rs b/config/src/keyassignment.rs index 5a9b5cf3d..d11bcdf13 100644 --- a/config/src/keyassignment.rs +++ b/config/src/keyassignment.rs @@ -1,7 +1,9 @@ +use crate::de_notnan; use crate::keys::KeyNoAction; use crate::ConfigHandle; use crate::LeaderKey; use luahelper::impl_lua_conversion; +use ordered_float::NotNan; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::PathBuf; @@ -220,7 +222,8 @@ pub enum KeyAssignment { ReloadConfiguration, MoveTabRelative(isize), MoveTab(usize), - ScrollByPage(isize), + #[serde(deserialize_with = "de_notnan")] + ScrollByPage(NotNan), ScrollByLine(isize), ScrollToPrompt(isize), ScrollToTop, @@ -554,11 +557,15 @@ impl InputMap { KeyCode::Physical(PhysKeyCode::PageDown), MoveTabRelative(1) ], - [Modifiers::SHIFT, KeyCode::PageUp, ScrollByPage(-1)], + [ + Modifiers::SHIFT, + KeyCode::PageUp, + ScrollByPage(NotNan::new(-1.0).unwrap()) + ], [ Modifiers::SHIFT, KeyCode::Physical(PhysKeyCode::PageDown), - ScrollByPage(1) + ScrollByPage(NotNan::new(1.0).unwrap()) ], [ Modifiers::ALT, diff --git a/config/src/lib.rs b/config/src/lib.rs index fb66b9242..7ba602185 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -4,6 +4,7 @@ use anyhow::{anyhow, bail, Context, Error}; use lazy_static::lazy_static; use luahelper::impl_lua_conversion; use mlua::Lua; +use ordered_float::NotNan; use serde::{Deserialize, Deserializer, Serialize}; use smol::channel::{Receiver, Sender}; use smol::prelude::*; @@ -661,6 +662,14 @@ impl std::ops::Deref for ConfigHandle { } } +pub(crate) fn de_notnan<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let value: f64 = de_number(deserializer)?; + NotNan::new(value).map_err(|err| serde::de::Error::custom(err.to_string())) +} + /// Deserialize either an integer or a float as a float pub(crate) fn de_number<'de, D>(deserializer: D) -> Result where diff --git a/docs/config/lua/keyassignment/ScrollByPage.md b/docs/config/lua/keyassignment/ScrollByPage.md index 7dbe24c81..2107f5888 100644 --- a/docs/config/lua/keyassignment/ScrollByPage.md +++ b/docs/config/lua/keyassignment/ScrollByPage.md @@ -14,4 +14,18 @@ return { } ``` +*Since: nightly builds only* +You may now use floating point values to scroll by partial pages. This example shows +how to make the `PageUp`/`PageDown` scroll by half a page at a time: + +```lua +local wezterm = require 'wezterm'; + +return { + keys = { + {key="PageUp", mods="SHIFT", action=wezterm.action{ScrollByPage=-0.5}}, + {key="PageDown", mods="SHIFT", action=wezterm.action{ScrollByPage=0.5}}, + } +} +``` diff --git a/wezterm-gui/src/termwindow/mod.rs b/wezterm-gui/src/termwindow/mod.rs index 653a04ba9..83eb44e0e 100644 --- a/wezterm-gui/src/termwindow/mod.rs +++ b/wezterm-gui/src/termwindow/mod.rs @@ -1756,7 +1756,7 @@ impl TermWindow { Ok(()) } - fn scroll_by_page(&mut self, amount: isize) -> anyhow::Result<()> { + fn scroll_by_page(&mut self, amount: f64) -> anyhow::Result<()> { let pane = match self.get_active_pane_or_overlay() { Some(pane) => pane, None => return Ok(()), @@ -1764,9 +1764,9 @@ impl TermWindow { let dims = pane.get_dimensions(); let position = self .get_viewport(pane.pane_id()) - .unwrap_or(dims.physical_top) - .saturating_add(amount * dims.viewport_rows as isize); - self.set_viewport(pane.pane_id(), Some(position), dims); + .unwrap_or(dims.physical_top) as f64 + + (amount * dims.viewport_rows as f64); + self.set_viewport(pane.pane_id(), Some(position as isize), dims); if let Some(win) = self.window.as_ref() { win.invalidate(); } @@ -1925,7 +1925,7 @@ impl TermWindow { ReloadConfiguration => config::reload(), MoveTab(n) => self.move_tab(*n)?, MoveTabRelative(n) => self.move_tab_relative(*n)?, - ScrollByPage(n) => self.scroll_by_page(*n)?, + ScrollByPage(n) => self.scroll_by_page(**n)?, ScrollByLine(n) => self.scroll_by_line(*n)?, ScrollToPrompt(n) => self.scroll_to_prompt(*n)?, ScrollToTop => self.scroll_to_top(pane),