From d4c64916f0efdad4774503e5bae4e86ba40770fa Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sun, 3 Mar 2019 14:24:15 +0200 Subject: [PATCH] Add configurable shortcuts for compact mail listing concerns #63 --- ui/src/conf.rs | 6 ++++ ui/src/conf/shortcuts.rs | 65 ++++++++++++++++++++++++++++++++++++++++ ui/src/types.rs | 4 ++- ui/src/types/keys.rs | 45 ++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 ui/src/conf/shortcuts.rs diff --git a/ui/src/conf.rs b/ui/src/conf.rs index 81e5f223..782bba26 100644 --- a/ui/src/conf.rs +++ b/ui/src/conf.rs @@ -26,11 +26,14 @@ extern crate bincode; pub mod pager; pub mod notifications; +pub mod shortcuts; pub mod accounts; pub use self::accounts::Account; +pub use self::shortcuts::*; use self::config::{Config, File, FileFormat}; + use melib::conf::AccountSettings; use melib::error::*; use pager::PagerSettings; @@ -113,6 +116,7 @@ struct FileSettings { accounts: HashMap, pager: PagerSettings, notifications: NotificationsSettings, + shortcuts: CompactListingShortcuts, } #[derive(Debug, Clone, Default)] @@ -138,6 +142,7 @@ pub struct Settings { pub accounts: HashMap, pub pager: PagerSettings, pub notifications: NotificationsSettings, + pub shortcuts: CompactListingShortcuts, } impl FileSettings { @@ -184,6 +189,7 @@ impl Settings { accounts: s, pager: fs.pager, notifications: fs.notifications, + shortcuts: fs.shortcuts, } } } diff --git a/ui/src/conf/shortcuts.rs b/ui/src/conf/shortcuts.rs new file mode 100644 index 00000000..1671cdb8 --- /dev/null +++ b/ui/src/conf/shortcuts.rs @@ -0,0 +1,65 @@ +use types::Key; +//use std::any::TypeId; +use fnv::FnvHashMap; + +#[macro_export] +macro_rules! key_values { + (derive ($($derives:ident),*) : pub struct $name:ident { $($fname:ident : Key),* }) => { + #[derive($($derives),*)] + #[serde(default)] + pub struct $name { + $($fname : Key),* + } + + impl $name { + pub fn key_values(&self) -> FnvHashMap<&'static str, &Key> { + let mut map: FnvHashMap<&'static str, &Key> = Default::default(); + $(map.insert(stringify!($fname),&(self.$fname));)* + map + } + } + } +} + +key_values!{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 +} +} + + +impl Default for CompactListingShortcuts { + fn default() -> Self { + CompactListingShortcuts { + open_thread: Key::Char('\n'), + exit_thread: Key::PageUp, + prev_page: Key::PageDown, + next_page: Key::Char('i'), + prev_folder: Key::Char('J'), + next_folder: Key::Char('K'), + prev_account:Key::Char('h'), + next_account:Key::Char('l'), + new_mail: Key::Char('m'), + } + } +} + + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_macro() { + panic!() + + + } +} diff --git a/ui/src/types.rs b/ui/src/types.rs index aaacec11..0908af10 100644 --- a/ui/src/types.rs +++ b/ui/src/types.rs @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with meli. If not, see . */ - +extern crate serde; #[macro_use] mod position; #[macro_use] @@ -39,6 +39,8 @@ use std; use std::fmt; use std::thread; use uuid::Uuid; +use self::serde::{de, Deserialize, Deserializer, }; +use self::serde::de::Visitor; #[derive(Debug)] pub enum StatusEvent { diff --git a/ui/src/types/keys.rs b/ui/src/types/keys.rs index 335e856e..6be97782 100644 --- a/ui/src/types/keys.rs +++ b/ui/src/types/keys.rs @@ -19,6 +19,7 @@ * along with meli. If not, see . */ +use super::*; use chan; use std::fmt; use std::io; @@ -199,3 +200,47 @@ derive_csi_sequence!("End Bracketed Paste Mode", BracketModeEnd, "?2003l"); pub const BRACKET_PASTE_START: &[u8] = b"\x1B[200~"; pub const BRACKET_PASTE_END: &[u8] = b"\x1B[201~"; + +const FIELDS: &'static [&'static str] = &[]; + + +impl<'de> Deserialize<'de> for Key { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct KeyVisitor; + + impl<'de> Visitor<'de> for KeyVisitor { + type Value = Key; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("`secs` or `nanos`") + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + match value { + "Backspace" => Ok(Key::Backspace), + "Left" => Ok(Key::Left), + "Right" => Ok(Key::Right), + "Up" => Ok(Key::Up), + "Down" => Ok(Key::Down), + "Home" => Ok(Key::Home), + "End" => Ok(Key::End), + "PageUp" => Ok(Key::PageUp), + "PageDown" => Ok(Key::PageDown), + "Delete" => Ok(Key::Delete), + "Insert" => Ok(Key::Insert), + "Esc" => Ok(Key::Esc), + ref s if s.len() == 1 => Ok(Key::Char(s.chars().nth(0).unwrap())), + _ => Err(de::Error::unknown_field(value, FIELDS)), + } + } + } + + deserializer.deserialize_identifier(KeyVisitor) + } +}