ui: shortcuts refactoring
parent
8798d84e43
commit
f1588f6002
|
@ -78,7 +78,7 @@ const _DOUBLE_UP_AND_RIGHT: char = '╚';
|
|||
type ComponentId = Uuid;
|
||||
|
||||
pub type ShortcutMap = FnvHashMap<&'static str, Key>;
|
||||
pub type ShortcutMaps = FnvHashMap<String, ShortcutMap>;
|
||||
pub type ShortcutMaps = FnvHashMap<&'static str, ShortcutMap>;
|
||||
|
||||
/// 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
|
||||
|
|
|
@ -552,7 +552,7 @@ impl Component for ContactList {
|
|||
let shortcuts = &self.get_shortcuts(context)[Self::DESCRIPTION];
|
||||
match *event {
|
||||
UIEvent::Input(ref key)
|
||||
if *key == shortcuts["create_contact"] && self.view.is_none() =>
|
||||
if key == shortcuts["create_contact"] && self.view.is_none() =>
|
||||
{
|
||||
let mut manager = ContactManager::default();
|
||||
manager.set_parent_id(self.id);
|
||||
|
@ -565,7 +565,7 @@ impl Component for ContactList {
|
|||
}
|
||||
|
||||
UIEvent::Input(ref key)
|
||||
if *key == shortcuts["edit_contact"] && self.length > 0 && self.view.is_none() =>
|
||||
if key == shortcuts["edit_contact"] && self.length > 0 && self.view.is_none() =>
|
||||
{
|
||||
let account = &mut context.accounts[self.account_pos];
|
||||
let book = &mut account.address_book;
|
||||
|
@ -580,7 +580,7 @@ impl Component for ContactList {
|
|||
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref key) if *key == shortcuts["next_account"] && self.view.is_none() => {
|
||||
UIEvent::Input(ref key) if key == shortcuts["next_account"] && self.view.is_none() => {
|
||||
let amount = if self.cmd_buf.is_empty() {
|
||||
1
|
||||
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
||||
|
@ -612,7 +612,7 @@ impl Component for ContactList {
|
|||
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref key) if *key == shortcuts["prev_account"] && self.view.is_none() => {
|
||||
UIEvent::Input(ref key) if key == shortcuts["prev_account"] && self.view.is_none() => {
|
||||
let amount = if self.cmd_buf.is_empty() {
|
||||
1
|
||||
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
||||
|
@ -747,13 +747,7 @@ impl Component for ContactList {
|
|||
.unwrap_or_default();
|
||||
|
||||
let config_map = context.settings.shortcuts.contact_list.key_values();
|
||||
map.insert(
|
||||
self.to_string(),
|
||||
config_map
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.clone()))
|
||||
.collect(),
|
||||
);
|
||||
map.insert(Self::DESCRIPTION, config_map);
|
||||
|
||||
map
|
||||
}
|
||||
|
|
|
@ -1034,10 +1034,8 @@ impl Component for Composer {
|
|||
Default::default()
|
||||
};
|
||||
|
||||
let mut our_map: ShortcutMap = Default::default();
|
||||
our_map.insert("Deliver draft to mailer.", Key::Char('s'));
|
||||
our_map.insert("Edit in $EDITOR", Key::Char('e'));
|
||||
map.insert(Composer::DESCRIPTION.to_string(), our_map);
|
||||
let our_map: ShortcutMap = context.settings.shortcuts.composing.key_values();
|
||||
map.insert(Composer::DESCRIPTION, our_map);
|
||||
|
||||
map
|
||||
}
|
||||
|
|
|
@ -508,7 +508,7 @@ impl Component for Listing {
|
|||
self.component.set_movement(PageMovement::Down(amount));
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref key) if *key == shortcuts["prev_page"] => {
|
||||
UIEvent::Input(ref key) if key == shortcuts["prev_page"] => {
|
||||
let mult = if self.cmd_buf.is_empty() {
|
||||
1
|
||||
} else if let Ok(mult) = self.cmd_buf.parse::<usize>() {
|
||||
|
@ -527,7 +527,7 @@ impl Component for Listing {
|
|||
self.component.set_movement(PageMovement::PageUp(mult));
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref key) if *key == shortcuts["next_page"] => {
|
||||
UIEvent::Input(ref key) if key == shortcuts["next_page"] => {
|
||||
let mult = if self.cmd_buf.is_empty() {
|
||||
1
|
||||
} else if let Ok(mult) = self.cmd_buf.parse::<usize>() {
|
||||
|
@ -564,7 +564,7 @@ impl Component for Listing {
|
|||
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0, None))));
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref key) if *key == shortcuts["search"] => {
|
||||
UIEvent::Input(ref key) if key == shortcuts["search"] => {
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::ExInput(Key::Paste("filter ".to_string())));
|
||||
|
@ -573,7 +573,7 @@ impl Component for Listing {
|
|||
.push_back(UIEvent::ChangeMode(UIMode::Execute));
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref key) if *key == shortcuts["set_seen"] => {
|
||||
UIEvent::Input(ref key) if key == shortcuts["set_seen"] => {
|
||||
let mut event = UIEvent::Action(Action::Listing(ListingAction::SetSeen));
|
||||
if match self.component {
|
||||
Plain(ref mut l) => l.process_event(&mut event, context),
|
||||
|
@ -647,13 +647,7 @@ impl Component for Listing {
|
|||
Conversations(ref l) => l.get_shortcuts(context),
|
||||
};
|
||||
let config_map = context.settings.shortcuts.listing.key_values();
|
||||
map.insert(
|
||||
Listing::DESCRIPTION.to_string(),
|
||||
config_map
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.clone()))
|
||||
.collect(),
|
||||
);
|
||||
map.insert(Listing::DESCRIPTION, config_map);
|
||||
|
||||
map
|
||||
}
|
||||
|
|
|
@ -1066,7 +1066,7 @@ impl Component for CompactListing {
|
|||
let shortcuts = &self.get_shortcuts(context)[CompactListing::DESCRIPTION];
|
||||
if self.length > 0 {
|
||||
match *event {
|
||||
UIEvent::Input(ref k) if !self.unfocused && *k == shortcuts["open_thread"] => {
|
||||
UIEvent::Input(ref k) if !self.unfocused && k == shortcuts["open_thread"] => {
|
||||
if self.filtered_selection.is_empty() {
|
||||
self.view = ThreadView::new(self.cursor_pos, None, context);
|
||||
} else {
|
||||
|
@ -1087,7 +1087,7 @@ impl Component for CompactListing {
|
|||
self.dirty = true;
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref k) if self.unfocused && *k == shortcuts["exit_thread"] => {
|
||||
UIEvent::Input(ref k) if self.unfocused && k == shortcuts["exit_thread"] => {
|
||||
self.unfocused = false;
|
||||
self.dirty = true;
|
||||
/* If self.row_updates is not empty and we exit a thread, the row_update events
|
||||
|
@ -1096,7 +1096,7 @@ impl Component for CompactListing {
|
|||
self.force_draw = true;
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref key) if !self.unfocused && *key == shortcuts["select_entry"] => {
|
||||
UIEvent::Input(ref key) if !self.unfocused && key == shortcuts["select_entry"] => {
|
||||
let thread_hash = self.get_thread_under_cursor(self.cursor_pos.2, context);
|
||||
self.selection.entry(thread_hash).and_modify(|e| *e = !*e);
|
||||
}
|
||||
|
@ -1306,13 +1306,7 @@ impl Component for CompactListing {
|
|||
};
|
||||
|
||||
let config_map = context.settings.shortcuts.compact_listing.key_values();
|
||||
map.insert(
|
||||
CompactListing::DESCRIPTION.to_string(),
|
||||
config_map
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.clone()))
|
||||
.collect(),
|
||||
);
|
||||
map.insert(CompactListing::DESCRIPTION, config_map);
|
||||
|
||||
map
|
||||
}
|
||||
|
|
|
@ -1013,7 +1013,7 @@ impl Component for ConversationsListing {
|
|||
let shortcuts = &self.get_shortcuts(context)[ConversationsListing::DESCRIPTION];
|
||||
if self.length > 0 {
|
||||
match *event {
|
||||
UIEvent::Input(ref k) if !self.unfocused && *k == shortcuts["open_thread"] => {
|
||||
UIEvent::Input(ref k) if !self.unfocused && k == shortcuts["open_thread"] => {
|
||||
if self.length == 0 {
|
||||
return true;
|
||||
}
|
||||
|
@ -1039,7 +1039,7 @@ impl Component for ConversationsListing {
|
|||
self.dirty = true;
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref k) if self.unfocused && *k == shortcuts["exit_thread"] => {
|
||||
UIEvent::Input(ref k) if self.unfocused && k == shortcuts["exit_thread"] => {
|
||||
self.unfocused = false;
|
||||
self.dirty = true;
|
||||
/* If self.row_updates is not empty and we exit a thread, the row_update events
|
||||
|
@ -1048,7 +1048,7 @@ impl Component for ConversationsListing {
|
|||
self.force_draw = true;
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref key) if !self.unfocused && *key == shortcuts["select_entry"] => {
|
||||
UIEvent::Input(ref key) if !self.unfocused && key == shortcuts["select_entry"] => {
|
||||
let thread_hash = self.get_thread_under_cursor(self.cursor_pos.2, context);
|
||||
self.selection.entry(thread_hash).and_modify(|e| *e = !*e);
|
||||
return true;
|
||||
|
@ -1263,13 +1263,7 @@ impl Component for ConversationsListing {
|
|||
};
|
||||
|
||||
let config_map = context.settings.shortcuts.compact_listing.key_values();
|
||||
map.insert(
|
||||
ConversationsListing::DESCRIPTION.to_string(),
|
||||
config_map
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.clone()))
|
||||
.collect(),
|
||||
);
|
||||
map.insert(ConversationsListing::DESCRIPTION, config_map);
|
||||
|
||||
map
|
||||
}
|
||||
|
|
|
@ -894,7 +894,7 @@ impl Component for PlainListing {
|
|||
let shortcuts = &self.get_shortcuts(context)[PlainListing::DESCRIPTION];
|
||||
if self.length > 0 {
|
||||
match *event {
|
||||
UIEvent::Input(ref k) if !self.unfocused && *k == shortcuts["open_thread"] => {
|
||||
UIEvent::Input(ref k) if !self.unfocused && k == shortcuts["open_thread"] => {
|
||||
let env_hash = self.get_env_under_cursor(self.cursor_pos.2, context);
|
||||
let temp = (self.cursor_pos.0, self.cursor_pos.1, env_hash);
|
||||
self.view = MailView::new(temp, None, None);
|
||||
|
@ -902,7 +902,7 @@ impl Component for PlainListing {
|
|||
self.dirty = true;
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref k) if self.unfocused && *k == shortcuts["exit_thread"] => {
|
||||
UIEvent::Input(ref k) if self.unfocused && k == shortcuts["exit_thread"] => {
|
||||
self.unfocused = false;
|
||||
self.dirty = true;
|
||||
/* If self.row_updates is not empty and we exit a thread, the row_update events
|
||||
|
@ -911,7 +911,7 @@ impl Component for PlainListing {
|
|||
self.force_draw = true;
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref key) if !self.unfocused && *key == shortcuts["select_entry"] => {
|
||||
UIEvent::Input(ref key) if !self.unfocused && key == shortcuts["select_entry"] => {
|
||||
let env_hash = self.get_env_under_cursor(self.cursor_pos.2, context);
|
||||
self.selection.entry(env_hash).and_modify(|e| *e = !*e);
|
||||
}
|
||||
|
@ -1074,13 +1074,7 @@ impl Component for PlainListing {
|
|||
};
|
||||
|
||||
let config_map = context.settings.shortcuts.compact_listing.key_values();
|
||||
map.insert(
|
||||
PlainListing::DESCRIPTION.to_string(),
|
||||
config_map
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.clone()))
|
||||
.collect(),
|
||||
);
|
||||
map.insert(PlainListing::DESCRIPTION, config_map);
|
||||
|
||||
map
|
||||
}
|
||||
|
|
|
@ -693,7 +693,7 @@ impl Component for MailView {
|
|||
|
||||
let shortcuts = &self.get_shortcuts(context)[MailView::DESCRIPTION];
|
||||
match *event {
|
||||
UIEvent::Input(ref k) if *k == shortcuts["reply"] => {
|
||||
UIEvent::Input(ref k) if k == shortcuts["reply"] => {
|
||||
let account = &context.accounts[self.coordinates.0];
|
||||
let folder_hash = account[self.coordinates.1].unwrap().folder.hash();
|
||||
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
|
||||
|
@ -710,7 +710,7 @@ impl Component for MailView {
|
|||
))));
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref k) if *k == shortcuts["edit"] => {
|
||||
UIEvent::Input(ref k) if k == shortcuts["edit"] => {
|
||||
context.replies.push_back(UIEvent::Action(Tab(Edit(
|
||||
self.coordinates.0,
|
||||
self.coordinates.2,
|
||||
|
@ -719,7 +719,7 @@ impl Component for MailView {
|
|||
}
|
||||
UIEvent::Input(ref key)
|
||||
if !self.mode.is_contact_selector()
|
||||
&& *key == shortcuts["add_addresses_to_contacts"] =>
|
||||
&& key == shortcuts["add_addresses_to_contacts"] =>
|
||||
{
|
||||
let account = &context.accounts[self.coordinates.0];
|
||||
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
|
||||
|
@ -766,7 +766,7 @@ impl Component for MailView {
|
|||
}
|
||||
UIEvent::Input(ref key)
|
||||
if (self.mode == ViewMode::Normal || self.mode == ViewMode::Subview)
|
||||
&& *key == shortcuts["view_raw_source"] =>
|
||||
&& key == shortcuts["view_raw_source"] =>
|
||||
{
|
||||
self.mode = ViewMode::Raw;
|
||||
self.set_dirty();
|
||||
|
@ -777,7 +777,7 @@ impl Component for MailView {
|
|||
|| self.mode == ViewMode::Subview
|
||||
|| self.mode == ViewMode::Url
|
||||
|| self.mode == ViewMode::Raw)
|
||||
&& *key == shortcuts["return_to_normal_view"] =>
|
||||
&& key == shortcuts["return_to_normal_view"] =>
|
||||
{
|
||||
self.mode = ViewMode::Normal;
|
||||
self.set_dirty();
|
||||
|
@ -786,7 +786,7 @@ impl Component for MailView {
|
|||
UIEvent::Input(ref key)
|
||||
if (self.mode == ViewMode::Normal || self.mode == ViewMode::Subview)
|
||||
&& !self.cmd_buf.is_empty()
|
||||
&& *key == shortcuts["open_mailcap"] =>
|
||||
&& key == shortcuts["open_mailcap"] =>
|
||||
{
|
||||
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
||||
self.cmd_buf.clear();
|
||||
|
@ -843,7 +843,7 @@ impl Component for MailView {
|
|||
}
|
||||
}
|
||||
UIEvent::Input(ref key)
|
||||
if *key == shortcuts["open_attachment"]
|
||||
if key == shortcuts["open_attachment"]
|
||||
&& !self.cmd_buf.is_empty()
|
||||
&& (self.mode == ViewMode::Normal || self.mode == ViewMode::Subview) =>
|
||||
{
|
||||
|
@ -975,7 +975,7 @@ impl Component for MailView {
|
|||
}
|
||||
};
|
||||
}
|
||||
UIEvent::Input(ref key) if *key == shortcuts["toggle_expand_headers"] => {
|
||||
UIEvent::Input(ref key) if key == shortcuts["toggle_expand_headers"] => {
|
||||
self.expand_headers = !self.expand_headers;
|
||||
self.dirty = true;
|
||||
return true;
|
||||
|
@ -983,7 +983,7 @@ impl Component for MailView {
|
|||
UIEvent::Input(ref key)
|
||||
if !self.cmd_buf.is_empty()
|
||||
&& self.mode == ViewMode::Url
|
||||
&& *key == shortcuts["go_to_url"] =>
|
||||
&& key == shortcuts["go_to_url"] =>
|
||||
{
|
||||
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
||||
self.cmd_buf.clear();
|
||||
|
@ -1041,7 +1041,7 @@ impl Component for MailView {
|
|||
}
|
||||
UIEvent::Input(ref key)
|
||||
if (self.mode == ViewMode::Normal || self.mode == ViewMode::Url)
|
||||
&& *key == shortcuts["toggle_url_mode"] =>
|
||||
&& key == shortcuts["toggle_url_mode"] =>
|
||||
{
|
||||
match self.mode {
|
||||
ViewMode::Normal => self.mode = ViewMode::Url,
|
||||
|
@ -1338,7 +1338,7 @@ impl Component for MailView {
|
|||
our_map.insert("toggle_url_mode", Key::Char('u'));
|
||||
}
|
||||
our_map.insert("toggle_expand_headers", Key::Char('h'));
|
||||
map.insert(MailView::DESCRIPTION.to_string(), our_map);
|
||||
map.insert(MailView::DESCRIPTION, our_map);
|
||||
|
||||
map
|
||||
}
|
||||
|
|
|
@ -1074,7 +1074,7 @@ impl Component for ThreadView {
|
|||
let config_map = context.settings.shortcuts.compact_listing.key_values();
|
||||
|
||||
map.insert(
|
||||
ThreadView::DESCRIPTION.to_string(),
|
||||
ThreadView::DESCRIPTION,
|
||||
[
|
||||
("reverse thread order", Key::Ctrl('r')),
|
||||
("toggle_mailview", Key::Char('p')),
|
||||
|
|
|
@ -311,7 +311,6 @@ impl Pager {
|
|||
|
||||
pub fn update_from_str(&mut self, text: &str, width: Option<usize>) {
|
||||
let lines: Vec<String> = text.split_lines_reflow(self.reflow, width);
|
||||
debug!(&lines);
|
||||
let height = lines.len() + 2;
|
||||
let width = width.unwrap_or_else(|| lines.iter().map(|l| l.len()).max().unwrap_or(0));
|
||||
let ascii_drawing = self.content.ascii_drawing;
|
||||
|
@ -616,23 +615,11 @@ impl Component for Pager {
|
|||
self.dirty = true;
|
||||
}
|
||||
fn get_shortcuts(&self, context: &Context) -> ShortcutMaps {
|
||||
let config_map: FnvHashMap<&'static str, &Key> =
|
||||
let config_map: FnvHashMap<&'static str, Key> =
|
||||
context.settings.shortcuts.pager.key_values();
|
||||
[(
|
||||
Pager::DESCRIPTION.to_string(),
|
||||
[
|
||||
("scroll_up", (*config_map["scroll_up"]).clone()),
|
||||
("scroll_down", (*config_map["scroll_down"]).clone()),
|
||||
("page_up", (*config_map["page_up"]).clone()),
|
||||
("page_down", (*config_map["page_down"]).clone()),
|
||||
]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<ShortcutMap>(),
|
||||
)]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect()
|
||||
let mut ret: ShortcutMaps = Default::default();
|
||||
ret.insert(Pager::DESCRIPTION, config_map);
|
||||
ret
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
|
@ -1382,7 +1369,9 @@ impl Component for Tabbed {
|
|||
get_x(bottom_right!(area)).saturating_sub(3),
|
||||
),
|
||||
);
|
||||
let children_maps = self.children[self.cursor_pos].get_shortcuts(context);
|
||||
let mut children_maps = self.children[self.cursor_pos].get_shortcuts(context);
|
||||
let our_map = self.get_shortcuts(context);
|
||||
children_maps.extend(our_map.into_iter());
|
||||
if children_maps.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
@ -1508,6 +1497,8 @@ impl Component for Tabbed {
|
|||
self.dirty = false;
|
||||
}
|
||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
let our_shortcuts = self.get_shortcuts(context);
|
||||
let shortcuts: &ShortcutMap = &our_shortcuts["general"];
|
||||
match *event {
|
||||
UIEvent::Input(Key::Alt(no)) if no >= '1' && no <= '9' => {
|
||||
let no = no as usize - '1' as usize;
|
||||
|
@ -1524,7 +1515,7 @@ impl Component for Tabbed {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(Key::Char('T')) => {
|
||||
UIEvent::Input(ref key) if *key == shortcuts["next_tab"] => {
|
||||
self.cursor_pos = (self.cursor_pos + 1) % self.children.len();
|
||||
context
|
||||
.replies
|
||||
|
@ -1664,6 +1655,12 @@ impl Component for Tabbed {
|
|||
self.id = id;
|
||||
}
|
||||
|
||||
fn get_shortcuts(&self, context: &Context) -> ShortcutMaps {
|
||||
let mut map = ShortcutMaps::default();
|
||||
map.insert("general", context.settings.shortcuts.general.key_values());
|
||||
map
|
||||
}
|
||||
|
||||
fn can_quit_cleanly(&mut self, context: &Context) -> bool {
|
||||
for (i, c) in self.children.iter_mut().enumerate() {
|
||||
if !c.can_quit_cleanly(context) {
|
||||
|
|
|
@ -4,9 +4,13 @@ use fnv::FnvHashMap;
|
|||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Shortcuts {
|
||||
#[serde(flatten)]
|
||||
pub general: GeneralShortcuts,
|
||||
#[serde(flatten)]
|
||||
pub listing: ListingShortcuts,
|
||||
#[serde(flatten)]
|
||||
pub composing: ComposingShortcuts,
|
||||
#[serde(flatten)]
|
||||
pub compact_listing: CompactListingShortcuts,
|
||||
#[serde(flatten)]
|
||||
pub contact_list: ContactListShortcuts,
|
||||
|
@ -38,9 +42,9 @@ macro_rules! shortcut_key_values {
|
|||
}
|
||||
}
|
||||
/// Returns a hashmap of all shortcuts and their values
|
||||
pub fn key_values(&self) -> FnvHashMap<&'static str, &Key> {
|
||||
pub fn key_values(&self) -> FnvHashMap<&'static str, Key> {
|
||||
[
|
||||
$((stringify!($fname),&(self.$fname)),)*
|
||||
$((stringify!($fname),(self.$fname).clone()),)*
|
||||
].iter().cloned().collect()
|
||||
}
|
||||
}
|
||||
|
@ -100,3 +104,17 @@ shortcut_key_values! { "pager",
|
|||
page_down: Key |> "Go to next pager page" |> Key::PageDown
|
||||
}
|
||||
}
|
||||
|
||||
shortcut_key_values! { "general",
|
||||
pub struct GeneralShortcuts {
|
||||
next_tab: Key |> "Next tab." |> Key::Char('T'),
|
||||
go_to_tab: Key |> "Go to the nth tab" |> Key::Alt('n')
|
||||
}
|
||||
}
|
||||
|
||||
shortcut_key_values! { "composing",
|
||||
pub struct ComposingShortcuts {
|
||||
send_mail: Key |> "Deliver draft to mailer" |> Key::Char('s'),
|
||||
edit_mail: Key |> "Edit mail." |> Key::Char('e')
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue