mirror of
https://github.com/alexpasmantier/television.git
synced 2025-06-06 11:35:25 +00:00
feat(config): allow specifying multiple keymaps for the same action + better defaults (#149)
Fixes #135
This commit is contained in:
parent
499bfdb8e5
commit
557686e197
@ -75,8 +75,8 @@ theme = "Coldark-Dark"
|
|||||||
# Quit the application
|
# Quit the application
|
||||||
quit = "esc"
|
quit = "esc"
|
||||||
# Scrolling through entries
|
# Scrolling through entries
|
||||||
select_next_entry = "down"
|
select_next_entry = ["down", "ctrl-n", "ctrl-j"]
|
||||||
select_prev_entry = "up"
|
select_prev_entry = ["up", "ctrl-p", "ctrl-k"]
|
||||||
select_next_page = "pagedown"
|
select_next_page = "pagedown"
|
||||||
select_prev_page = "pageup"
|
select_prev_page = "pageup"
|
||||||
# Scrolling the preview pane
|
# Scrolling the preview pane
|
||||||
@ -102,8 +102,8 @@ toggle_preview = "ctrl-o"
|
|||||||
# Quit the application
|
# Quit the application
|
||||||
quit = "esc"
|
quit = "esc"
|
||||||
# Scrolling through entries
|
# Scrolling through entries
|
||||||
select_next_entry = "down"
|
select_next_entry = ["down", "ctrl-n", "ctrl-j"]
|
||||||
select_prev_entry = "up"
|
select_prev_entry = ["up", "ctrl-p", "ctrl-k"]
|
||||||
select_next_page = "pagedown"
|
select_next_page = "pagedown"
|
||||||
select_prev_page = "pageup"
|
select_prev_page = "pageup"
|
||||||
# Select an entry
|
# Select an entry
|
||||||
@ -122,8 +122,8 @@ toggle_preview = "ctrl-o"
|
|||||||
# Quit the application
|
# Quit the application
|
||||||
quit = "esc"
|
quit = "esc"
|
||||||
# Scrolling through entries
|
# Scrolling through entries
|
||||||
select_next_entry = "down"
|
select_next_entry = ["down", "ctrl-n", "ctrl-j"]
|
||||||
select_prev_entry = "up"
|
select_prev_entry = ["up", "ctrl-p", "ctrl-k"]
|
||||||
select_next_page = "pagedown"
|
select_next_page = "pagedown"
|
||||||
select_prev_page = "pageup"
|
select_prev_page = "pageup"
|
||||||
# Select an entry
|
# Select an entry
|
||||||
|
@ -3,8 +3,7 @@ use std::{env, path::PathBuf};
|
|||||||
|
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
pub use keybindings::parse_key;
|
pub use keybindings::{parse_key, Binding, KeyBindings};
|
||||||
pub use keybindings::KeyBindings;
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use previewers::PreviewersConfig;
|
use previewers::PreviewersConfig;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
@ -118,7 +117,7 @@ impl Config {
|
|||||||
for (command, key) in default_bindings {
|
for (command, key) in default_bindings {
|
||||||
user_bindings
|
user_bindings
|
||||||
.entry(command.clone())
|
.entry(command.clone())
|
||||||
.or_insert_with(|| *key);
|
.or_insert_with(|| key.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,14 +3,34 @@ use crate::event::{convert_raw_event_to_key, Key};
|
|||||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Display;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use television_screen::mode::Mode;
|
use television_screen::mode::Mode;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
pub enum Binding {
|
||||||
|
SingleKey(Key),
|
||||||
|
MultipleKeys(Vec<Key>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Binding {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Binding::SingleKey(key) => write!(f, "{}", key),
|
||||||
|
Binding::MultipleKeys(keys) => {
|
||||||
|
let keys_str: Vec<String> =
|
||||||
|
keys.iter().map(|k| k.to_string()).collect();
|
||||||
|
write!(f, "{}", keys_str.join(", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct KeyBindings(pub config::Map<Mode, config::Map<Action, Key>>);
|
pub struct KeyBindings(pub config::Map<Mode, config::Map<Action, Binding>>);
|
||||||
|
|
||||||
impl Deref for KeyBindings {
|
impl Deref for KeyBindings {
|
||||||
type Target = config::Map<Mode, config::Map<Action, Key>>;
|
type Target = config::Map<Mode, config::Map<Action, Binding>>;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
@ -22,13 +42,20 @@ impl DerefMut for KeyBindings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum SerializedBinding {
|
||||||
|
SingleKey(String),
|
||||||
|
MultipleKeys(Vec<String>),
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for KeyBindings {
|
impl<'de> Deserialize<'de> for KeyBindings {
|
||||||
fn deserialize<D>(deserializer: D) -> color_eyre::Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> color_eyre::Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let parsed_map =
|
let parsed_map =
|
||||||
HashMap::<Mode, HashMap<Action, String>>::deserialize(
|
HashMap::<Mode, HashMap<Action, SerializedBinding>>::deserialize(
|
||||||
deserializer,
|
deserializer,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -37,7 +64,28 @@ impl<'de> Deserialize<'de> for KeyBindings {
|
|||||||
.map(|(mode, inner_map)| {
|
.map(|(mode, inner_map)| {
|
||||||
let converted_inner_map = inner_map
|
let converted_inner_map = inner_map
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(cmd, key_str)| (cmd, parse_key(&key_str).unwrap()))
|
.map(|(cmd, binding)| {
|
||||||
|
(
|
||||||
|
cmd,
|
||||||
|
match binding {
|
||||||
|
SerializedBinding::SingleKey(key_str) => {
|
||||||
|
Binding::SingleKey(
|
||||||
|
parse_key(&key_str).unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SerializedBinding::MultipleKeys(keys_str) => {
|
||||||
|
Binding::MultipleKeys(
|
||||||
|
keys_str
|
||||||
|
.iter()
|
||||||
|
.map(|key_str| {
|
||||||
|
parse_key(key_str).unwrap()
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
(mode, converted_inner_map)
|
(mode, converted_inner_map)
|
||||||
})
|
})
|
||||||
|
@ -5,7 +5,7 @@ use color_eyre::Result;
|
|||||||
use television_screen::mode::Mode;
|
use television_screen::mode::Mode;
|
||||||
|
|
||||||
use crate::action::Action;
|
use crate::action::Action;
|
||||||
use crate::config::KeyBindings;
|
use crate::config::{Binding, KeyBindings};
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
@ -23,8 +23,17 @@ impl From<&KeyBindings> for Keymap {
|
|||||||
let mut keymap = HashMap::new();
|
let mut keymap = HashMap::new();
|
||||||
for (mode, bindings) in keybindings.iter() {
|
for (mode, bindings) in keybindings.iter() {
|
||||||
let mut mode_keymap = HashMap::new();
|
let mut mode_keymap = HashMap::new();
|
||||||
for (action, key) in bindings {
|
for (action, binding) in bindings {
|
||||||
mode_keymap.insert(*key, action.clone());
|
match binding {
|
||||||
|
Binding::SingleKey(key) => {
|
||||||
|
mode_keymap.insert(*key, action.clone());
|
||||||
|
}
|
||||||
|
Binding::MultipleKeys(keys) => {
|
||||||
|
for key in keys {
|
||||||
|
mode_keymap.insert(*key, action.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
keymap.insert(*mode, mode_keymap);
|
keymap.insert(*mode, mode_keymap);
|
||||||
}
|
}
|
||||||
|
@ -458,6 +458,7 @@ impl Television {
|
|||||||
.get(&self.mode)
|
.get(&self.mode)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(&Action::ToggleHelp)
|
.get(&Action::ToggleHelp)
|
||||||
|
// just display the first keybinding
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string(),
|
.to_string(),
|
||||||
&self
|
&self
|
||||||
@ -466,6 +467,7 @@ impl Television {
|
|||||||
.get(&self.mode)
|
.get(&self.mode)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(&Action::TogglePreview)
|
.get(&Action::TogglePreview)
|
||||||
|
// just display the first keybinding
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string(),
|
.to_string(),
|
||||||
)?;
|
)?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user