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:
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)),
|
||||
};
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user