Files
ncspot/src/ui/help.rs
HMH 102acd803e Enable binding multiple commands to a key.
This enables useful combinations of commands like `Space -> queue; move
down 1` using ';' as command separator. ';' can be escaped using ';;'.
2021-09-11 21:40:00 +02:00

95 lines
3.1 KiB
Rust

use std::collections::HashMap;
use cursive::theme::Effect;
use cursive::utils::markup::StyledString;
use cursive::view::ViewWrapper;
use cursive::views::{ScrollView, TextView};
use cursive::Cursive;
use crate::command::{Command, MoveAmount, MoveMode};
use crate::commands::CommandResult;
use crate::config::config_path;
use crate::traits::ViewExt;
use cursive::view::scroll::Scroller;
pub struct HelpView {
view: ScrollView<TextView>,
}
impl HelpView {
pub fn new(bindings: HashMap<String, Vec<Command>>) -> HelpView {
let mut text = StyledString::styled("Keybindings\n\n", Effect::Bold);
let note = format!(
"Custom bindings can be set in {} within the [keybindings] section.\n\n",
config_path("config.toml").to_str().unwrap_or_default()
);
text.append(StyledString::styled(note, Effect::Italic));
let mut keys: Vec<&String> = bindings.keys().collect();
keys.sort();
for key in keys {
let commands = &bindings[key];
let binding = format!(
"{} -> {}\n",
key,
commands
.iter()
.map(|c| c.to_string())
.collect::<Vec<_>>()
.join("; ")
);
text.append(binding);
}
HelpView {
view: ScrollView::new(TextView::new(text)),
}
}
}
impl ViewWrapper for HelpView {
wrap_impl!(self.view: ScrollView<TextView>);
}
impl ViewExt for HelpView {
fn title(&self) -> String {
"Help".to_string()
}
fn on_command(&mut self, _s: &mut Cursive, cmd: &Command) -> Result<CommandResult, String> {
match cmd {
Command::Help => Ok(CommandResult::Consumed(None)),
Command::Move(mode, amount) => {
let scroller = self.view.get_scroller_mut();
let viewport = scroller.content_viewport();
match mode {
MoveMode::Up => {
match amount {
MoveAmount::Extreme => {
self.view.scroll_to_top();
}
MoveAmount::Integer(amount) => scroller
.scroll_to_y(viewport.top().saturating_sub(*amount as usize)),
};
Ok(CommandResult::Consumed(None))
}
MoveMode::Down => {
match amount {
MoveAmount::Extreme => {
self.view.scroll_to_bottom();
}
MoveAmount::Integer(amount) => scroller
.scroll_to_y(viewport.bottom().saturating_add(*amount as usize)),
};
Ok(CommandResult::Consumed(None))
}
_ => Ok(CommandResult::Consumed(None)),
}
}
_ => Ok(CommandResult::Ignored),
}
}
}