use shortcuts from config or default

closes #63
master
Manos Pitsidianakis 2019-03-04 10:15:11 +02:00
parent 1f200cfc88
commit b437e55b67
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
7 changed files with 130 additions and 52 deletions

View File

@ -142,7 +142,7 @@ impl Entity {
}
}
pub type ShortcutMap = FnvHashMap<Key, String>;
pub type ShortcutMap = FnvHashMap<&'static str, Key>;
/// Types implementing this Trait can draw on the terminal and receive events.
/// If a type wants to skip drawing if it has not changed anything, it can hold some flag in its
@ -157,7 +157,7 @@ pub trait Component: Display + Debug + Send {
fn kill(&mut self, _id: EntityId) {}
fn set_id(&mut self, _id: EntityId) {}
fn get_shortcuts(&self) -> ShortcutMap { Default::default() }
fn get_shortcuts(&self, context: &Context) -> ShortcutMap { Default::default() }
}
/*

View File

@ -130,8 +130,9 @@ impl Component for ContactList {
return true;
}
}
let shortcuts = self.get_shortcuts(context);
match event.event_type {
UIEventType::Input(Key::Char('c')) => {
UIEventType::Input(ref key) if *key == shortcuts["create_contact"] => {
let mut manager = ContactManager::default();
manager.account_pos = self.account_pos;
let entity = Entity::from(Box::new(manager));
@ -141,7 +142,8 @@ impl Component for ContactList {
return true;
},
UIEventType::Input(Key::Char('e')) if self.length > 0 => {
UIEventType::Input(ref key) if *key == shortcuts["edit_contact"] && self.length > 0 => {
let account = &mut context.accounts[self.account_pos];
let book = &mut account.address_book;
let card = book[&self.id_positions[self.cursor_pos]].clone();
@ -202,4 +204,13 @@ impl Component for ContactList {
fn kill(&mut self, uuid: Uuid) {
self.mode = ViewMode::Close(uuid);
}
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
let mut map = self.view.as_ref().map(|p| p.get_shortcuts(context)).unwrap_or_default();
let config_map = context.settings.shortcuts.contact_list.key_values();
map.insert("create_contact", (*config_map["create_contact"]).clone());
map.insert("edit_contact", (*config_map["edit_contact"]).clone());
map
}
}

View File

@ -116,11 +116,11 @@ impl Component for Listing {
}
}
fn get_shortcuts(&self) -> ShortcutMap {
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
match self {
Listing::Compact(l) => l.get_shortcuts(),
Listing::Plain(l) => l.get_shortcuts(),
Listing::Threaded(l) => l.get_shortcuts(),
Listing::Compact(l) => l.get_shortcuts(context),
Listing::Plain(l) => l.get_shortcuts(context),
Listing::Threaded(l) => l.get_shortcuts(context),
}
}
}

View File

@ -387,6 +387,8 @@ impl Component for CompactListing {
return true;
}
}
let shortcuts = self.get_shortcuts(context);
match event.event_type {
UIEventType::Input(Key::Up) => {
if self.cursor_pos.2 > 0 {
@ -402,20 +404,20 @@ impl Component for CompactListing {
}
return true;
}
UIEventType::Input(Key::Char('\n')) if !self.unfocused => {
UIEventType::Input(ref k) if !self.unfocused && *k == shortcuts["open_thread"] => {
self.unfocused = true;
self.dirty = true;
return true;
}
UIEventType::Input(Key::PageUp) => {
UIEventType::Input(ref key) if *key == shortcuts["prev_page"] => {
self.movement = Some(PageMovement::PageUp);
self.set_dirty();
}
UIEventType::Input(Key::PageDown) => {
UIEventType::Input(ref key) if *key == shortcuts["next_page"] => {
self.movement = Some(PageMovement::PageDown);
self.set_dirty();
}
UIEventType::Input(Key::Char('i')) if self.unfocused => {
UIEventType::Input(ref k) if self.unfocused && *k == shortcuts["exit_thread"] => {
self.unfocused = false;
self.dirty = true;
self.view = None;
@ -524,18 +526,19 @@ impl Component for CompactListing {
self.dirty = true;
}
fn get_shortcuts(&self) -> ShortcutMap {
let mut map = self.view.as_ref().map(|p| p.get_shortcuts()).unwrap_or_default();
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
let mut map = self.view.as_ref().map(|p| p.get_shortcuts(context)).unwrap_or_default();
map.insert(Key::Char('\n'), "Open thread.".into());
map.insert(Key::PageUp, "Go to previous page.".into());
map.insert(Key::PageDown, "Go to next page.".into());
map.insert(Key::Char('i'), "Exit thread view.".into());
map.insert(Key::Char('J'), "Go to previous folder.".into());
map.insert(Key::Char('K'), "Go to next folder.".into());
map.insert(Key::Char('h'), "Go to previous account.".into());
map.insert(Key::Char('l'), "Go to next account.".into());
map.insert(Key::Char('m'), "Start new mail draft in new tab.".into());
let config_map = context.settings.shortcuts.compact_listing.key_values();
map.insert("open_thread", if let Some(key) = config_map.get("open_thread") { (*key).clone() } else { Key::Char('\n') });
map.insert("prev_page", if let Some(key) = config_map.get("prev_page") { (*key).clone() } else { Key::PageUp });
map.insert("next_page", if let Some(key) = config_map.get("next_page") { (*key).clone() } else { Key::PageDown });
map.insert("exit_thread", if let Some(key) = config_map.get("exit_thread") { (*key).clone() } else { Key::Char('i') });
map.insert("prev_folder", if let Some(key) = config_map.get("prev_folder") { (*key).clone() } else { Key::Char('J') });
map.insert("next_folder", if let Some(key) = config_map.get("next_folder") { (*key).clone() } else { Key::Char('K') });
map.insert("prev_account", if let Some(key) = config_map.get("prev_account") { (*key).clone() } else { Key::Char('h') });
map.insert("next_account", if let Some(key) = config_map.get("next_account") { (*key).clone() } else { Key::Char('l') });
map.insert("new_mail", if let Some(key) = config_map.get("new_mail") { (*key).clone() } else { Key::Char('m') });
map
}

View File

@ -101,9 +101,9 @@ impl Component for HSplit {
self.bottom.component.set_dirty();
}
fn get_shortcuts(&self) -> ShortcutMap {
let mut top_map = self.top.get_shortcuts();
top_map.extend(self.bottom.get_shortcuts().into_iter());
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
let mut top_map = self.top.get_shortcuts(context);
top_map.extend(self.bottom.get_shortcuts(context).into_iter());
top_map
}
}
@ -197,9 +197,9 @@ impl Component for VSplit {
self.right.component.set_dirty();
}
fn get_shortcuts(&self) -> ShortcutMap {
let mut right_map = self.right.get_shortcuts();
right_map.extend(self.left.get_shortcuts().into_iter());
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
let mut right_map = self.right.get_shortcuts(context);
right_map.extend(self.left.get_shortcuts(context).into_iter());
right_map
}
}
@ -397,25 +397,26 @@ impl Component for Pager {
}
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
let shortcuts = self.get_shortcuts(context);
match event.event_type {
UIEventType::Input(Key::Char('k')) => {
UIEventType::Input(ref key) if *key == shortcuts["scroll_up"] => {
if self.cursor_pos > 0 {
self.cursor_pos -= 1;
self.dirty = true;
}
}
UIEventType::Input(Key::Char('j')) => {
UIEventType::Input(ref key) if *key == shortcuts["scroll_down"] => {
if self.height > 0 && self.cursor_pos + 1 < self.height {
self.cursor_pos += 1;
self.dirty = true;
}
}
UIEventType::Input(Key::PageUp) => {
UIEventType::Input(ref key) if *key == shortcuts["page_up"] => {
self.movement = Some(PageMovement::PageUp);
self.dirty = true;
}
UIEventType::Input(Key::PageDown) => {
UIEventType::Input(ref key) if *key == shortcuts["page_down"] => {
self.movement = Some(PageMovement::PageDown);
self.dirty = true;
}
@ -440,6 +441,17 @@ impl Component for Pager {
fn set_dirty(&mut self) {
self.dirty = true;
}
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
let mut map = FnvHashMap::with_capacity_and_hasher(4, Default::default());
let config_map = context.settings.shortcuts.pager.key_values();
map.insert("scroll_up", (*config_map["scroll_up"]).clone());
map.insert("scroll_down", (*config_map["scroll_down"]).clone());
map.insert("page_up", (*config_map["page_up"]).clone());
map.insert("page_down", (*config_map["page_down"]).clone());
map
}
}
/// Status bar.
@ -650,8 +662,8 @@ impl Component for StatusBar {
self.dirty = true;
}
fn get_shortcuts(&self) -> ShortcutMap {
self.container.get_shortcuts()
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
self.container.get_shortcuts(context)
}
}
@ -823,9 +835,9 @@ impl Component for Tabbed {
create_box(grid, area);
// TODO: print into a pager
for (idx, (k, v)) in self.children[self.cursor_pos].get_shortcuts().into_iter().enumerate() {
for (idx, (k, v)) in self.children[self.cursor_pos].get_shortcuts(context).into_iter().enumerate() {
let (x, y) = write_string_to_grid(
&format!("{:?}", k),
&k,
grid,
Color::Byte(29),
Color::Default,
@ -833,7 +845,7 @@ impl Component for Tabbed {
false,
);
write_string_to_grid(
&v,
&format!("{:?}", v),
grid,
Color::Default,
Color::Default,

View File

@ -116,7 +116,7 @@ struct FileSettings {
accounts: HashMap<String, FileAccount>,
pager: PagerSettings,
notifications: NotificationsSettings,
shortcuts: CompactListingShortcuts,
shortcuts: Shortcuts,
}
#[derive(Debug, Clone, Default)]
@ -142,7 +142,7 @@ pub struct Settings {
pub accounts: HashMap<String, AccountConf>,
pub pager: PagerSettings,
pub notifications: NotificationsSettings,
pub shortcuts: CompactListingShortcuts,
pub shortcuts: Shortcuts,
}
impl FileSettings {

View File

@ -2,9 +2,19 @@ use types::Key;
//use std::any::TypeId;
use fnv::FnvHashMap;
#[derive(Debug, Clone, Default, Deserialize)]
pub struct Shortcuts {
#[serde(flatten)]
pub compact_listing: CompactListingShortcuts,
#[serde(flatten)]
pub contact_list: ContactListShortcuts,
#[serde(flatten)]
pub pager: PagerShortcuts,
}
#[macro_export]
macro_rules! key_values {
( $cname:expr, derive ($($derives:ident),*) : pub struct $name:ident { $($fname:ident : Key),* }) => {
( $cname:expr, derive ($($derives:ident),*) : pub struct $name:ident { $($fname:ident : Key |> $fdesc:expr),* }) => {
#[derive($($derives),*)]
#[serde(default)]
#[serde(rename = $cname)]
@ -13,6 +23,12 @@ macro_rules! key_values {
}
impl $name {
pub fn key_desc(&self, key: &str) -> &'static str {
match key {
$(stringify!($fname) => $fdesc),*,
_ => unreachable!()
}
}
pub fn key_values(&self) -> FnvHashMap<&'static str, &Key> {
let mut map: FnvHashMap<&'static str, &Key> = Default::default();
$(map.insert(stringify!($fname),&(self.$fname));)*
@ -24,22 +40,22 @@ macro_rules! key_values {
key_values!{ "compact-listing", derive (Debug, Clone, Deserialize) :
pub struct CompactListingShortcuts {
open_thread: Key,
exit_thread: Key,
prev_page: Key,
next_page: Key,
prev_folder: Key,
next_folder: Key,
prev_account: Key,
next_account: Key,
new_mail: Key
open_thread: Key |> "Open thread.",
exit_thread: Key |> "Exit thread view.",
prev_page: Key |> "Go to previous page.",
next_page: Key |> "Go to next page.",
prev_folder: Key |> "Go to previous folder.",
next_folder: Key |> "Go to next folder.",
prev_account: Key |> "Go to previous account.",
next_account: Key |> "Go to next account.",
new_mail: Key |> "Start new mail draft in new tab."
}
}
impl Default for CompactListingShortcuts {
fn default() -> Self {
CompactListingShortcuts {
CompactListingShortcuts {
open_thread: Key::Char('\n'),
exit_thread: Key::Char('i'),
prev_page: Key::PageUp,
@ -52,3 +68,39 @@ impl Default for CompactListingShortcuts {
}
}
}
key_values!{ "contact-list", derive (Debug, Clone, Deserialize) :
pub struct ContactListShortcuts {
create_contact: Key |> "Create new contact.",
edit_contact: Key |> "Edit contact under cursor."
}
}
impl Default for ContactListShortcuts {
fn default() -> Self {
ContactListShortcuts {
create_contact: Key::Char('c'),
edit_contact: Key::Char('e'),
}
}
}
key_values!{ "pager", derive (Debug, Clone, Deserialize) :
pub struct PagerShortcuts {
scroll_up: Key |> "Scroll up pager.",
scroll_down: Key |> "Scroll down pager.",
page_up: Key |> "Go to previous pager page",
page_down: Key |> "Go to next pager page"
}
}
impl Default for PagerShortcuts {
fn default() -> Self {
PagerShortcuts {
scroll_up: Key::Char('k'),
scroll_down: Key::Char('j'),
page_up: Key::PageUp,
page_down: Key::PageDown,
}
}
}