Add vim-like page scrolling

* feat: added match fallback for handle_command SelectViewExt

* feat: HalfPage and FullPage MoveAmount variants

* feat: Display for MoveAmount variants

* feat: fallback for MoveAmount variants in TabView

* feat: ListView FullPage/HalfPage MoveAmount

* feat: default keybinds for page scrolling

* feat: HalfPage/FullPage MoveAmount for HelpView

* feat: removed new defaul keybinds for pagescroll

* style: "upwards" -> "halfpageup" etc.

* feat: toml parse "move pageup" / "move halfpageup"

* chore: cargo fmt

* feat: simplified page scroll command interface

* docs: added `move` to readme

* feat: replace FullPage and HalfPage with Float variant

* fix: remove stray variant

* dosc: update move command

* chore: fmt

* feat: implement MoveAmount::Float for selectview

* chore: fmt
This commit is contained in:
BlakeJC94
2023-03-12 23:26:00 +11:00
committed by GitHub
parent dc2f42fd07
commit 1a0258f197
6 changed files with 53 additions and 4 deletions

View File

@@ -33,6 +33,7 @@ pub enum MoveMode {
#[strum(serialize_all = "lowercase")]
pub enum MoveAmount {
Integer(i32),
Float(f32),
Extreme,
}
@@ -186,6 +187,7 @@ impl fmt::Display for Command {
(MoveMode::Down, MoveAmount::Extreme) => vec!["bottom".to_string()],
(MoveMode::Left, MoveAmount::Extreme) => vec!["leftmost".to_string()],
(MoveMode::Right, MoveAmount::Extreme) => vec!["rightmost".to_string()],
(mode, MoveAmount::Float(amount)) => vec![mode.to_string(), amount.to_string()],
(mode, MoveAmount::Integer(amount)) => vec![mode.to_string(), amount.to_string()],
},
Command::Shift(mode, amount) => vec![mode.to_string(), amount.unwrap_or(1).to_string()],
@@ -562,10 +564,10 @@ pub fn parse(input: &str) -> Result<Vec<Command>, CommandParseError> {
use MoveMode::*;
match move_mode_raw {
"playing" => Ok(Playing),
"top" | "up" => Ok(Up),
"bottom" | "down" => Ok(Down),
"leftmost" | "left" => Ok(Left),
"rightmost" | "right" => Ok(Right),
"top" | "pageup" | "up" => Ok(Up),
"bottom" | "pagedown" | "down" => Ok(Down),
"leftmost" | "pageleft" | "left" => Ok(Left),
"rightmost" | "pageright" | "right" => Ok(Right),
_ => Err(BadEnumArg {
arg: move_mode_raw.into(),
accept: vec![
@@ -574,6 +576,10 @@ pub fn parse(input: &str) -> Result<Vec<Command>, CommandParseError> {
"bottom".into(),
"leftmost".into(),
"rightmost".into(),
"pageup".into(),
"pagedown".into(),
"pageleft".into(),
"pageright".into(),
"up".into(),
"down".into(),
"left".into(),
@@ -585,6 +591,19 @@ pub fn parse(input: &str) -> Result<Vec<Command>, CommandParseError> {
let move_amount = match move_mode_raw {
"playing" => Ok(MoveAmount::default()),
"top" | "bottom" | "leftmost" | "rightmost" => Ok(MoveAmount::Extreme),
"pageup" | "pagedown" | "pageleft" | "pageright" => {
let amount = match args.get(1) {
Some(&amount_raw) => amount_raw
.parse::<f32>()
.map(MoveAmount::Float)
.map_err(|err| ArgParseError {
arg: amount_raw.into(),
err: err.to_string(),
})?,
None => MoveAmount::default(),
};
Ok(amount)
}
"up" | "down" | "left" | "right" => {
let amount = match args.get(1) {
Some(&amount_raw) => amount_raw

View File

@@ -1,4 +1,5 @@
use cursive::views::ViewRef;
use cursive::{View, XY};
use crate::command::{Command, MoveAmount, MoveMode};
use crate::commands::CommandResult;
@@ -37,6 +38,10 @@ impl<T: 'static> SelectViewExt for cursive::views::SelectView<T> {
MoveMode::Up => {
match amount {
MoveAmount::Extreme => self.set_selection(0),
MoveAmount::Float(scale) => {
let amount = (*self).required_size(XY::default()).y as f32 * scale;
self.select_up(amount as usize)
}
MoveAmount::Integer(amount) => self.select_up(*amount as usize),
};
Ok(CommandResult::Consumed(None))
@@ -44,6 +49,10 @@ impl<T: 'static> SelectViewExt for cursive::views::SelectView<T> {
MoveMode::Down => {
match amount {
MoveAmount::Extreme => self.set_selection(items),
MoveAmount::Float(scale) => {
let amount = (*self).required_size(XY::default()).y as f32 * scale;
self.select_down(amount as usize)
}
MoveAmount::Integer(amount) => self.select_down(*amount as usize),
};
Ok(CommandResult::Consumed(None))

View File

@@ -70,6 +70,11 @@ impl ViewExt for HelpView {
MoveAmount::Extreme => {
self.view.scroll_to_top();
}
MoveAmount::Float(scale) => {
let amount = (viewport.height() as f32) * scale;
scroller
.scroll_to_y(viewport.top().saturating_sub(amount as usize));
}
MoveAmount::Integer(amount) => scroller
.scroll_to_y(viewport.top().saturating_sub(*amount as usize)),
};
@@ -80,6 +85,11 @@ impl ViewExt for HelpView {
MoveAmount::Extreme => {
self.view.scroll_to_bottom();
}
MoveAmount::Float(scale) => {
let amount = (viewport.height() as f32) * scale;
scroller
.scroll_to_y(viewport.bottom().saturating_add(amount as usize));
}
MoveAmount::Integer(amount) => scroller
.scroll_to_y(viewport.bottom().saturating_add(*amount as usize)),
};

View File

@@ -542,6 +542,10 @@ impl<I: ListItem + Clone> ViewExt for ListView<I> {
if self.selected > 0 {
match amount {
MoveAmount::Extreme => self.move_focus_to(0),
MoveAmount::Float(scale) => {
let amount = (self.last_size.y as f32) * scale;
self.move_focus(-(amount as i32))
}
MoveAmount::Integer(amount) => self.move_focus(-(*amount)),
}
}
@@ -551,6 +555,10 @@ impl<I: ListItem + Clone> ViewExt for ListView<I> {
if self.selected < last_idx {
match amount {
MoveAmount::Extreme => self.move_focus_to(last_idx),
MoveAmount::Float(scale) => {
let amount = (self.last_size.y as f32) * scale;
self.move_focus(amount as i32)
}
MoveAmount::Integer(amount) => self.move_focus(*amount),
}
}

View File

@@ -144,6 +144,7 @@ impl ViewExt for TabView {
match amount {
MoveAmount::Extreme => self.move_focus_to(0),
MoveAmount::Integer(amount) => self.move_focus(-(*amount)),
_ => (),
}
return Ok(CommandResult::Consumed(None));
}
@@ -151,6 +152,7 @@ impl ViewExt for TabView {
match amount {
MoveAmount::Extreme => self.move_focus_to(last_idx),
MoveAmount::Integer(amount) => self.move_focus(*amount),
_ => (),
}
return Ok(CommandResult::Consumed(None));
}