Expand description
Manage keyboard/mouse-bindings while running minus.
Terminology in this module: We will call any keyboard/mouse event from the terminal as a binding and its associated predefined action as callback.
There are two ways to define binding in minus as you will see below.
§Newer (Recommended) Method
§Description
This method offers a much improved and ergonomic API for defining bindings and callbacks.
You use the HashedEventRegister for registering bindings and their associated callback.
It provides functions like add_key_events and
add_mouse_events which take &[&str] as its first
argument and a callback cb as its second argument and maps all &str in the &[&str] to
same callback function cb. Each &str of the &[&str] contains a description of the
key/mouse binding needed to activate it. For example c-c means pressing a Ctrl+c on the
keyboard. See Writing Binding Descriptions to know more on
writing these descriptions.
§Example
use minus::input::{InputEvent, HashedEventRegister, crossterm_event::Event};
let mut input_register = HashedEventRegister::default();
input_register.add_key_events(&["down"], |_, ps| {
InputEvent::UpdateUpperMark(ps.upper_mark.saturating_sub(1))
});
input_register.add_mouse_events(&["scroll:up"], |_, ps| {
InputEvent::UpdateUpperMark(ps.upper_mark.saturating_sub(5))
});
input_register.add_resize_event(|ev, _| {
let (cols, rows) = if let Event::Resize(cols, rows) = ev {
(cols, rows)
} else {
unreachable!();
};
InputEvent::UpdateTermArea(cols as usize, rows as usize)
});§Writing Binding Descriptions
§Defining Keybindings
The general syntax for defining keybindings is [MODIFIER]-[MODIFIER]-[MODIFIER]-{SINGLE KEY}
MODIFIERs include or or more of the Ctrl Alt and Shift keys. They are writeen with
the shorthands c, m and s respectively.
SINGLE CHAR includes any key on the keyboard which is not a modifier like a, z, 1, F1
or enter. Each of these pieces are separated by a -.
Here are some examples
| Key Input | Mean ing |
|---|---|
a | A literal a |
Z | A Z. Matched only when a caps lock is on |
c-q | Ctrl+q |
enter | ENTER key |
c-m-pageup | Ctrl+Alt+PageUp |
s-2 | Shift+2 |
backspace | Backspace Key |
left | Left Arrow key |
§Defining Mouse Bindings
The general syntax for defining keybindings is [MODIFIER]-[MODIFIER]-[MODIFIER]-{MOUSE ACTION}
MODIFIERs include or or more of the Ctrl Alt and Shift keys which are pressed along
with the mouse action. They are writeen with the shorthands c, m and s respectively.
MOUSE ACTION includes actions like pressing down the left mouse button or taking up the right
mouse button. It also includes scrolling up/down or pressing the middle click.
Here are some examples
| Key Input | Mean ing |
|---|---|
left:up | Releasing the left mouse button |
right:down | Pressing the right mouse button |
c-mid:down | Middle click in pressed along with Ctrl key |
m-scroll:up | Scrolled down while pressing the Alt key |
NOTE: Although minus’s description parser can correctly parse almost all if not all the
events that you can possibly register, not all of them are correctly registered by crossterm
itself. For example minus corrctly parses c-s-h as ctrl+shift-h but crossterm
categorically recognizes it as ctrl+h when reading events from the terminal.
§Legacy method
This method relies heavily on the InputClassifier trait and end-applications were needed to
manually copy the default definitions and make the required
modifications yourself in this method. This lead to very messy and error-prone system for
defining bindings and also required application authors to bring in the the underlying
crossterm crate to define the events.
§Example
use minus::{input::{InputEvent, InputClassifier}, Pager, PagerState};
use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers};
struct CustomInputClassifier;
impl InputClassifier for CustomInputClassifier {
fn classify_input(
&self,
ev: Event,
ps: &PagerState
) -> Option<InputEvent> {
match ev {
Event::Key(KeyEvent {
code: KeyCode::Up,
modifiers: KeyModifiers::NONE,
..
})
| Event::Key(KeyEvent {
code: KeyCode::Char('j'),
modifiers: KeyModifiers::NONE,
..
}) => Some(InputEvent::UpdateUpperMark
(ps.upper_mark.saturating_sub(1))),
_ => None
}
}
}
let mut pager = Pager::new();
pager.set_input_classifier(
Box::new(CustomInputClassifier)
);NOTE: Although you can define almost every combination of bindings that crossterm supports, not all of them are correctly registered by crossterm itself. For example you can define
Event::Key(KeyEvent {
code: KeyCode::Char(`h`),
modifiers: KeyModifiers::CONTROL | KeyModifiers::SHIFT,
..
})but crossterm will not match to it as crossterm
recognizes a ctrl+shift+h as ctrl+h when reading events from the terminal.
§Custom Actions on User Events
Sometimes you want to execute arbitrary code when a key/mouse action is pressed like fetching
more data from a server but not necessarily sending it to minus. In these types of scenarios,
you can leverage InputEvent::Ignore. When this is returned by a callback
function, minus will execute your code but not do anything special for the event on its part.
input_register.add_key_events(&["f"], |_, ps| {
fetch_data_from_server(...);
InputEvent::Ignore
});It can be used with the legacy method too.
struct CustomInputClassifier;
impl InputClassifier for CustomInputClassifier {
fn classify_input(
&self,
ev: Event,
ps: &PagerState
) -> Option<InputEvent> {
match ev {
Event::Key(KeyEvent {
code: KeyCode::Char('f'),
modifiers: KeyModifiers::NONE,
..
}) => {
fetch_data_from_server(...);
InputEvent::Ignore
},
_ => None
}
}
}Modules§
- crossterm_
event - A module to read events.
Structs§
- Default
Input Classifier Deprecated - The default set of input definitions
- Hashed
Event Register - A hash store for events and it’s related callback
Enums§
- Input
Event - Events handled by the
minuspager.
Traits§
- Input
Classifier Deprecated - Classifies the input and returns the appropriate
InputEvent
Functions§
- generate_
default_ bindings Deprecated - Insert the default set of actions into the
HashedEventRegister